1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-12-24 10:38:38 +00:00

(lm-display-statistics): Display stats in mode line.

(lm-number-of-trials, lm-sum-of-moves): New vars.
Various doc fixes.
This commit is contained in:
Karl Heuer 1997-06-18 04:23:02 +00:00
parent e36a387ddd
commit a7b88742ff

View File

@ -1,10 +1,17 @@
;;;_landmark.el --- Landmark learning neural network
;; Copyright (C) 1996 Free Software Foundation, Inc.
;;;_ landmark.el --- neural-network robot that learns landmarks
;; Copyright (c) 1996, 1997 Free Software Foundation, Inc.
;; Author: Terrence Brannon <brannon@rana.usc.edu>
;; Created: December 16, 1996 - first release to usenet
;; Keywords: gomoku neural network adaptive search chemotaxis
;;;_* Usage
;;; Just type
;;; M-x eval-current-buffer
;;; M-x lm-test-run
;; This file is part of GNU Emacs.
;; GNU Emacs is free software; you can redistribute it and/or modify
@ -22,10 +29,6 @@
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
;;;_* Usage
;;; Just type
;;; M-x eval-current-buffer
;;; M-x lm-test-run
;;;_* Commentary
;;; Lm is a relatively non-participatory game in which a robot
@ -36,7 +39,7 @@
;;; future. If the smell of the tree decreases, the robots weights are
;;; adjusted to discourage a correct move.
;;; In layman's terms, the search space is initially flat. The point
;;; In laymen's terms, the search space is initially flat. The point
;;; of training is to "turn up the edges of the search space" so that
;;; the robot rolls toward the center.
@ -52,45 +55,21 @@
;;; west will be improved when they shouldn't
;;; For further references see
;;; http://rana.usc.edu:8376/~yuri/CS564/hw5.html
;;; http://rana.usc.edu:8376/~brannon/warez/yours-truly/lm/
;;; Many thanks to Yuri Pryadkin (yuri@rana.usc.edu) for this
;;; concise problem description.
;;;_* Provide
(provide 'lm)
;;;_* Require
(require 'cl)
;;;_* From Gomoku
;;;_ + THE BOARD.
;; The board is a rectangular grid. We code empty squares with 0, X's with 1
;; and O's with 6. The rectangle is recorded in a one dimensional vector
;; containing padding squares (coded with -1). These squares allow us to
@ -115,6 +94,19 @@
;; This is usually set to 70% of the number of squares.
"After how many moves will Emacs offer a draw?")
(defvar lm-cx 0
"This is the x coordinate of the center of the board.")
(defvar lm-cy 0
"This is the y coordinate of the center of the board.")
(defvar lm-m 0
"This is the x dimension of the playing board.")
(defvar lm-n 0
"This is the y dimension of the playing board.")
(defun lm-xy-to-index (x y)
"Translate X, Y cartesian coords into the corresponding board index."
(+ (* y lm-board-width) x y))
@ -142,8 +134,22 @@
(aset lm-board i -1) ; and also all k*(width+1)
(setq i (+ i lm-board-width 1)))))
;;;_ + DISPLAYING THE BOARD.
;; You may change these values if you have a small screen or if the squares
;; look rectangular, but spacings SHOULD be at least 2 (MUST BE at least 1).
(defconst lm-square-width 2
"*Horizontal spacing between squares on the Lm board.")
(defconst lm-square-height 1
"*Vertical spacing between squares on the Lm board.")
(defconst lm-x-offset 3
"*Number of columns between the Lm board and the side of the window.")
(defconst lm-y-offset 1
"*Number of lines between the Lm board and the top of the window.")
;;;_ + LM MODE AND KEYMAP.
@ -252,9 +258,6 @@ is non-nil. One interesting value is `turn-on-font-lock'."
(run-hooks 'lm-mode-hook))
;;;_ + THE SCORE TABLE.
@ -506,9 +509,9 @@ is non-nil. One interesting value is `turn-on-font-lock'."
square -1 1 dval)))
(defun lm-update-score-in-direction (left right square dx dy dval)
"Update scores for all squares in the qtuples starting between the LEFTth
square and the RIGHTth after SQUARE, along the DX, DY direction, considering
that DVAL has been added on SQUARE."
"Update scores for all squares in the qtuples in range.
That is, those between the LEFTth square and the RIGHTth after SQUARE,
along the DX, DY direction, considering that DVAL has been added on SQUARE."
;; We always have LEFT <= 0, RIGHT <= 0 and DEPL > 0 but we may very well
;; have LEFT > RIGHT, indicating that no qtuple contains SQUARE along that
;; DX,DY direction.
@ -588,12 +591,12 @@ that DVAL has been added on SQUARE."
lm-board-height m
lm-vector-length (1+ (* (+ m 2) (1+ n)))
lm-draw-limit (/ (* 7 n m) 10))
(setq lm-emacs-won nil
lm-game-history nil
lm-number-of-moves 0
(setq lm-emacs-won nil
lm-game-history nil
lm-number-of-moves 0
lm-number-of-human-moves 0
lm-emacs-played-first nil
lm-human-took-back nil
lm-human-took-back nil
lm-human-refused-draw nil)
(lm-init-display n m) ; Display first: the rest takes time
(lm-init-score-table) ; INIT-BOARD requires that the score
@ -635,9 +638,13 @@ that DVAL has been added on SQUARE."
(setq lm-emacs-is-computing nil))
;;;_ + SESSION CONTROL.
(defvar lm-number-of-trials 0
"The number of times that landmark has been run.")
(defvar lm-sum-of-moves 0
"The total number of moves made in all games.")
(defvar lm-number-of-emacs-wins 0
"Number of games Emacs won in this session.")
@ -651,55 +658,11 @@ that DVAL has been added on SQUARE."
(defun lm-terminate-game (result)
"Terminate the current game with RESULT."
(message
(cond
((eq result 'emacs-won)
(setq lm-number-of-emacs-wins (1+ lm-number-of-emacs-wins))
(cond ((< lm-number-of-moves 20)
"This was a REALLY QUICK win.")
(lm-human-refused-draw
"I won... Too bad you refused my offer of a draw !")
(lm-human-took-back
"I won... Taking moves back will not help you !")
((not lm-emacs-played-first)
"I won... Playing first did not help you much !")
((and (zerop lm-number-of-human-wins)
(zerop lm-number-of-draws)
(> lm-number-of-emacs-wins 1))
"I'm becoming tired of winning...")
("I won.")))
((eq result 'human-won)
(setq lm-number-of-human-wins (1+ lm-number-of-human-wins))
(concat "OK, you won this one."
(cond
(lm-human-took-back
" I, for one, never take my moves back...")
(lm-emacs-played-first
".. so what ?")
(" Now, let me play first just once."))))
((eq result 'human-resigned)
(setq lm-number-of-emacs-wins (1+ lm-number-of-emacs-wins))
"So you resign. That's just one more win for me.")
((eq result 'nobody-won)
(setq lm-number-of-draws (1+ lm-number-of-draws))
(concat "This is a draw. "
(cond
(lm-human-took-back
"I, for one, never take my moves back...")
(lm-emacs-played-first
"Just chance, I guess.")
("Now, let me play first just once."))))
((eq result 'draw-agreed)
(setq lm-number-of-draws (1+ lm-number-of-draws))
(concat "Draw agreed. "
(cond
(lm-human-took-back
"I, for one, never take my moves back...")
(lm-emacs-played-first
"You were lucky.")
("Now, let me play first just once."))))
((eq result 'crash-game)
"Sorry, I have been interrupted and cannot resume that game...")))
(setq lm-number-of-trials (1+ lm-number-of-trials))
(setq lm-sum-of-moves (+ lm-sum-of-moves lm-number-of-moves))
(if (eq result 'crash-game)
(message
"Sorry, I have been interrupted and cannot resume that game..."))
(lm-display-statistics)
;;(ding)
(setq lm-game-in-progress nil))
@ -712,13 +675,8 @@ that DVAL has been added on SQUARE."
(lm-prompt-for-other-game))
;;;_ + INTERACTIVE COMMANDS.
(defun lm-emacs-plays ()
"Compute Emacs next move and play it."
(interactive)
@ -781,7 +739,7 @@ that DVAL has been added on SQUARE."
lm-square-height)
1)
lm-board-height))))
(defun lm-mouse-play (click)
"Play at the square where you click."
(interactive "e")
@ -858,8 +816,6 @@ If the game is finished, this command requests for another game."
(t
(lm-terminate-game 'human-resigned)))) ; OK. Accept it
;;;_ + PROMPTING THE HUMAN PLAYER.
(defun lm-prompt-for-move ()
@ -874,34 +830,17 @@ If the game is finished, this command requests for another game."
(defun lm-prompt-for-other-game ()
"Ask for another game, and start it."
(if (y-or-n-p "Another game ")
(lm lm-board-width lm-board-height)
(if (y-or-n-p "Retain learned weights ")
(lm 2)
(lm 1))
(message "Chicken !")))
(defun lm-offer-a-draw ()
"Offer a draw and return T if Human accepted it."
"Offer a draw and return t if Human accepted it."
(or (y-or-n-p "I offer you a draw. Do you accept it ")
(not (setq lm-human-refused-draw t))))
;;;_ + DISPLAYING THE BOARD.
;; You may change these values if you have a small screen or if the squares
;; look rectangular, but spacings SHOULD be at least 2 (MUST BE at least 1).
(defconst lm-square-width 2
"*Horizontal spacing between squares on the Lm board.")
(defconst lm-square-height 1
"*Vertical spacing between squares on the Lm board.")
(defconst lm-x-offset 3
"*Number of columns between the Lm board and the side of the window.")
(defconst lm-y-offset 1
"*Number of lines between the Lm board and the top of the window.")
(defun lm-max-width ()
"Largest possible board width for the current window."
(1+ (/ (- (window-width (selected-window))
@ -920,13 +859,6 @@ If the game is finished, this command requests for another game."
(let ((inhibit-point-motion-hooks t))
(1+ (/ (- (count-lines 1 (point)) lm-y-offset (if (bolp) 0 1))
lm-square-height))))
(defun my-lm-point-y ()
(interactive)
"Return the board row where point is."
(let ((inhibit-point-motion-hooks t))
(message (format "%S"
(1+ (/ (- (count-lines 1 (point)) lm-y-offset (if (bolp) 0 1))
lm-square-height))))))
(defun lm-point-square ()
"Return the index of the square point is on."
@ -1022,12 +954,11 @@ If the game is finished, this command requests for another game."
;; We store this string in the mode-line-process local variable.
;; This is certainly not the cleanest way out ...
(setq mode-line-process
(format ": Won %d, lost %d%s"
lm-number-of-human-wins
lm-number-of-emacs-wins
(if (zerop lm-number-of-draws)
""
(format ", drew %d" lm-number-of-draws))))
(format ": Trials: %d, Avg#Moves: %d"
lm-number-of-trials
(if (zerop lm-number-of-trials)
0
(/ lm-sum-of-moves lm-number-of-trials))))
(force-mode-line-update))
(defun lm-switch-to-window ()
@ -1042,7 +973,6 @@ If the game is finished, this command requests for another game."
(lm-mode))))
;;;_ + CROSSING WINNING QTUPLES.
;; When someone succeeds in filling a qtuple, we draw a line over the five
@ -1051,14 +981,14 @@ If the game is finished, this command requests for another game."
;; who won. The solution is to scan the board along all four directions.
(defun lm-find-filled-qtuple (square value)
"Return T if SQUARE belongs to a qtuple filled with VALUEs."
"Return t if SQUARE belongs to a qtuple filled with VALUEs."
(or (lm-check-filled-qtuple square value 1 0)
(lm-check-filled-qtuple square value 0 1)
(lm-check-filled-qtuple square value 1 1)
(lm-check-filled-qtuple square value -1 1)))
(defun lm-check-filled-qtuple (square value dx dy)
"Return T if SQUARE belongs to a qtuple filled with VALUEs along DX, DY."
"Return t if SQUARE belongs to a qtuple filled with VALUEs along DX, DY."
(let ((a 0) (b 0)
(left square) (right square)
(depl (lm-xy-to-index dx dy)))
@ -1091,10 +1021,10 @@ If the game is finished, this command requests for another game."
(skip-chars-forward " \t")
(point))))
((= dx 0) ; Vertical
(let ((n 1)
(let ((lm-n 1)
(column (current-column)))
(while (< n lm-square-height)
(setq n (1+ n))
(while (< lm-n lm-square-height)
(setq lm-n (1+ lm-n))
(forward-line 1)
(indent-to column)
(insert-and-inherit ?|))))
@ -1109,7 +1039,6 @@ If the game is finished, this command requests for another game."
(sit-for 0)) ; Display NOW
;;;_ + CURSOR MOTION.
;; previous-line and next-line don't work right with intangible newlines
@ -1162,43 +1091,50 @@ If the game is finished, this command requests for another game."
(provide 'lm)
(defun lm-xy-to-index (x y)
"Translate X, Y cartesian coords into the corresponding board index."
(+ (* y lm-board-width) x y))
(defun lm-index-to-x (index)
"Return corresponding x-coord of board INDEX."
(% index (1+ lm-board-width)))
(defun lm-index-to-y (index)
"Return corresponding y-coord of board INDEX."
(/ index (1+ lm-board-width)))
;;;_ + Simulation variables
;;;_ - lm-nvar
(defvar lm-nvar 0.0075
"Not used.
Affects a noise generator which was used in an earlier incarnation of
this program to add a random element to the way moves were made.")
;;;_ - lists of cardinal directions
;;;_ :
(defvar lm-ns '(lm-n lm-s)
"Used when doing something relative to the north and south axes.")
(defvar lm-ew '(lm-e lm-w)
"Used when doing something relative to the east and west axes.")
(defvar lm-directions '(lm-n lm-s lm-e lm-w)
"The cardinal directions.")
(defvar lm-8-directions
'((lm-n) (lm-n lm-w) (lm-w) (lm-s lm-w)
(lm-s) (lm-s lm-e) (lm-e) (lm-n lm-e))
"The full 8 possible directions.")
(defvar lm-number-of-moves
"The number of moves made by the robot so far.")
;;;_* Terry's mods to create lm.el
;;;_ + Debugging things
(setq debug-on-error t)
;;;(setq lm-debug nil)
(setq lm-debug t)
(defvar lm-debug nil
"If non-nil, debugging is printed.")
(defvar lm-one-moment-please nil
"If non-nil, print \"One moment please\" when a new board is generated.
The drawback of this is you don't see how many moves the last run took
because it is overwritten by \"One moment please\".")
(defvar lm-output-moves t
"If non-nil, output number of moves so far on a move-by-move basis.")
(defun lm-maybe-debug ()
(if lm-debug
(progn (lm-print-wts) (lm-blackbox) (lm-print-y,s,noise)
(lm-print-smell))))
(defun lm-weights-debug ()
(if lm-debug
(progn (lm-print-wts) (lm-blackbox) (lm-print-y,s,noise)
(lm-print-smell))))
;;;_ - Printing various things
(defun lm-print-distance-int (direction)
@ -1315,47 +1251,23 @@ If the game is finished, this command requests for another game."
(interactive)
(mapc 'lm-print-wts-int lm-directions))
;;;_ + Simulation variables
;;;_ - lm-nvar
(defvar lm-nvar 0.0075 "affects a noise generator which was used in an
earlier incarnation of this program to add a random element to the way
moves were made. not used")
;;;_ - lists of cardinal directions
;;;_ :
(defvar lm-ns '(lm-n lm-s) "used when doing something relative to the
north and south axes")
(defvar lm-ew '(lm-e lm-w) "used when doing something relative to the
north and south axes")
(defvar lm-directions '(lm-n lm-s lm-e lm-w) "the cardinal directions")
(defvar lm-8-directions '(
(lm-n) (lm-n lm-w) (lm-s)
(lm-s lm-w) (lm-e) (lm-s lm-e)
(lm-n lm-w) (lm-w))
"the full 8 possible directions.")
;;;_ - learning parameters
(defvar lm-bound 0.005 "the maximum that w0j may be.")
(defvar lm-c 1.0 "a factor applied to modulate the increase in
wij. used in the function lm-update-normal-weights")
(defvar lm-c-naught 0.5 "a factor applied to modulate the increase in
w0j. used in the function lm-update-naught-weights" )
(defvar lm-bound 0.005
"The maximum that w0j may be.")
(defvar lm-c 1.0
"A factor applied to modulate the increase in wij.
Used in the function lm-update-normal-weights.")
(defvar lm-c-naught 0.5
"A factor applied to modulate the increase in w0j.
Used in the function lm-update-naught-weights.")
(defvar lm-initial-w0 0.0)
(defvar lm-initial-wij 0.0)
(defvar lm-no-payoff 0 "the amount of simulation cycles that have
occurred with no movement. used to move the robot when he is stuck in
a rut for some reason")
(defvar lm-max-stall-time 3 "the maximum of amount of simulation
cycles that the robot can get stuck in a place before lm-random-move
is called to push him out of it")
(defvar lm-no-payoff 0
"The amount of simulation cycles that have occurred with no movement.
Used to move the robot when he is stuck in a rut for some reason.")
(defvar lm-max-stall-time 2
"The maximum number of cycles that the robot can remain stuck in a place.
After this limit is reached, lm-random-move is called to push him out of it.")
;;;_ + Randomizing functions
@ -1365,45 +1277,33 @@ is called to push him out of it")
-1
1))
;;;_ : lm-very-small-random-number ()
(defun lm-very-small-random-number ()
(/
(* (/ (random 900000) 900000.0) .0001)))
;(defun lm-very-small-random-number ()
; (/
; (* (/ (random 900000) 900000.0) .0001)))
;;;_ : lm-randomize-weights-for (direction)
(defun lm-randomize-weights-for (direction)
(mapc '(lambda (target-direction)
(mapc '(lambda (target-direction)
(put direction
target-direction
target-direction
(* (lm-flip-a-coin) (/ (random 10000) 10000.0))))
lm-directions))
;;;_ : lm-noise ()
(defun lm-noise ()
(* (- (/ (random 30001) 15000.0) 1) lm-nvar))
(defun lm-randomize-weights-for (direction)
(mapc '(lambda (target-direction)
(put direction
target-direction
(* (lm-flip-a-coin) (/ (random 10000) 10000.0))))
lm-directions))
;;;_ : lm-fix-weights-for (direction)
(defun lm-fix-weights-for (direction)
(mapc '(lambda (target-direction)
(mapc '(lambda (target-direction)
(put direction
target-direction
target-direction
lm-initial-wij))
lm-directions))
;;;_ + Plotting functions
;;;_ - lm-plot-internal (sym)
(defun lm-plot-internal (sym)
(lm-plot-square (lm-xy-to-index
(lm-plot-square (lm-xy-to-index
(get sym 'x)
(get sym 'y))
(get sym 'sym)))
@ -1412,8 +1312,8 @@ is called to push him out of it")
(setq lm-cx (/ lm-board-width 2))
(setq lm-cy (/ lm-board-height 2))
(put 'lm-n 'x lm-cx)
(put 'lm-n 'y 1)
(put 'lm-n 'x lm-cx)
(put 'lm-n 'y 1)
(put 'lm-n 'sym 2)
(put 'lm-tree 'x lm-cx)
@ -1462,10 +1362,9 @@ is called to push him out of it")
0)))
;;;_ + Learning (neural) functions
(defun lm-f (x)
(cond
(cond
((> x lm-bound) lm-bound)
((< x 0.0) 0.0)
(t x)))
@ -1482,29 +1381,28 @@ is called to push him out of it")
(put direction target-direction
(+
(get direction target-direction)
(* lm-c
(- (get 'z 't) (get 'z 't-1))
(* lm-c
(- (get 'z 't) (get 'z 't-1))
(get target-direction 'y_t)
(get direction 'smell)))))
lm-directions))
(defun lm-update-naught-weights (direction)
(mapc '(lambda (target-direction)
(put direction 'w0
(lm-f
(lm-f
(+
(get direction 'w0)
(* lm-c-naught
(- (get 'z 't) (get 'z 't-1))
(- (get 'z 't) (get 'z 't-1))
(get direction 'y_t))))))
lm-directions))
;;;_ + Statistics gathering and creating functions
(defun lm-calc-current-smells ()
(mapc '(lambda (direction)
(mapc '(lambda (direction)
(put direction 'smell (calc-smell-internal direction)))
lm-directions))
@ -1516,21 +1414,19 @@ is called to push him out of it")
(setf lm-no-payoff 0)))
(defun lm-store-old-y_t ()
(mapc '(lambda (direction)
(mapc '(lambda (direction)
(put direction 'y_t-1 (get direction 'y_t)))
lm-directions))
;;;_ + Functions to move robot
;;;_ + Functions to move robot
(defun lm-confidence-for (target-direction)
(+
(get target-direction 'w0)
(reduce '+
(mapcar '(lambda (direction)
(*
(*
(get direction target-direction)
(get direction 'smell))
)
@ -1538,7 +1434,7 @@ is called to push him out of it")
(defun lm-calc-confidences ()
(mapc '(lambda (direction)
(mapc '(lambda (direction)
(put direction 's (lm-confidence-for direction)))
lm-directions))
@ -1546,11 +1442,13 @@ is called to push him out of it")
(if (and (= (get 'lm-n 'y_t) 1.0) (= (get 'lm-s 'y_t) 1.0))
(progn
(mapc '(lambda (dir) (put dir 'y_t 0)) lm-ns)
(message "n-s normalization.")))
(if lm-debug
(message "n-s normalization."))))
(if (and (= (get 'lm-w 'y_t) 1.0) (= (get 'lm-e 'y_t) 1.0))
(progn
(mapc '(lambda (dir) (put dir 'y_t 0)) lm-ew)
(message "e-w normalization")))
(if lm-debug
(message "e-w normalization"))))
(mapc '(lambda (pair)
(if (> (get (car pair) 'y_t) 0)
@ -1561,11 +1459,13 @@ is called to push him out of it")
(lm-e forward-char)
(lm-w backward-char)))
(lm-plot-square (lm-point-square) 1)
(incf lm-moves))
(incf lm-number-of-moves)
(if lm-output-moves
(message (format "Moves made: %d" lm-number-of-moves))))
(defun lm-random-move ()
(mapc
(mapc
'(lambda (direction) (put direction 'y_t 0))
lm-directions)
(dolist (direction (nth (random 8) lm-8-directions))
@ -1590,12 +1490,10 @@ is called to push him out of it")
(mapc 'lm-update-normal-weights lm-directions)
(mapc 'lm-update-naught-weights lm-directions)
(lm-maybe-debug))
(let ((lm-res-str (format "%S moves." lm-moves)))
(if lm-debug
(lm-print-moves lm-res-str))
(message (format "%S moves." lm-moves))))
(lm-weights-debug)))
(lm-terminate-game nil))
;;;_ - lm-start-robot ()
(defun lm-start-robot ()
@ -1630,17 +1528,17 @@ If the game is finished, this command requests for another game."
(mapc 'lm-update-normal-weights lm-directions)
(mapc 'lm-update-naught-weights lm-directions)
(lm-maybe-debug)
(lm-amble-robot)
)))))))
;;;_ + Misc functions
;;;_ - lm-init (auto-start save-weights)
(defvar lm-tree-r "")
(defun lm-init (auto-start save-weights)
(setq lm-moves 0)
(setq lm-number-of-moves 0)
(lm-plot-landmarks)
@ -1680,8 +1578,7 @@ If the game is finished, this command requests for another game."
(progn
(lm-goto-xy (1+ (random lm-board-width)) (1+ (random lm-board-height)))
(lm-start-robot))))
;;;_ - something which doesn't work
; no-a-worka!!
@ -1702,18 +1599,15 @@ If the game is finished, this command requests for another game."
(setq lm-tree-r (* (sqrt (+ (square lm-cx) (square lm-cy))) 1.5))
(mapc '(lambda (direction)
(mapc '(lambda (direction)
(put direction 'r (* lm-cx 1.1)))
lm-ew)
(mapc '(lambda (direction)
(mapc '(lambda (direction)
(put direction 'r (* lm-cy 1.1)))
lm-ns)
(put 'lm-tree 'r lm-tree-r))
;;;_ + lm-test-run ()
(defun lm-test-run ()
@ -1727,11 +1621,9 @@ If the game is finished, this command requests for another game."
(lm 2)))
;;;_ + lm: The function you invoke to play
;;;###autoload
(defun landmark (parg)
(defun lm (parg)
"Start an Lm game.
If a game is in progress, this command allows you to resume it.
Here is the relation between prefix args and game options:
@ -1743,11 +1635,11 @@ none / 1 | yes | no
3 | no | yes
4 | no | no
You start by moving to a square and typing \\[lm-start-robot].
You start by moving to a square and typing \\[lm-start-robot]
Use \\[describe-mode] for more info."
(interactive "p")
(setf n nil m nil)
(setf lm-n nil lm-m nil)
(lm-switch-to-window)
(cond
(lm-emacs-is-computing
@ -1756,29 +1648,31 @@ Use \\[describe-mode] for more info."
(<= lm-number-of-moves 2))
(let ((max-width (lm-max-width))
(max-height (lm-max-height)))
(or n (setq n max-width))
(or m (setq m max-height))
(cond ((< n 1)
(or lm-n (setq lm-n max-width))
(or lm-m (setq lm-m max-height))
(cond ((< lm-n 1)
(error "I need at least 1 column"))
((< m 1)
((< lm-m 1)
(error "I need at least 1 row"))
((> n max-width)
(error "I cannot display %d columns in that window" n)))
(if (and (> m max-height)
(not (eq m lm-saved-board-height))
((> lm-n max-width)
(error "I cannot display %d columns in that window" lm-n)))
(if (and (> lm-m max-height)
(not (eq lm-m lm-saved-board-height))
;; Use EQ because SAVED-BOARD-HEIGHT may be nil
(not (y-or-n-p (format "Do you really want %d rows " m))))
(setq m max-height)))
(message "One moment, please...")
(lm-start-game n m)))
(eval (cons 'lm-init
(cond
((= parg 1) '(t nil))
((= parg 2) '(t t))
((= parg 3) '(nil t))
((= parg 4) '(nil nil))
(t '(nil t))))))
(not (y-or-n-p (format "Do you really want %d rows " lm-m))))
(setq lm-m max-height)))
(if lm-one-moment-please
(message "One moment, please..."))
(lm-start-game lm-n lm-m)
(eval (cons 'lm-init
(cond
((= parg 1) '(t nil))
((= parg 2) '(t t))
((= parg 3) '(nil t))
((= parg 4) '(nil nil))
(t '(nil t))))))))
;;;_ + Local variables
;;; The following `outline-layout' local variable setting:
@ -1790,5 +1684,4 @@ Use \\[describe-mode] for more info."
;;;outline-layout: (0 : -1 -1 0)
;;;End:
;;; landmark.el ends here