0xD009
3862 字
19 分钟
异常Exception——不错的编程启蒙游戏
2024-12-21

0x0 前言#

笔者高二春季学期正值新冠疫情期间,上网课是很轻松的,于是有余力玩一些电脑游戏,不过当时的 PC 性能堪忧,只能体验一些小体量游戏,于是我寻到了几款小而耐玩的游戏,其中有一款叫做《异常Exception》。

笔者当时对它颇为沉迷,不过当时玩到后期卡关卡得严重,已经忘了是怎么从游戏过渡到 Python 学习上的,或是想从实际编程中找些灵感,或是玩了游戏之后自认为自己颇有编码天赋,总之我后来学习了 Python ,而且用它写了不少小玩意,以提高我作为物理课代表的工作效率(诸如点名、清点同学作业提交情况等),不过后来再也没回去玩过《异常》了。

前些阵子突然想起这事来,于是在 Steam 上补票了,历时 11 小时后终于通关了。

学习编程前后,对《异常》的游玩体验是有差异的,所以我想在这篇博客简单分享一下,可能涉及一些关卡的解法泄露。

0x1 游戏剧情#

“我”是 159 号检查员,在一次检查过程中,“我”发现了能够稳定地维持异常状态的异常单元,正要将其销毁,这时,“奥思”出现,劝“我”留下它。

如果“我”决定留下它,就需要通过编写程序来控制它到达指定的地方。

“我”同意了,通过写程序帮助“奥思”完成了很多任务,逐渐解锁新的命令、特性,战胜了敌人“赛恩”。

后来发现“奥思”只是利用了我们(不过这感觉并不难受)。

0x2 游戏流程#

游戏的玩法非常简单,就是通过设置条件和对应的命令来控制异常单元的行为,以达到关卡的要求。

笔者游玩时并没有仔细看提示,导致了一些不必要的卡关,现在梳理一下游戏中关键的提示(主要在前 20 关),读者可以随意浏览或者直接跳过。

第一关我们首先学会了最简单的移动方式——路径点,通过关卡预设的几个特定点来控制异常单元的移动路径,这种移动方式非常简单,但如果路径点在异常单元直线不可达的地方,单元就会开始随机游走,直到路径点可达为止,这很大程度上限制了单元行为的自由度。

不过相比直接设置单元按上下左右方向移动,这大大简化了编码逻辑,而且这种做法确实更能体现策略性,也和实际编程有了差异化。

帮助手册也非常有程序员的味道。

第二关学习的是“视野”的概念,正常单元和异常单元都有视野,可以设置对视野内的敌人发起攻击,视野大是有较大优势的。

第三关提醒我们开始编程之前可以先试运行一次,观察敌人的动向。

第四关需要我们利用视野优势卡位敌人,同时在这一关,我们学到了设置攻击模式:开火。

第五关我们学到了第一个条件:发现敌人,这是非常好用的一个条件。

第六关揭示了程序的执行路径,并给出了优先级,优先级非常重要,因为游戏中没有 else 对应的关键字。

第七关给出了新的移动模式:追击和撤退,主要被用于战斗,同时也学到了新的攻击模式:停火,可以通过停火再开火来刷新狙击手等慢攻速单元的攻击冷却,这是我通关后才知道的,而在帮助是写明的。

第八关我们学到了信号,它既可以作为条件也可以作为命令,是单元交互的桥梁,也是完成多环节任务的关键一环。

至此,命令系统基本完备,接下来将对编辑系统进行升级。

第九关开始支持指令复制,Ctrl+CV 工程师的最爱,同时,这关对需要玩家对信号有一定的理解,游戏从这里开始有点难度了。

第十关同样是考察对信号的掌握,同时推出了编辑器新功能:页签,可以用于命令的版本管理。

接下来是条件性能的升级。

第十一关开始,我们可以将到路径点的距离作为条件了,这是非常强大的条件,而且支持所有的双目布尔运算符。

第十二关平平无奇,应该是用于帮助玩家熟悉路径距离作为条件。

第十三关,同上,但是还要加上信号控制。

第十四关,正式说明了路径点不可达则随机转向,提示了多条件的使用(逻辑与)。

第十五关,比较正常。

第十六关,引入了路径点的循环,异常单元可以转圈了,循环消耗地方单位,这关不难打出来,但是观赏性很好,我当时还发了个说说。

第十七关,条件性能升级,单元可以检查自身耐久度作为条件了,可与回复站进行配合。

这里可以顺便说一下,单元分为几类:

  • 士兵比较中规中矩,各方面平均
  • 侦察兵以视野见长,但是攻击伤害低
  • 狙击手视野和伤害都不赖,但是速度和攻速较差
  • 堡垒可以进行范围攻击,视野不小,耐久也较高,但是移速太慢
  • 怒火攻速极快,移动龟速
  • 蜘蛛移速很快,耐久低
  • 回复站顾名思义可以提供回复
  • 核心是关键,通常需要保护己方核心,攻破敌方核心
  • 传送门会不断生成单元 不过单元具体的数值在不同的关卡不一定完全一致。

配合使用不同的单元、对地方单元提出针对性的措施都是很重要的,这一点在游戏中一直有体现,但暂不作为讨论的重点。

第十八关,条件性能再次升级,引入了警戒状态作为条件,当单元被攻击或者发现敌人时,都会进入警戒状态,同时,编辑器也引入了缩进,支持条件嵌套。警戒与发现敌人不同的点就在于它有延续性,一段时间后才消失,同时,对于己方视野不如敌方视野的情况,也可以通过设置警戒状态下追击敌人来作为对策,警戒条件不应被低估。

第十九关,终于有新的移动模式:寻路了,设置寻路某点,单元即会自动寻找最短路径,同时也引入了警戒时长,警戒时长默认为 3 秒,可以通过命令设置,而且可以设置为 0 。

第二十关,引入了视野共享的机制,当单元发现敌人,则会将其位置传递给视野内的所有己方单元,这对一些视野劣势的单元是很大的优势。

接下来游戏的难度更上一层楼,不再涉及新的机制了,我会简单讲讲我的思路。

第二十一关,引入塔防玩法和视野内单元数判断(分友方和敌方)。

这一关的打法基本是通过利用侦察兵协助我方传送门单元军团压制对方,积累人数优势之后吸引下方堡垒追击,然后与上方的己方士兵群共享视野,它们就会一拥而上干掉堡垒。注意侦察兵在兵力积累阶段不能太靠近敌方传送门,很容易被杀掉,侦察兵死后我们就完全失去主观能动性了。

第二十二关是我卡的比较久的一关。

这关的思路是利用侦察兵的信号给堡垒和狙击手提供情报,狙击手擅长打单怪,堡垒擅长打群怪,但是怎么判断单怪和群怪就见仁见智了,我自己并没有很好地解决,通关后看其他玩家的攻略,其实可以让侦察兵发现敌人后后退来增加判断的精度。如果保持站立的话,由于群怪的队尾也是单怪,所以群怪信号的传递时间非常有限。

我这边直接设置了堡垒留守 A 点,相比 B 点有更多缓冲空间,如果侦察兵发现视野内的敌方较多,则狙击手往回走,但是由于前面提到的,只会往回走一点,这就导致了我不得不把堡垒放在 A 点;否则如果侦察兵发现视野内的敌方较少,则狙击手主动出击,遭遇敌人后边打边退,其实这里也可以用前面提到的通过开火和停火转换来刷新狙击手冷却,不过我没有用到。

第二十三关相对简单点了,需要同时打掉敌方的三个士兵,否则它们警戒后就会摧毁核心。

只要控制号三个狙击手同步行动,先干掉堡垒,再分别干掉士兵即可。

第二十四关我的解法可能比较偏门。

像第 16 关那样让三个单元绕圈,轮流经过回复站,保持耐久度,同时保持它们互相可见,可以随时共享视野围攻敌方。

第二十五关,引出右侧的混乱堡垒然后溜走,堡垒出来后会发现敌方蜘蛛,将它们消灭殆尽后返回,这时我们再偷袭核心即可,利用信号进行多环节编程即可。

第二十六关,包围住敌方让它们无法回到回复站。

总感觉应该利用 L 形的结构进行包围,我起初也是这么设计的,不过阴差阳错弄成了这样,但感觉包围得更死了。

第二十七关,怒火的视野不够,但是注意它的射程充足。

利用侦察兵水平移动和怒火共享视野即可,同时,当出怪有明显局部集中性的时候要通过信号控制怒火互相支援。这关如果不关注视野共享就很难处理,否则不难。

第二十八关,思路一目了然,但是需要注意细节。

首先,狙击手移动不能设为撤退,撤退它会向上撤(因为敌方并非走在道路中轴线,而是偏内环),转向的时候会因为速度不够而被敌方追上,但是,又不能简单设为寻路,狙击手走的太快。敌方追不上,输出空间就变小了,我的解决方法是:设置视野内没有敌人但警戒时站立。

其次,通过设置停火再开火来提高攻速,成功率会有所提升。

再次,可以把警戒时间调短来防止消灭敌人后站立太久。

最后,如何判断应该往哪边走,我的解决方案是先撤退两步,然后通过判断到 B D 两点的距离来决定寻路点。

第二十九关,两军对垒。

基本对称,各有一个传送门,两个额外的机动士兵,但对方还有两个守城士兵,应该是为了防止玩家直接绕到核心。敌方的两个机动士兵在耐久较低时撤退到回复站,我也模仿了这一战术,但最多和对方打个平手,后来想到了一个偷鸡思路:我的两个士兵先埋伏在对方的一个回复站守株待兔,打掉对方一个机动士兵后再加入正面战场,后面就比较轻松了。

第三十关,比较有意思,没有路径点。

三个士兵会依次从面前经过,只有跟着第三个士兵才能到目标点。通过构造一个状态机即可完成。

这里可以直接看我的解法:

更新状态是通过第 1 2 行发现敌人后视野内无敌人的复式条件,然后进行状态变化,注意第 3 4 5 行的顺序有讲究,可以避免连续两次变化,最后第 7 8 行用于跟踪第三个士兵但不被其发现。

当然,还有很大的优化空间,有一个成就即为在 5 行内解决第三十关,需要化简这个有限状态机,笔者还尚未仔细研究。

0x3 不同视角下的体验#

对于 5 年前还未学过编程的我,卡关确实是在所难免的,但是将《异常》作为编程启蒙,让我在后面正式学习一些编程语言,甚至计算机学科课程的时候有了不少既视感,同时,一开始就以这样直接有趣的方式进行编程,让我后来一点也不害怕编码,反而让我乐于用所学的编程知识来解决实际的问题。

(不过我依然感到高中时的自己是聪明的,或者说思维不那么僵化的,当时就已经想出了相当不错的解决方案。)

以现在的视角来看,《异常》真实程序员味满满,包括各处的一些小 tips ,包括程序的执行、优先级、缩进、条件判断;包括可以在程序运行时暂停和查看状态,这很像调试,痛苦程度也是;包括最后一关“永恒”,明显和状态机有关联;包括信号,不就类似操作系统中信号量吗…还有很多。不过,并非我学习了这些相关的机制之后游戏就顺风顺水,事实上,正如我前面提到的,由于自己忽略了一些关键的游戏特性,我还是会卡关,这体现了《异常》是编程和游戏的有机结合,也提醒我不能因为掌握了一些九牛一毛的小知识就不再扎实地继续学习了。

在游戏的第七关,“奥思”对我们说:

我想五年前的我一定被这话激励了,现在的我看到它只会默默在心里答“是”。

0x4 意外之喜#

令我万万没有想到的是,《异常》的玩家社区目前仍在活跃中,我们可以在“玩家关卡”中游玩到远比游戏本体丰富的内容,而且它们甚至超出了原本游戏的玩法之外(不是通过编程来过关),taptap 上《异常》也还有不少人在讨论,去年官方甚至还发布了玩家关卡作者招募,不过“选项”里的“攻略”网站已经 404 了,导致我起初以为《异常》团队早就死了。

异常Exception——不错的编程启蒙游戏
https://0xd009.github.io/posts/异常exception不错的编程启蒙游戏/
作者
0xD009
发布于
2024-12-21
许可协议
CC BY-NC-SA 4.0