2023年终总结

(头图为我用DALL-E为小虎设计的个人徽章)

我2023年的关键词只有一个:适应。

学习

5月,我开始读master,整体的难度不算很大。写了几年代码以后,对计算机的基础知识也不算陌生,相比一些零基础转码的同学要轻松一些。在学习上,经常在碰到某个此前不了解的知识点、和过往的工作经历产生一些联系。对于正常读计算机、然后成为程序员的人来说,顺序一般是先学习理论知识再用代码实践,而我的顺序相反。这种逆序学习带来的感受,非常奇妙。

举个例子,在学习操作系统的进程间同步时,涉及到进程的fork概念,期中还包含如何处理内存等等细节。以前我在创建新进程时,并不会考虑这些理论,只是把系统API当作语言本身的普通功能来使用。显然这种理解不足以支撑一个健壮的系统。我已熟稔这个功能,所以理解理论的时候反倒异常简单。

类似的情况时有发生,让我对学习计算机有了一点新的认识:先实践、后理论,是否是一个更好的学习方法?计算机本科大一大二的基础课,是否应该挪到大三大四以后再学?

带娃

小虎越来越壮,现在已经16个月了。我看到他圆胖的脸,就会想起他从母体中被剖出、继而大声哭闹的那一瞬间,居然已经是480天前的事情。

3月,我从Vancouver搬家到Richmond,来到了一个小区,我们全家很快和小区的娃爹娃妈们熟络起来,彼此经常聊天、帮忙、互相带娃等等。这个小社区的存在,让我们的生活温馨了很多,也方便了很多。缺了干活工具,直接去隔壁要;带娃时临时有事,就让邻居看一会;各个节日,几家人凑到一起吃饭;连我在外面车子无法启动时,都直接让邻居开车过来救援。有这一群邻居,千金难换。

邻居家中都有孩子,从0岁到5岁,彼此友爱非凡、关系亲密,我尤其喜欢对门家的两个女孩,漂亮可爱,她们也很喜欢小虎。孩子们来我家玩的时候,我喜欢给他们读书。看着几个小孩倚靠着我围坐一圈、认认真真的听我讲儿童绘本上的简单故事,老父亲的温暖情绪就像一缕香火,慢慢的环绕心脏。

再过2个月,小虎要去day care了,他会面对一些严峻的挑战。对我来说,也是一样。

开车

4月,买了一辆二手SUV,随后紧锣密鼓的持续学习汽车知识。如今从一个完全不会开车的新手司机,变得可以给汽车做各种保养、家中陆陆续续添置了若干工具,甚至时不时还可以帮朋友检查检查车况、换换油液等。回想起2023年4月那个买了车都需要让邻居帮忙把车开回家的小白,时间真的过的很快。

2024年,老婆也需要添置一辆刚需车,目前在研究 Nissan Leaf,这个廉价纯电车比较适合我的需求,无论价格还是功能都不错。缺点是电池容量较低,二手续航也就100公里出头。在 Facebook 的车主群里咨询了一番,Leaf车主们都觉得这车挺适合我的通勤需求。

新年里,买第二辆车,更多的实操整备车辆。期待自己的修车技术继续提高。

理解

年底,我带领学生们发动了一场对抗学校选课新政的活动,和系主任有很大冲突,被叫了保安赶出办公室等等。一直觉得有某些地方不对劲,但说不出来。前些天,趁着圣诞节和一个本地朋友 Jade 会面,聊了聊这些问题,询问了很多关于价值观的问题。

Jade 认为,应该 respect,应该 be humble,这是此地的基本规则。被允许在加拿大学习和生活,是主人对客人的邀请,客人不应该反过来教主人做事。这一点我深表赞同。

我的个人经历造就了身上的斗争精神,遇到事情的第一反应并不是「合作」「商讨」和「求助」,而是「对抗」「强硬」和「斗争」。在跟「造反团队」成员内部沟通的时候,我说「我的个人经历告诉我,让我幸存下来的从来都是强硬的对抗而非软弱妥协」,这个观点现在有了一些改观。毕竟加拿大不是中国,这里有新的社会规范,我源自中国的世界观,似乎还应该做更多的适变。

我的脑子里时常存在两种完全矛盾的想法,例如一方面会觉得对抗是争取利益的唯一途径,另一方面深深的厌恶持久的「斗争」、想和所有人友好相处;又例如我愿意从恐怖分子的角度去理解他们的思考逻辑甚至同情他们的处境,但坚决站在他们的对立面。

加拿大是个奇怪的国家。思来想去,想要理解这个国家,可能最好的方式是「冲突」,用摩擦来互相调和,最终和平共处。我不喜欢用「躲避」的方法来规避理念冲突,因为这本质上只是延迟了冲突、并没有达到互相理解的目的。以后,我和加拿大社会恐怕还会有更多的冲突,这就是我和这个社会彼此真正兼容和接纳之前的阵痛吧。

工作

圣诞节前夕,我开始投简历,目标是软件类 Intern,截至目前无一斩获。后面还要继续投,希望可以早点找到第一个落脚点,有一点收入。毕竟已经靠积蓄在加拿大呆了一年半,生活上捉襟见肘。

很多同学目前在做一些无门槛的工作,例如门店销售、仓库管理员等等。我不想用时间换钱,想把时间用来滚雪球。最近听朋友老婆的劝(我身边唯一一个零基础转码上岸微软的牛人),从Udemy上买了一个 Unreal 5 的课程,用零碎时间学习一下游戏开发。相比普通的软件公司,温哥华的游戏公司倒是不少,而且很多知名企业,例如 CDPR 和暴雪等等,掌握一些引擎开发技术,对找工作应该有些帮助。

朋友

除了天天见面的邻居,我的朋友主要是大陆老同学、桌游玩伴、刚登陆时帮过我忙的本地人、几个同学、隔壁装修请的工人等等。2023年新认识了不少人,大多数是中国人。2024年,我想更多接触不同族裔的人,了解大家各自的想法,让自己变得更加友善和柔软,收收身上的尖刺,花更多时间关心朋友。

2024

活着不容易,不出大事就很好。没什么新的期盼,只是希望生活越来越顺滑,家人健康,小虎在day care开心,我掌握更多的知识、有一个安稳工作。人到中年,想要的东西越来越实在了。

祝各位读者2024年一切顺心。

Tagged : / / / / /

抛弃「确定性」

普通人往往高估「确定性」的收益、又低估「确定性」带来的风险。

例如考公的人看到了后面三十年连续不断的几千元/月工资外加各项福利的稳定性,却忽视了自己的真实需求和沉没成本。考公的显著沉没成本之一,就是牺牲了自己未来所有可能性和应对风险的抵抗力。当风险来袭,你将没有任何应对能力。从去年开始的大范围、高强度的公务员降薪,已经实在的影响全国上千万体制内选手;而 90 年代的「国企工人下岗潮」带来的无数人间悲剧,就是「确定性」危害的一次大规模显现。

除了考公大军以外,因就业困难而去考研的兄弟姐妹们,更只是延后了处理风险的时间,不仅没有消弭风险,反而给自己注射了麻醉剂,使得下次面对风险更加弱势(年龄增长、对市场的敏锐度下降、学历成本带来的经济压力等)。一言以蔽之,还不如考公。

除了考公考研等传统项目,当代市场化职业中,“转码”也是一种“赛博考公”。你做了500道 Leetcode 算法题,便可以中人之姿跻身Google/Microsoft等一流大厂,获得稳定的高薪和社会地位,哪怕这几百道题对真实工作而言毫无意义,亦算是你进入大厂的「投名状」。其付出的时间、精力、沉没成本,虽足以让你获取更有价值、历久弥新的知识,却并无即刻的、现金化的收益。

更何况,在人工智能等技术的加持之下,传统工程师的职业寿命到底能否继续维持下去,这是一个尚无答案的问题。但是,此类职业风险的出现,意味着「大厂工程师」的收益期望被降低了。而这,仅仅是一个开始。

上述「确定性」的存在,为很多人提供了舒适的生活,但,是时候抛弃这些「确定性」了。

我的老读者都知道,我是一直是「不确定性」的拥趸。2015年以政治学本科+互联网运营总监背景裸辞自学编程,在2016年顺利成为初级后端开发工程师,这在当时是一种巨大的不确定性,后来却为我带来了巨大的好处:掌握了工程技能,深入理解计算机系统,也为多年后「润加」做了铺垫。

2019离职,此后两年间家里蹲写公众号。这可能是我风险最高的一段职业经历,因言获罪,得到了警察的「登门认证」,以及百度的「诉讼认证」。同时,我也习得了普通人终生难以获得的技能:大量的法律实践。在与百度长达半年的缠斗中,我学到了很多法律知识以及法律实践(在中国的司法体系中,对法条的理解和对司法的实践,几乎是各占50%的独立知识),也获得了「打官司」这个业余爱好。

2022年再次转职,回归职场,成为字节跳动高级工程师,很快与字节撕逼,凭借过去的自媒体经历和对法律的熟稔,全身而退,开开心心拿钱走人。至此,我清楚自己可能与国内任何一家大厂都水火不容,未来不会再为 BAT 之流贡献任何一行代码、任何一次管理实践。

去年以旅行签入境加拿大,一个月后莫名决定留下,接着在加拿大境内考雅思、申学校、申学签,从毫无准备到尘埃落定,每一步都充满风险,但每一步都带给我巨大的收益。

可以说,我生命中最宝贵的这些经验和收益,全部来自于「风险」。一来,我本人对于「确定性」的实际收益一直报以怀疑态度,二来作为一个风险偏好的个体,我对于「确定性」有一种来自 DNA 的排斥。

在「系统性风险」越来越鲜明的今天,不确定性,实际上是这个世界的主流;确定性,才是一种「例外」。我不觉得对于「确定性」的追求有什么道德劣势,但「追求确定性」这个行为本身最严重的问题,是其存在着手段与目的的二律背反:将身家性命寄托于「确定性」,这本身就是一种高风险行为,而这种会导致高风险的手段,恰恰与「追求确定性和安全性」的目标背道而驰。换言之,你明明想寻求安全,最终却将导向危险。这就是「确定性」最大的逻辑悖论。

既然如此,是时候抛弃「确定性」和「安全」,拥抱「不确定性」和「风险」,拥抱自己的本性。这样,每天都会收获意料之外的命运馈赠。剩下的,交给时间即可。

最近小虎7个多月大,学会了扶站,早于平均速度约2.5个月。我很好奇,为什么他学习的这么快?经过观察,一方面是因为他天生强壮,另一方面,就是他胆子大、敢冒险、不怕磕碰、屡败屡战。简单说,就是他对于“风险”有较高的偏好,对于安安稳稳的“确定性”(例如用躺、坐等安全姿势玩耍)则较为厌恶。反反复复的冒险,让他快速习得了很多实用技能,又进一步加速了学习速度、不断的自我强化。这是小虎示范给我的「不确定性」的优点,看来他未来恐怕也是一个风险偏好者。
Tagged : / / / / / /

成长,就是持续创造价值

我时不时会收到一些小朋友们的私信,问是否招实习生或者「程序员学徒」的,可以不要薪水。我一般回复「没有」,就不再多说什么了。并不是我高冷,而是觉得这样的小朋友恐怕并没有什么潜力值得去挖掘。
这么冷酷的结论,并不是拍脑门想出来的。经历了多次打脸,我最终明白一个道理——如果一个人把「廉价」甚至「不要工资」作为核心竞争力,那么他不仅对自己没有信心,其实也不会有任何主动性去发展自身。他们只期待一个武林高手从一招一式开始教起,像妈妈带娃一样照顾始终,而自己只需负责饭来张口即可,希望在人畜无害的气氛中,无能的成长起来。
显然这是做梦。即便这样一位「程序员学徒」不要工资,其他人为了培养他而投入的巨大精力和时间难道不值钱?武林高手有这个时间干点什么不好,不能去争一争武林至尊吗?为什么要把时间浪费在一个连学习知识技能都需要他人喂食的巨婴身上呢?这些幻想成为「程序员学徒」的小朋友明显算错了数,他们以为「不要工资」是自己的巨大优势,实际上这样的人带来的往往是负价值,对团队和项目都有巨大损害。
举一个我自己的例子。我曾经在一个水平相当低的工程师身上耗费了近半年时间,从 Google 搜索引擎和 stackoverflow 的用法,到代码规范,到 Python 各个标准库的用法,再到各类 Pythonic 代码的写法。之所以耗费这么大精力,是因为我是一个不错的老师,能把很多道理讲的深入浅出(例如我可以在 1 分钟时间里让任意一个无技术背景的人理解金融量化交易引擎的技术原理),经过我的细致培训,他一定有机会成为一个代码细腻而简洁的工程师。
直到被我劝退前,他都一直在用百度搜中文关键词并跳转到 CSDN 上看技术文。
这是什么概念呢?就是一个数学老师教了你半年的二项式展开,最终面对最简单的二项式题,你依然在掰手指数数。
这样的程序员带给同事的往往是噩梦。在他离职之后,我们依然时不时的从他代码中发现骇人的 bug,然而数据已经被污染,重新修正几乎不可能。由他引入的问题,很有可能直到公司破产都不会有人愿意去解决。这样巨大的负担,当年的我如果更成熟一点,是万万不会惹祸上身的。所以现在收到各类的「不要工资」的申请,心里都会默默的想,「你当我是傻子么」。
每个人都渴望成长,但成长不是商品,不是你用「不要工资」就能够换回来的。成长源于你一步一个脚印的学习,在学习过程中,你又创造出了价值。本质上,只有当你持续创造价值的时候,你才会成长;而不是反过来。
如果你技术不好、没公司要你,能否在力所能及的范围内,对开源社区做一点贡献?
如果你技术不好,能否仔细研究业务代码,试着花一个月甚至两个月的时间写一个简单但核心的模块?
如果你技术不好、又想找个老师,能否先帮这个老师做一点事情、哪怕只是帮他写单元测试?
……
可做的事情太多了,简直数都数不过来,而它们的共同点就是——持续创造价值,而不是持续索取关照。
所以,当我们对一件事情有了强烈的渴求时,最好先问问自己,能不能用已有的技能先创造一些价值出来。如果不能,说明你其实并没有那么渴求。那么,请不要再去骚扰那些工作量已经很饱和的工程师了,码农滞销,可怜可怜老乡们吧。

Tagged : / / /

技术部门团队管理的一点心得

最近半年公司一直在对整体业务后端数据存储做大修改,由我负责开发核心的数据存储、拉取组件,这个组件以 gRPC 为协议,完全重构了早先的 Java 业务,即将部署到公司线上产品以及机构产品。除了数据存储拉取以外,其他组件之间也统一使用 gRPC 协议,这种情况下,需要一个简单易用的 gRPC 接口测试框架对各个接口进行压力测试。
而此时,我刚开始管理公司的测试开发团队,团队的常规任务是完成开发团队的测试需求,但最重要的任务是为开发团队提供简单易用的测试工具。总的来说,更偏重于开发而非测试。因此近期测试开发团队的最重要任务就是搭建一个上述框架出来,保障即将上线的新产品顺利交付。
目前团队只有我和另一个新入职的测试工程师(正在招聘手工测试员一名)共二人,由于测试工程师并无开发经验,刚开始上手开发有一些障碍,因此对稍微复杂的开发任务表现出无力感。
在这种情况下,团队管理出现几个挑战:

1. 新入职员工对工作内容不熟悉、以及技术上有欠缺,无法独力完成项目
2. 团队人数较少时,人事关系容易出现扭曲,表现为团队负责人与成员过于亲密或过于疏远,这两种情况都会伤害团队未来的发展。
3. 新成立的部门往往被委以重任,甫一成立就会面对攻坚战类型的技术难题,而此时恰恰是作为新生儿的团队最脆弱的时候。

针对挑战一,我的解决方式是,结伴编程快速提升工程师的基础开发能力,并使之在短时间内熟悉公司的技术栈和代码规范。这段时间压力会很大,学习内容也会很多,但是要求并不能放松,需要管理者持续关注工程师的进度和心态,对成员烦躁、失落的情绪及时进行安慰和疏导,同时在某些环节进行必要的技术辅助。
针对挑战二,首先避免过分亲密的关系,保持普通的社交距离,同时也在处理「挑战一」的时候让对方感受到你的关心。张弛有度,会使双方关系有序的发展下去,也为团队的长远发展打下基础。
针对挑战三,要和部门的上级主管进行沟通,确定部门的目标方向,然后主动将目标按优先级一一列出,根据实际情况向上级索要资源(要么给人,要么给时间,要么降低任务量)。以我的经验,能够主动索要资源的团队,往往是资源最充沛、进度最快的团队;对于管理者来说,一个能够合理索要资源的下属,也大概率是一个有思考深度和执行力的团队成员。
在数年前做运营的时候,团队管理就是一个我很重视的问题,每个工种对人有不同的影响。例如运营部门的基础运营成员往往看不到职业发展的前景,进而转行到其他行业;一线工程师则埋头于技术,疏于梳理工作内容和工作前瞻。这样其实给团队管理提出了很大挑战:作为管理者,到底能在多大程度上纾解这些职业对成员的负面影响、并提高团队运行效率?
在前些天给 CTO 提交的一份测试开发团队工作计划书中,我提到了进行人才梯度建设。虽然测试开发团队人数不多,以后最多也不会超过5人,但是由于分工不同,必然产生事业层次的高低。在团队内部明确人才梯度,告知每个人未来的上升渠道,指明上升的途径,不仅成员会主动成长,人员流失率也会得到降低(软件测试行业的流失率非常高)。一旦形成稳定的循环,那么这个部门将能够实现「无人驾驶」,几乎自动化的在公司内部高效运转。这也是我未来的工作目标。


最近买了一款 CMON 出品的卡牌构筑类的塔防主题游戏《XenoShyft: Onslaughter》,感觉比领土好玩很多,无论美术或游戏机制都远远超过其先辈们。先贴几张图以飨读者,后面会写一篇文章,来介绍和评论一下这款游戏(前两张图是我拍的,图中还乱入了我的猫「三十」。最后一张游戏图是 Google 来的,仅供示范)。
WechatIMG55
WechatIMG56
Xenoshyft-Board

Tagged : / / / / / /

代码、桌游、结肠息肉

代码

和郭老师在泰国过完了2017年春节,回深后就很快完成了三个月的试用期,成为一名正式工。我的工作内容也从开发变成了测试,强度相对低了一些,让我松了一口气,不过也面临很多新知识的学习。这段时间,深入学习了 Selenium/PhantomJS 等前端测试工具,感觉前端测试比后端难不少,主要在于测试用例很不容易写完善,往往代码写好了但因为各种网络原因就是无法通过、然后自己再去处理网络超时、页面加载错误之类的问题,似乎前端的不稳定性远远超过后端,需要对各种情况进行处理。
除了学习 Selenium,还在朱老师的推荐下买了一本《单元测试的艺术》,不过这本书以 C# 作为讲解语言,看起来略吃力。同时买了早就想一睹为快的《Python绝技:运用Python成为顶级黑客》,这本书绝对不能带到公司去,不然一定会被同事笑话……

桌游

前段时间由于还没适应程序员的工作强度,完全没有时间玩桌游,现在闲暇时间多起来,已经可以有机会约朋友玩桌游了。原本以为自己对桌游的热情在入坑一年多以后会慢慢消退,没想到不减反增,还有了更大的热情去探索自己早先并不了解的桌游分类。
三周前,加入DM熊猫的SDE(Super Dungeon Explore超级地城探险)团,玩了一次纯模型主题桌游。说实话并不感冒,玩起来和 DND/Pathfinder 的战斗阶段毫无二致,而且自由度低很多,不知道乐趣何在。一下午也没有完结一场战斗,节奏慢的要命,让我对这种战斗为主的模型游戏很失望。手机摄像头坏掉了,拍的照片很渣,将就看一下。
DSC_0604_meitu_1
DSC_0603_meitu_3
看着就很无聊吧?那你的感觉和我一样诶!
不过还好我自己最近也买了一套模型游戏,就是大名鼎鼎的《约德尔战斗学院Mechs VS Minions》!目前在BGG上居然排到主题类桌游第6名!相对价格不菲的SDE,这套桌游的超大箱体、超多模型、5个预喷涂的精致手办(4个英雄+1个超大Boss)简直是在以赔本价的450元人民币销售,难怪 Dice Tower 的节目里3个主持人大约花了1/3的篇幅在感慨《约德尔战斗学院》有多超值……
超大箱体入境!
mmexport1488284721287
mmexport1488284756062
mmexport1488284795099
mmexport1488284813244
mmexport1488284816149
mmexport1488284823344
mmexport1488284829504
mmexport1488284832627
《约德尔战斗学院》是合作类桌游,玩家扮演4个约德尔人驾驶机甲在战斗中完成特定任务。
两周前,张老师、郭老师和我在家中完成了这套游戏的第一个任务(11个任务分别密封在11个牛皮纸信封中),三人需要顶着小兵的猛攻下将炸弹推送至维修站。游戏规则简单,容易上手,同时也非常欢乐。强烈推荐用游戏配件中的沙漏进行计时,会让游戏进程变得异常紧凑,从而产生意想不到的状况。我们三人经常在沙漏的催促下手忙脚乱的做决定,使机甲颠三倒四的乱跑,确实符合约德尔人的不靠谱性格。
mmexport1488641701615
mmexport1488641704824
游戏机制为行动编程,很新颖的机制。由于是 Riot 公司官方出品的 LOL 主题桌游,粉丝量之巨大毋庸置疑,这也可能是这款桌游能在发售后迅速攀登至如此高位的重要原因。不过遗憾的是,游戏设计师在 Reddit 的 boardgame 板块和大家交流的时候表示,这款桌游仅仅是 Riot 的玩票之作,不会成为公司的利润点,言下之意就是估计不会有续作或扩展了,让人非常伤心。
mmexport1488641712168
mmexport1488641721340
除了《约德尔战斗学院》,还买了向往已久的《银河卡车司机》。这是一款欢乐向的策略游戏,玩家在规定时间内拼凑出一家太空卡车,然后进入太空装载货物,期间还会遇到人贩子、陨石等危险,灾难过后飞船往往濒临解体。到达终点时,再根据载货价值和船体损伤,计算每个人的分数。
mmexport1489673558292
mmexport1489673547014
mmexport1489673525801
《银河卡车司机 Galaxy Trucker》有安卓版 App,强烈推荐下载试玩一下,很有趣的游戏!由于刚刚入手,还没有机会试玩,因此没有游戏现场图片,偷一张国外桌游店的照片做演示,见下图。
137832221538

结肠息肉

其实半个月来最大的事情,是做了一场小手术,切除结肠息肉。大约一年前,我右侧肋骨下方在吃完饭后经常会有隐痛,剧烈的时候需要用手抵住,同时最近几个月一直拉肚子。一直以为是胃或胆的问题,2016年12月份做了胃肠镜才知道,胃口没什么问题(其实也有慢性胃炎),关键是结肠里长了一个大息肉,需要手术切除。于是上周二做了手术并一直在医院休养,这周也无法出门,只能在家里上班。
手术后无法进食饮水,完全靠点滴葡萄糖提供能量。连续3天水米未进的我居然并没有饥渴感,大为惊奇。术后4天才能进食流食,同时持续葡萄糖注射。从周一入院到周日出院,一直是郭老师悉心照顾并陪床,我的精神状态很好,反倒是郭老师在几天操劳下迅速憔悴了很多,令人心疼。出院后我俩都大舒一口气。
在家工作的日子也不轻松,除了需要按时坐到电脑前写代码、第一时间对同事的需求做出反馈外,还要时刻对抗自己的懒惰。所以说实话,这一周的工作效率还蛮低的,难怪大家还是要去办公室上班的,程序员可能更是如此。
算了算,手术后至今10天,居然瘦了10斤,主要原因是医嘱提到的饮食规范:不可吃粗纤维的蔬菜和肉,只能吃烂面条、粥等物。我本人的精力在这几天一直很充沛,可见目前的饮食也是可以提供充分的能量,减肥所谓『三分练七分吃』诚不余欺也!希望把这个减肥势头保持下去,不要浪费了这段强制控制饮食的经历。

其他

除了上述的几件事,还有其他一些功课压在我心头。例如一篇关于断网后如何利用互联网的稿件,我已经拖欠了约一个多月,每每动笔都会犯懒,不知为什么。
在泰国清迈期间一口气看了 Neil Gaiman 的《American Gods》前几章后,至今也没再看几页,也颇为焦急,希望自己早点看完。
几本积灰的技术书都还没看几页,总没有一个学习计划去填充自己的知识空白。
一直想写的微信群助手迄今没动笔,只是下载了几个库试着发了几条消息而已。
『编程随想』维护的 Resilio Sync 文件夹(就是那个翻墙软件大合集)里面的翻墙软件版本已经很老旧,我一直想搞一个能及时更新的新同步文件夹出来,也拖了好久。
要做的事情太多了,而我最想做的为什么永远只是玩……

Tagged : / / / / /

万用骰子脚本(跑团专用)

几个月前,我写过一个专门用来玩卡坦岛的命令行骰子工具,里面的骰子函数都是写死的,只能选2d6/2d10/3d4这几个,够用,但是不方便,适用性太差。最近入了《Pathfinder基础包》,准备重新开始跑团,看几个跑团QQ群里都有骰子机器人(方便大家开网团的时候投骰子),他们输入『.r 3d6』『.r 4d10』甚至『.r 1d97』这种实际中并不存在的骰子都可以得到值,自由度非常高。
于是我计划用Python来实现这种高自由度的骰子。首先遇到的问题就是如何让程序识别『3d6』『1d4』『1d8』这种跑团黑话。先普及一下,d4/d6/d8/d10/d20等都指骰子的面数,例如d4指的是四面骰,d20则指二十面骰,1d4指扔1个四面骰,2d6则指扔两个六面骰。普通游戏一般用不到这么多种类的骰子,而在以大量数值检定为核心的TRPG(桌面角色扮演游戏)中,这些骰子就不可或缺了。
首先想到的方法是用正则表达式来解析命令。以最常用的『1d6』为例,『1』指骰子个数,『6』是骰子类型(面数),『d』则是分割二者的分隔符。用正则表达式来写的话,应该是这样:

roll = input('> ')
match = re.search(r'(\d+)([Dd])(\d+)', roll)

先让用户输入命令,然后开始解析命令。命令的结构是『数字』+『D或d』+『数字』,正则表达式如上图。最早的版本里,是 r'(\d)([Dd])(\d)’ ,两个数字位都没『+』,后来发现第二个数字位必须带『+』(因为骰子类型有可能是两位数甚至三位数,例如1d20,1d100),于是我干脆把两个数字位都变成可以无限位取值的。
到此,解析命令完成。下一个问题发生在定义函数时的全局变量上。早期版本如下:

result = 0
def d(n):
    result = randint(1, n)

函数外部出现了变量 result,函数内部又给 result 赋值,电脑就懵圈了。在这里,我一直没搞懂的问题是,定义函数时的返回值,并不是返回给某个变量,而是对应了这个函数本身。result = 0 这个变量的初始化也可以删掉。在朱老师的指导下,终于搞明白这个问题,于是代码顺利改成这样:

def d(n):
    return randint(1, n)

最后,做好一个 for 循环来实现反复扔骰子的动作即可:

for i in range(m):
    result = d(n)
    dice.append(result)
    print(result)
print('和为: ', sum(dice))

至此,其实还没有写完,脚本还有很多地方需要完善,但是已经不再是当初那个被朱老师批评的『到处给全局变量赋值的超级烂代码』了。日拱一卒,余欣慰也。
Github地址
欢迎各位去围观我写的其他小脚本,帮我改改这些超级烂代码!

Tagged : / /