Mercurial > emacs
changeset 18290:d87d578b953d
(lm-display-statistics): Display stats in mode line.
(lm-number-of-trials, lm-sum-of-moves): New vars.
Various doc fixes.
author | Karl Heuer <kwzh@gnu.org> |
---|---|
date | Wed, 18 Jun 1997 04:23:02 +0000 |
parents | 3a43376db2be |
children | 130a48e6cc13 |
files | lisp/play/landmark.el |
diffstat | 1 files changed, 182 insertions(+), 289 deletions(-) [+] |
line wrap: on
line diff
--- a/lisp/play/landmark.el Wed Jun 18 01:26:55 1997 +0000 +++ b/lisp/play/landmark.el Wed Jun 18 04:23:02 1997 +0000 @@ -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 @@ (run-hooks 'lm-mode-hook)) - - - ;;;_ + THE SCORE TABLE. @@ -506,9 +509,9 @@ 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 @@ 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 @@ (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 @@ (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 @@ (lm-prompt-for-other-game)) - - - ;;;_ + INTERACTIVE COMMANDS. - - (defun lm-emacs-plays () "Compute Emacs next move and play it." (interactive) @@ -781,7 +739,7 @@ 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 @@ (t (lm-terminate-game 'human-resigned)))) ; OK. Accept it - - ;;;_ + PROMPTING THE HUMAN PLAYER. (defun lm-prompt-for-move () @@ -874,34 +830,17 @@ (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 @@ (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 @@ ;; 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 @@ (lm-mode)))) - ;;;_ + CROSSING WINNING QTUPLES. ;; When someone succeeds in filling a qtuple, we draw a line over the five @@ -1051,14 +981,14 @@ ;; 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 @@ (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 @@ (sit-for 0)) ; Display NOW - ;;;_ + CURSOR MOTION. ;; previous-line and next-line don't work right with intangible newlines @@ -1162,43 +1091,50 @@ (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))) +;;;_ + Simulation variables -(defun lm-index-to-y (index) - "Return corresponding y-coord of board INDEX." - (/ index (1+ lm-board-width))) - +;;;_ - 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) - -(defun lm-maybe-debug () +(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.") - (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 @@ (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 @@ -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 @@ (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 @@ 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 @@ (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 @@ (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 @@ (defun lm-calc-confidences () - (mapc '(lambda (direction) + (mapc '(lambda (direction) (put direction 's (lm-confidence-for direction))) lm-directions)) @@ -1546,11 +1442,13 @@ (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 @@ (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 @@ (mapc 'lm-update-normal-weights lm-directions) (mapc 'lm-update-naught-weights lm-directions) - (lm-maybe-debug)) + (if lm-debug + (lm-weights-debug))) + (lm-terminate-game nil)) - (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-start-robot () (defun lm-start-robot () @@ -1630,17 +1528,17 @@ (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 @@ (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 @@ (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 @@ (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 @@ 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 @@ (<= 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 @@ ;;;outline-layout: (0 : -1 -1 0) ;;;End: - ;;; landmark.el ends here