about summary refs log tree commit diff stats
path: root/js/games/nluqo.github.io/~bh/downloads/simply
diff options
context:
space:
mode:
authorelioat <elioat@tilde.institute>2023-08-23 07:52:19 -0400
committerelioat <elioat@tilde.institute>2023-08-23 07:52:19 -0400
commit562a9a52d599d9a05f871404050968a5fd282640 (patch)
tree7d3305c1252c043bfe246ccc7deff0056aa6b5ab /js/games/nluqo.github.io/~bh/downloads/simply
parent5d012c6c011a9dedf7d0a098e456206244eb5a0f (diff)
downloadtour-562a9a52d599d9a05f871404050968a5fd282640.tar.gz
*
Diffstat (limited to 'js/games/nluqo.github.io/~bh/downloads/simply')
-rw-r--r--js/games/nluqo.github.io/~bh/downloads/simply/database.scm84
-rw-r--r--js/games/nluqo.github.io/~bh/downloads/simply/functions.scm244
-rw-r--r--js/games/nluqo.github.io/~bh/downloads/simply/index.html?C=D;O=A21
-rw-r--r--js/games/nluqo.github.io/~bh/downloads/simply/index.html?C=D;O=D21
-rw-r--r--js/games/nluqo.github.io/~bh/downloads/simply/index.html?C=M;O=A21
-rw-r--r--js/games/nluqo.github.io/~bh/downloads/simply/index.html?C=N;O=A21
-rw-r--r--js/games/nluqo.github.io/~bh/downloads/simply/index.html?C=N;O=D21
-rw-r--r--js/games/nluqo.github.io/~bh/downloads/simply/index.html?C=S;O=A21
-rw-r--r--js/games/nluqo.github.io/~bh/downloads/simply/index.html?C=S;O=D21
-rw-r--r--js/games/nluqo.github.io/~bh/downloads/simply/match.scm107
-rw-r--r--js/games/nluqo.github.io/~bh/downloads/simply/newttt.scm59
-rw-r--r--js/games/nluqo.github.io/~bh/downloads/simply/simply.scm1149
-rw-r--r--js/games/nluqo.github.io/~bh/downloads/simply/spread.scm550
-rw-r--r--js/games/nluqo.github.io/~bh/downloads/simply/ttt.scm102
14 files changed, 2442 insertions, 0 deletions
diff --git a/js/games/nluqo.github.io/~bh/downloads/simply/database.scm b/js/games/nluqo.github.io/~bh/downloads/simply/database.scm
new file mode 100644
index 0000000..5f9c17f
--- /dev/null
+++ b/js/games/nluqo.github.io/~bh/downloads/simply/database.scm
@@ -0,0 +1,84 @@
+;;; Database.scm:  This file contains the code we show in the database
+;;; chapter of _Simply_Scheme_.  You should add your new work to this file.
+
+;;; The database ADT: a filename, list of fields and list of records
+
+(define (make-db filename fields records)
+  (vector filename fields records))
+
+(define (db-filename db)
+  (vector-ref db 0))
+
+(define (db-set-filename! db filename)
+  (vector-set! db 0 filename))
+
+(define (db-fields db)
+  (vector-ref db 1))
+
+(define (db-set-fields! db fields)
+  (vector-set! db 1 fields))
+
+(define (db-records db)
+  (vector-ref db 2))
+
+(define (db-set-records! db records)
+  (vector-set! db 2 records))
+
+
+;;; Stuff about the current state
+
+(define current-state (vector #f))
+
+(define (no-db?)
+  (not (vector-ref current-state 0)))
+
+(define (current-db)
+  (if (no-db?)
+      (error "No current database!")
+      (vector-ref current-state 0)))
+
+(define (set-current-db! db)
+  (vector-set! current-state 0 db))
+
+(define (current-fields)
+  (db-fields (current-db)))
+
+;; User commands
+
+(define (new-db filename fields)
+  (set-current-db! (make-db filename fields '()))
+  'created)
+
+(define (insert)
+  (let ((new-record (get-record)))
+    (db-insert new-record (current-db)))
+  (if (ask "Insert another? ")
+      (insert)
+      'inserted))
+
+(define (db-insert record db)
+  (db-set-records! db (cons record (db-records db))))
+
+(define (get-record)
+  (get-record-loop 0
+		   (make-vector (length (current-fields)))
+		   (current-fields)))
+
+(define (get-record-loop which-field record fields)
+  (if (null? fields)
+      record
+      (begin (display "Value for ")
+	     (display (car fields))
+	     (display "--> ")
+	     (vector-set! record which-field (read))
+	     (get-record-loop (+ which-field 1) record (cdr fields)))))
+
+;;; Utilities
+
+(define (ask question)
+  (display question)
+  (let ((answer (read)))
+    (cond ((equal? (first answer) 'y) #t)
+	  ((equal? (first answer) 'n) #f)
+	  (else (show "Please type Y or N.")
+		(ask question)))))
diff --git a/js/games/nluqo.github.io/~bh/downloads/simply/functions.scm b/js/games/nluqo.github.io/~bh/downloads/simply/functions.scm
new file mode 100644
index 0000000..e421ee3
--- /dev/null
+++ b/js/games/nluqo.github.io/~bh/downloads/simply/functions.scm
@@ -0,0 +1,244 @@
+;;; The functions program
+
+(define (functions)
+  (read-line)
+  (show "Welcome to the FUNCTIONS program.")
+  (functions-loop))
+
+(define (functions-loop)
+  (let ((fn-name (get-fn)))
+    (if (equal? fn-name 'exit)
+	"Thanks for using FUNCTIONS!"
+	(let ((args (get-args (arg-count fn-name))))
+	  (if (not (in-domain? args fn-name))
+	     (show "Argument(s) not in domain.")
+	     (show-answer (apply (scheme-function fn-name) args)))
+	  (functions-loop)))))
+
+(define (get-fn)
+  (display "Function: ")
+  (let ((line (read-line)))
+    (cond ((empty? line)
+	   (show "Please type a function!")
+	   (get-fn))
+	  ((not (= (count line) 1))
+	   (show "You typed more than one thing!  Try again.")
+	   (get-fn))
+	  ((not (valid-fn-name? (first line)))
+	   (show "Sorry, that's not a function.")
+	   (get-fn))
+	  (else (first line)))))
+
+(define (get-args n)
+  (if (= n 0)
+      '()
+      (let ((first (get-arg)))
+	(cons first (get-args (- n 1))))))
+
+(define (get-arg)
+  (display "Argument: ")
+  (let ((line (read-line)))
+    (cond ((empty? line)
+	   (show "Please type an argument!")
+	   (get-arg))
+	  ((and (equal? "(" (first (first line)))
+		(equal? ")" (last (last line))))
+	   (let ((sent (remove-first-paren (remove-last-paren line))))
+	     (if (any-parens? sent)
+		 (begin
+		  (show "Sentences can't have parentheses inside.")
+		  (get-arg))
+		 (map booleanize sent))))
+	  ((any-parens? line)
+	   (show "Bad parentheses")
+	   (get-arg))
+	  ((empty? (bf line)) (booleanize (first line)))
+	  ((member? (first (first line)) "\"'")
+	   (show "No quoting arguments in this program.  Try again.")
+	   (get-arg))
+	  (else (show "You typed more than one argument!  Try again.")
+		(get-arg)))))
+
+(define (any-parens? line)
+  (let ((letters (accumulate word line)))
+    (or (member? "(" letters)
+	(member? ")" letters))))
+
+(define (remove-first-paren line)
+  (if (equal? (first line) "(")
+      (bf line)
+      (se (bf (first line)) (bf line))))
+
+(define (remove-last-paren line)
+  (if (equal? (last line) ")")
+      (bl line)
+      (se (bl line) (bl (last line)))))
+
+(define (booleanize x)
+  (cond ((equal? x "#t") #t)
+	((equal? x "#f") #f)
+	(else x)))
+
+(define (show-answer answer)
+  (newline)
+  (display "The result is: ")
+  (if (not answer)
+      (show "#F")
+      (show answer))
+  (newline))
+
+(define (scheme-function fn-name)
+  (cadr (assoc fn-name *the-functions*)))
+
+(define (arg-count fn-name)
+  (caddr (assoc fn-name *the-functions*)))
+
+(define (type-predicate fn-name)
+  (cadddr (assoc fn-name *the-functions*)))
+
+(define (in-domain? args fn-name)
+  (apply (type-predicate fn-name) args))
+
+
+;; Type predicates
+
+(define (word-or-sent? x)
+  (or (word? x) (sentence? x)))
+
+(define (not-empty? x)
+  (and (word-or-sent? x) (not (empty? x))))
+
+(define (two-numbers? x y)
+  (and (number? x) (number? y)))
+
+(define (two-reals? x y)
+  (and (real? x) (real? y)))
+
+(define (two-integers? x y)
+  (and (integer? x) (integer? y)))
+
+(define (can-divide? x y)
+  (and (number? x) (number? y) (not (= y 0))))
+
+(define (dividable-integers? x y)
+  (and (two-integers? x y) (not (= y 0))))
+
+(define (trig-range? x)
+  (and (number? x) (<= (abs x) 1)))
+
+(define (hof-types-ok? fn-name stuff range-predicate)
+  (and (valid-fn-name? fn-name)
+       (= 1 (arg-count fn-name))
+       (word-or-sent? stuff)
+       (empty? (keep (lambda (element)
+		       (not ((type-predicate fn-name) element)))
+		     stuff))
+       (null? (filter (lambda (element)
+			(not (range-predicate element)))
+		      (map (scheme-function fn-name)
+			   (every (lambda (x) x) stuff))))))
+
+(define (member-types-ok? small big)
+  (and (word? small)
+       (or (sentence? big) (= (count small) 1))))
+
+
+;; Names of functions as functions
+
+(define (named-every fn-name list)
+  (every (scheme-function fn-name) list))
+
+(define (named-keep fn-name list)
+  (keep (scheme-function fn-name) list))
+
+(define (valid-fn-name? name)
+  (assoc name *the-functions*))
+
+
+;; The list itself
+          
+(define *the-functions*
+  (list (list '* * 2 two-numbers?)
+	(list '+ + 2 two-numbers?)
+	(list '- - 2 two-numbers?)
+	(list '/ / 2 can-divide?)
+	(list '< < 2 two-reals?)
+	(list '<= <= 2 two-reals?)
+	(list '= = 2 two-numbers?)
+	(list '> > 2 two-reals?)
+	(list '>= >= 2 two-reals?)
+	(list 'abs abs 1 real?)
+
+	(list 'acos acos 1 trig-range?)
+	(list 'and (lambda (x y) (and x y)) 2 
+	      (lambda (x y) (and (boolean? x) (boolean? y))))
+	(list 'appearances appearances 2 member-types-ok?)
+	(list 'asin asin 1 trig-range?)
+	(list 'atan atan 1 number?)
+	(list 'bf bf 1 not-empty?)
+	(list 'bl bl 1 not-empty?)
+	(list 'butfirst butfirst 1 not-empty?)
+	(list 'butlast butlast 1 not-empty?)
+	(list 'ceiling ceiling 1 real?)
+	(list 'cos cos 1 number?)
+	(list 'count count 1 word-or-sent?)
+	(list 'equal? equal? 2 (lambda (x y) #t))
+	(list 'even? even? 1 integer?)
+	(list 'every named-every 2
+	      (lambda (fn stuff)
+		(hof-types-ok? fn stuff word-or-sent?)))
+	(list 'exit '() 0 '())
+	   ; in case user applies number-of-arguments to exit
+	(list 'exp exp 1 number?)
+	(list 'expt expt 2
+	      (lambda (x y)
+		(and (number? x) (number? y)
+		     (or (not (real? x)) (>= x 0) (integer? y)))))
+	(list 'first first 1 not-empty?)
+	(list 'floor floor 1 real?)
+	(list 'gcd gcd 2 two-integers?)
+	(list 'if (lambda (pred yes no) (if pred yes no)) 3
+	      (lambda (pred yes no) (boolean? pred)))
+	(list 'item item 2
+	      (lambda (n stuff)
+		(and (integer? n) (> n 0)
+		     (word-or-sent? stuff) (<= n (count stuff)))))
+	(list 'keep named-keep 2
+	      (lambda (fn stuff)
+		(hof-types-ok? fn stuff boolean?)))
+	(list 'last last 1 not-empty?)
+	(list 'lcm lcm 2 two-integers?)
+	(list 'log log 1 (lambda (x) (and (number? x) (not (= x 0)))))
+	(list 'max max 2 two-reals?)
+	(list 'member? member? 2 member-types-ok?)
+	(list 'min min 2 two-reals?)
+	(list 'modulo modulo 2 dividable-integers?)
+	(list 'not not 1 boolean?)
+
+	(list 'number-of-arguments arg-count 1 valid-fn-name?)
+	(list 'odd? odd? 1 integer?)
+	(list 'or (lambda (x y) (or x y)) 2
+	      (lambda (x y) (and (boolean? x) (boolean? y))))
+	(list 'quotient quotient 2 dividable-integers?)
+	(list 'random random 1 (lambda (x) (and (integer? x) (> x 0))))
+	(list 'remainder remainder 2 dividable-integers?)
+	(list 'round round 1 real?)
+	(list 'se se 2
+	      (lambda (x y) (and (word-or-sent? x) (word-or-sent? y))))
+	(list 'sentence sentence 2
+	      (lambda (x y) (and (word-or-sent? x) (word-or-sent? y))))
+	(list 'sentence? sentence? 1 (lambda (x) #t))
+	(list 'sin sin 1 number?)
+	(list 'sqrt sqrt 1 (lambda (x) (and (real? x) (>= x 0))))
+	(list 'tan tan 1 number?)
+	(list 'truncate truncate 1 real?)
+	(list 'vowel?
+	      (lambda (x)
+		(and (word? x)
+		     (= (count x) 1)
+		     (member? x '(a e i o u))))
+	      1
+	      (lambda (x) #t))
+	(list 'word word 2 (lambda (x y) (and (word? x) (word? y))))
+	(list 'word? word? 1 (lambda (x) #t))))
+
diff --git a/js/games/nluqo.github.io/~bh/downloads/simply/index.html?C=D;O=A b/js/games/nluqo.github.io/~bh/downloads/simply/index.html?C=D;O=A
new file mode 100644
index 0000000..c03dd0f
--- /dev/null
+++ b/js/games/nluqo.github.io/~bh/downloads/simply/index.html?C=D;O=A
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+ <head>
+  <title>Index of /~bh/downloads/simply</title>
+ </head>
+ <body>
+<h1>Index of /~bh/downloads/simply</h1>
+  <table>
+   <tr><th valign="top"><img src="../../../icons/blank.gif" alt="[ICO]"></th><th><a href="index.html?C=N%3BO=A">Name</a></th><th><a href="index.html?C=M%3BO=A">Last modified</a></th><th><a href="index.html?C=S%3BO=A">Size</a></th><th><a href="index.html?C=D%3BO=D">Description</a></th></tr>
+   <tr><th colspan="5"><hr></th></tr>
+<tr><td valign="top"><img src="../../../icons/back.gif" alt="[PARENTDIR]"></td><td><a href="../index.html">Parent Directory</a>       </td><td>&nbsp;</td><td align="right">  - </td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="database.scm">database.scm</a>           </td><td align="right">2006-07-05 04:59  </td><td align="right">1.9K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="functions.scm">functions.scm</a>          </td><td align="right">2006-07-05 04:59  </td><td align="right">6.7K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="match.scm">match.scm</a>              </td><td align="right">2006-07-05 04:59  </td><td align="right">3.3K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="newttt.scm">newttt.scm</a>             </td><td align="right">2006-07-05 04:59  </td><td align="right">1.6K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="simply.scm">simply.scm</a>             </td><td align="right">2006-07-05 04:59  </td><td align="right"> 32K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="spread.scm">spread.scm</a>             </td><td align="right">2006-07-05 04:59  </td><td align="right"> 14K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="ttt.scm">ttt.scm</a>                </td><td align="right">2006-07-05 04:59  </td><td align="right">2.8K</td><td>&nbsp;</td></tr>
+   <tr><th colspan="5"><hr></th></tr>
+</table>
+</body></html>
diff --git a/js/games/nluqo.github.io/~bh/downloads/simply/index.html?C=D;O=D b/js/games/nluqo.github.io/~bh/downloads/simply/index.html?C=D;O=D
new file mode 100644
index 0000000..26054d4
--- /dev/null
+++ b/js/games/nluqo.github.io/~bh/downloads/simply/index.html?C=D;O=D
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+ <head>
+  <title>Index of /~bh/downloads/simply</title>
+ </head>
+ <body>
+<h1>Index of /~bh/downloads/simply</h1>
+  <table>
+   <tr><th valign="top"><img src="../../../icons/blank.gif" alt="[ICO]"></th><th><a href="index.html?C=N%3BO=A">Name</a></th><th><a href="index.html?C=M%3BO=A">Last modified</a></th><th><a href="index.html?C=S%3BO=A">Size</a></th><th><a href="index.html?C=D%3BO=A">Description</a></th></tr>
+   <tr><th colspan="5"><hr></th></tr>
+<tr><td valign="top"><img src="../../../icons/back.gif" alt="[PARENTDIR]"></td><td><a href="../index.html">Parent Directory</a>       </td><td>&nbsp;</td><td align="right">  - </td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="ttt.scm">ttt.scm</a>                </td><td align="right">2006-07-05 04:59  </td><td align="right">2.8K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="spread.scm">spread.scm</a>             </td><td align="right">2006-07-05 04:59  </td><td align="right"> 14K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="simply.scm">simply.scm</a>             </td><td align="right">2006-07-05 04:59  </td><td align="right"> 32K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="newttt.scm">newttt.scm</a>             </td><td align="right">2006-07-05 04:59  </td><td align="right">1.6K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="match.scm">match.scm</a>              </td><td align="right">2006-07-05 04:59  </td><td align="right">3.3K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="functions.scm">functions.scm</a>          </td><td align="right">2006-07-05 04:59  </td><td align="right">6.7K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="database.scm">database.scm</a>           </td><td align="right">2006-07-05 04:59  </td><td align="right">1.9K</td><td>&nbsp;</td></tr>
+   <tr><th colspan="5"><hr></th></tr>
+</table>
+</body></html>
diff --git a/js/games/nluqo.github.io/~bh/downloads/simply/index.html?C=M;O=A b/js/games/nluqo.github.io/~bh/downloads/simply/index.html?C=M;O=A
new file mode 100644
index 0000000..0fc3d16
--- /dev/null
+++ b/js/games/nluqo.github.io/~bh/downloads/simply/index.html?C=M;O=A
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+ <head>
+  <title>Index of /~bh/downloads/simply</title>
+ </head>
+ <body>
+<h1>Index of /~bh/downloads/simply</h1>
+  <table>
+   <tr><th valign="top"><img src="../../../icons/blank.gif" alt="[ICO]"></th><th><a href="index.html?C=N%3BO=A">Name</a></th><th><a href="https://people.eecs.berkeley.edu/~bh/downloads/simply/?C=M;O=D">Last modified</a></th><th><a href="index.html?C=S%3BO=A">Size</a></th><th><a href="index.html?C=D%3BO=A">Description</a></th></tr>
+   <tr><th colspan="5"><hr></th></tr>
+<tr><td valign="top"><img src="../../../icons/back.gif" alt="[PARENTDIR]"></td><td><a href="../index.html">Parent Directory</a>       </td><td>&nbsp;</td><td align="right">  - </td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="database.scm">database.scm</a>           </td><td align="right">2006-07-05 04:59  </td><td align="right">1.9K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="functions.scm">functions.scm</a>          </td><td align="right">2006-07-05 04:59  </td><td align="right">6.7K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="match.scm">match.scm</a>              </td><td align="right">2006-07-05 04:59  </td><td align="right">3.3K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="newttt.scm">newttt.scm</a>             </td><td align="right">2006-07-05 04:59  </td><td align="right">1.6K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="simply.scm">simply.scm</a>             </td><td align="right">2006-07-05 04:59  </td><td align="right"> 32K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="spread.scm">spread.scm</a>             </td><td align="right">2006-07-05 04:59  </td><td align="right"> 14K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="ttt.scm">ttt.scm</a>                </td><td align="right">2006-07-05 04:59  </td><td align="right">2.8K</td><td>&nbsp;</td></tr>
+   <tr><th colspan="5"><hr></th></tr>
+</table>
+</body></html>
diff --git a/js/games/nluqo.github.io/~bh/downloads/simply/index.html?C=N;O=A b/js/games/nluqo.github.io/~bh/downloads/simply/index.html?C=N;O=A
new file mode 100644
index 0000000..761d1dd
--- /dev/null
+++ b/js/games/nluqo.github.io/~bh/downloads/simply/index.html?C=N;O=A
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+ <head>
+  <title>Index of /~bh/downloads/simply</title>
+ </head>
+ <body>
+<h1>Index of /~bh/downloads/simply</h1>
+  <table>
+   <tr><th valign="top"><img src="../../../icons/blank.gif" alt="[ICO]"></th><th><a href="index.html?C=N%3BO=D">Name</a></th><th><a href="index.html?C=M%3BO=A">Last modified</a></th><th><a href="index.html?C=S%3BO=A">Size</a></th><th><a href="index.html?C=D%3BO=A">Description</a></th></tr>
+   <tr><th colspan="5"><hr></th></tr>
+<tr><td valign="top"><img src="../../../icons/back.gif" alt="[PARENTDIR]"></td><td><a href="../index.html">Parent Directory</a>       </td><td>&nbsp;</td><td align="right">  - </td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="database.scm">database.scm</a>           </td><td align="right">2006-07-05 04:59  </td><td align="right">1.9K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="functions.scm">functions.scm</a>          </td><td align="right">2006-07-05 04:59  </td><td align="right">6.7K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="match.scm">match.scm</a>              </td><td align="right">2006-07-05 04:59  </td><td align="right">3.3K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="newttt.scm">newttt.scm</a>             </td><td align="right">2006-07-05 04:59  </td><td align="right">1.6K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="simply.scm">simply.scm</a>             </td><td align="right">2006-07-05 04:59  </td><td align="right"> 32K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="spread.scm">spread.scm</a>             </td><td align="right">2006-07-05 04:59  </td><td align="right"> 14K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="ttt.scm">ttt.scm</a>                </td><td align="right">2006-07-05 04:59  </td><td align="right">2.8K</td><td>&nbsp;</td></tr>
+   <tr><th colspan="5"><hr></th></tr>
+</table>
+</body></html>
diff --git a/js/games/nluqo.github.io/~bh/downloads/simply/index.html?C=N;O=D b/js/games/nluqo.github.io/~bh/downloads/simply/index.html?C=N;O=D
new file mode 100644
index 0000000..26054d4
--- /dev/null
+++ b/js/games/nluqo.github.io/~bh/downloads/simply/index.html?C=N;O=D
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+ <head>
+  <title>Index of /~bh/downloads/simply</title>
+ </head>
+ <body>
+<h1>Index of /~bh/downloads/simply</h1>
+  <table>
+   <tr><th valign="top"><img src="../../../icons/blank.gif" alt="[ICO]"></th><th><a href="index.html?C=N%3BO=A">Name</a></th><th><a href="index.html?C=M%3BO=A">Last modified</a></th><th><a href="index.html?C=S%3BO=A">Size</a></th><th><a href="index.html?C=D%3BO=A">Description</a></th></tr>
+   <tr><th colspan="5"><hr></th></tr>
+<tr><td valign="top"><img src="../../../icons/back.gif" alt="[PARENTDIR]"></td><td><a href="../index.html">Parent Directory</a>       </td><td>&nbsp;</td><td align="right">  - </td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="ttt.scm">ttt.scm</a>                </td><td align="right">2006-07-05 04:59  </td><td align="right">2.8K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="spread.scm">spread.scm</a>             </td><td align="right">2006-07-05 04:59  </td><td align="right"> 14K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="simply.scm">simply.scm</a>             </td><td align="right">2006-07-05 04:59  </td><td align="right"> 32K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="newttt.scm">newttt.scm</a>             </td><td align="right">2006-07-05 04:59  </td><td align="right">1.6K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="match.scm">match.scm</a>              </td><td align="right">2006-07-05 04:59  </td><td align="right">3.3K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="functions.scm">functions.scm</a>          </td><td align="right">2006-07-05 04:59  </td><td align="right">6.7K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="database.scm">database.scm</a>           </td><td align="right">2006-07-05 04:59  </td><td align="right">1.9K</td><td>&nbsp;</td></tr>
+   <tr><th colspan="5"><hr></th></tr>
+</table>
+</body></html>
diff --git a/js/games/nluqo.github.io/~bh/downloads/simply/index.html?C=S;O=A b/js/games/nluqo.github.io/~bh/downloads/simply/index.html?C=S;O=A
new file mode 100644
index 0000000..51fc0ca
--- /dev/null
+++ b/js/games/nluqo.github.io/~bh/downloads/simply/index.html?C=S;O=A
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+ <head>
+  <title>Index of /~bh/downloads/simply</title>
+ </head>
+ <body>
+<h1>Index of /~bh/downloads/simply</h1>
+  <table>
+   <tr><th valign="top"><img src="../../../icons/blank.gif" alt="[ICO]"></th><th><a href="index.html?C=N%3BO=A">Name</a></th><th><a href="index.html?C=M%3BO=A">Last modified</a></th><th><a href="index.html?C=S%3BO=D">Size</a></th><th><a href="index.html?C=D%3BO=A">Description</a></th></tr>
+   <tr><th colspan="5"><hr></th></tr>
+<tr><td valign="top"><img src="../../../icons/back.gif" alt="[PARENTDIR]"></td><td><a href="../index.html">Parent Directory</a>       </td><td>&nbsp;</td><td align="right">  - </td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="newttt.scm">newttt.scm</a>             </td><td align="right">2006-07-05 04:59  </td><td align="right">1.6K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="database.scm">database.scm</a>           </td><td align="right">2006-07-05 04:59  </td><td align="right">1.9K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="ttt.scm">ttt.scm</a>                </td><td align="right">2006-07-05 04:59  </td><td align="right">2.8K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="match.scm">match.scm</a>              </td><td align="right">2006-07-05 04:59  </td><td align="right">3.3K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="functions.scm">functions.scm</a>          </td><td align="right">2006-07-05 04:59  </td><td align="right">6.7K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="spread.scm">spread.scm</a>             </td><td align="right">2006-07-05 04:59  </td><td align="right"> 14K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="simply.scm">simply.scm</a>             </td><td align="right">2006-07-05 04:59  </td><td align="right"> 32K</td><td>&nbsp;</td></tr>
+   <tr><th colspan="5"><hr></th></tr>
+</table>
+</body></html>
diff --git a/js/games/nluqo.github.io/~bh/downloads/simply/index.html?C=S;O=D b/js/games/nluqo.github.io/~bh/downloads/simply/index.html?C=S;O=D
new file mode 100644
index 0000000..2b4516e
--- /dev/null
+++ b/js/games/nluqo.github.io/~bh/downloads/simply/index.html?C=S;O=D
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+ <head>
+  <title>Index of /~bh/downloads/simply</title>
+ </head>
+ <body>
+<h1>Index of /~bh/downloads/simply</h1>
+  <table>
+   <tr><th valign="top"><img src="../../../icons/blank.gif" alt="[ICO]"></th><th><a href="index.html?C=N%3BO=A">Name</a></th><th><a href="index.html?C=M%3BO=A">Last modified</a></th><th><a href="index.html?C=S%3BO=A">Size</a></th><th><a href="index.html?C=D%3BO=A">Description</a></th></tr>
+   <tr><th colspan="5"><hr></th></tr>
+<tr><td valign="top"><img src="../../../icons/back.gif" alt="[PARENTDIR]"></td><td><a href="../index.html">Parent Directory</a>       </td><td>&nbsp;</td><td align="right">  - </td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="simply.scm">simply.scm</a>             </td><td align="right">2006-07-05 04:59  </td><td align="right"> 32K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="spread.scm">spread.scm</a>             </td><td align="right">2006-07-05 04:59  </td><td align="right"> 14K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="functions.scm">functions.scm</a>          </td><td align="right">2006-07-05 04:59  </td><td align="right">6.7K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="match.scm">match.scm</a>              </td><td align="right">2006-07-05 04:59  </td><td align="right">3.3K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="ttt.scm">ttt.scm</a>                </td><td align="right">2006-07-05 04:59  </td><td align="right">2.8K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="database.scm">database.scm</a>           </td><td align="right">2006-07-05 04:59  </td><td align="right">1.9K</td><td>&nbsp;</td></tr>
+<tr><td valign="top"><img src="../../../icons/unknown.gif" alt="[   ]"></td><td><a href="newttt.scm">newttt.scm</a>             </td><td align="right">2006-07-05 04:59  </td><td align="right">1.6K</td><td>&nbsp;</td></tr>
+   <tr><th colspan="5"><hr></th></tr>
+</table>
+</body></html>
diff --git a/js/games/nluqo.github.io/~bh/downloads/simply/match.scm b/js/games/nluqo.github.io/~bh/downloads/simply/match.scm
new file mode 100644
index 0000000..f454f68
--- /dev/null
+++ b/js/games/nluqo.github.io/~bh/downloads/simply/match.scm
@@ -0,0 +1,107 @@
+(define (match pattern sent)
+  (match-using-known-values pattern sent '()))
+
+(define (match-using-known-values pattern sent known-values)
+  (cond ((empty? pattern)
+	 (if (empty? sent) known-values 'failed))
+	((special? (first pattern))
+	 (let ((placeholder (first pattern)))
+	   (match-special (first placeholder)
+			  (bf placeholder)
+			  (bf pattern)
+			  sent
+			  known-values)))
+	((empty? sent) 'failed)
+	((equal? (first pattern) (first sent))
+	 (match-using-known-values (bf pattern) (bf sent) known-values))
+	(else 'failed)))
+
+(define (special? wd)
+  (member? (first wd) '(* & ? !)))
+
+(define (match-special howmany name pattern-rest sent known-values)
+  (let ((old-value (lookup name known-values)))
+    (cond ((not (equal? old-value 'no-value))
+	   (if (length-ok? old-value howmany)
+	       (already-known-match
+		  old-value pattern-rest sent known-values)
+	       'failed))
+	  ((equal? howmany '?)
+	   (longest-match name pattern-rest sent 0 #t known-values))
+	  ((equal? howmany '!)
+	   (longest-match name pattern-rest sent 1 #t known-values))
+	  ((equal? howmany '*)
+	   (longest-match name pattern-rest sent 0 #f known-values))
+	  ((equal? howmany '&)
+	   (longest-match name pattern-rest sent 1 #f known-values)))))
+
+(define (length-ok? value howmany)
+  (cond ((empty? value) (member? howmany '(? *)))
+	((not (empty? (bf value))) (member? howmany '(* &)))
+	(else #t)))
+
+(define (already-known-match value pattern-rest sent known-values)
+  (let ((unmatched (chop-leading-substring value sent)))
+    (if (not (equal? unmatched 'failed))
+	(match-using-known-values pattern-rest unmatched known-values)
+	'failed)))
+
+(define (chop-leading-substring value sent)
+  (cond ((empty? value) sent)
+	((empty? sent) 'failed)
+	((equal? (first value) (first sent))
+	 (chop-leading-substring (bf value) (bf sent)))
+	(else 'failed)))
+
+(define (longest-match name pattern-rest sent min max-one? known-values)
+  (cond ((empty? sent)
+	 (if (= min 0)
+	     (match-using-known-values pattern-rest
+				       sent
+				       (add name '() known-values))
+	     'failed))
+	(max-one?
+	 (lm-helper name pattern-rest (se (first sent))
+		    (bf sent) min known-values))
+	(else (lm-helper name pattern-rest
+			 sent '() min known-values))))
+
+(define (lm-helper name pattern-rest
+		   sent-matched sent-unmatched min known-values)
+  (if (< (length sent-matched) min)
+      'failed
+      (let ((tentative-result (match-using-known-values
+			       pattern-rest
+			       sent-unmatched
+			       (add name sent-matched known-values))))
+	(cond ((not (equal? tentative-result 'failed)) tentative-result)
+	      ((empty? sent-matched) 'failed)
+	      (else (lm-helper name
+			       pattern-rest
+			       (bl sent-matched)
+			       (se (last sent-matched) sent-unmatched)
+			       min
+			       known-values))))))
+
+;;; Known values database abstract data type
+
+(define (lookup name known-values)
+  (cond ((empty? known-values) 'no-value)
+	((equal? (first known-values) name)
+	 (get-value (bf known-values)))
+	(else (lookup name (skip-value known-values)))))
+
+(define (get-value stuff)
+  (if (equal? (first stuff) '!)
+      '()
+      (se (first stuff) (get-value (bf stuff)))))
+
+(define (skip-value stuff)
+  (if (equal? (first stuff) '!)
+      (bf stuff)
+      (skip-value (bf stuff))))
+
+(define (add name value known-values)
+  (if (empty? name)
+      known-values
+      (se known-values name value '!)))
diff --git a/js/games/nluqo.github.io/~bh/downloads/simply/newttt.scm b/js/games/nluqo.github.io/~bh/downloads/simply/newttt.scm
new file mode 100644
index 0000000..368472e
--- /dev/null
+++ b/js/games/nluqo.github.io/~bh/downloads/simply/newttt.scm
@@ -0,0 +1,59 @@
+;;; ttt.scm
+;;; Tic-Tac-Toe program
+
+(define (ttt position me)
+  (one-okay-move (number-squares position) me))
+
+(define (one-okay-move position me)
+  (find-one (lambda (sq) (no-lose? (plug-in me sq position) me))
+	    (free-squares position)))
+
+(define (no-lose? position me)
+  (cond ((already-lost? position me) #f)
+	((already-won? position me) #t)
+	(else (not (find-one (lambda (pos) (not (one-okay-move pos me)))
+			     (extend position (opponent me)) )))))
+
+(define (free-squares pos)
+  (keep number? pos))
+
+(define (number-squares pos)
+  (ns-help pos 1))
+
+(define (ns-help pos num)
+  (cond ((empty? pos) "")
+	((equal? (first pos) '_) (word num (ns-help (bf pos) (+ num 1))))
+	(else (word (first pos) (ns-help (bf pos) (+ num 1)))) ))
+
+(define (plug-in letter sq pos)
+  (cond ((empty? pos) "")
+	((= sq 1) (word letter (bf pos)))
+	(else (word (first pos) (plug-in letter (- sq 1) (bf pos)))) ))
+
+(define (find-one pred stuff)
+  (cond ((empty? stuff) #f)
+	((pred (first stuff)) (first stuff))
+	(else (find-one pred (bf stuff))) ))
+
+(define (extend pos who)
+  (every (lambda (sq) (plug-in who sq pos))
+	 (free-squares pos)))
+
+(define (opponent letter)
+  (if (equal? letter 'x) 'o 'x))
+
+(define (already-won? pos me)
+  (find-one (lambda (win) (match-win? pos me win))
+	    '(yyynnnnnn nnnyyynnn nnnnnnyyy ynnynnynn nynnynnyn nnynnynny
+			ynnnynnny nnynynynn)))
+
+(define (already-lost? pos me)
+  (already-won? pos (opponent me)))
+
+(define (match-win? pos me win)
+  (cond ((empty? win) #t)
+	((equal? (first win) 'y)
+	 (if (equal? (first pos) me)
+	     (match-win? (bf pos) me (bf win))
+	     #f))
+	(else (match-win? (bf pos) me (bf win))) ))
diff --git a/js/games/nluqo.github.io/~bh/downloads/simply/simply.scm b/js/games/nluqo.github.io/~bh/downloads/simply/simply.scm
new file mode 100644
index 0000000..501a7da
--- /dev/null
+++ b/js/games/nluqo.github.io/~bh/downloads/simply/simply.scm
@@ -0,0 +1,1149 @@
+;;; simply.scm version 3.13 (8/11/98)
+;;; (Numbered to agree with berkeley.scm version.)
+
+
+;;; This file uses Scheme features we don't talk about in _Simply_Scheme_.
+;;; Read at your own risk.
+
+(if (equal? 'foo (symbol->string 'foo))
+    (error "Simply.scm already loaded!!")
+    #f)
+
+;; Make number->string remove leading "+" if necessary
+
+(if (char=? #\+ (string-ref (number->string 1.0) 0))
+    (let ((old-ns number->string)
+	  (char=? char=?)
+	  (string-ref string-ref)
+	  (substring substring)
+	  (string-length string-length))
+      (set! number->string
+	    (lambda args
+	      (let ((result (apply old-ns args)))
+		(if (char=? #\+ (string-ref result 0))
+		    (substring result 1 (string-length result))
+		    result)))))
+    'no-problem)
+
+(define number->string
+  (let ((old-ns number->string)
+	(string? string?))
+    (lambda args
+      (if (string? (car args))
+	  (car args)
+	  (apply old-ns args)))))
+
+;; Get strings in error messages to print nicely (especially "")
+
+(define whoops
+  (let ((string? string?)
+	(string-append string-append)
+	(error error)
+	(cons cons)
+	(map map)
+	(apply apply))
+    (define (error-printform x)
+      (if (string? x)
+	  (string-append "\"" x "\"")
+	  x))
+    (lambda (string . args)
+      (apply error (cons string (map error-printform args))))))
+
+
+;; ROUND returns an inexact integer if its argument is inexact,
+;; but we think it should always return an exact integer.
+;; (It matters because some Schemes print inexact integers as "+1.0".)
+;; The (exact 1) test is for PC Scheme, in which nothing is exact.
+(if (and (inexact? (round (sqrt 2))) (exact? 1))
+    (let ((old-round round)
+	  (inexact->exact inexact->exact))
+      (set! round
+	    (lambda (number)
+	      (inexact->exact (old-round number)))))
+    'no-problem)
+
+;; Remainder and quotient blow up if their argument isn't an integer.
+;; Unfortunately, in SCM, (* 365.25 24 60 60) *isn't* an integer.
+
+(if (inexact? (* .25 4))
+    (let ((rem remainder)
+	  (quo quotient)
+	  (inexact->exact inexact->exact)
+	  (integer? integer?))
+      (set! remainder
+	    (lambda (x y)
+	      (rem (if (integer? x) (inexact->exact x) x)
+		   (if (integer? y) (inexact->exact y) y))))
+      (set! quotient
+	    (lambda (x y)
+	      (quo (if (integer? x) (inexact->exact x) x)
+		   (if (integer? y) (inexact->exact y) y)))))
+    'done)
+
+
+;; Random
+;; If your version of Scheme has RANDOM, you should take this out.
+;; (It gives the same sequence of random numbers every time.) 
+
+(define random
+  (let ((*seed* 1) (quotient quotient) (modulo modulo) (+ +) (- -) (* *) (> >))
+    (lambda (x)
+      (let* ((hi (quotient *seed* 127773))
+	     (low (modulo *seed* 127773))
+	     (test (- (* 16807 low) (* 2836 hi))))
+	(if (> test 0)
+	    (set! *seed* test)
+	    (set! *seed* (+ test 2147483647))))
+      (modulo *seed* x))))
+
+
+;;; Logo-style word/sentence implementation
+
+(define word?
+  (let ((number? number?)
+	(symbol? symbol?)
+	(string? string?))
+    (lambda (x)
+      (or (symbol? x) (number? x) (string? x)))))
+
+(define sentence?
+  (let ((null? null?)
+	(pair? pair?)
+	(word? word?)
+	(car car)
+	(cdr cdr))    
+    (define (list-of-words? l)
+      (cond ((null? l) #t)
+	    ((pair? l)
+	     (and (word? (car l)) (list-of-words? (cdr l))))
+	    (else #f)))
+    list-of-words?))
+
+(define empty?
+  (let ((null? null?)
+	(string? string?)
+	(string=? string=?))
+    (lambda (x)
+      (or (null? x)
+	  (and (string? x) (string=? x ""))))))
+
+
+(define char-rank
+  ;; 0 Letter in good case or special initial
+  ;; 1 ., + or -
+  ;; 2 Digit
+  ;; 3 Letter in bad case or weird character
+  (let ((*the-char-ranks* (make-vector 256 3))
+	(= =)
+	(+ +)
+	(string-ref string-ref)
+	(string-length string-length)
+	(vector-set! vector-set!)
+	(char->integer char->integer)
+	(symbol->string symbol->string)
+	(vector-ref vector-ref))
+    (define (rank-string str rank)
+      (define (helper i len)
+	(if (= i len)
+	    'done
+	    (begin (vector-set! *the-char-ranks*
+				(char->integer (string-ref str i))
+				rank)
+		   (helper (+ i 1) len))))
+      (helper 0 (string-length str)))
+    (rank-string (symbol->string 'abcdefghijklmnopqrstuvwxyz) 0)
+    (rank-string "!$%&*/:<=>?~_^" 0)
+    (rank-string "+-." 1)
+    (rank-string "0123456789" 2)
+    (lambda (char)		    ;; value of char-rank
+      (vector-ref *the-char-ranks* (char->integer char)))))
+
+(define string->word
+  (let ((= =) (<= <=) (+ +) (- -)
+	(char-rank char-rank)
+	(string-ref string-ref)
+	(string-length string-length)
+	(string=? string=?)
+	(not not)
+	(char=? char=?)
+	(string->number string->number)
+	(string->symbol string->symbol))
+    (lambda (string)
+      (define (subsequents? string i length)
+	(cond ((= i length) #t)
+	      ((<= (char-rank (string-ref string i)) 2)
+	       (subsequents? string (+ i 1) length))
+	      (else #f)))
+      (define (special-id? string)
+	(or (string=? string "+")
+	    (string=? string "-")
+	    (string=? string "...")))
+      (define (ok-symbol? string)
+	(if (string=? string "")
+	    #f
+	    (let ((rank1 (char-rank (string-ref string 0))))
+	      (cond ((= rank1 0) (subsequents? string 1 (string-length string)))
+		    ((= rank1 1) (special-id? string))
+		    (else #f)))))
+      (define (nn-helper string i len seen-point?)
+	(cond ((= i len)
+	       (if seen-point?
+		   (not (char=? (string-ref string (- len 1)) #\0))
+		   #t))
+	      ((char=? #\. (string-ref string i))
+	       (cond (seen-point? #f)
+		     ((= (+ i 2) len) #t)  ; Accepts "23.0"
+		     (else (nn-helper string (+ i 1) len #t))))
+	      ((= 2 (char-rank (string-ref string i)))
+	       (nn-helper string (+ i 1) len seen-point?))
+	      (else #f)))
+      (define (narrow-number? string)
+	(if (string=? string "")
+	    #f
+	    (let* ((c0 (string-ref string 0))
+		   (start 0)
+		   (len (string-length string))
+		   (cn (string-ref string (- len 1))))
+	      (if (and (char=? c0 #\-) (not (= len 1)))
+		  (begin
+		   (set! start 1)
+		   (set! c0 (string-ref string 1)))
+		  #f)
+	      (cond ((not (= (char-rank cn) 2)) #f)  ; Rejects "-" among others
+		    ((char=? c0 #\.) #f)
+		    ((char=? c0 #\0)
+		     (cond ((= len 1) #t)  ; Accepts "0" but not "-0"
+			   ((= len 2) #f)  ; Rejects "-0" and "03"
+			   ((char=? (string-ref string (+ start 1)) #\.)
+			    (nn-helper string (+ start 2) len #t))
+			   (else #f)))
+		    (else (nn-helper string start len #f)))))) 
+
+      ;; The body of string->word:
+      (cond ((narrow-number? string) (string->number string))
+	    ((ok-symbol? string) (string->symbol string))
+	    (else string)))))
+
+(define char->word
+  (let ((= =)
+	(char-rank char-rank)
+	(make-string make-string)
+	(string->symbol string->symbol)
+	(string->number string->number)
+	(char=? char=?))
+    (lambda (char)
+      (let ((rank (char-rank char))
+	    (string (make-string 1 char)))
+	(cond ((= rank 0) (string->symbol string))
+	      ((= rank 2) (string->number string))
+	      ((char=? char #\+) '+)
+	      ((char=? char #\-) '-)
+	      (else string))))))
+
+(define word->string
+  (let ((number? number?)
+	(string? string?)
+	(number->string number->string)
+	(symbol->string symbol->string))
+    (lambda (wd)
+      (cond ((string? wd) wd)
+	    ((number? wd) (number->string wd))
+	    (else (symbol->string wd))))))
+
+(define count
+  (let ((word? word?)
+	(string-length string-length)
+	(word->string word->string)
+	(length length))
+    (lambda (stuff)
+      (if (word? stuff)
+	  (string-length (word->string stuff))
+	  (length stuff)))))
+
+(define word
+  (let ((string->word string->word)
+	(apply apply)
+	(string-append string-append)
+	(map map)
+	(word? word?)
+	(word->string word->string)
+	(whoops whoops))
+    (lambda x
+      (string->word
+       (apply string-append
+	      (map (lambda (arg)
+		     (if (word? arg)
+			 (word->string arg)
+			 (whoops "Invalid argument to WORD: " arg)))
+		   x))))))
+
+(define se
+  (let ((pair? pair?)
+	(null? null?)
+	(word? word?)
+	(car car)
+	(cons cons)
+	(cdr cdr)
+	(whoops whoops))
+    (define (paranoid-append a original-a b)
+      (cond ((null? a) b)
+	    ((word? (car a))
+	     (cons (car a) (paranoid-append (cdr a) original-a b)))
+	    (else (whoops "Argument to SENTENCE not a word or sentence"
+			 original-a ))))
+    (define (combine-two a b)                ;; Note: b is always a list
+      (cond ((pair? a) (paranoid-append a a b))
+	    ((null? a) b)
+	    ((word? a) (cons a b))
+	    (else (whoops "Argument to SENTENCE not a word or sentence:" a))))
+    ;; Helper function so recursive calls don't show up in TRACE
+    (define (real-se args)
+      (if (null? args)
+	  '()
+	  (combine-two (car args) (real-se (cdr args)))))
+    (lambda args
+      (real-se args))))
+
+(define sentence se)
+
+(define first
+  (let ((pair? pair?)
+	(char->word char->word)
+	(string-ref string-ref)
+	(word->string word->string)
+	(car car)
+	(empty? empty?)
+	(whoops whoops)
+	(word? word?))
+    (define (word-first wd)
+      (char->word (string-ref (word->string wd) 0)))
+    (lambda (x)
+      (cond ((pair? x) (car x))
+	    ((empty? x) (whoops "Invalid argument to FIRST: " x))
+	    ((word? x) (word-first x))
+	    (else (whoops "Invalid argument to FIRST: " x))))))
+
+(define last
+  (let ((pair? pair?)
+	(- -)
+	(word->string word->string)
+	(char->word char->word)
+	(string-ref string-ref)
+	(string-length string-length)
+	(empty? empty?)
+	(cdr cdr)
+	(car car)
+	(whoops whoops)
+	(word? word?))
+    (define (word-last wd)
+      (let ((s (word->string wd)))
+	(char->word (string-ref s (- (string-length s) 1)))))
+    (define (list-last lst)      
+      (if (empty? (cdr lst))
+	  (car lst)
+	  (list-last (cdr lst))))
+    (lambda (x)
+      (cond ((pair? x) (list-last x))
+	    ((empty? x) (whoops "Invalid argument to LAST: " x))
+	    ((word? x) (word-last x))
+	    (else (whoops "Invalid argument to LAST: " x))))))
+
+(define bf
+  (let ((pair? pair?)
+	(substring substring)
+	(string-length string-length)
+	(string->word string->word)
+	(word->string word->string)
+	(cdr cdr)
+	(empty? empty?)
+	(whoops whoops)
+	(word? word?))
+    (define string-bf
+      (lambda (s)
+      (substring s 1 (string-length s))))
+    (define (word-bf wd)
+      (string->word (string-bf (word->string wd))))
+    (lambda (x)
+      (cond ((pair? x) (cdr x))
+	    ((empty? x) (whoops "Invalid argument to BUTFIRST: " x))
+	    ((word? x) (word-bf x))
+	    (else (whoops "Invalid argument to BUTFIRST: " x))))))
+
+(define butfirst bf)
+
+(define bl
+  (let ((pair? pair?) (- -)
+	(cdr cdr)
+	(cons cons)
+	(car car)
+	(substring substring)
+	(string-length string-length)
+	(string->word string->word)
+	(word->string word->string)
+	(empty? empty?)
+	(whoops whoops)
+	(word? word?))
+    (define (list-bl list)
+      (if (null? (cdr list))
+	  '()
+	  (cons (car list) (list-bl (cdr list)))))
+    (define (string-bl s)
+      (substring s 0 (- (string-length s) 1)))  
+    (define (word-bl wd)
+      (string->word (string-bl (word->string wd))))
+    (lambda (x)
+      (cond ((pair? x) (list-bl x))
+	    ((empty? x) (whoops "Invalid argument to BUTLAST: " x))
+	    ((word? x) (word-bl x))
+	    (else (whoops "Invalid argument to BUTLAST: " x))))))
+
+(define butlast bl)
+
+(define item
+  (let ((> >) (- -) (< <) (integer? integer?) (list-ref list-ref)
+	(char->word char->word)
+	(string-ref string-ref)
+	(word->string word->string)
+	(not not)
+	(whoops whoops)
+	(count count)
+	(word? word?)
+	(list? list?))
+    (define (word-item n wd)
+      (char->word (string-ref (word->string wd) (- n 1))))
+    (lambda (n stuff)
+      (cond ((not (integer? n))
+	     (whoops "Invalid first argument to ITEM (must be an integer): "
+		     n))
+	    ((< n 1)
+	     (whoops "Invalid first argument to ITEM (must be positive): "
+		     n))
+	    ((> n (count stuff))
+	     (whoops "No such item: " n stuff))
+	    ((word? stuff) (word-item n stuff))
+	    ((list? stuff) (list-ref stuff (- n 1)))
+	    (else (whoops "Invalid second argument to ITEM: " stuff))))))
+
+(define equal?
+  ;; Note that EQUAL? assumes strings are numbers.
+  ;; (strings-are-numbers #f) doesn't change this behavior.
+  (let ((vector-length vector-length)
+	(= =)
+	(vector-ref vector-ref)
+	(+ +)
+	(string? string?)
+	(symbol? symbol?)
+	(null? null?)
+	(pair? pair?)
+	(car car)
+	(cdr cdr)
+	(eq? eq?)
+	(string=? string=?)
+	(symbol->string symbol->string)
+	(number? number?)
+	(string->word string->word)
+	(vector? vector?)
+	(eqv? eqv?))
+    (define (vector-equal? v1 v2)
+      (let ((len1 (vector-length v1))
+	    (len2 (vector-length v2)))
+	(define (helper i)
+	  (if (= i len1)
+	      #t
+	      (and (equal? (vector-ref v1 i) (vector-ref v2 i))
+		   (helper (+ i 1)))))
+	(if (= len1 len2)
+	    (helper 0)
+	    #f)))
+    (lambda (x y)
+      (cond ((null? x) (null? y))
+	    ((null? y) #f)
+	    ((pair? x)
+	     (and (pair? y)
+		  (equal? (car x) (car y))
+		  (equal? (cdr x) (cdr y))))
+	    ((pair? y) #f)
+	    ((symbol? x)
+	     (or (and (symbol? y) (eq? x y))
+		 (and (string? y) (string=? (symbol->string x) y))))
+	    ((symbol? y)
+	     (and (string? x) (string=? x (symbol->string y))))
+	    ((number? x)
+	     (or (and (number? y) (= x y))
+		 (and (string? y)
+		      (let ((possible-num (string->word y)))
+			(and (number? possible-num)
+			     (= x possible-num))))))
+	    ((number? y)
+	     (and (string? x)
+		  (let ((possible-num (string->word x)))
+		    (and (number? possible-num)
+			 (= possible-num y)))))
+	    ((string? x) (and (string? y) (string=? x y)))
+	    ((string? y) #f)
+	    ((vector? x) (and (vector? y) (vector-equal? x y)))
+	    ((vector? y) #f)
+	    (else (eqv? x y))))))
+
+(define member?
+  (let ((> >) (- -) (< <)
+	(null? null?)
+	(symbol? symbol?)
+	(eq? eq?)
+	(car car)
+	(not not)
+	(symbol->string symbol->string)
+	(string=? string=?)
+	(cdr cdr)
+	(equal? equal?)
+	(word->string word->string)
+	(string-length string-length)
+	(whoops whoops)
+	(string-ref string-ref)
+	(char=? char=?)
+	(list? list?)
+	(number? number?)
+	(empty? empty?)
+	(word? word?)
+	(string? string?))
+    (define (symbol-in-list? symbol string lst)
+      (cond ((null? lst) #f)
+	    ((and (symbol? (car lst))
+		  (eq? symbol (car lst))))
+	    ((string? (car lst))
+	     (cond ((not string)
+		    (symbol-in-list? symbol (symbol->string symbol) lst))
+		   ((string=? string (car lst)) #t)
+		   (else (symbol-in-list? symbol string (cdr lst)))))
+	    (else (symbol-in-list? symbol string (cdr lst)))))
+    (define (word-in-list? wd lst)
+      (cond ((null? lst) #f)
+	    ((equal? wd (car lst)) #t)
+	    (else (word-in-list? wd (cdr lst)))))
+    (define (word-in-word? small big)
+      (let ((one-letter-str (word->string small)))
+	(if (> (string-length one-letter-str) 1)
+	    (whoops "Invalid arguments to MEMBER?: " small big)
+	    (let ((big-str (word->string big)))
+	      (char-in-string? (string-ref one-letter-str 0)
+			       big-str
+			       (- (string-length big-str) 1))))))
+    (define (char-in-string? char string i)
+      (cond ((< i 0) #f)
+	    ((char=? char (string-ref string i)) #t)
+	    (else (char-in-string? char string (- i 1)))))
+    (lambda (x stuff)
+      (cond ((empty? stuff) #f)
+	    ((word? stuff) (word-in-word? x stuff))
+	    ((not (list? stuff))
+	     (whoops "Invalid second argument to MEMBER?: " stuff))
+	    ((symbol? x) (symbol-in-list? x #f stuff))
+	    ((or (number? x) (string? x))
+	     (word-in-list? x stuff))
+	    (else (whoops "Invalid first argument to MEMBER?: " x))))))
+
+(define before?
+  (let ((not not)
+	(word? word?)
+	(whoops whoops)
+	(string<? string<?)
+	(word->string word->string))
+    (lambda (wd1 wd2)
+      (cond ((not (word? wd1))
+	     (whoops "Invalid first argument to BEFORE? (not a word): " wd1))
+	    ((not (word? wd2))
+	     (whoops "Invalid second argument to BEFORE? (not a word): " wd2))
+	    (else (string<? (word->string wd1) (word->string wd2)))))))
+
+
+;;; Higher Order Functions
+
+(define filter
+  (let ((null? null?)
+	(car car)
+	(cons cons)
+	(cdr cdr)
+	(not not)
+	(procedure? procedure?)
+	(whoops whoops)
+	(list? list?))
+    (lambda (pred l)
+      ;; Helper function so recursive calls don't show up in TRACE
+      (define (real-filter l)
+	(cond ((null? l) '())
+	      ((pred (car l))
+	       (cons (car l) (real-filter (cdr l))))
+	      (else (real-filter (cdr l)))))
+      (cond ((not (procedure? pred))
+	     (whoops "Invalid first argument to FILTER (not a procedure): "
+		     pred))
+	    ((not (list? l))
+	     (whoops "Invalid second argument to FILTER (not a list): " l))
+	    (else (real-filter l))))))
+
+(define keep
+  (let ((+ +) (= =) (pair? pair?)
+	(substring substring)
+	(char->word char->word)
+	(string-ref string-ref)
+	(string-set! string-set!)
+	(word->string word->string)
+	(string-length string-length)
+	(string->word string->word)
+	(make-string make-string)
+	(procedure? procedure?)
+	(whoops whoops)
+	(word? word?)
+	(null? null?))
+    (lambda (pred w-or-s)
+      (define (keep-string in i out out-len len)
+	(cond ((= i len) (substring out 0 out-len))
+	      ((pred (char->word (string-ref in i)))
+	       (string-set! out out-len (string-ref in i))
+	       (keep-string in (+ i 1) out (+ out-len 1) len))
+	      (else (keep-string in (+ i 1) out out-len len))))
+      (define (keep-word wd)
+	(let* ((string (word->string wd))
+	       (len (string-length string)))
+	  (string->word
+	   (keep-string string 0 (make-string len) 0 len))))
+      (cond ((not (procedure? pred))
+	     (whoops "Invalid first argument to KEEP (not a procedure): "
+		    pred))
+	    ((pair? w-or-s) (filter pred w-or-s))
+	    ((word? w-or-s) (keep-word w-or-s))
+	    ((null? w-or-s) '())
+	    (else
+	     (whoops "Bad second argument to KEEP (not a word or sentence): "
+		     w-or-s))))))
+
+(define appearances
+  (let ((count count)
+	(keep keep)
+	(equal? equal?))
+    (lambda (item aggregate)
+      (count (keep (lambda (element) (equal? item element)) aggregate)))))
+
+(define every
+  (let ((= =) (+ +)
+	(se se)
+	(char->word char->word)
+	(string-ref string-ref)
+	(empty? empty?)
+	(first first)
+	(bf bf)
+	(not not)
+	(procedure? procedure?)
+	(whoops whoops)
+	(word? word?)
+	(word->string word->string)
+	(string-length string-length))
+    (lambda (fn stuff)
+      (define (string-every string i length)
+	(if (= i length)
+	    '()
+	    (se (fn (char->word (string-ref string i)))
+		(string-every string (+ i 1) length))))
+      (define (sent-every sent)
+	;; This proc. can't be optimized or else it will break the
+	;; exercise where we ask them to reimplement sentences as
+	;; vectors and then see if every still works.
+	(if (empty? sent)
+	    sent		; Can't be '() or exercise breaks.
+	    (se (fn (first sent))    
+		(sent-every (bf sent)))))
+      (cond ((not (procedure? fn))
+	     (whoops "Invalid first argument to EVERY (not a procedure):"
+		     fn))
+	    ((word? stuff)
+	     (let ((string (word->string stuff)))
+	       (string-every string 0 (string-length string))))
+	    (else (sent-every stuff))))))
+
+(define accumulate
+  (let ((not not)
+	(empty? empty?)
+	(bf bf)
+	(first first)
+	(procedure? procedure?)
+	(whoops whoops)
+	(member member)
+	(list list))
+    (lambda (combiner stuff)
+      (define (real-accumulate stuff)
+	(if (empty? (bf stuff))
+	    (first stuff)
+	    (combiner (first stuff) (real-accumulate (bf stuff)))))
+      (cond ((not (procedure? combiner))
+	     (whoops "Invalid first argument to ACCUMULATE (not a procedure):"
+		     combiner))
+	    ((not (empty? stuff)) (real-accumulate stuff))
+	    ((member combiner (list + * word se)) (combiner))
+	    (else
+	     (whoops "Can't accumulate empty input with that combiner"))))))
+
+(define reduce
+  (let ((null? null?)
+	(cdr cdr)
+	(car car)
+	(not not)
+	(procedure? procedure?)
+	(whoops whoops)
+	(member member)
+	(list list))
+    (lambda (combiner stuff)
+      (define (real-reduce stuff)
+	(if (null? (cdr stuff))
+	    (car stuff)
+	    (combiner (car stuff) (real-reduce (cdr stuff)))))
+      (cond ((not (procedure? combiner))
+	     (whoops "Invalid first argument to REDUCE (not a procedure):"
+		     combiner))
+	    ((not (null? stuff)) (real-reduce stuff))
+	    ((member combiner (list + * word se append)) (combiner))
+	    (else (whoops "Can't reduce empty input with that combiner"))))))
+
+(define repeated
+  (let ((= =) (- -))
+    (lambda (fn number)
+      (if (= number 0)
+	  (lambda (x) x)
+	  (lambda (x)
+	    ((repeated fn (- number 1)) (fn x)))))))
+
+
+;; Tree stuff
+(define make-node cons)
+(define datum car)
+(define children cdr)
+
+
+;; I/O
+        
+(define show
+  (let ((= =)
+	(length length)
+	(display display)
+	(car car)
+	(newline newline)
+	(not not)
+	(output-port? output-port?)
+	(apply apply)
+	(whoops whoops))
+    (lambda args
+      (cond
+       ((= (length args) 1)
+	(display (car args))
+	(newline))
+       ((= (length args) 2)
+	(if (not (output-port? (car (cdr args))))
+	    (whoops "Invalid second argument to SHOW (not an output port): "
+		    (car (cdr args))))
+	(apply display args)
+	(newline (car (cdr args))))
+       (else (whoops "Incorrect number of arguments to procedure SHOW"))))))
+
+(define show-line
+  (let ((>= >=)
+	(length length)
+	(whoops whoops)
+	(null? null?)
+	(current-output-port current-output-port)
+	(car car)
+	(not not)
+	(list? list?)
+	(display display)
+	(for-each for-each)
+	(cdr cdr)
+	(newline newline))
+    (lambda (line . args)
+      (if (>= (length args) 2)
+	  (whoops "Too many arguments to show-line")
+	  (let ((port (if (null? args) (current-output-port) (car args))))
+	    (cond ((not (list? line))
+		   (whoops "Invalid argument to SHOW-LINE (not a list):" line))
+		  ((null? line) #f)
+		  (else
+		   (display (car line) port)
+		   (for-each (lambda (wd) (display " " port) (display wd port))
+			     (cdr line))))
+	    (newline port))))))
+
+(define read-string
+  (let ((read-char read-char)
+	(eqv? eqv?)
+	(apply apply)
+	(string-append string-append)
+	(substring substring)
+	(reverse reverse)
+	(cons cons)
+	(>= >=) (+ +)
+	(string-set! string-set!)
+	(length length)
+	(whoops whoops)
+	(null? null?)
+	(current-input-port current-input-port)
+	(car car)
+	(cdr cdr)
+	(eof-object? eof-object?)
+	(list list)
+	(make-string make-string)
+	(peek-char peek-char))
+    (define (read-string-helper chars all-length chunk-length port)
+      (let ((char (read-char port))
+	    (string (car chars)))
+	(cond ((or (eof-object? char) (eqv? char #\newline))
+	       (apply string-append
+		      (reverse
+		       (cons
+			(substring (car chars) 0 chunk-length)
+			(cdr chars)))))
+	      ((>= chunk-length 80)
+	       (let ((newstring (make-string 80)))
+		 (string-set! newstring 0 char)
+		 (read-string-helper (cons newstring chars)
+				     (+ all-length 1)
+				     1
+				     port)))
+	      (else
+	       (string-set! string chunk-length char)
+	       (read-string-helper chars
+				   (+ all-length 1)
+				   (+ chunk-length 1)
+				   port)))))
+    (lambda args
+      (if (>= (length args) 2)
+	  (whoops "Too many arguments to read-string")
+	  (let ((port (if (null? args) (current-input-port) (car args))))
+	    (if (eof-object? (peek-char port))
+		(read-char port)
+		(read-string-helper (list (make-string 80)) 0 0 port)))))))
+
+(define read-line
+  (let ((= =)
+	(list list)
+	(string->word string->word)
+	(substring substring)
+	(char-whitespace? char-whitespace?)
+	(string-ref string-ref)
+	(+ +)
+	(string-length string-length)
+	(apply apply)
+	(read-string read-string))
+    (lambda args
+      (define (tokenize string)
+	(define (helper i start len)
+	  (cond ((= i len)
+		 (if (= i start)
+		     '()
+		     (list (string->word (substring string start i)))))
+		((char-whitespace? (string-ref string i))
+		 (if (= i start)
+		     (helper (+ i 1) (+ i 1) len)
+		     (cons (string->word (substring string start i))
+			   (helper (+ i 1) (+ i 1) len))))
+		(else (helper (+ i 1) start len))))
+        (if (eof-object? string)
+            string
+            (helper 0 0 (string-length string))))
+      (tokenize (apply read-string args)))))
+
+(define *the-open-inports* '())
+(define *the-open-outports* '())
+
+(define align
+  (let ((< <) (abs abs) (* *) (expt expt) (>= >=) (- -) (+ +) (= =)
+	(null? null?)
+	(car car)
+	(round round)
+	(number->string number->string)
+	(string-length string-length)
+	(string-append string-append)
+	(make-string make-string)
+	(substring substring)
+	(string-set! string-set!)
+	(number? number?)
+	(word->string word->string))
+    (lambda (obj width . rest)
+      (define (align-number obj width rest)
+	(let* ((sign (< obj 0))
+	       (num (abs obj))
+	       (prec (if (null? rest) 0 (car rest)))
+	       (big (round (* num (expt 10 prec))))
+	       (cvt0 (number->string big))
+	       (cvt (if (< num 1) (string-append "0" cvt0) cvt0))
+	       (pos-str (if (>= (string-length cvt0) prec)
+			    cvt
+			    (string-append
+			     (make-string (- prec (string-length cvt0)) #\0)
+			     cvt)))
+	       (string (if sign (string-append "-" pos-str) pos-str))
+	       (length (+ (string-length string)
+			  (if (= prec 0) 0 1)))
+	       (left (- length (+ 1 prec)))
+	       (result (if (= prec 0)
+			   string
+			   (string-append
+			    (substring string 0 left)
+			    "."
+			    (substring string left (- length 1))))))
+	  (cond ((= length width) result)
+		((< length width)
+		 (string-append (make-string (- width length) #\space) result))
+		(else (let ((new (substring result 0 width)))
+			(string-set! new (- width 1) #\+)
+			new)))))
+      (define (align-word string)
+	(let ((length (string-length string)))
+	  (cond ((= length width) string)
+		((< length width)
+		 (string-append string (make-string (- width length) #\space)))
+		(else (let ((new (substring string 0 width)))
+			(string-set! new (- width 1) #\+)
+			new)))))
+      (if (number? obj)
+	  (align-number obj width rest)
+	  (align-word (word->string obj))))))
+
+(define open-output-file
+  (let ((oof open-output-file)
+	(cons cons))
+    (lambda (filename)
+      (let ((port (oof filename)))
+	(set! *the-open-outports* (cons port *the-open-outports*))
+	port))))
+
+(define open-input-file
+  (let ((oif open-input-file)
+	(cons cons))
+    (lambda (filename)
+      (let ((port (oif filename)))
+	(set! *the-open-inports* (cons port *the-open-inports*))
+	port))))
+
+(define remove!
+  (let ((null? null?)
+	(cdr cdr)
+	(eq? eq?)
+	(set-cdr! set-cdr!)
+	(car car))
+    (lambda (thing lst)
+      (define (r! prev)
+	(cond ((null? (cdr prev)) lst)
+	      ((eq? thing (car (cdr prev)))
+	       (set-cdr! prev (cdr (cdr prev)))
+	       lst)
+	      (else (r! (cdr prev)))))
+      (cond ((null? lst) lst)
+	    ((eq? thing (car lst)) (cdr lst))
+	    (else (r! lst))))))
+
+(define close-input-port
+  (let ((cip close-input-port)
+	(remove! remove!))
+    (lambda (port)
+      (set! *the-open-inports* (remove! port *the-open-inports*))
+      (cip port))))
+
+(define close-output-port
+  (let ((cop close-output-port)
+	(remove! remove!))
+    (lambda (port)
+      (set! *the-open-outports* (remove! port *the-open-outports*))
+      (cop port))))
+
+(define close-all-ports
+  (let ((for-each for-each)
+	(close-input-port close-input-port)
+	(close-output-port close-output-port))
+    (lambda ()
+      (for-each close-input-port *the-open-inports*)
+      (for-each close-output-port *the-open-outports*)
+      'closed)))
+
+;; Make arithmetic work on numbers in string form:
+(define maybe-num
+  (let ((string? string?)
+    	(string->number string->number))
+    (lambda (arg)
+      (if (string? arg)
+	  (let ((num (string->number arg)))
+	    (if num num arg))
+	  arg))))
+
+(define logoize
+  (let ((apply apply)
+	(map map)
+	(maybe-num maybe-num))
+    (lambda (fn)
+      (lambda args
+	(apply fn (map maybe-num args))))))
+
+;; special case versions of logoize, since (lambda args ...) is expensive
+(define logoize-1
+  (let ((maybe-num maybe-num))
+    (lambda (fn)
+      (lambda (x) (fn (maybe-num x))))))
+
+(define logoize-2
+  (let ((maybe-num maybe-num))
+    (lambda (fn)
+      (lambda (x y) (fn (maybe-num x) (maybe-num y))))))
+
+(define strings-are-numbers
+  (let ((are-they? #f)
+        (real-* *)
+        (real-+ +)
+        (real-- -)
+        (real-/ /)
+        (real-< <)
+        (real-<= <=)
+        (real-= =)
+        (real-> >)
+        (real->= >=)
+        (real-abs abs)
+        (real-acos acos)
+        (real-asin asin)
+        (real-atan atan)
+        (real-ceiling ceiling)
+        (real-cos cos)
+        (real-even? even?)
+        (real-exp exp)
+        (real-expt expt)
+        (real-floor floor)
+	(real-align align)
+        (real-gcd gcd)
+        (real-integer? integer?)
+        (real-item item)
+        (real-lcm lcm)
+        (real-list-ref list-ref)
+        (real-log log)
+        (real-make-vector make-vector)
+        (real-max max)
+        (real-min min)
+        (real-modulo modulo)
+        (real-negative? negative?)
+        (real-number? number?)
+        (real-odd? odd?)
+        (real-positive? positive?)
+        (real-quotient quotient)
+        (real-random random)
+        (real-remainder remainder)
+        (real-repeated repeated)
+        (real-round round)
+        (real-sin sin)
+        (real-sqrt sqrt)
+        (real-tan tan)
+        (real-truncate truncate)
+        (real-vector-ref vector-ref)
+        (real-vector-set! vector-set!)
+        (real-zero? zero?)
+	(maybe-num maybe-num)
+	(number->string number->string)
+	(cons cons)
+	(car car)
+	(cdr cdr)
+	(eq? eq?)
+	(show show)
+	(logoize logoize)
+	(logoize-1 logoize-1)
+	(logoize-2 logoize-2)
+	(not not)
+	(whoops whoops))
+
+    (lambda (yesno)
+      (cond ((and are-they? (eq? yesno #t))
+	     (show "Strings are already numbers"))
+	    ((eq? yesno #t)
+	     (set! are-they? #t)
+	     (set! * (logoize real-*))
+	     (set! + (logoize real-+))
+	     (set! - (logoize real--))
+	     (set! / (logoize real-/))
+	     (set! < (logoize real-<))
+	     (set! <= (logoize real-<=))
+	     (set! = (logoize real-=))
+	     (set! > (logoize real->))
+	     (set! >= (logoize real->=))
+	     (set! abs (logoize-1 real-abs))
+	     (set! acos (logoize-1 real-acos))
+	     (set! asin (logoize-1 real-asin))
+	     (set! atan (logoize real-atan))
+	     (set! ceiling (logoize-1 real-ceiling))
+	     (set! cos (logoize-1 real-cos))
+	     (set! even? (logoize-1 real-even?))
+	     (set! exp (logoize-1 real-exp))
+	     (set! expt (logoize-2 real-expt))
+	     (set! floor (logoize-1 real-floor))
+	     (set! align (logoize align))
+	     (set! gcd (logoize real-gcd))
+	     (set! integer? (logoize-1 real-integer?))
+	     (set! item (lambda (n stuff)
+			  (real-item (maybe-num n) stuff)))
+	     (set! lcm (logoize real-lcm))
+	     (set! list-ref (lambda (lst k) 
+			      (real-list-ref lst (maybe-num k))))
+	     (set! log (logoize-1 real-log))
+	     (set! max (logoize real-max))
+	     (set! min (logoize real-min))
+	     (set! modulo (logoize-2 real-modulo))
+	     (set! negative? (logoize-1 real-negative?))
+	     (set! number? (logoize-1 real-number?))
+	     (set! odd? (logoize-1 real-odd?))
+	     (set! positive? (logoize-1 real-positive?))
+	     (set! quotient (logoize-2 real-quotient))
+	     (set! random (logoize real-random))
+	     (set! remainder (logoize-2 real-remainder))
+	     (set! round (logoize-1 real-round))
+	     (set! sin (logoize-1 real-sin))
+	     (set! sqrt (logoize-1 real-sqrt))
+
+	     (set! tan (logoize-1 real-tan))
+	     (set! truncate (logoize-1 real-truncate))
+	     (set! zero? (logoize-1 real-zero?))
+	     (set! vector-ref
+		   (lambda (vec i) (real-vector-ref vec (maybe-num i))))
+	     (set! vector-set!
+		   (lambda (vec i val)
+		     (real-vector-set! vec (maybe-num i) val)))
+	     (set! make-vector
+		   (lambda (num . args)
+		     (apply real-make-vector (cons (maybe-num num)
+						   args))))
+	     (set! list-ref
+		   (lambda (lst i) (real-list-ref lst (maybe-num i))))
+	     (set! repeated
+		   (lambda (fn n) (real-repeated fn (maybe-num n)))))
+	    ((and (not are-they?) (not yesno))
+	     (show "Strings are already not numbers"))
+	    ((not yesno)
+	     (set! are-they? #f) (set! * real-*) (set! + real-+)
+	     (set! - real--) (set! / real-/) (set! < real-<)
+	     (set! <= real-<=) (set! = real-=) (set! > real->)
+	     (set! >= real->=) (set! abs real-abs) (set! acos real-acos)
+	     (set! asin real-asin) (set! atan real-atan)
+	     (set! ceiling real-ceiling) (set! cos real-cos)
+	     (set! even? real-even?)
+	     (set! exp real-exp) (set! expt real-expt)
+	     (set! floor real-floor) (set! align real-align)
+	     (set! gcd real-gcd) (set! integer? real-integer?)
+	     (set! item real-item)
+	     (set! lcm real-lcm) (set! list-ref real-list-ref)
+	     (set! log real-log) (set! max real-max) (set! min real-min)
+	     (set! modulo real-modulo) (set! odd? real-odd?)
+	     (set! quotient real-quotient) (set! random real-random)
+	     (set! remainder real-remainder) (set! round real-round)
+	     (set! sin real-sin) (set! sqrt real-sqrt) (set! tan real-tan)
+	     (set! truncate real-truncate) (set! zero? real-zero?)
+	     (set! positive? real-positive?) (set! negative? real-negative?)
+	     (set! number? real-number?) (set! vector-ref real-vector-ref)
+	     (set! vector-set! real-vector-set!)
+	     (set! make-vector real-make-vector)
+	     (set! list-ref real-list-ref) (set! item real-item)
+	     (set! repeated real-repeated))
+	    (else (whoops "Strings-are-numbers: give a #t or a #f")))
+	    are-they?)))
+
+
+;; By default, strings are numbers:
+(strings-are-numbers #t)
diff --git a/js/games/nluqo.github.io/~bh/downloads/simply/spread.scm b/js/games/nluqo.github.io/~bh/downloads/simply/spread.scm
new file mode 100644
index 0000000..d52ebab
--- /dev/null
+++ b/js/games/nluqo.github.io/~bh/downloads/simply/spread.scm
@@ -0,0 +1,550 @@
+(define (spreadsheet)
+  (init-array)
+  (set-selection-cell-id! (make-id 1 1))
+  (set-screen-corner-cell-id! (make-id 1 1))
+  (command-loop))
+
+(define (command-loop)
+  (print-screen)
+  (let ((command-or-formula (read)))
+    (if (equal? command-or-formula 'exit)
+	"Bye!"
+	(begin (process-command command-or-formula)
+	       (command-loop)))))
+
+(define (process-command command-or-formula)
+  (cond ((and (list? command-or-formula)
+	      (command? (car command-or-formula)))
+	 (execute-command command-or-formula))
+	((command? command-or-formula)
+	 (execute-command (list command-or-formula 1)))
+	(else (exhibit (ss-eval (pin-down command-or-formula
+					  (selection-cell-id)))))))
+
+(define (execute-command command)
+  (apply (get-command (car command))
+	 (cdr command)))
+
+(define (exhibit val)
+  (show val)
+  (show "Type RETURN to redraw screen")
+  (read-line)
+  (read-line))
+
+
+;;; Commands
+
+;; Cell selection commands: F, B, N, P, and SELECT
+
+(define (prev-row delta)
+  (let ((row (id-row (selection-cell-id))))
+    (if (< (- row delta) 1)
+	(error "Already at top.")
+	(set-selected-row! (- row delta)))))
+
+(define (next-row delta)
+  (let ((row (id-row (selection-cell-id))))
+    (if (> (+ row delta) 30)
+	(error "Already at bottom.")
+	(set-selected-row! (+ row delta)))))
+
+(define (prev-col delta)
+  (let ((col (id-column (selection-cell-id))))
+    (if (< (- col delta) 1)
+	(error "Already at left.")
+	(set-selected-column! (- col delta)))))
+
+(define (next-col delta)
+  (let ((col (id-column (selection-cell-id))))
+    (if (> (+ col delta) 26)
+	(error "Already at right.")
+	(set-selected-column! (+ col delta)))))
+
+(define (set-selected-row! new-row)
+  (select-id! (make-id (id-column (selection-cell-id)) new-row)))
+
+(define (set-selected-column! new-column)
+  (select-id! (make-id new-column (id-row (selection-cell-id)))))
+
+(define (select-id! id)
+  (set-selection-cell-id! id)
+  (adjust-screen-boundaries))
+
+(define (select cell-name)
+  (select-id! (cell-name->id cell-name)))
+
+(define (adjust-screen-boundaries)
+  (let ((row (id-row (selection-cell-id)))
+	(col (id-column (selection-cell-id))))
+    (if (< row (id-row (screen-corner-cell-id)))
+	(set-corner-row! row)
+	'do-nothing)
+    (if (>= row (+ (id-row (screen-corner-cell-id)) 20))
+	(set-corner-row! (- row 19))
+	'do-nothing)
+    (if (< col (id-column (screen-corner-cell-id)))
+	(set-corner-column! col)
+	'do-nothing)
+    (if (>= col (+ (id-column (screen-corner-cell-id)) 6))
+	(set-corner-column! (- col 5))
+	'do-nothing)))
+
+(define (set-corner-row! new-row)
+  (set-screen-corner-cell-id!
+   (make-id (id-column (screen-corner-cell-id)) new-row)))
+
+(define (set-corner-column! new-column)
+  (set-screen-corner-cell-id!
+   (make-id new-column (id-row (screen-corner-cell-id)))))
+
+
+;; LOAD
+
+(define (spreadsheet-load filename)
+  (let ((port (open-input-file filename)))
+    (sl-helper port)
+    (close-input-port port)))
+
+(define (sl-helper port)
+  (let ((command (read port)))
+    (if (eof-object? command)
+	'done
+	(begin (show command)
+	       (process-command command)
+	       (sl-helper port)))))
+
+
+;; PUT
+
+(define (put formula . where)
+  (cond ((null? where)
+	 (put-formula-in-cell formula (selection-cell-id)))
+	((cell-name? (car where))
+	 (put-formula-in-cell formula (cell-name->id (car where))))
+	((number? (car where))
+	 (put-all-cells-in-row formula (car where)))
+	((letter? (car where))
+	 (put-all-cells-in-col formula (letter->number (car where))))
+	(else (error "Put it where?"))))
+
+(define (put-all-cells-in-row formula row)
+  (put-all-helper formula (lambda (col) (make-id col row)) 1 26))
+
+(define (put-all-cells-in-col formula col)
+  (put-all-helper formula (lambda (row) (make-id col row)) 1 30))
+
+(define (put-all-helper formula id-maker this max)
+  (if (> this max)
+      'done
+      (begin (try-putting formula (id-maker this))
+	     (put-all-helper formula id-maker (+ 1 this) max))))
+
+(define (try-putting formula id)
+  (if (or (null? (cell-value id)) (null? formula))
+      (put-formula-in-cell formula id)
+      'do-nothing))
+
+(define (put-formula-in-cell formula id)
+  (put-expr (pin-down formula id) id))
+
+
+;;; The Association List of Commands
+
+(define (command? name)
+  (assoc name *the-commands*))
+
+(define (get-command name)
+  (let ((result (assoc name *the-commands*)))
+    (if (not result)
+	#f
+	(cadr result))))
+
+(define *the-commands*
+  (list (list 'p prev-row)
+	(list 'n next-row)
+	(list 'b prev-col)
+	(list 'f next-col)
+	(list 'select select)
+	(list 'put put)
+	(list 'load spreadsheet-load)))
+
+
+;;; Pinning Down Formulas Into Expressions
+
+(define (pin-down formula id)
+  (cond ((cell-name? formula) (cell-name->id formula))
+	((word? formula) formula)
+	((null? formula) '())
+	((equal? (car formula) 'cell)
+	 (pin-down-cell (cdr formula) id))
+	(else (bound-check
+	       (map (lambda (subformula) (pin-down subformula id))
+		    formula)))))
+
+(define (bound-check form)
+  (if (member 'out-of-bounds form)
+      'out-of-bounds
+      form))
+
+(define (pin-down-cell args reference-id)
+  (cond ((null? args)
+	 (error "Bad cell specification: (cell)"))
+	((null? (cdr args))
+	 (cond ((number? (car args))         ; they chose a row
+		(make-id (id-column reference-id) (car args)))
+	       ((letter? (car args))         ; they chose a column
+		(make-id (letter->number (car args))
+			 (id-row reference-id)))
+	       (else (error "Bad cell specification:"
+			    (cons 'cell args)))))
+	(else
+	 (let ((col (pin-down-col (car args) (id-column reference-id)))
+	       (row (pin-down-row (cadr args) (id-row reference-id))))
+	   (if (and (>= col 1) (<= col 26) (>= row 1) (<= row 30))
+	       (make-id col row)
+	       'out-of-bounds)))))
+
+(define (pin-down-col new old)
+  (cond ((equal? new '*) old)
+	((equal? (first new) '>) (+ old (bf new)))
+	((equal? (first new) '<) (- old (bf new)))
+	((letter? new) (letter->number new))
+	(else (error "What column?"))))
+
+(define (pin-down-row new old)
+  (cond ((number? new) new)
+	((equal? new '*) old)
+	((equal? (first new) '>) (+ old (bf new)))
+	((equal? (first new) '<) (- old (bf new)))
+	(else (error "What row?"))))
+
+
+;;; Dependency Management
+
+(define (put-expr expr-or-out-of-bounds id)
+  (let ((expr (if (equal? expr-or-out-of-bounds 'out-of-bounds)
+		  '()
+		  expr-or-out-of-bounds)))
+    (for-each (lambda (old-parent)
+		(set-cell-children!
+		 old-parent
+		 (remove id (cell-children old-parent))))
+	      (cell-parents id))
+    (set-cell-expr! id expr)
+    (set-cell-parents! id (remdup (extract-ids expr)))
+    (for-each (lambda (new-parent)
+		(set-cell-children!
+		 new-parent
+		 (cons id (cell-children new-parent))))
+	      (cell-parents id))
+    (figure id)))
+
+(define (extract-ids expr)
+  (cond ((id? expr) (list expr))
+	((word? expr) '())
+	((null? expr) '())
+	(else (append (extract-ids (car expr))
+		      (extract-ids (cdr expr))))))
+
+(define (figure id)
+  (cond ((null? (cell-expr id)) (setvalue id '()))
+	((all-evaluated? (cell-parents id))
+	 (setvalue id (ss-eval (cell-expr id))))
+	(else (setvalue id '()))))
+
+(define (all-evaluated? ids)
+  (cond ((null? ids) #t)
+	((not (number? (cell-value (car ids)))) #f)
+	(else (all-evaluated? (cdr ids)))))
+
+(define (setvalue id value)
+  (let ((old (cell-value id)))
+    (set-cell-value! id value)
+    (if (not (equal? old value))
+	(for-each figure (cell-children id))
+	'do-nothing)))
+
+
+;;; Evaluating Expressions
+
+(define (ss-eval expr)
+  (cond ((number? expr) expr)
+	((quoted? expr) (quoted-value expr))
+	((id? expr) (cell-value expr))
+	((invocation? expr)
+	 (apply (get-function (car expr))
+		(map ss-eval (cdr expr))))
+	(else (error "Invalid expression:" expr))))
+
+(define (quoted? expr)
+  (or (string? expr)
+      (and (list? expr) (equal? (car expr) 'quote))))
+
+(define (quoted-value expr)
+  (if (string? expr)
+      expr
+      (cadr expr)))
+
+(define (invocation? expr)
+  (list? expr))
+
+(define (get-function name)
+  (let ((result (assoc name *the-functions*)))
+    (if (not result)
+	(error "No such function: " name)
+	(cadr result))))
+
+(define *the-functions*
+  (list (list '* *)
+	(list '+ +)
+	(list '- -)
+	(list '/ /)
+	(list 'abs abs)
+	(list 'acos acos)
+	(list 'asin asin)
+	(list 'atan atan)
+	(list 'ceiling ceiling)
+	(list 'cos cos)
+	(list 'count count)
+	(list 'exp exp)
+	(list 'expt expt)
+	(list 'floor floor)
+	(list 'gcd gcd)
+	(list 'lcm lcm)
+	(list 'log log)
+	(list 'max max)
+	(list 'min min)
+	(list 'modulo modulo)
+	(list 'quotient quotient)
+	(list 'remainder remainder)
+	(list 'round round)
+	(list 'sin sin)
+	(list 'sqrt sqrt)
+	(list 'tan tan)
+	(list 'truncate truncate)))
+
+;;; Printing the Screen
+
+(define (print-screen)
+  (newline)
+  (newline)
+  (newline)
+  (show-column-labels (id-column (screen-corner-cell-id)))
+  (show-rows 20
+	     (id-column (screen-corner-cell-id))
+	     (id-row (screen-corner-cell-id)))
+  (display-cell-name (selection-cell-id))
+  (display ":  ")
+  (show (cell-value (selection-cell-id)))
+  (display-expression (cell-expr (selection-cell-id)))
+  (newline)
+  (display "?? "))
+
+(define (display-cell-name id)
+  (display (number->letter (id-column id)))
+  (display (id-row id)))
+
+(define (show-column-labels col-number)
+  (display "  ")
+  (show-label 6 col-number)
+  (newline))
+
+(define (show-label to-go this-col-number)
+  (cond ((= to-go 0) '())
+	(else
+	 (display "  -----")
+	 (display (number->letter this-col-number))
+	 (display "----")
+	 (show-label (- to-go 1) (+ 1 this-col-number)))))
+
+(define (show-rows to-go col row)
+  (cond ((= to-go 0) 'done)
+	(else
+	 (display (align row 2 0))
+	 (display " ")
+	 (show-row 6 col row)
+	 (newline)
+	 (show-rows (- to-go 1) col (+ row 1)))))
+
+(define (show-row to-go col row)
+  (cond ((= to-go 0) 'done)
+	(else
+	   (display (if (selected-indices? col row) ">" " "))
+	   (display-value (cell-value-from-indices col row))
+	   (display (if (selected-indices? col row) "<" " "))
+	   (show-row (- to-go 1) (+ 1 col) row))))
+
+(define (selected-indices? col row)
+  (and (= col (id-column (selection-cell-id)))
+       (= row (id-row (selection-cell-id)))))
+
+(define (display-value val)
+  (display (align (if (null? val) "" val) 10 2)))
+
+(define (display-expression expr)
+  (cond ((null? expr) (display '()))
+	((quoted? expr) (display (quoted-value expr)))
+	((word? expr) (display expr))
+	((id? expr)
+	 (display-cell-name expr))
+	(else (display-invocation expr))))
+
+(define (display-invocation expr)
+  (display "(")
+  (display-expression (car expr))
+  (for-each (lambda (subexpr)
+	      (display " ")
+	      (display-expression subexpr))
+	    (cdr expr))
+  (display ")"))
+      
+
+;;; Abstract Data Types
+
+;; Special cells: the selected cell and the screen corner
+
+(define *special-cells* (make-vector 2))
+
+(define (selection-cell-id)
+  (vector-ref *special-cells* 0))
+
+(define (set-selection-cell-id! new-id)
+  (vector-set! *special-cells* 0 new-id))
+
+(define (screen-corner-cell-id)
+  (vector-ref *special-cells* 1))
+
+(define (set-screen-corner-cell-id! new-id)
+  (vector-set! *special-cells* 1 new-id))
+
+
+;; Cell names
+
+(define (cell-name? expr)
+  (and (word? expr)
+       (letter? (first expr))
+       (number? (bf expr))))
+
+(define (cell-name-column cell-name)
+  (letter->number (first cell-name)))
+
+(define (cell-name-row cell-name)
+  (bf cell-name))
+
+(define (cell-name->id cell-name)
+  (make-id (cell-name-column cell-name)
+	   (cell-name-row cell-name)))
+	
+;; Cell IDs
+
+(define (make-id col row)
+  (list 'id col row))
+
+(define (id-column id)
+  (cadr id))
+
+(define (id-row id)
+  (caddr id))
+
+(define (id? x)
+  (and (list? x)
+       (not (null? x))
+       (equal? 'id (car x))))
+
+;; Cells
+
+(define (make-cell)
+  (vector '() '() '() '()))
+
+(define (cell-value id)
+  (vector-ref (cell-structure id) 0))
+
+(define (cell-value-from-indices col row)
+  (vector-ref (cell-structure-from-indices col row) 0))
+
+(define (cell-expr id)
+  (vector-ref (cell-structure id) 1))
+
+(define (cell-parents id)
+  (vector-ref (cell-structure id) 2))
+
+(define (cell-children id)
+  (vector-ref (cell-structure id) 3))
+
+(define (set-cell-value! id val)
+  (vector-set! (cell-structure id) 0 val))
+
+(define (set-cell-expr! id val)
+  (vector-set! (cell-structure id) 1 val))
+
+(define (set-cell-parents! id val)
+  (vector-set! (cell-structure id) 2 val))
+
+(define (set-cell-children! id val)
+  (vector-set! (cell-structure id) 3 val))
+
+(define (cell-structure id)
+  (global-array-lookup (id-column id)
+		       (id-row id)))
+
+(define (cell-structure-from-indices col row)
+  (global-array-lookup col row))
+
+(define *the-spreadsheet-array* (make-vector 30))
+
+(define (global-array-lookup col row)
+  (if (and (<= row 30) (<= col 26))
+      (vector-ref (vector-ref *the-spreadsheet-array* (- row 1))
+		  (- col 1))
+      (error "Out of bounds")))
+
+(define (init-array)
+  (fill-array-with-rows 29))
+
+(define (fill-array-with-rows n)
+  (if (< n 0)
+      'done
+      (begin (vector-set! *the-spreadsheet-array* n (make-vector 26))
+	     (fill-row-with-cells
+	      (vector-ref *the-spreadsheet-array* n) 25)
+	     (fill-array-with-rows (- n 1)))))
+
+(define (fill-row-with-cells vec n)
+  (if (< n 0)
+      'done
+      (begin (vector-set! vec n (make-cell))
+	     (fill-row-with-cells vec (- n 1)))))
+
+;;; Utility Functions
+
+(define alphabet
+  '#(a b c d e f g h i j k l m n o p q r s t u v w x y z))
+
+(define (letter? something)
+  (and (word? something)
+       (= 1 (count something))
+       (vector-member something alphabet)))
+
+(define (number->letter num)
+  (vector-ref alphabet (- num 1)))
+
+(define (letter->number letter)
+  (+ (vector-member letter alphabet) 1))
+
+(define (vector-member thing vector)
+  (vector-member-helper thing vector 0))
+
+(define (vector-member-helper thing vector index)
+  (cond ((= index (vector-length vector)) #f)
+	((equal? thing (vector-ref vector index)) index)
+	(else (vector-member-helper thing vector (+ 1 index)))))
+
+(define (remdup lst)
+  (cond ((null? lst) '())
+	((member (car lst) (cdr lst))
+	 (remdup (cdr lst)))
+	(else (cons (car lst) (remdup (cdr lst))))))
+
+(define (remove bad-item lst)
+  (filter (lambda (item) (not (equal? item bad-item)))
+	  lst))
diff --git a/js/games/nluqo.github.io/~bh/downloads/simply/ttt.scm b/js/games/nluqo.github.io/~bh/downloads/simply/ttt.scm
new file mode 100644
index 0000000..71adb0b
--- /dev/null
+++ b/js/games/nluqo.github.io/~bh/downloads/simply/ttt.scm
@@ -0,0 +1,102 @@
+;;; ttt.scm
+;;; Tic-Tac-Toe program
+
+(define (ttt position me)
+  (ttt-choose (find-triples position) me))
+
+(define (find-triples position)
+  (every (lambda (comb) (substitute-triple comb position))
+         '(123 456 789 147 258 369 159 357)))
+
+(define (substitute-triple combination position)
+  (accumulate word
+	      (every (lambda (square)
+		       (substitute-letter square position))
+		     combination) ))
+
+(define (substitute-letter square position)
+  (if (equal? '_ (item square position))
+      square
+      (item square position) ))
+
+(define (ttt-choose triples me)
+  (cond ((i-can-win? triples me))
+        ((opponent-can-win? triples me))
+        ((i-can-fork? triples me))
+        ((i-can-advance? triples me))
+        (else (best-free-square triples)) ))
+
+(define (i-can-win? triples me)
+  (choose-win
+   (keep (lambda (triple) (my-pair? triple me))
+         triples)))
+
+(define (my-pair? triple me)
+  (and (= (appearances me triple) 2)
+       (= (appearances (opponent me) triple) 0)))
+
+(define (opponent letter)
+  (if (equal? letter 'x) 'o 'x))
+
+(define (choose-win winning-triples)
+  (if (empty? winning-triples)
+      #f
+      (keep number? (first winning-triples)) ))
+
+(define (opponent-can-win? triples me)
+  (i-can-win? triples (opponent me)) )
+
+(define (i-can-fork? triples me)
+  (first-if-any (pivots triples me)) )
+
+(define (first-if-any sent)
+  (if (empty? sent)
+      #f
+      (first sent) ))
+
+(define (pivots triples me)
+  (repeated-numbers (keep (lambda (triple) (my-single? triple me))
+                          triples)))
+
+(define (my-single? triple me)
+  (and (= (appearances me triple) 1)
+       (= (appearances (opponent me) triple) 0)))
+
+(define (repeated-numbers sent)
+  (every first
+         (keep (lambda (wd) (>= (count wd) 2))
+               (sort-digits (accumulate word sent)) )))
+
+(define (sort-digits number-word)
+  (every (lambda (digit) (extract-digit digit number-word))
+         '(1 2 3 4 5 6 7 8 9) ))
+
+(define (extract-digit desired-digit wd)
+  (keep (lambda (wd-digit) (equal? wd-digit desired-digit)) wd))
+
+(define (i-can-advance? triples me)
+  (best-move (keep (lambda (triple) (my-single? triple me)) triples)
+             triples
+             me))
+
+(define (best-move my-triples all-triples me)
+  (if (empty? my-triples)
+      #f
+      (best-square (first my-triples) all-triples me) ))
+
+(define (best-square my-triple triples me)
+  (best-square-helper (pivots triples (opponent me))
+		      (keep number? my-triple)))
+
+(define (best-square-helper opponent-pivots pair)
+  (if (member? (first pair) opponent-pivots)
+      (first pair)
+      (last pair)))
+
+(define (best-free-square triples)
+  (first-choice (accumulate word triples)
+                '(5 1 3 7 9 2 4 6 8)))
+
+(define (first-choice possibilities preferences)
+  (first (keep (lambda (square) (member? square possibilities))
+               preferences)))