- 示例工程
【免费下载链接】basic-computer-games
An updated version of the classic "Basic Computer Games" book, with well-written examples in a variety of common MEMORY SAFE, SCRIPTING programming languages. See https://coding-horror.github.io/basic-computer-games/
本篇文章基于 basic-computer-games 仓库中 16_Bug 的 MiniScript 移植版 编写,介绍经典《BASIC Computer Games》书中 Bug 游戏的 MiniScript 实现方式、两种运行环境(命令行 MiniScript 与 Mini Micro)的安装启动流程,并结合 bug.ms 源码讲解游戏的核心数据结构、骰子判定规则与 ASCII 绘图原理。读完本文,你可以在本机完整运行这款双人竞速拼装游戏,并能看懂其与现代面向对象风格的移植思路。
一、Bug 游戏与 MiniScript 移植背景
Bug 是收录于 1978 年经典书籍《BASIC Computer Games》(David H. Ahl 编著,Creative Computing 出版)中的一款骰子竞速游戏。它的玩法是:玩家与计算机轮流掷一个六面骰子,每个点数对应小虫身体的一个部件(身体、脖子、头、触须、尾巴、腿),先完整拼出自己的小虫者获胜。
在本仓库中,Bug 的原始 BASIC 源码位于 00_Alternate_Languages/16_Bug/bug.bas,而 00_Alternate_Languages/16_Bug/MiniScript/README.md 明确指出:
Original source downloaded from Vintage Basic. Conversion to MiniScript.
即该版本的原始源码下载自 Vintage Basic,随后被转换为 MiniScript 语言。MiniScript 是一门强调可读性与教学友好的脚本语言,其官网为 miniscript.org,同时提供命令行解释器(Command-Line MiniScript)和带图形界面的 Mini Micro 两种运行形态。
按照仓库 00_Alternate_Languages/README.md 的约定,MiniScript 不属于项目约定的 10 种主流移植语言(C#、Java、JavaScript、Kotlin、Lua、Perl、Python、Ruby、Rust、VB.NET),因此被放在00_Alternate_Languages目录下,属于教育用途的补充移植。
二、运行方式一:命令行 MiniScript
README 给出的第一种运行方式是使用命令行版 MiniScript 解释器:
- 前往 https://miniscript.org/cmdline/ 下载适配你操作系统的命令行 MiniScript,并完成安装;
- 进入存放移植程序的目录,执行:
miniscript bug.ms其中bug.ms即为本移植版的核心源码文件,位于仓库 00_Alternate_Languages/16_Bug/MiniScript/bug.ms。启动后程序会在终端中依次打印标题、询问是否查看游戏说明,然后进入"掷骰子—拼部件—看图画"的对局循环。
三、运行方式二:Mini Micro
第二种运行方式使用 Mini Micro,它是带虚拟磁盘与图形终端界面的 MiniScript 运行时:
- 从 https://miniscript.org/MiniMicro/ 下载并启动 Mini Micro;
- 点击顶部磁盘槽位(top disk slot),选择 "Mount Folder...",选中包含
bug.ms与 README 文件的MiniScript目录; - 在 Mini Micro 命令提示符中输入:
load "bug" runload会从已挂载的虚拟磁盘加载名为bug的程序(即bug.ms),run启动游戏。两种方式得到的游戏行为完全一致,区别仅在于运行环境:命令行版更轻量、适合脚本化执行,Mini Micro 则提供图形化窗口体验。
四、源码结构:用类与方法重构老式 GOTO 程序
原始 bug.bas 是一段典型的 70 年代 BASIC:通篇使用GOTO/ON Z GOTO跳转、以A/B/H/L/N/P/Q/R/S/T/U/V/Y等单字母变量记录双方部件状态(如B=1表示玩家有身体、A=2表示玩家有 2 根触须),且玩家与计算机的逻辑被拆成两套几乎重复的代码块(行 340–960 与行 990–1620)。
MiniScript 移植版遵循项目"使用现代编码规范重构"的要求(见根目录 README.md 中的 Porting Guidelines),做了三处关键改进:
1. 用 Bug 类封装部件状态
bug.ms 定义了一个Bug字典类,把所有部件收敛为对象的属性:
Bug = {} Bug.body = false Bug.neck = false Bug.head = false Bug.feelers = 0 Bug.tail = false Bug.legs = 0 Bug.feelerLetter = "F" Bug.pronoun = "I"其中布尔值表示是否拥有该部件,feelers与legs用整数计数(最多 2 根触须、6 条腿);feelerLetter用于绘制触须时的字符(玩家的触须用 "A",计算机的用 "F"),pronoun用于输出"我/你"对应的人称代词。
2. complete 方法:判定胜利条件
complete 方法集中表达了胜利判定逻辑:
Bug.complete = function return self.tail and self.feelers >= 2 and self.legs >= 6 end function有趣的是,与原始 BASIC 相比,这里将"完成"简化定义为拥有尾巴、2 根触须和 6 条腿——因为按照addPart的依赖规则,能装上这些部件的前提必然是身体、脖子、头都已就位。原始 BASIC 则在行 1650–1700 中分别用A=2 AND T=1 AND L=6(玩家)与S=2 AND P=1 AND V=6(计算机)各自判断。
3. addPart 方法:统一部件追加与依赖校验
addPart 是游戏的核心规则引擎,输入骰子点数partNum(1–6),按顺序处理六种部件:
| 点数 | 部件 | 需求数量 | 前置依赖 |
|---|---|---|---|
| 1 | body(身体) | 1 | 无 |
| 2 | neck(脖子) | 1 | 必须有 body |
| 3 | head(头) | 1 | 必须有 neck |
| 4 | feelers(触须) | 2 | 必须有 head |
| 5 | tail(尾巴) | 1 | 必须有 body |
| 6 | legs(腿) | 6 | 必须有 body |
依赖规则与原始 BASIC 完全一致(例如 BASIC 行 450 的IF B=0 THEN 520即"没有身体则不能装脖子")。addPart在成功装配或失败提示后返回 0 或 true,用于指示"本次是否发生了部件变化"——这与 BASIC 中用标志变量C追踪变化(C=0表示有变化)的作用相同。
五、主循环:轮流掷骰与按需绘图
主循环位于 bug.ms:
while not you.complete and not me.complete anyChange = false die = floor(6 * rnd + 1) print; print "You rolled a " + die if you.addPart(die) then anyChange = true wait 2 die = floor(6 * rnd + 1) print; print "I rolled a " + die if me.addPart(die) then anyChange = true ... end while其流程为:
- 用
floor(6 * rnd + 1)生成 1–6 的均匀随机数模拟掷骰(等价于 BASIC 的INT(6*RND(1)+1)); - 先给玩家
you追加部件,再给计算机me追加部件,中间用wait 2制造节奏停顿(对应 BASIC 行 975 的FOR DELAY=1 TO 2000:NEXT DELAY空循环延时); - 一旦任一方
complete为真,立即输出 "Your bug is finished." / "My bug is finished." 并退出循环; - 只有当本轮
anyChange为真(任一 bug 发生变化)时,才会询问 "Do you want the pictures?",非 "n" 的回答会触发 Bug.draw 绘制双方小虫的 ASCII 图形,然后继续下一轮。
循环结束后打印 "I hope you enjoyed the game, play it again soon!!" 收尾,与 BASIC 行 2540 的结束语保持一致。
六、ASCII 绘图:用 print 拼出小虫
draw 方法把每个部件渲染成纯文本图案,draw只绘制已拥有的部件,从触须到腿按从上到下排列:
- 触须:用
(feelerLetter + " ") * self.feelers打印 4 行,玩家显示A A,计算机显示F F; - 头:
HHHHHHH字符构成的方框,内含两只眼睛(H O O H)与嘴/鼻子(H V H); - 脖子:两行
N N; - 身体:
BBBBBBBBBBBB围成的椭圆,尾巴(TTTTT)从身体右侧伸出; - 腿:两行
L L L ...,数量等于self.legs。
字符串乘法(如"L " * self.legs)与range(1,4)循环是 MiniScript 的表达特色,替代了 BASIC 中层层嵌套的FOR/TAB排版(见 bug.bas 行 1780–2430),整体输出效果保持与原版一致,符合项目"忠实还原命令行外观"的移植准则。
七、输入兼容与可玩性细节
移植版在输入处理上遵循项目"支持大小写输入"的现代化要求(见根目录 README.md 的 Emulation and Bugfixes 一节):
- 游戏说明询问
ans = input("Do you want instructions? ").lower,把输入转为小写后判断首字符是否非 "n",因此y/yes/任意非 n 输入都会展示说明,大小写均可; - 同样的技巧用于 "Do you want the pictures?" 的询问;
- 掷骰、等待、绘图之间的
wait 2调用让回合推进有明确的节奏感,避免输出瞬间刷屏。
从源码结构看,该移植版完整保留了原游戏的所有规则细节(部件依赖、数量上限、胜负判定),同时把 250 多行的 GOTO 式 BASIC 重构为约 190 行的类 + 方法结构,是学习"如何将老式 BASIC 程序现代化移植"的合适范本。
八、快速上手总结
| 项目 | 内容 |
|---|---|
| 源码位置 | 00_Alternate_Languages/16_Bug/MiniScript/bug.ms |
| 说明文档 | 00_Alternate_Languages/16_Bug/MiniScript/README.md |
| 原始 BASIC | 00_Alternate_Languages/16_Bug/bug.bas |
| 命令行运行 | 安装命令行 MiniScript 后执行miniscript bug.ms |
| Mini Micro 运行 | 挂载MiniScript目录后执行load "bug"与run |
| 语言文档 | 详见 00_Alternate_Languages/README.md 与根目录 README.md 的项目规范 |
无论你选择命令行 MiniScript 还是 Mini Micro,只需两三条命令即可在本机体验这款经典小游戏;如果想要深入理解移植技巧,对照 bug.ms 与 bug.bas 逐行比对,是很有价值的阅读方式。
- 示例工程
【免费下载链接】basic-computer-games
An updated version of the classic "Basic Computer Games" book, with well-written examples in a variety of common MEMORY SAFE, SCRIPTING programming languages. See https://coding-horror.github.io/basic-computer-games/
相关推荐
basic-computer-games 之 Boxing 的 MiniScript 移植版:安装运行与源码玩法解析
basic computer games 之 Boxing 的 MiniScript 移植版:安装运行与源码玩法解析 本篇技术指南聚焦《Basic Comput
示例工程basic-computer-games 中的 KING 游戏:MiniScript 移植版的两种运行方式与源码剖析
basic computer games 中的 KING 游戏:MiniScript 移植版的两种运行方式与源码剖析 本文围绕《Basic Computer G
示例工程basic-computer-games 中 Slalom 的 MiniScript 移植:安装运行与源码级玩法解析
basic computer games 中 Slalom 的 MiniScript 移植:安装运行与源码级玩法解析 导读 本文围绕 00_Alternate_
示例工程
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考