首页 > 其他分享 >【Land of Lisp】一次练习:巫师文本冒险游戏

【Land of Lisp】一次练习:巫师文本冒险游戏

时间:2023-08-26 21:23:50浏览次数:45  
标签:Land 冒险游戏 string Lisp object list defun objects location

绪论

Common Lisp是一门多范式语言,支持多种编程模式,包括面向对象编程、函数式编程。但Common Lisp鼓励函数式编程,并且包含有许多函数式编程相关的功能。

《Land of Lisp》是一本寓教于乐的学习Lisp语法的书籍。这本书配以漫画插图来进行表达,并且将小游戏的制作作为演示和练习实例。本文就《Land of Lisp》第5、6章演示、练习给出相应的代码,并作一定的辅助的分析解释。

代码实现

基本框架

场景机制

;;;; 定义场景
(defparameter *nodes* '((living-room
                         (you are in the living-room.
                          a wizard is snoring loudly on the couch.))
                        (garden
                         (you are in a beautiful garden.
                          there is a well in front of you.))
                        (attic
                         (you are in the attic.
                          there is a giant welding torch in the corner.))))
(defparameter *edges* '((living-room (garden west door)
                         (attic upstairs ladder))
                        (garden (living-room east door))
                        (attic (living-room downstairs ladder))))

(defun describe-location (location nodes)
  "1. assoc将'(listA listB listC)中,listA/B/C的第一个元素作为关键字,获取listA/B/C
   2. (cadr list) => (car(cdr list)) 获取列表中第二个元素"
  (cadr (assoc location nodes)))
(defun describe-path (edge)
  `(there is a ,(caddr edge) going ,(cadr edge) from here.))
(defun describe-paths (location edges)
  "mapcar: (mapcar method list) 将method依次作用于list中各元素"
  (apply #'append (mapcar #'describe-path (cdr (assoc location edges)))))

;;;; 查看场景
(defparameter *location* 'living-room)
(defun look ()
  (append (describe-location *location* *nodes*)
          (describe-paths *location* *edges*)
          (describe-objects *location* *objects* *object-locations*)))

(defun walk (direction)
  "find的用法示范: (find 'y '((5 x) (3 y) (7 z)) :key #'cadr)
  => (3 Y)"
  (let ((next (find direction
                    (cdr (assoc *location* *edges*))
                    :key #'cadr)))
    (if next
        (progn (setf *location* (car next))
               (look))
        '(you cannot go that way.))))

物品机制

;;;; 定义物品
(defparameter *objects* '(whiskey bucket frog chain))
(defparameter *object-locations* '((whiskey living-room)
                                   (bucket living-room)
                                   (chain garden)
                                   (frog garden)))
(defun objects-at (loc objs obj-locs)
  "对于给定的loc地点,给定objs物品列表,检查是否处在该地点
  remove-if-not过滤掉列表中不符合条件的元素"
  (labels ((at-loc-p (obj)
             (eq (cadr (assoc obj obj-locs)) loc)))
    (remove-if-not #'at-loc-p objs)))
(defun describe-objects (loc objs obj-loc)
  (labels ((describe-obj (obj)
             `(you see a ,obj on the floor.)))
    (apply #'append (mapcar #'describe-obj (objects-at loc objs obj-loc)))))

;;;; 捡起物品
(defun pickup (object)
  "检查在当前loc地点下,输入的物品object是否存在
  若存在,则“将物品转移”到身体
  否则,输出禁止的提示语句"
  (cond ((member object
                 (objects-at *location* *objects* *object-locations*))
         (push (list object 'body) *object-locations*)
         `(you are now carrying the ,object))
        (t '(you cannot get that.))))
(defun inventory ()
  "将身体内的物品列出并输出为提示"
  (cons 'items- (objects-at 'body *objects* *object-locations*)))

用户界面

(defun game-repl ()
  (let ((cmd (game-read)))
    (unless (eq (car cmd) 'quit)
      (game-print (game-eval cmd))
      (game-repl))))

(defun game-read ()
  "read-from-string: 把字符串转变为表达式/符号(去除双引号)"
  (let ((cmd (read-from-string
              (concatenate 'string "(" (read-line) ")"))))
    (flet ((quote-it (x)
             (list 'quote x)))
      (cons (car cmd) (mapcar #'quote-it (cdr cmd))))))

(defparameter *allowed-commands* '(look walk pickup inventory))
(defun game-eval (sexp)
  (if (member (car sexp) *allowed-commands*)
      (eval sexp)
      '(i do not know that command.)))

(defun tweak-text (lst caps lit)
  "给定字符列表,逐字扫描,调整大小写
  1. 如果为空格,将大小写设置保留到下一字符
  2. 如果为标点符号,设置下一字符为大写
  3. 如果出现双引号字符,开启lit(literal)不设置大小写,不扫描字符,不作处理
  4. 如果开启cap(capital)则将字母转换为为大写
  5. 否则,将字母转换为小写"
  (when lst
    (let ((item (car lst))
          (rest (cdr lst)))
      (cond ((eq item #\space) (cons item (tweak-text rest caps lit)))
            ((member item '(#\! #\? #\.)) (cons item (tweak-text rest t lit)))
            ((eq item #\") (tweak-text rest caps (not lit)))
            (lit (cons item (tweak-text rest nil lit)))
            (caps (cons (char-upcase item) (tweak-text rest nil lit)))
            (t (cons (char-downcase item) (tweak-text rest nil nil)))))))
(defun game-print (lst)
  "打印储存在lst中的符号。实现句首大写,引号中的部分保留大小写和符号
  1. prin1-to-string: 将lisp列表打印成字符串且不输出
  2. string-trim: (string-trim str1 str2)将字符串str2中,位于左侧或右侧的特定字符去除,直到遇到给定范围外的字符;特定字符由str1给定
  3. coerce: 
     - (coerce string 'list)将字符串string转换成字符列表
     - (coerce list 'string)将字符列表list转换为字符串
  4. tweak-text: 自定义函数,用于中字符列表中逐字检查,并中必要时作调整"
  (princ
   (coerce 'string (tweak-text
            (coerce (string-trim "() "
                                 (prin1-to-string lst)) 'list)
            t nil) 'string))
  (fresh-line))

标签:Land,冒险游戏,string,Lisp,object,list,defun,objects,location
From: https://www.cnblogs.com/suspended-monitor/p/17659465.html

相关文章

  • JLR DOIP VCI SDD Pathfinder Interface: The Best Choice for Jaguar Land Rover Lov
    IfyouareaJaguarLandRover(JLR)enthusiast,youmustbefamiliarwiththeimportanceofhavingtherightdiagnostictoolathand.Inthisblogpost,wewilldiscusstheJLRDOIPVCISDDPathfinderInterfaceandwhyitstandsoutasthebestchoicefo......
  • 一种基于Common Lisp的用lambda从头构建逻辑、整数、算数、斐波拉契的方案
    绪论本文参考视频教程,教程给出了一系列编程题目。该教程作者裘香莲已经基于JavaScript,用lambda运算从头构建了一系列编程基础概念。本文则对其编程题以CommonLisp语言另外给出答案。逻辑与判断的实现代码展示(defparameter*t*(lambda(opt1opt2)`,opt2(funcallop......
  • goland基于wsl编译构建程序
    问题在window上构建出linux-amd64程序解决https://www.jetbrains.com/help/go/how-to-use-wsl-development-environment-in-product.htmlx01|windowwsl2安装点击查看x02|从store下载linuxdeepincentosx03|配置golangpassx04|新建项目......
  • 一种基于clisp的Common Lisp集成开发环境可行简易搭建方案
    绪论背景CommonLisp是一种优美的、小巧的语言,然而新手在入门CommonLisp时往往会遇到集成开发环境搭建的门槛,为CommonLisp的入门造成了障碍。尽管技术人员的推荐中,存在一种常见的集成开发环境配置方案是Emacs+Slime+SBCL三件套的方案,但该方案存在一些问题:Emacs和CommonLis......
  • QOJ # 6504. Flower's Land 2
    题面传送门感觉,非常高妙的随机化!考虑怎么判定一个序列合法,将每种颜色的奇数位置看成左括号,偶数位置看成右括号,则一个序列合法当且仅当其括号序列合法。现在带修,我们维护的东西需要满足如下性质:可逆:将相邻奇数位的信息和偶数位的信息合并需要等于单位元。有结合律:不然没有办......
  • 带你读论文丨S&P21 Survivalism: Living-Off-The-Land 经典离地攻击
    本文分享自华为云社区《[论文阅读](21)S&P21Survivalism:Living-Off-The-Land 经典离地攻击》,作者:eastmount。摘要随着恶意软件检测算法和方法变得越来越复杂(sophisticated),恶意软件作者也采用(adopt)同样复杂的逃避机制(evasionmechansims)来对抗(defeat)它们。民间证据表明离......
  • GoLand 2023(GO语言集成开发工具环境)mac版
    GoLand是一个非常简单的Go语言开发工具,它使您能够在各种平台上构建Go应用程序。在过去的几年里,GoLand2023在各个领域进行了改进,并且继续发展。我们从这篇文章开始,以了解GoLand的新功能。GoLand的一个很棒的功能是允许您设置源代码,而不仅仅是编译它。这使您可以在编写代码之前......
  • Goland 技巧
    postfix#.var会自动转化成如下内容,包括.forfmt.Sprintf("abc%d",10).varsprintf:=fmt.Sprintf("abc%d",10)快捷代码:forforiforrmethodlike(快捷键Ctrl+Space+Space)Command+p显示参数信息emm这个功能不晓得该叫什么,自行领悟吧。快捷键option+space,......
  • 如何将Python代码转换为Goland
    本文将介绍如何将Python代码转换为Goland,包括转换工具、转换步骤和注意事项。1.转换工具目前市面上有很多Python到Go的转换工具,例如:Transcrypt:一个命令行工具,可以将Python代码转换为Go代码。PyGo:一个Python库,可以在Python代码中嵌入Go代码,从而实现Python到Go的转换。GoPy:一个Pytho......
  • 8-13|Cannot run program "C:\Users\Administrator\AppData\Local\Temp\GoLand
    您的错误消息指的是尝试运行的程序与您当前的Windows版本不兼容。这可能是因为您正在使用一个旧版本的Windows(例如32位的版本)并试图运行一个为新版本(例如64位)编译的程序。以下是解决这个问题的建议步骤:1.**确认您的操作系统版本**: -打开“运行”(按`Win+R`),输入`msinfo32......