
原文作者为 Rahul Sridhar和 Brian Chen。全文均为个人翻译,如有错漏之处欢迎指出。
原文地址:https://github.com/fortenforge/suggestions-for-running-a-puzzlehunt
这份文档描述了一些有关举办解谜寻宝活动的设计决策和技术细节。本文试着总结一些解谜寻宝社区的观点并列出一些在设计谜题时应避开的陷阱。欢迎各位提出评论和建议!
这项工程受PPP的指南[1]启发。
游玩足够多的解谜寻宝活动是一个好主意,这样你就能知道你的目标观众并且熟悉你将做出的一些决定。请记住准备并举办一场解谜寻宝活动总是要花远超预期的时间和努力的,所以要确保预留充足的时间:-)。
用谜题日历[2]来避免时间安排上的冲突。你可以给Dan egonr发邮件(egnor@ofb.net)来将你的活动加到日历上。持续举办的活动最好安排在周末进行,这样人们就不用罢工来参加了。
显然无论你使用什么样的计分系统都应当对所有队伍是公平的。也许不那么显然的是,你的计分系统应该激励队伍去提交答案从而解决谜题。如果你的计分系统给现在表现不好的队伍额外的好处,那么一个战略团队可能会倾向于扣压答案来去解决能够获得那些好处的谜题。
你还需要考虑如何避免平局。这在谜题寻宝式的活动中是很容易的,因为队伍按照第一个完成最终元谜题的时间排名。如果你正在举办一场澳大利亚式的寻宝活动,使用平均解决谜题时间(在更小的程度上)或最后的解决时间,可能会给在最佳时区的解谜者一些优势。
大致来说,以下是如何写一场解谜寻宝的过程:首先选择一个主题和与主题相关的元元谜题(metameta),然后写元谜题,最后是普通谜题。请记住在你开始安排谜题或者是元谜题的答案之前要试解并且彻底地事实核查(factcheck)你的元元谜题和元谜题。如果你发现元谜题或者是元元谜题中的一个错误,那么你可能需要重写整个谜题。
如果你不是完全由你自己写整个寻宝活动(或者你是自己写的但是你的寻宝活动规模很大),你会想密切关注所有谜题的状态并且确保它们能够在你的寻宝活动开始前完成。如果你的寻宝活动规模相对较小,你可能需要一个简单的表格来处理;但是如果你有超过20道谜题要写,我们建议你考虑建立Puzzlord[3]来管理进度。除了检查你所有的谜题状态以外,Puzzlord的一个主要好处是管理你的试解部分(下面会详细介绍)。
Puzzlord是Puzzletron[4]的重新设计版本,那是谜题寻宝团队以前使用的管理他们谜题写作的软件。Puzzlord是一个Django应用(Puzzletron使用的是PHP),并且具有精简的权限系统和更现代化的用户界面。更多有关Puzzlord的设计可以参考[5]。
试解是让未被剧透的解谜者尝试你的谜题的过程。试解是谜题写作中最重要的步骤。甚至是非常有经验的谜题设计师写那些很难被解决的谜题时。
试解不仅允许其他人给你有价值的反馈,而且证明了你的谜题是可解的。为MIT谜题寻宝写作的团队通常需要所有的谜题经过两轮成功的,独立的,未被剧透的试解。你应该非常小心,不要在你的寻宝活动中加入一个没有成功试解的谜题,这取决于有多少人参与试解,可能有一个很高的门槛。
如果你有许多谜题,谜题作者和试解员,那么试解过程是很难运行的。Puzzlord的一个最有用的特点是它允许试解员独立地找到一个未被剧透的谜题并且试解它。它也迫使试解员写他们努力的报告,并将它传递给作者和编辑。
对于你写的谜题,很难忍受去干涉正在进行的试解过程的诱惑。尽管如此,重要的是不要以任何方式进行干预,以复刻真正的解答者在你的寻宝活动中所处的条件。如果你一定要给一个提示,试着模仿你在寻宝活动中认同的提示提供过程。(比如你计划采用的是/否提示,那就允许试解者问你是/否问题)
你能够发布所有谜题写好的解答的时刻应当在寻宝活动结束之后。 因此,给你的谜题写解答是谜题成功试解后的第一步。
解答的主要目标人群是没有解开谜题的,因此在写作时有一些重要的注意事项。解答应当帮助别人理解解开谜题的路径,不让他们感到不解决它很糟。 起草解答时要注意你的语气:我们希望避免以任何方式屈尊俯就或贬低。
首先考虑解答者在解你的谜题时所走的路径。按照求解顺序写下的解答可以完成两件事:
(1)它们给那些做了但没做出谜题的人读起来更加合理。
(2)它们可以充当提示的资源——阅读解答直到你卡的那步,然后回到谜题。这不是必要的,但是有了更好。
举例来说,如果解答者一开始回答了线索,你应该把解答列在线索旁边。如果解答者一开始要填满纵横字谜的格子,那就加一张填满格子的图片[6]。如果解答者一开始要辨认图片,那就加入图片和它们的名字[7]。
在任何一个包含顿悟时刻的步骤中,加入解答者可能得到顿悟时刻的感受是很好的。可以参考[8]:
“根据风味文本(‘一年接一年’),或者回忆上一年寻宝活动的主题,我们注意到星星区域的背景看起来比去年的要暗一些。”
你不希望解答者看见一个解答然后思考“什么样的病人会让我做出这种联想?”。
确保你的解答包括了你谜题每一步的数据——包括中间步骤的所有答案,不留下任何隐含内容。如果有太多数据和一些会打断解答流畅程度的步骤,可以增加附录[9]。也可以先概述解答,然后再说细节,尤其是对于长谜题来说。
请记住,当你的谜题被后期处理(请参阅下一节)时,解答可能会被转换为HTML格式。然而,大多数人觉得在Google文档中迭代解答更为容易。所以不要花太多时间在你的Google文档表格格式上,因为它们被使用的时间不长。
许多寻宝活动在提及解答者的时候都是用“我们”(例如“我们首先注意到”)。对谜题作者(你自己!)的引用通常应限于末尾标题为“作者笔记”的部分,并以第一人称书写。
对于一些特定谜题类型的建议:
逻辑谜题:如果你的解答涉及逻辑谜题,你的解答应当包括一个从开始到结束的完整的逻辑推理路径。如果写出完整的解答太长,你可以考虑录制一个视频[10]。
纵横字谜:对于直接的线索,列一个线索和它们答案的表通常就足够了(也许可以加上一些比较模糊或是不直接的答案的链接)
加密线索和其它的文字游戏:线索应该被解构以解释文字游戏。例如[11]。
一旦一个谜题成功地符合你预期地被试解,下一步工作就是让它可以呈现在解答者面前,无论这意味着将其呈现为PDF还是转换为HTML。后期制作在Puzzletron上被列为事实核查之后的步骤,但是在后期制作之后做事实核查也是合理的,这样你可以在谜题渲染过程中找出问题。
在后期制作过程中要记住的最重要的一件事是确保谜题的呈现一致。用Dan Katz的话来说:
“这看起来可能没什么大不了的,但有点像Van Halen座驾中的棕色M&M……当一个有经验的解答者看到建造者没有花时间给谜题一个至少在最低程度上一致的外观,他(们)会立刻怀疑在其它地方有什么值得注意的细节。”
如果你在HTML网页上展示你的谜题,你应该确保它们在打印时看起来很好,尤其是那些用复印纸解答起来更方便的谜题。另一个生活质量(quality-of-life)的小变化是将HTML页面标题设置为谜题名称,这样解答者在你的网站上打开多个页面也能区分不同的谜题。
通常,你会想在你的谜题解答中包含一个数据表。手工用HTML编写这些内容可能很费力,因此你可能会发现[12]是一个将Google表格转换为HTML表格的有用资源。
如果你的谜题是动态的,你要确保解答者不会查看你网页上的源代码来规避一些步骤。考虑通过[13]传递脚本,在源码中加入红鲱鱼,或者只是明确要求解答者不要查看谜题本身的源代码。
这一过程旨在找出任何你和试解者都未能发现的错误,无论是琐碎的还是破坏谜题的。(这些可能包括在编写谜题时和预定的寻宝活动时之间出现的错误,因为世界的状态在变化,你的谜题中的线索变得不再准确!)事实核查应当由志愿者而非谜题作者完成。事实核查人员的责任是质问每一个假设并验证每一处步骤。事实核查者必须检查谜题和给出的答案,确保它们是完美匹配的。
其它有关谜题设计的资料:[14],[15],[16],[17]。
尽可能让你的答案是真实存在的英语单词或短语。众所周知的专有名词或外国短语也通常是好的,很长的短语也是好的,但随机的单词混合在一起(例如“VIBRATING BANANA”)就不那么好了,脸滚键盘(“JDIELDNSDFJKLSD”)是绝对禁止的。当选择主题答案时要注意:如果有元谜题或谜题结构的诸多限制,解答者通过向引擎查询主题答案,也许能够绕过大块的谜题。
有时你安排的答案可能达不到你想要提取的施加的约束。在这种情况下,你想要你的提取结果包含在线索词组(一种纵横字谜式的线索,能够得到你安排的答案)中。对于解答者来说,在解谜寻宝活动中很少有比卡在一个谜题的线索词组更糟的体验。因此,你应该思考很多来选择一个好的线索词组。在你花很多时间和努力创造谜题之前,先让编辑或是另一个人做一下你的线索词组,确保他们能够解开它。另外,如果你的谜题不包含加密线索,你的线索词组也不应该是一个加密线索。
如果你选择的线索词组在试解过程中很难解析,可以考虑提供一个谜题词组的长度。请参考[18]。
有一个广泛的谜题寻宝惯例是在你的谜题中,任何特定的步骤都不应该涉及对一串字母的无线索解码以产生一个单词或短语。(新手谜题作者总是违背这一原则,这在社区中已经成为一个笑话了。[19])
确切地说,有线索的变位词是完全合理的,你需要给出一些额外的方式来确认有正确的解读(例如加密线索的一半定义)。甚至通常较短单词的无线索变位词是允许的,只要它不是谜题的最终步骤。
作为一个粗糙的规则,有80%的谜题后通常可以来解决元谜题,并且反解谜题不应该超过这一轮谜题的30%。这应该反映在你的试解过程中:当你给试解者的答案时候随机略去一些meta中要用到的答案。如果他们卡住了并且需要提示,你能够给他们一些额外的答案。
几乎不可避免的是,尽管你进行了细致的试解和事实核查,但一些错误仍将存在于你的寻宝活动中。在寻宝活动中,解答者应该有方法来给你汇报这些错误(你定期监控的电子邮件地址往往效果最好)。当其中一个报告出现时,你的首要任务是核查错误是否真实存在!发布勘误感觉很糟,但是发布一个错误的勘误更糟。如果你相信报告是错误的,最好在不提供额外的信息下回复。我们发现“谜题在写下时是正确的”效果不错。
如果报告是正确的,你在回复报告中首先要承认错误,承诺你将尽可能修复错误。然后纠正错误并在网站的某处同时发布并正确描述。一个专门介绍“勘误表/更新”的页面就足够了。如果一个错误是严重的(在你的判断之下),你可能会通过一些其他的交流通道(通常是群发电子邮件)来警告解答者。
从你的答案中去掉非字母字符,并在检查之前将其转换为大写。
有些寻宝活动接受一个谜题的多个不同答案,但当解答者提交其他答案之一时,会为解答者提供一个“典范答案”用于元谜题。这通常被解谜寻宝社区视为不雅/不好的形式,但也有容忍模棱两可的线索短语的优势。其他一些寻宝活动有答案检查器,可以用信息来回应特定的错误答案,从“继续前进!”这样的确认信息到下一步的明确指示,这可能特别有用,尤其是对于缺乏经验的解谜者来说,但这也被许多人认为是不优雅的。最好的解决方案是确保你的谜题只有唯一的答案;有时,正确的方法是在谜题的末尾提供一个明确的答案长度或空格序列。
解谜寻宝队伍之间的技术水平有很大的差距。如果不依靠提示,一些参与你的寻宝活动的队伍很可能无法完赛。这里有几种不同的方式可以提供提示。操作上最简单的方法可能是“准备(预先写好的)提示”。预设提示的一个问题是,提示通常会帮助队伍解决已经解决的部分难题。为每个谜题生成多个预设提示并用其对应的谜题的大致阶段对其进行注释可能会很有用。
如果你有野心,你可以提供某种形式的动态提示,让队伍根据他们目前在谜题上的进展收到个性化提示。我们发现给队伍一个空的文本框很有帮助,他们可以用它来请求帮助、确认数据、提出特定问题,或者简单地发一个他们当前用的电子表格。
2015年MIT谜题寻宝活动推广的一个系统是是/否提示系统,在这个系统中,队伍可以就他们想要的谜题提出任何是/否的问题。这确保了每个有提示的队伍都能从中准确地接收到1位信息,同时允许陷入谜题不同部分的队伍接收到不同的信息。有些人还发现对谜题提出一个好的是/否问题是一种有趣的练习,在某种意义上这本身就是一个谜题。如果你真的要提出是/否的问题,不要太吝啬!1个是否问题往往帮助不大,但一系列有针对性的是/否问题通常会让队伍走出困境,而不会觉得你破坏了谜题的主要部分。
自2015年以来,是/否提示系统已经失宠,主要是因为最能利用它们的队伍往往是那些一开始就在寻宝活动中表现良好的队伍。不可避免的是,会有一些团队需要具体的帮助,你应该提供一些预设提示系统,让他们得到帮助。
参考[20]。
根据你的技术水平,你有很多选择来举办你的解谜寻宝活动。一方面,将你的寻宝活动发布为pdf文件,并让人们通过给你发电子邮件来检查猜测是完全合理的。这不能很好地扩展到大量的团队,但至少是简单的。
如果你愿意建立一个静态网站,你可以使用[21]或者一些等价的服务当作你的寻宝活动网站。这不会让你有任何解锁逻辑或速率限制答案提交,但它确实增加了一定程度的润色。你可以使用[22]的[23](或类似的东西),来让团队检查自己的答案,只需让队伍通过电子邮件向你发送最终谜题的答案。
然而,如果你想要团队帐户、自定义解锁或实时排行榜,你可能需要建立一个动态网站。[24]和[25]是两个开源应用程序,允许你运行自定义解谜寻宝活动。两者都是用Django编写的,并且都被用于多个在线寻宝活动中。
少数解谜寻宝活动采取的一条路线是在Discord举办。你可以使用角色为每个团队提供自己的个人频道,然后创建一个Discord机器人,控制答案提交和谜题解锁。如果你对Discord和机器人程序感到满意,并且你的团队不到100个人,这可能是一个合理的解决方案。
电子邮件是一个令人惊讶的棘手问题。区分两种不同的用例是很有用的。给每个人发电子邮件,给一个团队发电子邮件。
反直觉的是,给某个团队的每个成员发电子邮件可能更容易。[24]和[25]使用Django内置的电子邮件功能,将其连接到像Mailgun[26]这样的事务性电子邮件服务相对容易且便宜,并将您的网站配置为在团队注册或解决元谜题时发送电子邮件。
同时给所有参与者发电子邮件(比如说,如果你想宣布一个勘误或宣布一个获胜者)更为棘手。如果你尝试使用Mailgun这样的服务,你会发现许多像Gmail这样的客户会拒收你发送的大部分电子邮件,作为垃圾邮件的预防措施。甚至批量发送电子邮件也会给你带来麻烦。相反,你最好使用像Mailchimp[27]这样的专用电子邮件营销服务或[28]。但这两种都很贵(每月约30美元),但你能得到你所付的。
如果你使用的是像Mailchimp这样的自动电子邮件系统,请确保将回复地址设置为可以接收电子邮件的地址(比如Gmail帐户)。如果您手动发送大量电子邮件,请确保BCC参与者的电子邮件地址无误。
[1]Suggestions for Running a CTF. https://github.com/pwning/docs/blob/master/suggestions-for-running-a-ctf.markdown
[2]Puzzle Hunt Calendar. http://puzzlehuntcalendar.com/
[3]Puzzlord. https://github.com/galacticpuzzlehunt/puzzlord
[4]Puzzletron. https://github.com/mysteryhunt/puzzle-editing
[5]https://blog.vero.site/post/2021-hunt
[6]https://2019.galacticpuzzlehunt.com/solution/a-crossword.html
[7]https://2019.galacticpuzzlehunt.com/solution/cross-lines.html
[8]https://2019.galacticpuzzlehunt.com/solution/observatory.html
[9]https://2019.galacticpuzzlehunt.com/solution/ministry-of-word-searches.html
[10]https://perpendicular.institute/puzzle/the-greatest-jigsaw/solution/
[11]https://docs.google.com/document/d/1WecRZDhDC2x0iepjP3sjcccYWSc4kBJrjr2egvIPAMI/edit
[12]Table HTMLifier 3000. https://docs.google.com/spreadsheets/d/1eYyLOHWZfh574DPlfQWsWKl-xSlKo2T1DHuuHDf6BNE/edit#gid=0
[13]https://obfuscator.io
[14]Dwilson. http://web.mit.edu/dwilson/www/puzzles/puzzlewriting.html
[15]Foggy Brume. https://foggyb.livejournal.com/42978.html
[16]Foggy Brume. https://foggyb.livejournal.com/43107.html
[17]Foggy Brume. https://foggyb.livejournal.com/43360.html
[18]https://2018.galacticpuzzlehunt.com/puzzle/exceptional-expedition.html
[19]http://web.mit.edu/puzzle/www/2015/puzzle/a_puzzle_consisting_entirely_of_random_anagrams/
[20]A Puzzlehunt Tech Checklist. https://www.alexirpan.com/2020/03/16/puzzlehunt-tech.html
[21]Github Pages. https://pages.github.com/
[22]puzzlehunt.net. https://www.puzzlehunt.net
[23]Client-Side Answer Checker. https://www.puzzlehunt.net/checker
[24]gph-site. https://github.com/galacticpuzzlehunt/gph-site
[25]puzzlehunt_server. https://github.com/dlareau/puzzlehunt_server
[26]https://www.mailgun.com/
[27]Mailchimp. https://mailchimp.com
[28]Sendgrid. https://sendgrid.com/