|
|
1.1 ! root 1: ; Blackbox game in Emacs Lisp ! 2: ! 3: ; by F. Thomas May ! 4: ; [email protected] ! 5: ! 6: (defvar blackbox-mode-map nil "") ! 7: ! 8: (if blackbox-mode-map ! 9: () ! 10: (setq blackbox-mode-map (make-keymap)) ! 11: (suppress-keymap blackbox-mode-map t) ! 12: (define-key blackbox-mode-map "\C-f" 'bb-right) ! 13: (define-key blackbox-mode-map "\C-b" 'bb-left) ! 14: (define-key blackbox-mode-map "\C-p" 'bb-up) ! 15: (define-key blackbox-mode-map "\C-n" 'bb-down) ! 16: (define-key blackbox-mode-map "\C-e" 'bb-eol) ! 17: (define-key blackbox-mode-map "\C-a" 'bb-bol) ! 18: (define-key blackbox-mode-map " " 'bb-romp) ! 19: (define-key blackbox-mode-map "\C-m" 'bb-done)) ! 20: ! 21: ! 22: ;; Blackbox mode is suitable only for specially formatted data. ! 23: (put 'blackbox-mode 'mode-class 'special) ! 24: ! 25: (defun blackbox-mode () ! 26: "Major mode for playing blackbox. ! 27: ! 28: SPC -- send in a ray from point, or toggle a ball ! 29: RET -- end game and get score ! 30: ! 31: Precisely,\\{blackbox-mode-map}" ! 32: (interactive) ! 33: (kill-all-local-variables) ! 34: (use-local-map blackbox-mode-map) ! 35: (setq truncate-lines t) ! 36: (setq major-mode 'blackbox-mode) ! 37: (setq mode-name "Blackbox")) ! 38: ! 39: (defun blackbox (num) ! 40: "Play blackbox. Arg is number of balls." ! 41: (interactive "P") ! 42: (switch-to-buffer "*Blackbox*") ! 43: (blackbox-mode) ! 44: (setq buffer-read-only t) ! 45: (buffer-flush-undo (current-buffer)) ! 46: (setq bb-board (bb-init-board (or num 4))) ! 47: (setq bb-balls-placed nil) ! 48: (setq bb-x -1) ! 49: (setq bb-y -1) ! 50: (setq bb-score 0) ! 51: (setq bb-detour-count 0) ! 52: (bb-insert-board) ! 53: (bb-goto (cons bb-x bb-y))) ! 54: ! 55: (defun bb-init-board (num-balls) ! 56: (random t) ! 57: (let (board pos) ! 58: (while (>= (setq num-balls (1- num-balls)) 0) ! 59: (while ! 60: (progn ! 61: (setq pos (cons (logand (random) 7) (logand (random) 7))) ! 62: (bb-member pos board))) ! 63: (setq board (cons pos board))) ! 64: board)) ! 65: ! 66: (defun bb-insert-board () ! 67: (let (i (buffer-read-only nil)) ! 68: (erase-buffer) ! 69: (insert " \n") ! 70: (setq i 8) ! 71: (while (>= (setq i (1- i)) 0) ! 72: (insert " - - - - - - - - \n")) ! 73: (insert " \n"))) ! 74: ! 75: (defun bb-right () ! 76: (interactive) ! 77: (if (= bb-x 8) ! 78: () ! 79: (forward-char 2) ! 80: (setq bb-x (1+ bb-x)))) ! 81: ! 82: (defun bb-left () ! 83: (interactive) ! 84: (if (= bb-x -1) ! 85: () ! 86: (backward-char 2) ! 87: (setq bb-x (1- bb-x)))) ! 88: ! 89: (defun bb-up () ! 90: (interactive) ! 91: (if (= bb-y -1) ! 92: () ! 93: (previous-line 1) ! 94: (setq bb-y (1- bb-y)))) ! 95: ! 96: (defun bb-down () ! 97: (interactive) ! 98: (if (= bb-y 8) ! 99: () ! 100: (next-line 1) ! 101: (setq bb-y (1+ bb-y)))) ! 102: ! 103: (defun bb-eol () ! 104: (interactive) ! 105: (setq bb-x 8) ! 106: (bb-goto (cons bb-x bb-y))) ! 107: ! 108: (defun bb-bol () ! 109: (interactive) ! 110: (setq bb-x -1) ! 111: (bb-goto (cons bb-x bb-y))) ! 112: ! 113: (defun bb-romp () ! 114: (interactive) ! 115: (cond ! 116: ((and ! 117: (or (= bb-x -1) (= bb-x 8)) ! 118: (or (= bb-y -1) (= bb-y 8)))) ! 119: ((bb-outside-box bb-x bb-y) ! 120: (bb-trace-ray bb-x bb-y)) ! 121: (t ! 122: (bb-place-ball bb-x bb-y)))) ! 123: ! 124: (defun bb-place-ball (x y) ! 125: (let ((coord (cons x y))) ! 126: (cond ! 127: ((bb-member coord bb-balls-placed) ! 128: (setq bb-balls-placed (bb-delete coord bb-balls-placed)) ! 129: (bb-update-board "-")) ! 130: (t ! 131: (setq bb-balls-placed (cons coord bb-balls-placed)) ! 132: (bb-update-board "O"))))) ! 133: ! 134: (defun bb-trace-ray (x y) ! 135: (let ((result (bb-trace-ray-2 ! 136: t ! 137: x ! 138: (cond ! 139: ((= x -1) 1) ! 140: ((= x 8) -1) ! 141: (t 0)) ! 142: y ! 143: (cond ! 144: ((= y -1) 1) ! 145: ((= y 8) -1) ! 146: (t 0))))) ! 147: (cond ! 148: ((eq result 'hit) ! 149: (bb-update-board "H") ! 150: (setq bb-score (1+ bb-score))) ! 151: ((equal result (cons x y)) ! 152: (bb-update-board "R") ! 153: (setq bb-score (1+ bb-score))) ! 154: (t ! 155: (setq bb-detour-count (1+ bb-detour-count)) ! 156: (bb-update-board (format "%d" bb-detour-count)) ! 157: (save-excursion ! 158: (bb-goto result) ! 159: (bb-update-board (format "%d" bb-detour-count))) ! 160: (setq bb-score (+ bb-score 2)))))) ! 161: ! 162: (defun bb-trace-ray-2 (first x dx y dy) ! 163: (cond ! 164: ((and (not first) ! 165: (bb-outside-box x y)) ! 166: (cons x y)) ! 167: ((bb-member (cons (+ x dx) (+ y dy)) bb-board) ! 168: 'hit) ! 169: ((bb-member (cons (+ x dx dy) (+ y dy dx)) bb-board) ! 170: (bb-trace-ray-2 nil x (- dy) y (- dx))) ! 171: ((bb-member (cons (+ x dx (- dy)) (+ y dy (- dx))) bb-board) ! 172: (bb-trace-ray-2 nil x dy y dx)) ! 173: (t ! 174: (bb-trace-ray-2 nil (+ x dx) dx (+ y dy) dy)))) ! 175: ! 176: (defun bb-done () ! 177: (interactive) ! 178: (let (bogus-balls) ! 179: (if (not (= (length bb-balls-placed) (length bb-board))) ! 180: (message "Spud! You have only %d balls in the box." ! 181: (length bb-balls-placed)) ! 182: (setq bogus-balls (bb-show-bogus-balls bb-balls-placed bb-board)) ! 183: (if (= bogus-balls 0) ! 184: (message "Right! Your score is %d." bb-score) ! 185: (setq bb-score (+ bb-score (* 5 bogus-balls))) ! 186: (message "Veg! You missed %d balls. Your score is %d." ! 187: bogus-balls bb-score)) ! 188: (bb-goto '(-1 . -1))))) ! 189: ! 190: (defun bb-show-bogus-balls (balls-placed board) ! 191: (bb-show-bogus-balls-2 balls-placed board "x") ! 192: (bb-show-bogus-balls-2 board balls-placed "o")) ! 193: ! 194: (defun bb-show-bogus-balls-2 (list-1 list-2 c) ! 195: (cond ! 196: ((null list-1) ! 197: 0) ! 198: ((bb-member (car list-1) list-2) ! 199: (bb-show-bogus-balls-2 (cdr list-1) list-2 c)) ! 200: (t ! 201: (bb-goto (car list-1)) ! 202: (bb-update-board c) ! 203: (1+ (bb-show-bogus-balls-2 (cdr list-1) list-2 c))))) ! 204: ! 205: (defun bb-outside-box (x y) ! 206: (or (= x -1) (= x 8) (= y -1) (= y 8))) ! 207: ! 208: (defun bb-goto (pos) ! 209: (goto-char (+ (* (car pos) 2) (* (cdr pos) 22) 26))) ! 210: ! 211: (defun bb-update-board (c) ! 212: (let ((buffer-read-only nil)) ! 213: (backward-char (1- (length c))) ! 214: (delete-char (length c)) ! 215: (insert c) ! 216: (backward-char 1))) ! 217: ! 218: (defun bb-member (elt list) ! 219: "Returns non-nil if ELT is an element of LIST. Comparison done with equal." ! 220: (eval (cons 'or (mapcar (function (lambda (x) (equal x elt))) list)))) ! 221: ! 222: (defun bb-delete (item list) ! 223: "Deletes ITEM from LIST and returns a copy." ! 224: (cond ! 225: ((equal item (car list)) (cdr list)) ! 226: (t (cons (car list) (bb-delete item (cdr list)))))) ! 227: ! 228: ! 229:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.