altos/lisp: Add license to hanoi demo
[fw/altos] / src / test / hanoi.lisp
1 ;
2 ; Towers of Hanoi
3 ;
4 ; Copyright © 2016 Keith Packard <keithp@keithp.com>
5 ;
6 ; This program is free software; you can redistribute it and/or modify
7 ; it under the terms of the GNU General Public License as published by
8 ; the Free Software Foundation, either version 2 of the License, or
9 ; (at your option) any later version.
10 ;
11 ; This program is distributed in the hope that it will be useful, but
12 ; WITHOUT ANY WARRANTY; without even the implied warranty of
13 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 ; General Public License for more details.
15 ;
16
17
18 ; ANSI control sequences
19
20 (defun move-to (col row)
21   (patom "\033[" row ";" col "H" nil)
22   )
23
24 (defun clear ()
25   (patom "\033[2J" nil)
26   )
27
28 (defun display-string (x y str)
29   (move-to x y)
30   (patom str)
31   )
32
33 ; Here's the pieces to display
34
35 (setq stack '("*" "**" "***" "****" "*****" "******" "*******"))
36
37 (setq top (+ (length stack) 3))
38
39 ;
40 ; Here's all of the stacks of pieces
41 ; This is generated when the program is run
42 ;
43 (setq stacks nil)
44
45 ; Display one stack, clearing any
46 ; space above it
47
48 (defun display-stack (x y clear stack)
49   (cond ((= 0 clear)
50          (cond (stack (progn
51                         (display-string x y (car stack))
52                         (display-stack x (1+ y) 0 (cdr stack))
53                         )
54                       )
55                )
56          )
57         (t (progn
58              (display-string x y "          ")
59              (display-stack x (1+ y) (1- clear) stack)
60              )
61            )
62         )
63   )
64
65 ; This should probably be included in the rom image...
66
67 (defun length (list)
68   (cond (list (1+ (length (cdr list))))
69         (0)
70         )
71   )
72
73 ; Position of the top of the stack on the screen
74 ; Shorter stacks start further down the screen
75
76 (defun stack-pos (y stack)
77   (- y (length stack))
78   )
79
80 ; Display all of the stacks, spaced 20 columns apart
81
82 (defun display-stacks (x y stacks)
83   (cond (stacks (progn
84                   (display-stack x 0 (stack-pos y (car stacks)) (car stacks))
85                   (display-stacks (+ x 20) y (cdr stacks)))
86                 )
87         )
88   )
89
90 ; Display all of the stacks, then move the cursor
91 ; out of the way and flush the output
92
93 (defun display ()
94   (display-stacks 0 top stacks)
95   (move-to 1 21)
96   (flush)
97   )
98
99 ; Reset stacks to the starting state, with
100 ; all of the pieces in the first stack and the
101 ; other two empty
102
103 (defun reset-stacks ()
104   (setq stacks (list stack nil nil))
105   (length stack)
106   )
107
108 ; more functions which could usefully
109 ; be in the rom image
110
111 (defun min (a b)
112   (cond ((< a b) a)
113         (b)
114         )
115   )
116
117 (defun nth (list n)
118   (cond ((= n 0) (car list))
119         ((nth (cdr list) (1- n)))
120         )
121   )
122
123 ; Replace a stack in the list of stacks
124 ; with a new value
125
126 (defun replace (list pos member)
127   (cond ((= pos 0) (cons member (cdr list)))
128         ((cons (car list) (replace (cdr list) (1- pos) member)))
129         )
130   )
131
132 ; Move a piece from the top of one stack
133 ; to the top of another
134
135 (defun move-piece (from to)
136   (let ((from-stack (nth stacks from))
137         (to-stack (nth stacks to))
138         (piece (car from-stack)))
139     (setq from-stack (cdr from-stack))
140     (setq to-stack (cons piece to-stack))
141     (setq stacks (replace stacks from from-stack))
142     (setq stacks (replace stacks to to-stack))
143     (display)
144     (delay 100)
145     )
146   )
147
148 ; The implementation of the game
149
150 (defun _hanoi (n from to use)
151   (cond ((= 1 n)
152          (progn
153           (move-piece from to)
154           nil)
155          )
156         (t
157          (progn
158           (_hanoi (1- n) from use to)
159           (_hanoi 1 from to use)
160           (_hanoi (1- n) use to from)
161           )
162          )
163         )
164   )
165
166 ; A pretty interface which
167 ; resets the state of the game,
168 ; clears the screen and runs
169 ; the program
170
171 (defun hanoi ()
172   (setq len (reset-stacks))
173   (clear)
174   (_hanoi len 0 1 2)
175   )