- 示例工程
【免费下载链接】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/
导读
本文围绕经典游戏 Fur Trader(毛皮贸易)的 MiniScript 移植版展开,完整讲解如何在命令行 MiniScript 与 Mini Micro 两种环境下安装、加载并运行该程序,并深入解析 furtrader.ms 的源码结构与游戏机制,帮助你既能把游戏跑起来,也能读懂每一段逻辑背后的设计。读完本文,你将掌握 MiniScript 移植版的完整运行命令、Mini Micro 的文件夹挂载流程,以及从原版 BASIC 到 MiniScript 的移植实现要点。
一、游戏溯源与移植背景
Fur Trader 原版程序收录于 Vintage Basic 资料站(vintage-basic.net)的经典 BASIC 游戏合集,标题栏注明 "Creative Computing Morristown, New Jersey"。在 00_Alternate_Languages/38_Fur_Trader/ 目录中,除了 原版 BASIC 源码 furtrader.bas,还提供了 MiniScript、C、Go 等多个移植版本,其中 MiniScript 版位于 MiniScript 子目录,包含README.md与furtrader.ms两个文件。
根据 00_Alternate_Languages/README.md 的说明,00_Alternate_Languages目录收纳的是非约定的 10 种主流语言(这些约定语言需满足流行度高、内存安全、脚本化三个标准)之外的移植版本,属于教育用途的补充实现。MiniScript 正是这样一种轻量脚本语言,因此 Fur Trader 的 MiniScript 移植版被归类于此。
二、游戏规则与核心机制
2.1 背景设定与初始资产
游戏背景为 1776 年,你是一位法国毛皮贸易远征队的领袖,从安大略湖(Lake Ontario)地区出发,前往三个堡垒之一出售皮货并采购来年补给。初始状态为:
- 储蓄$600(见 furtrader.ms 的
money=600); - 携带190 张毛皮,分布在四种皮货中:mink(貂)、beaver(海狸)、ermine(银鼠)、fox(狐狸),对应源码第 7 行的
furNames = "mink beaver ermine fox".split。
2.2 每年的交易回合
每轮交易(对应 主循环)依次执行:
- 询问 "Do you wish to trade furs?",回答 NO 则退出游戏;
- 显示当前储蓄与 "190 furs to begin the expedition" 提示;
- 依次输入四种皮货的数量,合计不得超过 190:
- 输入过程中若累计达到 190 会提前结束输入(
if furs.sum >= 190 then break); - 若合计超过 190,程序输出反作弊提示 "Do not try to cheat. I can add. You must start again." 并要求重新开始本轮;
- 输入过程中若累计达到 190 会提前结束输入(
- 选择交易堡垒;
- 依据堡垒发生定价与旅行事件;
- 按beaver、fox、ermine、mink的顺序(源码第 161 行的
for j in [1, 3, 2, 0])结算收入revenue = value[j] * furs[j],累加到储蓄中; - 循环进入下一年交易。
2.3 三个堡垒的取舍
选择堡垒由 pickFort 函数 处理,输入 1、2、3 分别对应:
| 编号 | 堡垒 | 路线特点 | 皮货价格 | 补给与旅费 |
|---|---|---|---|---|
| 1 | Fort Hochelaga(蒙特利尔) | 最易路线,但远离海港 | 价格低 | $150 + $10 =$160 |
| 2 | Fort Stadacona(魁北克) | 中等难度,需翻越 portage、渡 Lachine 急流 | 平均 | $125 + $15 =$140 |
| 3 | Fort New York | 最险路线,需穿越易洛魁人领地 | 最高 | $80 + $25 =$105 |
选完堡垒后,程序会询问 "Do you want to trade at another fort?",由getYesNo函数(furtrader.ms)校验输入,只接受以 Y 或 N 开头的回答。
2.4 随机定价机制
皮货单价由 visitFort 函数 依据堡垒生成,公式统一为floor((区间系数*rnd+基准值)*100+0.5)/100,即保留两位小数的随机价格。各堡垒价格区间如下:
主循环预置价(每轮开始时设定,第 134-135 行):
- 银鼠 ermine:
0.15*rnd + 0.95→ 约[0.95, 1.10) - 海狸 beaver:
0.25*rnd + 1.00→ 约[1.00, 1.25)
Fort 1(Hochelaga): | 皮货 | 公式 | 区间 | |---|---|---| | mink |0.2*rnd + 0.7| [0.70, 0.90) | | beaver |0.2*rnd + 0.75| [0.75, 0.95) | | ermine |0.2*rnd + 0.65| [0.65, 0.85) | | fox |0.2*rnd + 0.8| [0.80, 1.00) |
Fort 2(Stadacona): | 皮货 | 公式 | 区间 | |---|---|---| | mink |0.3*rnd + 0.85| [0.85, 1.15) | | ermine |0.15*rnd + 0.8| [0.80, 0.95) | | beaver |0.2*rnd + 0.9| [0.90, 1.10) | | fox | 未重新设定 | 沿用上一轮取值(详见 2.6 节说明) |
Fort 3(New York): | 皮货 | 公式 | 区间 | |---|---|---| | mink |0.15*rnd + 1.05| [1.05, 1.20) | | fox |0.25*rnd + 1.1| [1.10, 1.35) | | ermine / beaver | 保持主循环预置价 | [0.95, 1.10) / [1.00, 1.25) |
可以看出,价格区间与路线难度成正比:路线越险,单价越高,但风险事件也越致命。
2.5 旅行随机事件
前往 Fort 2 与 Fort 3 时会掷出一个 1~10 的随机数p = floor(10*rnd)+1,不同区间触发不同事件:
Fort 2(魁北克)事件表: | 概率 | 事件 | 后果 | |---|---|---| | p ≤ 2(20%) | 海狸太重无法过 portage,返回时被盗 | 海狸皮清零 | | p ≤ 6(40%) | 安全抵达 | 无损失 | | p ≤ 8(20%) | 独木舟在 Lachine 急流倾覆 |所有皮货清零| | 其余(20%) | 狐狸皮未妥善硝制,无人购买 | 狐狸皮清零 |
Fort 3(纽约)事件表: | 概率 | 事件 | 后果 | |---|---|---| | p ≤ 2(20%) | 遭遇易洛魁人袭击,全员遇难 |游戏结束(globals.gameOver = true) | | p ≤ 6(40%) | 幸运安全抵达 | 无损失 | | p ≤ 8(20%) | 险遭易洛魁人袭击,被迫弃货 |所有皮货清零| | 其余(20%) | 貂皮与海狸皮受损 | 这两类皮货单价减半|
此外,每访问一个堡垒都会从储蓄中扣除对应的补给与旅费(如 Fort 1 扣除150 + 10),若在 Fort 3 遇难则直接gameOver终止游戏。
2.6 一个值得注意的原版遗留特性
从源码结构看,Fort 2 分支(furtrader.ms)没有为 fox 重新设定单价。对照 原版 BASIC 可以发现,BASIC 版同样只在 Fort 1(第 1177 行)与 Fort 3(第 1263 行)分支为 D1(fox 价)赋值。因此若首轮选择 Fort 2 交易,value[3]仍为初始值 0,狐狸皮会按 $0 出售;若此前访问过 Fort 1 或 Fort 3,则沿用上一轮价格。这一行为属于对原版逻辑的忠实复刻,而非移植引入的缺陷。
三、运行方式一:命令行 MiniScript
这是 MiniScript README 给出的第一种运行途径,适合在纯文本终端中体验,步骤如下:
- 安装命令行版 MiniScript:从 MiniScript 官方命令行版本页面(
miniscript.org/cmdline/)下载适配你操作系统的安装包并安装; - 进入游戏目录:切换到仓库中的 MiniScript 目录:
cd 00_Alternate_Languages/38_Fur_Trader/MiniScript - 运行程序:
miniscript furtrader.ms程序启动后即打印标题("FUR TRADER" 与 "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"),随后进入 1776 毛皮贸易远征的交互流程。也可以从仓库根目录直接指定相对路径运行:
miniscript 00_Alternate_Languages/38_Fur_Trader/MiniScript/furtrader.ms
命令行版本的输入输出均为纯文本交互:input()负责读取玩家回答,print输出剧情文本,与游戏在 1970 年代原始终端上的体验保持一致。
四、运行方式二:Mini Micro
Mini Micro 是 MiniScript 官方提供的图形化模拟主机(miniscript.org/MiniMicro/可下载),提供虚拟磁盘与命令行界面,适合在图形窗口中体验经典游戏。操作流程:
- 下载并启动 Mini Micro;
- 挂载游戏文件夹:点击顶部的磁盘插槽(disk slot),选择 "Mount Folder...",在弹出的对话框中选中包含
furtrader.ms与本 README 文件的目录,即 00_Alternate_Languages/38_Fur_Trader/MiniScript/; - 加载并运行:在 Mini Micro 命令提示符下依次输入:
load "furtrader" runload会从当前挂载的虚拟磁盘中读取furtrader.ms并编译为程序内存映像,run开始执行主程序。
注意:
load时省略.ms扩展名是 Mini Micro 的标准用法;若挂载的不是该文件夹,请先确认虚拟磁盘内存在furtrader.ms文件。
五、MiniScript 源码结构解析
furtrader.ms 全文约 170 行,是典型的"顶层脚本 + 若干函数"式 MiniScript 程序,结构清晰:
| 代码段 | 位置 | 职责 |
|---|---|---|
| 标题打印 | L1-L3 | 输出游戏标题与版权信息 |
| 全局数据 | L5-L7 | furs(四种皮货数量)、value(单价)、furNames |
getYesNo | L9-L16 | 循环读取输入,仅接受 Y/N 开头回答 |
printInstructions | L18-L26 | 打印游戏背景说明 |
pickFort | L28-L61 | 选择堡垒并打印对应路线评述 |
visitFort | L63-L124 | 定价、触发旅行事件、扣除费用、可能置gameOver |
| 主循环 | L126-L169 | 年度交易循环:输数量、选堡、结算 |
几个值得关注的实现细节:
globals.money的显式使用:在visitFort内部,函数默认对变量赋值会创建局部变量,因此扣款必须写成globals.money -= 150 + 10才能修改顶层作用域的money(见 L72);同理,L105 用globals.gameOver = true结束游戏。而furs、value作为数组对象是引用传递,函数内value[j] = ...、furs[j] = 0直接修改元素即生效,无需globals前缀。- 数组聚合语法:
furs.sum(第 147、149 行)直接对数组求和,用于 190 张上限的累计与作弊检测,是 MiniScript 相比原版 BASIC 手写累加循环更简洁的体现。 - 输入容错:
input(...).val将字符串转为数值,getYesNo对空输入continue重新询问,pickFort对非 1/2/3 的输入同样continue重试,保证了交互的健壮性。 - 随机价格四舍五入:
floor((...)*100+0.5)/100是"加 0.5 后取整"的经典保留两位小数手法,与原版 BASIC 中INT((.2*RND(1)+.7)*10^2+.5)/10^2逐行对应。
六、与原版 BASIC 及 Go 移植版的对照
将 furtrader.ms 与 原版 furtrader.bas 逐行对照,可以确认 MiniScript 移植对数值模型的高度忠实:
- 定价公式、事件概率(
P<=2/6/8/10四档)、费用金额(160/140/105)与出售顺序(beaver、fox、ermine、mink)均与原版一致; - 原版用
GOSUB/RETURN子程序组织流程,MiniScript 版改用具名函数(getYesNo、pickFort、visitFort),结构更可读,但语义等价; - 原版使用
F(1)~F(4)一维数组存四种皮货数量,MiniScript 版同样用furs数组,并引入furNames字符串数组消除原版DATA "MINK","BEAVER",...+READ的样板代码。
作为另一参照,Go 移植版 main.go 用显式状态机(GameState枚举:STARTING/TRADING/CHOOSINGFORT/TRAVELLING)和Player结构体重构了同一游戏,但其在 Fort 3 的补给费用为 $85 + $25 = $110(源码注释标注 "not in original code"),与 MiniScript 版及原版的 $105 存在细微差异,且 Go 版为 Fort 2、Fort 3 补充了 fox 单价设定。这些差异可作为阅读移植代码时对比原版数值模型的参考。
七、常见问题与注意事项
- 文件缺失导致加载失败:确保
furtrader.ms与README.md位于同一目录(MiniScript 子目录),Mini Micro 挂载时应选中该目录而非仓库根目录; - 命令行找不到
miniscript:通常是未安装命令行版或未将其加入 PATH,需先完成安装步骤; - "Do not try to cheat" 提示反复出现:输入的四种皮货总数超过 190,程序会拒绝本轮并让你重新输入;
- 游戏规则认知:Fort 3 有 20% 概率直接导致游戏结束(全员遇难),高收益伴随高风险是这款游戏的核心策略张力;
- 仓库为只读镜像:本仓库用于查看与运行,游戏与文档文件均为只读,运行时无需修改任何源码。
通过本文提供的两种运行方式,你可以立刻在命令行或 Mini Micro 中启动这场 1776 年的毛皮贸易远征;结合源码解析与各移植版对照,也能更深入地理解 MiniScript 的函数作用域、数组操作与随机逻辑等语言特性。
- 示例工程
【免费下载链接】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 之 Bullfight 的 MiniScript 移植版:安装与运行指南
Basic Computer Games 之 Bullfight 的 MiniScript 移植版:安装与运行指南 本指南面向希望以 MiniScript 语言
示例工程Basic Computer Games 之 Checkers 的 MiniScript 移植:玩法、运行环境与源码实现解析
Basic Computer Games 之 Checkers 的 MiniScript 移植:玩法、运行环境与源码实现解析 本指南以 basic comput
示例工程shopspring/decimal 深入解析:Loki 依赖链中防止浮点精度丢失的任意精度十进制库
shopspring/decimal 深入解析:Loki 依赖链中防止浮点精度丢失的任意精度十进制库 导读 本文以 Loki 仓库中 vendored 的 sh
示例工程
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考