Fix types/initforms
[reversi.git] / io.lisp
1 ;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; Package: reversi -*-
2 ;;;;***************************************************************************
3 ;;;;
4 ;;;; FILE IDENTIFICATION
5 ;;;;
6 ;;;;  Name:           io.lisp
7 ;;;;  Purpose:        Basic Input-Output for reversi
8 ;;;;  Programer:      Kevin Rosenberg based on code by Peter Norvig
9 ;;;;  Date Started:   1 Nov 2001
10 ;;;;
11 ;;;; $Id$
12 ;;;;
13 ;;;; This file is Copyright (c) 2001-2003 by Kevin M. Rosenberg
14 ;;;; and Copyright (c) 1998-2002 Peter Norvig
15 ;;;;
16 ;;;; Reversi users are granted the rights to distribute and use this software
17 ;;;; as governed by the terms of the Lisp Lesser GNU Public License
18 ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL.
19 ;;;;***************************************************************************
20
21 (in-package #:reversi)
22
23
24 (eval-when (:compile-toplevel :load-toplevel :execute)
25 (let ((square-names
26         (cross-product #'concat-symbol
27                        '(? A B C D E F G H ?)
28                        '(? 1 2 3 4 5 6 7 8 ?))))
29   (declare (type list square-names))
30
31   (defun h8->88 (str)
32     "Convert from alphanumeric to numeric square notation."
33     (or (position (string str) square-names :test #'string-equal)
34         str))
35
36   (defun 88->h8 (num)
37     "Convert from numeric to alphanumeric square notation."
38     (if (valid-p num)
39         (nth num square-names)
40       num)))
41
42 (defun moves-to-string (moves)
43   (let (move-list)
44     (dotimes (i (length moves))
45       (push (format nil "~2d: ~a ~a~%"
46                     (1+ i)
47                     (title-of (nth 1 (elt moves i)))
48                     (symbol-name (88->h8 (nth 0 (elt moves i)))))
49             move-list))
50     (setq move-list (nreverse move-list))
51     (list-to-delimited-string move-list #\space))))
52
53 (defun human (player board)
54   "A human player for the game of Reversi"
55   (format t "~&~c to move ~a: " (name-of player)
56           (mapcar #'88->h8 (legal-moves player board)))
57   (h8->88 (read)))
58
59
60 (defun print-board (&optional (board *board*) clock)
61   "Print a board, along with some statistics."
62   ;; First print the header and the current score
63   (format t "~2&    A B C D E F G H   [~c=~2a ~c=~2a (~@d)]"
64           (name-of black) (count black board)
65           (name-of white) (count white board)
66           (count-difference black board))
67   ;; Print the board itself
68   (loop for row from 1 to 8 do
69         (format t "~&  ~d " row)
70         (loop for col from 1 to 8
71               for piece = (bref board (+ col (* 10 row)))
72               do (format t "~c " (name-of piece))))
73   ;; Finally print the time remaining for each player
74   (when clock
75     (format t "  [~c=~a ~c=~a]~2&"
76             (name-of black) (time-string (elt clock black))
77             (name-of white) (time-string (elt clock white)))))
78
79
80 (defun time-string (time)
81   "Return a string representing this internal time in min:secs."
82   (multiple-value-bind (min sec)
83       (floor (round time internal-time-units-per-second) 60)
84     (format nil "~2d:~2,'0d" min sec)))
85
86
87
88