« April 2008 | Main | June 2008 »

May 31, 2008

3d 引擎中对场景数据的接口设计

目前是我第一次设计 3d engine ,虽然主要贡献 3d 方面代码的同事不是第一次做了。我们做了两年多,大方向上是我在把握设计。但是毕竟是没有什么经验,也就老在修改。

这个周末再审以前做的东西,觉得接口上还需要调整一下。比如精灵的控制接口、摄象机的控制接口、场景描述的接口等等。以一个游戏开发人员的角度来看,我需要接口是什么样子的?

我希望是最方便的描述虚拟世界中各样东西的相互关系,引擎当隐藏住不必要的细节,比如 3d 方面的数学知识,专业化的术语,复杂的坐标转换等等。今天写下这些,不是定论,而是做些思考的记录。

我想知道,对于 3d 引擎的使用人员,如何描述虚拟场景,暴露出怎样的接口是比较合适的。

对于我们的游戏,和大多数游戏,角色在场景中的坐标是二维而不是三维的。就好象描述你在地球上的位置,大体上经纬度就够了,只有在需要更在很复杂的场景中(比如一栋高楼中),再加上一个离地面的高度。

这里,我们取的都是离地面的高度,而不是相对地心的。所以你站在南极比站在赤道上离地面更近,或是站在拉萨的街道上比站在上海的商场里离地心更远,都是不需要考虑的事情。

高度这个维度,远不需要经纬度的精度高。在一些需要得到高度信息的位置,比如我们在高层建筑里,只需要说自己在第几层。而在小河边,则只需要了解在桥上还是桥下。因为大多数情况下, 人必须脚踏实地。

最终,我需要 3d engine 加载完场景数据后,使用它时,只需要设置经纬度,就可以把一个物件放置在那里了。默认情况下,物体总是紧贴地面的。如果需要让物体悬浮在空中,我们只需要外加一个高度属性,这个属性的值描述了物体相当当前经纬坐标上的地表的高度值。

当同一个经纬坐标上,有多层地表怎么办?解决方法是分层表示。地面可分成多个层面。举个例子,有一条河,两岸之间架了一座桥。这样一个场景当被分成三个层面。

两岸及河床是第一层,水面是第二层,桥面是第三层。

当河水干涸的时候,水面一层消失,退化成两层。(通常在建模的时,岸边和河床就是一体的,水是额外做上去的)

人从岸边上桥,就从一个层跨越到了更高的层,这个跨越线,可以额外标注出来。

同样,从岸边下水,也是一个跨层的过程,同时触发游泳的事件。从水面下潜,也有类似的过程。

根据逻辑需要,引擎还应该提供层与层之间的高度换算。比如桥面的高度相当于从水面计算的高度值。

那么空中的物体如何计算?方法是,提供一个零层,这个层面一定是在欧式几何空间中保持水平的。(当然如果想做一个球面的游戏,这个层面也可以是球形的)浮在空中的物体可以依据这个来换算坐标。

我们还需要引擎提供同一层面上每个经纬坐标点上的法向量值,或是两个不同点之间相对零层面的高度差(这个值可以通过上面的方法换算得到)。这个用途之一是为了处理四足动物的摆放。

不是每个层面的任意坐标点上都有有效的法向量的,比如一座桥,桥面以外的空间在它那个层面上都是无效的。如果命令物体移动到无效的位置上,我们可以知道该物体会发生坠落,掉到下个层面上。或是简单的阻止这样干。所以这个信息还可以用于描述阻挡物。


大多数情况下,我们并不需要精确的描述物体的坐标。正如我们在现实生活中,除非手持 GPS 设备,否则很少用经纬度来汇报自己的方位。我们只需要知道什么在什么的附近就够了。所以确定位置通常是编辑器做的事情,而游戏逻辑只用知道物体在哪个地点。

坐标值通常只用在描述和计算物体运动的过程里面。存在于比较低阶层次的接口上。

尽量脱离坐标值本身,我们也不必太在意坐标是二维量,还是一个三维量;物体在空间中的状态,是用一个向量表示、还是一个矩阵,或是四元数等等。我们也就隐藏了引擎是 3d 还是 2d 或是所谓 2.5D 这些细节了。

最后的目标就是,用图象引擎提供的接口来描述物体和物体之间的关系,而不是单个物体在空间中的绝对位置。应该抽象出哪些接口供开发者使用,还需要再斟酌一下。

May 25, 2008

会抽到自己的那张吗?

周末和一个朋友聊天,说是要去阿里巴巴报道了。听说阿里巴巴的入职培训中有个有趣的游戏。所有学员都要在一张纸条上写下自己的一个短期愿望,投进纸箱中。然后大家各抽一张。抽到别人的愿望后,要想办法帮那个人实现愿望,且不能告诉对方是你抽到了他的愿望。

我突然想,如果抽到自己的愿望怎么办?:D

抽到自己的写的那张的概率是 1/n (n 为人数),这个概率和你先抽后抽无关。当人数很多时,概率自然是很小的,但是整个集体中,至少有一个人抽到自己那张的概率看起来却不小。到底是多少呢?我饶有兴趣的算了一下。

简化一下题目,其实就是把 1-n 个自然数,排成一个数列里,至少有一个数字 i 刚好排到第 i 个位置的概率。

n 个数字的全排列有 n! 种,我们只需要计算出,没有一个数字排在它所在次序位置的排列数。

先定义一个函数 f(n) ,表示把 n-1 个数字排到 n 个位置上,每个数字都不在自己位置上的排列数。

可知 f(2)=1 (把 1 排在两个位置上 , X 1) f(3)=3 (把 1 2 排在三个位置上, X 1 2 ,2 1 X ,2 X 1) ...

再定义一个函数 g(n) ,表示把 n 个数字,排到 n 个位置上,每个数字都不在自己位置的排列数。

可知 g(n+1) = n * f(n) ,这么理解, g(3)=g(1+2) 也就是排 3 个数字时,先把 2 或 3 排到第一个位置。剩下的两个数字中,1 一定不会在自己位置了。另一个数字排到 2 个空位不在自己位置的排列数就是 f(2)

又可以推导出: f(n+1) = g (n) + n * f(n)

这样理解: f(n+1) 可以分成两种情况,一种是空出那个多余的位置,剩下 n 个数字都不在自己位置的排列数即 g(n) ;另一种情况是,从 n 个数字里挑出一个放在多余的位置上,剩下 n-1 个数字去排 n 个空位,这种情况总数为 n 倍的 f(n) 。

两式联立得到 g(n+1) = n * ( g(n-1) + g (n) )

这样,我们就得到了一个递推式。由于已知 g(3) = 2 * f(2) = 2 ;g(4) = 3 * f(3) = 9 ,所以写个程序很容易求出后续数值。

然后来算概率,n 个数时,概率 h(n) = g(n)/n! 。

我用程序计算了前 100 项,发现从第 8 项开始,概率就几乎不变了,稳定在 0.3679 左右。这引起了我的好奇心,然后重新用笔来推导上面的公式。

h(n+1) * (n+1)! = n * ( h(n-1) * (n-1)! + h(n) * n! )

可以得到

和 ( h(n+1) - h (n) ) *(n+1) = h(n-1) - h (n)

我们可以看到, h(n) 这个数列,相邻两项的差是 1/2! , -1/3! , +1/4! ....

因为我们已知,h(2) = g(2) / 2! = 1/2 , h(3) = g(3) / 3! = 1/3

可以得到 h(n) = 1 -1 + 1/2! - 1/3! + 1/4! - 1/5! .... 1/n!

这看起来是什么?哈,正好是 1/e 的麦克劳林展开式 :D 所以 h(n) 当 n 增大时,它会收敛到 1/e = 0.367879 。且收敛速度极快 :D


结论:当 n 较大(n>5) 时,没有一个人抽到自己那张纸条的概率是 1/e = 36.8% 左右。还句话说,至少有一个人抽到自己写的那个愿望的可能性有 63.2% 左右,这种事情还是很容易发生的,无论人多还是人少。这个概率随 n 变化的量很小。

哈,怎么又绕到欧拉数 e上面去了,数学还真是神奇啊。

May 23, 2008

关于 openGL 的 4444 贴图

我们在实现游戏界面时,用了一张 RGBA 4444 的贴图做 buffer 。最近同事测试效率时总不满意,发现上载 4444 贴图时,openGL 表现出来的性能实在是太差。(显卡为 ATI X300 ,最新版驱动)

几个人一开始怀疑是显卡或驱动程序的缺陷,进而想换总做法,不用软件渲染界面的方案。改把界面元素全部放到显存里。前几年,我为天下二设计界面的模块时,也有同事有此疑惑,编写代码做过比较。记得当时的结论是:仅仅从性能角度上考虑,把界面所用资源全部放到显存里,并不能提高太多速度(反而可能性能更低)。当时用的 Direct3D 做底层,似乎没有今天遇到的问题。

后来又经过测试,如果这张贴图换成 RGBA 8888 时,速度可以提高几倍。我们揣测可能是因为现代显卡对不常用的 16bit RGBA4444 贴图模式放弃了(软件或硬件)支持的缘故。原本希望采用 16bit 贴图节省一半的显存传输带宽,没想到适得其反。

一度,我们考虑了更换界面的美术制作标准,换为 RGBA8888 的格式。甚至讨论设计了一种采用 DXT 压缩算法压缩的图片内存数据格式。

不过我有点不死心,多试了几次。后来发现,居然把 GL_UNSIGNED_SHORT_4_4_4_4 换成 GL_UNSIGNED_SHORT_4_4_4_4_REV 速度就明显提高了 :D 比 8888 的模式要快许多。

想来是 ATI 的 openGL 驱动没有写好。上载贴图时,一旦和硬件支持的色彩模式不符,用了一种极其低效的方式做像素格式转换。

btw, 测试了另几块不同的显卡,有的显卡(比如一些较新的 N 卡上,GL_UNSIGNED_SHORT_4_4_4_4_REV`GL_UNSIGNED_SHORT_4_4_4_4 几乎没有区别。

May 22, 2008

防止中间人攻击

去年,几个游戏组的同事给我描述了他们发现的针对游戏的中间人攻击(MITM attack)。有人做了一个代理服务,种植木马到用户机器上,使用户机器对游戏服务器的 tcp 连接都重定向到代理服务上。(这个步骤其实不一定在用户机器上做,网关和路由器上都理论上存在被做手脚的可能,这是用户自身无法保证的。

代理服务可以一直监听用户到服务器的通讯,直到认为认证过程结束,不再转发用户的数据,改由自己操作用户的帐号。这样就可以达到转移用户虚拟财产的目的。

今天,和几个同事讨论了这个问题和解决方案。

之前,游戏部门的同事已经做出很多改进,增强了通讯协议的安全。但仔细分析后,我发现还是有些漏洞,想总结一下,找到个更安全的方案。

先列出一个简化版的协议,后面再讨论其中的问题:

  1. client 产生一个随机数,用 client 和 server 共知的秘密(在这里是用户密码和将军令产生的 OTP 一次性密码),加密个随机数,发还给 server 。为了保证 server 能认可这个结果,还需要附加一个校验值 checksum 共同编码。

  2. server 解出一个随机数,校验完毕后,以此为通讯密钥,建立一个加密信道,和 client 保持通讯。

在这里,由于中间人不知道 client 和 server 公有的秘密,而这个秘密又没有在通讯中传递,所以它只能充当转发人的角色,而不能监听和伪造双方中的任一方。


这里存在的问题:

网易的将军令产品(以及市面上的类似产品)能产生的 OTP 长度有限,是 6 位 10 进制数字,大约是 20bit 左右。如果把安全寄托在 OTP 上,强度太低。

因为协议中的握手过程,大家需要相互认可,这个认可标准是不受保护的。唯一可以利用的是事先约定的秘密。中间人完全可以截获握手过程的一切通讯,然后离线暴力尝试,以这个握手成功的标准去找出 OTP。当 OTP 的强度只有 20bit 时,在很短的时间就可以试出来。而 OTP 的有效期可以长达一分钟,是很难理论上杜绝这种暴力攻击的。

我的建议:

第一,可以使用 RSA 这样的算法,把共有的秘密转移到 RSA 的 key pair 中。这样就有了 128bit 甚至更高的强度。RSA 的 public key 可以有更多的方案发放到 client 中,所以理论上可行。问题仅在于 RSA 等不对称加密算法运算量太大,仅靠软件实现时,有可能服务器承担不起。

第二,我们降低 checksum 的长度,不超过 8bit 。这样,不只合法的 OTP 会满足这个 checksum ,还会有大量的 fake OTP 也满足 checksum 。中间人在穷举的时候会拿到大量 fake OTP 。按 OTP 一共 20bit 计算,大约有 2^12 约四千种可能。由于 OTP 有一分钟的生命期,只需要限制在这一分钟内允许尝试的次数(比如说 4 次),那么,单次握手,被试出的可能性就只有千分之一了。在此基础上需要进一步限制同一 ip 对任意帐号的尝试频率。可以提高安全性。


有道 的周枫在我们讨论的时候找到了一份 ppt ,其中 16 到 19 页讨论了类似的问题( Page 16: How to set up a strong, shared key, given only a short OTP ),可供参考。

May 20, 2008

那些日子(终)

由于《仙履奇缘》这个名字已经被人使用过,公司决定给新产品换个更响亮一点的名称。内部征集了很多意见,大家决定使用《梦幻西游》。

《梦幻西游》这个项目比《大话西游二》更为稳健,策划有相当长的时间做调整。我依稀记得早期徐波在论坛上和玩家们的争执。哪些门派应该增强一些,哪些应该削弱一点。被逼急了,他也放过话,“谁说各个门派需要做成平衡的了?”。

游戏的各种玩法也是一样。徐波自己的角色慢慢练了上去,建立了服务器上第一个帮派。还不想让人知道帮主就是他,怕被人怀疑是作弊练出来的。我想设计人员能有机会耐心的把自己的游戏玩上一年,以一个普通玩家的身份去玩,各种细节自然就照顾的到了。大部分策划不是不想这么干,而是没有机会。有多少项目有如此长的测试期,在稳定的环境下,拥有这样多的玩家一同游戏呢。

梦幻的美术部分也算是精益求精了。虽然有同行对他评价不算太高,但我觉得大家是尽了很多心力的。

到后来,丁磊请了一个从中国美院退休的老教授来给美术人员上课,为美术质量把关。第一堂课我也去旁听了,讲的一些概论性质的东西。我以前没学过专业的美术,听起来自然是收益非浅。后来经常看见晚上会议室有在上课,原画稿也被更严格的审核。

程序方面更不用多说,前面已经讲的很多了。我和郭老搭档的非常愉快,基本上他不会提什么非常要求,因为他在提需求时已经仔细考虑过了。然后,我把需求都一一实现。大家也时常探讨一下接口的设计,不为眼前的问题做草率的决定。后期,为大话二写界面逻辑的许扬调过来做梦幻的界面逻辑。这次 C++ 到 python 的接口比大话二时设计的对 lua 的接口要漂亮一些,工作进行很顺利。

郭老自己也玩梦幻,做起来更来劲一些。后来,帮派地图,玩家家中的家具摆设这些玩法实现都花了很多心思去做。在梦幻运营之后,我们还更换过一次通讯加密的方案。研究了很久,只是觉得新方案更 Cool 一点,然后两个人很努力的干了几个月。

起初有一个外挂花了很长时间研究(我们在 client 中下了些套子,一些不正常操作会被记录下来备案),最终发布了出来正式版本,打算准备收费。就在第二天,我们就更新了几乎全部的相关代码(其实之前已经做了很久了,时间上完全是巧合),狠狠的挫伤了为梦幻做外挂的人的信心。


03 年底,梦幻公测之前,我就脱离梦幻的一线开发了。这一年,随着网易股价的疯长,在福布斯中国富豪榜上,丁磊被排在了首位。他信心高涨,一心想把公司发展壮大。

年底,我们还是按往年的那样,从网上和广州本地的学校里选了几份简历,打算做个简单的招聘活动。突然 dingdang 被老丁的邮件批评了一顿。他说,郭斌打算新成立一个研发 P2P 产品的部门,都填了二十人以上的人员预算,你们若大一个游戏部怎么才要这么几个人?不行,得多招人。人才最宝贵,不能让别的公司抢了去。

dingdang 急匆匆的制定新的招聘计划,我隐隐有些担忧。这种担忧 dingdang 也有,人员扩张太快,会不会消化不良?但是在一片大好形势下,老板的殷切希望中,我们开始了新的招聘之旅。全国各大城市间做宣讲会,收集简历,做笔试面试。

记得那几天,每天都有成箱的简历运到公司,几乎所有程序员晚上都在看简历。我们八九个人围在会议室中,每个人分到半箱,一份份的读。把简历分为好中差三类。最好的一堆要求比较严格,按一个高标准,只要一个人认可就可以归去那类;差的一类底线非常的低,也是一个人认可就可以扔掉。中间类别的堆的最高。全部梳理完毕,接下来再如法重新轮换一圈,换人翻阅,从中选出较好的出来。

此时,ruiheng 已经被大家公推升认技术部总监,而因 micro 已经正式离开公司,dingdang 从原来的技术部总监升为游戏部总监。我和 ruiheng 两人一组开始奔波于全国各地做巡回招聘,同时还有别的组别分头去各地,有时我们也汇合在某一个大学较多的大城市。有丁老板的指示,游戏部的技术人员几乎全员出动了。相比前一年 02 年的招聘工作,完全不是一个阵势。

头一次没有什么经验,也没想过委托专业的招聘公司协办。记得 03 年底我和 ruiheng 第一站去浙江大学最为狼狈。事先完全没有和校方联系,就是网上的 bbs 上发了个消息。直到我们进了校园才跑过去找毕分办的老师借教室,名片还正巧用完,ruiheng 拿着身份证去登记的 (._.!) 。然后我一个个的给学生打电话,通知他们来笔试加面试。笔试题都是在飞机上现出的。广州很热,杭州很冷。我就穿了件衬衣,在小雨中的校园里冻了个半死。好在之前简历挑的很细,来面试的同学许多成了日后的同事。不过这次得罪了浙大的老师,等我们回到广州后,怪罪我们不跟他们事先联系就去招聘学生。为了陪罪,一个月后,大家又组织人马去浙大做了次规模盛大的宣讲会。

接下来有些经验和准备了,事前都让公司和学校打好招呼,然后再过去先搞个宣讲活动。那些天那个累啊,每到一个学校先讲上一个多小时。然后发下头天编好的题目,开始笔试。晚上回酒店开始批改卷子,找到答卷中的亮点,并比对收来的简历研究。

因为丁的要求是多招人,我们的要求放的较低,这就更不好挑人(否则直接找出出类拔萃的就够了)。往往选出一大堆,第二天开始面试。面试从早上排到夜晚,基本上是没时间吃中饭的。为了保证质量,每场面试都是一对一做 40 分钟左右。全部面试结束后,还要出下一份笔试题(一份题目一直用下去显然是不合适的)。 所以晚上只能睡上五六个小时。

有些学生过来做完面试,一兴奋就拉上他的同学。通常这样的拉过来的人都不错,而我们又有多多益善的指示在先,加班加点是常有的事。记得那年在重庆站,就因为面试排的太多,我一个人改签机票多留了一天。

这样高负荷工作,也找出不少优秀的人才。甚至一些是从别的公司口中抢出来的。现在大话三的 client 主程祥子,当时在成都读书。本来他已经拿了金山的 offer ,被同学介绍到我们面试现场看看。然后就让我“连蒙带骗”硬是说到网易来了。当时他说,他对破解很有兴趣,我就给他介绍 ida pro ,说怎么做效率比较高,如何分析别人游戏资源中的图片格式。还讨论他刚做的一些东西的细节,告诉他我的办公室电脑里还有自己写的很多好玩的程序。聊到兴奋处,祥子就决定把金山毒霸组给他的 offer 拒掉。我没有问他那份 offer 的薪水数值,只承诺了一个不高的数字。他说,不比那份高。

那一年,我们能许诺的待遇不高(以后几年也是如此),只能靠跟学生聊聊技术。让优秀的人觉得来我们这里工作会很有趣。曾经有几个学生,他们刚考完人工智能的考试,就来参加我们的面试。我就和他们聊刚刚考过的试题,说出我的解法,列举这些知识以后能怎样运用。让大家觉得,学到的东西是有用的,以后的工作中,还会有更多人一起来探讨这些。我始终觉得,这是吸纳人才最有效的方法。

等招聘活动结束,我想自己也闲着没事,就搭了一个 maillist ,给每个签了 offer 的学生发 email 联系。一是想促进交流,避免再被别的公司挖走,二是想进一步了解每个人的实际水平,为日后进入公司组织工作做计划。

当时做这件事很来劲,给大家出了题目布置下去做,列出书目供大家读。为每个人批改作业,写邮件交流。我觉得为团队培养新鲜血液,是促进整体发展的重中之重。

03 04 05 做了三年的招聘工作,感触很深。也面试了太多人。现在想想,在公司里和许多程序员关系很好,也来源于此呢。到 04 年许多新同事到公司报道,头几个月都是一到周末就领着大家到处玩耍吃喝,一个月吃饭买单的开销都是五六千,挺快活。

ruiheng 提议在在公司里多组织技术交流和专题课程,我想我准备的最多。前后做了五六个,有些课程还做了两次。

HR 的工作真是非常重要,也需要有心去做好的人去做。看到后来 google 进入中国,李开复亲自组织 HR 工作,我是由衷的理解。


《梦幻西游》在招聘的间隙公测,那是 2003 年 12 月中的事情。之前的内测反应相当的好,公测后在线人数也是节节上升。不少游戏制作圈子的老朋友都跟我说,梦幻西游挺好玩的。而以往,这些人都是单机游戏的玩家,对网络游戏不屑一顾。我想我们这次成功了。

丁显然也是充满信心。有上次顶住玩家漫骂,把大话西游二从三毛提价到四毛的成功收费经验;这次他想把价格定在五毛一小时。在正式收费前,大家都没太多意见。毕竟没什么好说的,大话二有前车之鉴。反对的话也是找骂。

但是在 2004 年 1 月正式收费那天,游戏的同时在线人数瞬间从 10 万以上跌到了 3 万以下。丁丁和徐波都坐不住了。我能理解他们的心情,测试期间的繁华到收费后的冷清,落差太大。

他们想降价。那天晚上我在公司,跟他们争论了很久。我是不主张立刻降价的,虽然一开始不赞成把价格定的过高。但既然定下来了,也不是坏事,我们不应该在第一天就否定掉这个决定。如果图一时之块把价格又降下来,可能日后会损失一大笔长期的收入。dingdang 也是急促不安,他给步步高的阿段打了电话,征询意见。最后犹豫了一天,终于拍板说降。

这是个没有答案的争论,至今我还坚持我当时的观点。而没过几天,梦幻就宣布调低了收费标准

以我今天的观点,当时更应该做的是延长免费公测期,并同时开放点卡交易系统(收费后,点卡交易系统并没有立刻移植到梦幻中)。让游戏内的经济尽快达到一个平衡,然后再依原计划标准收费。在时间收费是唯一收费模式的游戏中,辅以点卡交易系统后,玩家群体的消费能力是由群体的支付能力决定的,而不是个体。如今的许多道具收费游戏,平均每个玩家的消费水平都要略高于梦幻。但梦幻却只有一个手段扩大收入——增加玩家群,而很难提高个体的平均消费水平。

当然这是一家之言了,也说不定因为坚持五毛一小时的收费标准,梦幻就从此一蹶不振,谁又能说的清呢。

无论怎样,《梦幻西游》一路凯歌走到了今天,成为了中国第一大 MMORPG 。你说它颓势尽显也好,无聊之极也罢。它的最高同时在线人数还是在前不久又创下了新记录:200 万人。不能否认,这是款成功的产品。

我为自己在那些日子,为之贡献了代码,贡献了想法,贡献了力量而骄傲。


尾声:

故事远没有结束,但我想应该停笔了。

泡泡游戏的故事、大唐的故事、飞飞的故事、大话三的故事、天下二的故事…… 千百人经历过,正在经历。我想如果有缘,会有人接下去讲述。

网易互动娱乐 从 04 年开始极速壮大,不再是一个小小的团队。方方面面,我们多了更多的观察角度。每个人的眼睛里都看到了不同的东西。如果你也身在其中,也许你会喜欢上这些人,也许你突生反感,也许你因为和这样一些人一起工作而兴奋,也许你有许多无奈。

但每个人都应该想着:只要自己努力,明天会更好,不是吗?


附一张 04 年和同事一起负重爬山,登顶扎营前的留影 :D 那天一起爬山的同事好几个已不在网易了。但大家仍是朋友。


谢绝转载

那些日子(目录)

May 19, 2008

那些日子(二十)

2003 年 3 月,网易最大的一家风险投资商,新闻集团,套现。短时间内,公司的股价从 15 块以上跌到了 11 块。我想公司那个时候是有许多人感到不安的,毕竟咬在嘴的肉一下子少了一块,多少有些不舒服。接下来的股票执行窗口(按美国法律,公司员工买卖自己公司的股票,必须在限定的时间段内进行,这个时间段被简称为交易窗口),许多人抛掉了自己手上的股票。但游戏部门的人对将来都充满信心。

这段时间,公司又为员工颁发了奖励性质的期权。我拿的比前一年少,dingdang 也是。而游戏部的人多了许多,每个人都有。我还记得那天,CEO Ted 亲自颁发的文件。他头发花白,看起来比实际年纪大许多。人很和善。读到我的名字,当我上去领文件时,特地与我握了下手。当时说了些什么不太记得了,但是他给我传递的那种感觉,影响非常深刻。这是我第一次见他,也是最后一次。

Ted 人缘很好,是慢慢感觉到的。第二年跟 Michael Tong 去美国出差时,有机会拜访了几位跟网易有些渊源的朋友。见面后,大家一定会很关切的询问 Ted 的身体情况。聊起来都会说,Ted 真是个不错的人啊。

05 年底收到丁发给我的 Ted 手术失败的消息时,我正从岩道上下来休整,一下子感慨万千。多好的一个人走了,活着的人更应该保重身体。上海一个同事曾给我转述了他听来的故事,据说是北京办公室的同事讲的。Ted 走的那一晚,他在北京空着的那间办公室的天花板上的消防水龙头突发故障,喷出的水洒了一屋。周一大家得到了噩耗,纷纷说那是 Ted 放心不下,又回来看看了。


五月间,非典袭来。最早是深圳的同学给我发短信,说是他们那的醋被抢购一空,让我赶紧备一点。接下来几天,广州满大街的酸味。我是从头到尾没觉得多大个事儿,每天照样去健身房锻炼,到公司上班。我能理解人们的恐慌,但不知为啥,无论别人怎么渲染,我就是觉得没啥。倒是健身房和公司里的消毒水味道有点不好受。最严重那几天,公司的同事都在家办公了。我家里没有计算机,所以依旧泡在公司里。

这个事件对运营的游戏的影响说不太清,有好有坏吧。大话正处于加速上升期,而在此同时短信方面的业务量在萎缩。游戏部门相对独立,大部分时间,部门以外的人甚至别的部门的高管都不清楚游戏的情况。不然,到 03 年年底的时候,也不会有无线部的头儿违反规定,私自抛售公司股票,最终被美国证监会抓个正着了。

我在 03 年年中的时候,卖过一点点公司的股票,换到一些美圆。很好奇的炒了几个月外汇。读了许多技术分析的书,颇有些心得。大约玩了半年,起起落落,最终赚了百分之二三十,相比同期许多赔了的人,已经是很好的成绩了。但终究觉得无论是外汇还是股票,都只能当玩具玩玩。

炒这些东西,从中找到些许规律,并尽量做出准确的趋势估计,固然可以满足自己的成就感。但那实在是太浪费时间和精力了。人不能把美好的青春浪费在这么点成就感上。

不过一直以来,我还是乐于帮同事做分析,许多人也信任我的判断。只是每每说到自己公司的股票,我只有一句话,要相信自己的公司,自己做的事业。因为自己公司的股价,是股市上唯一能靠自己把握的东西了。

今天,ntes 几经沉浮,再次升到 24~25 美圆(曾经一拆四,相当于以前的 100 美圆左右)。我很庆幸我坚持的理念,把自己大半的积蓄都投资在上面(19 美金,大家都纷纷套现时还继续跟进过,当然是在窗口交易的),它给了我莫大的回报。


03 年的下半年,我们确认要购买一个成熟的引擎制作 3d 项目(不久被定名为天下二)。dingdang 最终选择了 bigworld ,价格不菲。再此之前,我们也和很多游戏公司谈过。曾考虑过无冬之夜的引擎,甚至还联系过暴雪,希望他们把魔兽三的引擎授权给我们开发,结果当然是被拒绝。

bigworld 几乎是最后唯一的选择。dingdang 看中的是他们宣称的网络模块的优秀性能。这是一种动态负载均衡的技术。

bigworld 和别的网络游戏不同,它并不是把地图切分成一个个独立部分分担到独立的进程中去管理。这样比较来讲,bigworld 是以人群而不是以地图区域来分担负载的。举个例子,如果有一大堆人拥挤在一起,那么他们就由一台服务器为它们服务。当这个人群群体向一个方向移动时,那么为他们服务的服务器也会跟着在虚拟场景中移动。只到有人从里面分流出来,在资源允许的情况下,分流出来的人会进入一个新的服务器。

听起来很神奇,bigworld 理论上可以支撑无限大(其实还是有限的,只是比常规做法大几个数量级)的游戏世界。世界间的每个区域都是无缝连接的。因为服务器本就不是按区域划分的,那就谈不到缝了。

我们拿到了部分代码,服务器真正核心的那部分(负载均衡)他们不愿意卖给我们,只是提供了二进制文件。dingdang 读过入手的一些程序,据说代码质量很高。反复衡量后,决定购买这套引擎。我说,其实没有什么东西是绝对神秘的,让我试试,可能可以还原被隐去的代码。

如果允许我接触已经购买的代码,需要签下一份保密协议。这样,我就签了,和许多正式转入 3d 组的程序员一起签的。kyo 也在那时脱离了大话二的开发,进入这个小组。

bigworld 的服务器是用 C++ 编写的,跑在 linux 上。当时只支持 red hat ,而我们公司用较多的是 freebsd 。部分源码缺失,使得移植很困难。我拿到 C++ 的头文件和那些 .o 文件后,发现做个简单的逆向工程,甚至可以把大部分缺失的代码还原出来。隐藏的源码的那部分其实和开放源码的部分耦合度很高,设计上根本不应该拆分开。它们中间有着千丝万缕的联系。部分内部数据结构虽然表面看不到,但是到后来我基本都推测出来了。

由于 bigworld 大量用了多重继承,早期分析还是挺麻烦的。读这些汇编,让我对 C++ 编译器生成出来的复杂的数据结构有了几分认识。几个月后,对于各种形式的 C++ 程序最终编译出来的汇编形式,以及对象的内存布局,我几乎都能立刻在脑海里做出条件反射般的印象了。对着这些汇编码,新写下的 C++ 程序重新编译后,可以做到和无源码的 .o 文件,逐字节一致。

这个工作其实只做了一半,后来公司花了极大价钱买下了全部的代码。只是那个时候我已退出天下组,没有权限去看那些东西了。

从 bigworld 的源代码中我倒没学到什么新鲜东西。那段时间只是把逆向工程当成一件有挑战的趣事在做。做的过于细节,反而无法高屋建瓴的来看 bigworld 的整体设计。额外的收益就是实践了一把 C++ 的对象模型,我想当时的公司里不会有比我对 C++ 语言 更熟悉的人了。


年底,由 dingdang 带队,kyo 我还有老王三个程序,月猫和陈由金两个美术,六个人出发去悉尼接受 bigworld 开发公司给我们做的短期培训,学习 bigworld 的用法。

此行让我感触比较深的是老外程序员的敬业。他们工作很正规,一天八小时都在那写程序,如果没有特别的事情,不会像我们那样在办公室里穿来串去。下了班就准时回家,上班就工作。可以说,一个工作日就是一个,不象我们公司,程序员们相对懒散,除了短期的兴奋期,每天集中精力能写程序的时间远不到八小时。想来这也不是网易一家如此,我见过的许多国内公司都有此问题。所以在澳洲看到的情景给我不小触动。

另外他们的电脑,大多数人都装的 linux ,运行 windows 的机器上没有任何盗版软件。一个个把画笔和记事本用的相当娴熟,因为只有这些是不用额外掏钱买的。

回到 bigworld 的话题上,我学到并欣赏的一点是:他们嵌入的 python ,使用起来非常方便。client 和 server 之间完全屏蔽了网络这个东西。server 的各个进程之间也感觉不到跨进程通讯的存在。这应该算是一个设计非常良好的引擎了。给予了我后来几年独立开发的东西许多灵感。只是隐藏了太多细节,也出现了很多局限性。从我的感觉上,引擎是为特定游戏类型去设计的(或许他们最早想做一个 MMOFPS?),离我们心目中 MMORPG 的需求有一些距离。

后来的发展也的确是这样。可以说,03 年到今天(08 年),网易和 bigworld 公司是一种相互依存的关系。我们用他们的引擎,提出各种意见,找到设计问题和 bug ,反馈给他们修改,一步步的把 bigworld 打造成更适合现代 MMORPG 的游戏引擎。kyo 后来担任天下二的技术主管,坚定着不自己开发服务器的分支版本,一切问题交给澳洲处理的方针。虽然开发过程往往有点憋火,但也保持了最终版本的唯一。最近几天在看《人月神话》,里面提到设计概念一致的重要性,这就是一个佐证。

如果让我主观的评价一下网易购买 bigworld 的意义,我想说,我们其实是花钱雇佣了一支海外军团,帮我们干活呢。


在澳洲,别人公司的办公室里,我跟 dingdang 吵过一架。可能让老外看去有点莫名其妙了。

我说,花了这么多钱,购买这么贵一个游戏引擎,我们就应该在游戏设计上有所突破。既然 bigworld 的技术优势就在于更大的世界,更多的人互动。我们为何不为之实现一个不一样的游戏出来,突出这些特点。而不仅仅是重复已有的网游游戏模式,只是把我们已经做到的 2d 游戏 3d 化。如果不做这些,让我们自己开发一个 3d engine 就够用了,不过半年的时间,我有信心搞定。

大概就是这样的观点吧,具体也记不清了。不知为什么,我们的分歧越来越大。最后,我坐在桌子上一言不发。过了好久,dingdang 心情也平静了些,主动过来向我道歉,为他的态度道歉。这是我们第一次,也是最后一次争吵。其实我能理解他,一如既往。

回广州的一年后,类似的问题我和叶航也争过一次。慢慢我就明白,永远不要对别人的项目指手画脚,当局者未必迷,旁观者未必清。有什么事情自己有想法的话,最好的办法是自己去做。


在我们一队人去澳洲上飞机的那一天,还有一个有趣的小插曲。当天公司的中层人员都被安排去参加一个管理培训。虽然我手下没有一个兵,可也被安排去了。

估计是丁磊故意的,dingdang 我 还有张金等五个人被分到一个组。培训课上做了一个小游戏颇有意思,培训结束后,我们还热烈讨论。真的是可以看出每个人的性格来了。有兴趣的同学可以找人做上一次。

游戏是这样的,五个人被发了五张纸。游戏开始后,大家阅读手上的纸,并努力完成游戏。这个游戏需要五个人合作,但不许语言交流。信息沟通只能靠传字条。便签纸是可以无限取用的,但是每个小组只指定了一个人可以向任何一个人传字条,而其他人只允许向他传。

我们这一组,这个关键人是张金。游戏一开始她就收到了大量的字条,忙个不停。

我拿到的纸上什么字都没有,只画了五个奇怪的符号。我觉得其他人也应该是如此,我们借助张金传递着信息,想弄清楚别人手上都画了些什么。大家都在猜测这个游戏到底想让我们做什么。很快我们就达成了一项约定,在字条上写上 to XXX, from XXX ,让张金负责转发。比如我想问 dingdang 点什么,就写上 to dingdang from 云风。

一开始我在字条上写了好多,写了我看到的图案,还有我的猜测。写了很多字,比如,假设游戏需要我们找出所有的图案,我们应该怎么办;假设游戏需要我们找出一个特别的图案应该怎么办,假设游戏需要找到某个人手上一个特别的图案应该怎么办……

而旁边 kyo 的组没多久就完成了游戏,相继还有许多组。我们这里还一筹莫展。

我是颇为着急,写了个字条给张金,让她把所有手上的条子全部给我。因为我看她在那里一边分析着手上的情报,一边帮其他人传递,实在忙不过来了。dingdang 也在那边沉思,不断的找张金要新的条子。我想这么下去也不是办法,索性一个人来做算了。

当我对比了所有人的字条,艰难的从杂乱无章的各种信息中判断游戏的真实意图时,我发现每个人的图案都有一些共同点。如果这是有一道智力题,那么就应该是找出大家公有的部分了。但是老师不理会我的结果,直到 dingdang 最后也做出了判定,才结束了游戏。


游戏的谜底原来是这样的,dingdang 那张纸上除了五个图案外,还有详细的文字解说。明明白白的写着,找到五个人手中共有的一个符号。

老师向我们解释,其实这个游戏中每个角色都是有象征意义的。拿到 dingdang 那张纸的象征着老板,他知道目标;负责中转的人,张金那个角色,相当于管理人员,她负责跟员工沟通;剩下的三个人,就是公司的员工,他们负责实现目标。

在游戏中,dingdang 始终没有想到,别人其实都不知道游戏要干什么,他以为大家手上均有文字说明。认为只要通过张金,最后总能有一个人完成游戏。而我当时所想,就是大家和我一样,都只看到一堆莫名其妙的图案,我们的目的是猜测游戏目的。

kyo 那个组之所以完成的快,和 kyo 的第一张字条分不开。kyo 明确的写道,我不知道我要做什么,我的纸上只画了这些……。并且他不厌其烦的把这段话 copy 了 4 份,转发给每个人。当“老板”得到这个消息后,再向“管理人员”要求把所有信息转到他那里,很顺利的就找出了答案。

真是可笑,我们这一组,做如此要求的人却是什么都不知道的我。

这个游戏教会了我,让一个团队有一个明确的目标是多么的重要。由于信息不对等,每个人看到的东西都不一样,想的也不一样。我们在团队合作时,沟通胜过一切。说出你之所想你所知,了解他人之所想所知,道理很简单,做起来很难。


谢绝转载

那些日子(目录)

May 18, 2008

那些日子(十九)

不计算周边工具,我一共为《梦幻西游》贡献了引擎部分(包括图象、声音、网络和 UI 以及对象管理)三万多行 C++ 代码。这是今天用工具统计出来的数字。这些全部是在大话西游二完成后,从零开始写的,几经增删留到今天的部分。

对于梦幻的 client ,郭老的代码贡献量更大。除了保留修整少量我从大话二遗留下来的底层部分外,他写了个 python 的接口部分,和所有的游戏逻辑部分的 C++ 支持。再次设计,我们做的比以前好。代码很精简,而完成的功能要多的多。依稀记得总共 C++ 代码不会超过五万行吧(手头没有数据可供统计)。而对应的大话二的 client 代码量则是图象及声音的引擎部分二万七千行,逻辑和网络及 UI 部分三万一千行。

我想,合理的构架下,代码的体积应该是更为精巧,而不要过于膨胀。代码写的短小,是自然而然的结果,其成因是避免了重复。代码行数多少,则不是刻意去追求的。对于网游 client (也包括 server ),都不应是超过 10 万行 C++ 的规模。从程序角度上说,网络游戏是个小项目,不是吗?如果有人硬把一个小项目做成了大项目,不出问题才怪。

郭老是个很勤奋的人,非常主动的完善程序。当时他改进了地图文件的格式,重写了地图数据生成工具。对于已完成可以正常工作的东西不满足,自己去改进。这样的程序员对项目非常难得。

这种在这种追求完美的心态下的产物,几乎不可能从工程管理角度上去保证有人做。这也是我后来作为项目管理人员也一定要自己参于写代码的原因之一。对于一个项目,如果我们只从完成功能角度去验收,充其量只能达到合格,远谈不上优秀。何况是一些很难度量的质量、细节方面,做到怎样的程度可达到多少收益,这中间的关系没有人说的清楚。

想把游戏项目塞进一个流水线中,拧上闹钟,到时间了来收割。绝对是一个笑话,只存在于投资人的梦想中。

梦幻里的很多画面细节,并非专职策划人员写进文档、提出需求,然后交给程序员实现出来的。那些日子,郭老玩了许多网游,他自己就是个《魔力宝贝》的玩家。看到别人游戏中有趣的亮点,就想办法实现。同时也想一些有趣的东西加进去。我也乐于配合。

到梦幻发行时,许多老朋友表示游戏挺好玩,有些单机游戏的感觉。这中间,大家对细节的把握甚关重要。既然是互动游戏,我们就应该和提交电子表单区分开,游戏玩的是过程,而不是结果。


我想梦幻这个项目,大家都很努力,并不因项目没有指定确切的结束日期而松懈。记得那个夏天的一个周末,有 QC 部门的同事报告了一个 bug ,会引起 client 崩溃。但是 bug 如何发生的,毫无规律可寻。只是玩了几个甚至十几个小时后,程序异常退出而已,没有任何方法可以重现错误。发生的概率也非常之低,几天才碰到一次。出错之后,查看调用栈,发生问题处的代码逻辑一切正常,引起问题的是一个对象里的数值不太正确。而这类对象在内存中有上千个同类,每次出错点都不太相同。

有过程序调试经验的同学当知道,这种 bug 是极其难追查的。你无法通过出错现场判断 bug 成因,无法设置断点来侦察早期的内存异常状态。通常只能靠阅读代码来分析那些部分写的有问题。当出错现场周围的代码正确时,程序员面临的可能是通读所有相关代码。

如果没有一切 bug 都是可以追查出成因的信念,我想对于这种出现概率相当低又束手无策的问题,对于很多急迫的项目都会暂时搁置。而郭老和我都认为,不查到原因,就一定不能把程序做下去。bug 就像心里的疙瘩,解不开,干什么事都不舒服。

记得那几天,我们从周四找到周六,一直没有进展。周日上午,我在健身房推杠铃,突然手机响了,郭老兴奋的说采集到一个录象,在启动 client 开始半小时后就程序崩溃了。前面谈过录象文件对 bug 追踪的帮助。之前面对这个问题时,录象都是长达几个小时的。我们为重现一次现场就等上几十分钟,那样效率实在太低。当采集到这个只有半小时的录象时,意义非常重大。立刻打车回来公司,我们两人就在空空的办公室中,调试这个问题。

事后的发现让我们解开了心结。真正导致问题发生的时刻比引起内存错乱的程序崩溃点提前了几分钟。是由于 python 和 C++ 的接口处,一次增减引用的次序写反了。这使得在某一瞬间,python 引用了一个刚好被释放的 C++ 对象。通常,引用随即被解开。但在一种巧合下,中间一块内存的指针有可能被传递到别处重新引用起来。这种错误的引用关系保持了很久,在后继的一系列临时对象销毁过程中暴露出来。

这是我职业生涯中,最难调试的一个 bug ,印象极为深刻。以后再少有对已知 bug 三天内还解决不了的了。


除了忙梦幻的事情,还有大话方面的一些工作。

03 年 2 月的时候,我跟 dingdang 聊天,说能不能在大话二中试着加一些卡片类小游戏。可能我受 console game 的影响比较深,许多 console game 都在主体游戏之外,还做一些分支游戏(比如最终幻想 X 中的水球)。这些分支游戏并非零碎的硬凑到里面的小游戏,而是也有它们的线路。

我的建议是在大话中增加一种卡片收集对战类的游戏。但是大话二的策划组不太愿意整体的来考虑这件事情。他们担心工作量太大,并且不能预知对游戏整体系统的影响,这种心情是可以体谅的。后来我拉着叶航一起来做大话牌,考虑到重新设计规则需要投入太多精力,便直接搬来了最终幻想八中的卡片游戏规则。这个对于程序很好实现,而我的想法是想在大话中试验多条游戏线路,具体这第二线路的玩法就不太在意了。

事实证明,独立于游戏主体规则之外的第二游戏玩法是不能成功的,玩家不买帐。这也算是一次宝贵的经验吧。事后想,若是把奖励和主体规则挂钩会好一些。这件事让我明白了,网游和从前单机游戏不同,玩家有很深的成果导向,对游戏性本身的注重远不如单机游戏那么多。

倒是为这个大话牌制作的美术资源没有浪费,这也是我们立项开始做前就想好的退路。我们为之设计了变身卡的玩法,可以充分利用外包美术制作的卡片图案。整个大话牌的制作,全程都有叶航的参与,他编写了所有的文档。不知道这件事对日后设计天下二的元魂珠变成有多大影响。

这段故事中间有个小插曲。在做卡片调落和集换规则时,我想尝试做一些新的东西,不以调落概率来控制卡片的稀有度,而做一个中心服务来统一发放卡片。kyo 对这种做法非常的反对。他认为,一切程序都是不可靠的,我们应该绝对避免中心式的数据服务,因为一旦中心式的服务出现问题,所有游戏系统中的玩家都会受到影响。按照这个思路,在服务器中出现唯一(或有限)资源就是应该回避的设计。他希望系统能保证:每个玩家的私有数据,都不跟其他人发生交互。(这种交互应该从广义上理解,比如有样虚拟道具在服务器中需要严格存在 10 件,那么你能不能拥有这件道具,以及获得这件道具的概率,就跟还有哪些人已经拥有了发生了关系,这也是一种交互)。也就是说,服务器程序应该对任何一个玩家的服务都是独立的。

而我站在了他的对立面,按我的想法,网络游戏的发展趋势应该是交互。这可以提供游戏更多的游戏性。稳定性第一、游戏性第二固然正确,但是死守着稳定性,而不尝试在游戏性方面做一些技术突破是不行的。这个问题和 kyo 争论了很久,最终的结果是我自己实现了代码,并在数据可靠性方面做了额外的保护(为此专门写了一个双份交互备份的简易数据库防止系统以外掉电引起的数据残缺,以此用来保证卡片发放的正确)。

让程序员做自己不认可的工作是很难做好的,很多情况下,自己来实现是无奈之举。这也是为什么许多不懂程序的策划难以把游戏做好的原因。因为最终的实现还是在程序员手上,同样的工作,做的好和差,质量相差巨大。有些设计,看起来很美好,但是很可能因为实现质量不够,好事也变成了坏事。作为游戏策划,当然希望做实现的程序员可以懂点游戏,这样写程序的时候更容易达到预期的目标;但程序员太懂游戏了,不免有自己的想法,我们又很难让他们心甘情愿的去按自己的思路做。

另一个是做大话兵器谱,同样是一次失败的尝试。也是想试着在玩家间建立联系,而不是按从前通常的做法:采取简单的积分制。由于策划们的担心,这个系统没有和游戏中的实际利益挂钩,是一个完全独立的系统。刚开始我觉得无所谓,只是先看看这个排名积分系统是否能正常工作。后来才发现,脱离整个游戏的任何独立系统,都是不受玩家欢迎的。

于之可以做比较的是几年之后的 wow 中的荣誉系统,同样是设计一套规则,用来计算玩家间的胜负关系。我们可以设想一下,如果荣誉系统不给玩家荣誉整备这样的奖励,这个系统还有多大的存在意义。

最终,我意识到,其实游戏的策划设计跟程序一样,一个项目永远只能有一个主导人。无论游戏项目如何分工合作,在任一方面,都只需也只能有一个人把握。从此我不再干预公司其它游戏的开发。


03 年,我的生活远比今天丰富多彩。

在我和叶航的倡议下,公司组织员工进修日语。dingdang 专门找了个外语学院的学生来办公室给我们上课,一周两晚。我们的政策是只要考试一次过关,公司免去学费,并额外颁发 1000 元奖金;如果补考不及格,则要交纳双倍学费。平时不准无故旷课。

仿佛又回到了学校。甚至比读大学时更卖力,大学里,我可从来没有哪门课有那样高的出勤率。考试前还连夜复习。到后来真是苦不堪言呐 :D 。第一期结业后,就没再继续。不过收获也挺大,至少打日文游戏时,不至于两眼一抹黑只会认里面几个汉字了。

到了夏天时,我莫名其妙的爱上了自行车运动。怂恿 dingdang 一起去装了两部车。他没我玩的那么起劲。经过半年的锻炼,我的身体状态非常不错,腿部肌肉也挺有力。每个周末都出门骑行,平均时速 30 公里以上,每次都是 100 公里左右。把珠三角逛了个遍。每次都是一个人中午出去,然后到天黑了才回来。

沿途乡村里的人都挺热情,还好奇的问这是为啥。我知道自己看起来就是自找折腾。啥事不干,背着地图,挂上指南针,骑个车几十公里出去,立刻折返。速度还挺快,不作停留,不为欣赏风景。在出城前的那一段,还要忍受一路的汽车尾气。

路上觉得孤独的时候,就放声的唱歌,不着调儿的老歌,感觉很好。每次爬坡的时候都特别累,但我发现,每当爬上坡顶,接下来就是非常惬意的下坡。老天绝对不亏待你,有上就一定有下,有下那么一定接着一段上。

八月,我和 dingdang 约定骑车去一趟珠海,他刚参加工作时干过一次,认识路。我们周六早上九点出发,我来负责背行李,走省道过去。那次是我骑行生涯中最有挑战的一次。太阳很大,晒的人很不舒服。广州到珠海的路很不好走,许多地方满是碎石子。一路好多拱桥,上上下下累的半死。后半程路上刮起了风,一路都是顶风前进的,只能勉强维持 15 公里的时速。路上被铁钉扎破了胎,掉了两次链子,走错一次路,多跑了十几公里。中间有个大下坡时,拿着水壶喝水,一仰头,帽子被吹掉了。下意识的单手去捏刹车,不小心摔了一跤。中午弄的胃口全无,在路边的小餐馆里,就只觉得那两条生黄瓜特别好吃。

到珠海已经是晚上八点。帮我们预先定了酒店房间的赵青一个劲的打电话问怎么还没有到。珠海海滨的情侣路,骑在上面才觉得怎么如此漫长。到达酒店时已是晚上九点,马表上显示超过 150 公里了。

夜里吃完饭去金山的办公室见了雷军,随便聊了几句就回去睡觉了。

第二天我们骑到码头,乘船到了深圳蛇口。从深圳回来的路程也是 150 公里左右,但是路面非常的好。虽然头一天消耗的不少体力,但是轻松了许多。深刻感受到珠江两岸的经济发展差异。

这次魔鬼之旅,我身上晒脱了一层皮,半个月以后长出新的来,痒痒的。可能是因为脱水和劳累的缘故,体重一周内掉下去 15 斤,到 04 年都没完全补回来。后来就没再做长途骑行了,也打消了从广州骑车回武汉的念头。

路上我跟 dingdang 聊了许多,聊我们的项目,我们的公司,我们公司里的人。也谈这个行业,说说听来的一些八卦。诸如盛大是怎么起来的,为什么当年中华网撤资后,陈天桥还有钱去买传奇之类。

这次以后,dingdang 少有时间出去了。接下来几年,我经常组织同事在周末出去活动。但每次叫他,他都很忙。起初我不太理解,认为工作和生活可以分开,周末出去放松一下不会有什么影响;后来跟 dingdang 的妻子在网上聊天,可以感觉到一些他的心理状况,慢慢的理解了。

如今,我自己带了一个团队,更加感同身受。当承担了太多人的责任时,更多的是心累。脑子里自然无法分心做完全属于自己的事情。


附一张 03 年底在家用 pda 自拍的照片,怀念我那两年的骑行时光。


谢绝转载

那些日子(目录)

May 17, 2008

那些日子(十八)

大话二收费以后,因为我脱离了这个项目的开发组,也就没什么记忆了。不过也时常关心一下,记得十月刚回公司时,在游戏里的聊天频道中,经常有玩家哭述自己被骗。他们用游戏币和人交换点卡,却总有单方面失信的事情发生。

我们曾想过在玩家条款中加入禁止游戏虚拟物品和虚拟货币与现实货币交易的条款,正如暴雪今天在 wow 中做的那样。有一种直觉告诉我们,游戏牵扯进金钱交易,游戏本身会受到冲击,不是什么好事。

直觉不总是正确的。固然,我们可以利用程序规则限制虚拟物品的转移,但那也会极大的破坏游戏性。有如美国当年的禁酒令最终执行不下去一样,禁止不了的事情,不如提供更大的便利去疏通。开发团队决定给系统增加一个公正的点卡交易系统。

这个系统,在 02 年 10 月底一台服务器上试运行 。不久就在全部服务器推广开。我很赞同这个系统,但技术上没出什么力。讨论过程中,我只强调了一点,一定要在交易过程中征税,这个意见被顺利采纳了。

点卡交易系统一开始并不起眼,没人会想到它能起到多大价值。只是几个程序员看见玩家的需求,临时拍脑袋加上的。设计实现时也完全没考虑它会促进游戏的收益。开始时,有玩家传言,某些玩家寄售的点卡是由系统变出钱来凭空买下的。这种事情从未发生过,如果真的这么做了,其实也很容易被玩家发觉。其实,经过仔细考虑,我们也觉得没有必要这样去做。

玩家在这个系统的辅助下,游戏内的经济系统达到一个更为稳定的平衡状态。实际上促进了游戏的发展。金融工具可以促进经济的发展,点卡交易系统,就是一种在现实社会中不可能存在的金融工具,但对于网络游戏中的虚拟社会,则是非常有益的补充。

ps, 几年之后,我重新研究了这个问题。写过一篇 blog

慢慢的我也明白了,网络游戏和从前单机游戏之不同。网络游戏更为注重人和人之间的交流,更多的是在模拟一个社会。而社会的稳定和平衡是一个动态的过程,并非一开始设计好规则,就可以保证的。人的行为没有固定的模式,尤其是对比现实社会少的多的人群,规律更不确定。没有游戏规则是普适的。对规则的不断修改,增删,调整,就是一个动态调节的过程。后来我们的许多产品,包括许多同行发行的产品,没能经历这样一段调整期,也是最终没能成功的因素之一。


由于没有项目开发的压力,我的注意力主要放在了学习研究各种有趣的东西上。因为对 C++ 的热爱,那些日子大部分的精力都是围绕这方面。比如 boost ,阅读它的源码是主要的工作之一。

一开始看的是 boost.thread ,因为之前的多线程程序的复杂度印象太深刻了。我相信 C++ 可以带来一些方法来回避其复杂度。设计良好的线程库非常值得参考。当时和泡泡组黄晓东的后继者李鑫也有讨论,他们在项目中尝试用过 boost.thread 。我询问过他的意见,他说他们发现这个东西还不太稳定,有一些 bug 。现在无法确定当时泡泡那个版本遇到的问题是否真的有 boost.thread 的问题。但是,C++ 模板库不好调试,已经深深的影响了实际的开发。

从我们那个 C++ 邮件列表 02 年 10 月的信笺存档中,可以找到当时大家关心的许多话题。当时我还去看了 boost.python ,它是 boost 中不多见的几个需要编译才能使用的部件之一。为什么不是 boost.ruby 而是 boost.python ,引起了我的好奇心。看起来 C++ 社区对 python 真的是特别有爱啊。这引起我对 python 语言的关注。

boost.python 挺有趣,不仅仅是它做到的事情,也包括它怎样做到这些。比如它给指针分类,让 python 可以正确的处理 C++ 的对象生命期,用以避免 dangling pointer 。

boost.python 相当活跃,就在我把玩它的那几天,就经过一次翻天覆地的变动,把接口全改了。

那几天,孟岩曾在北京采访过 C++ 之父 Stroustrup 。回来在 C++ 邮件列表里投了一帖。其中也提到 python :

“他(Stroustrup)说 Python 很有趣,不过说 Python 是 C++ 的最佳搭档言过其实,因为 C++ 一直都是很多种语言的最佳排挡。关键不在于那种语言多么的出色,而在于你应该选择最合适的工具解决问题。而 C++ 很少被用来构造整个系统,通常只构造系统中的关键部分,这时候,他当然鼓励把其他语言与 C++ 共同使用,而且实际上,一直以来都是这样。”

另外值得一提的是 Stroustrup 的其他一些观点,例如对于 boost 和 loki ,他毫不犹豫地赞同我们这个圈子当时许多人的观点,“某些库中有过分运用模板机制的倾向”。并强调,“ C++ 是一种多范式语言,最好的风格是综合运用各种范式,保持平衡,求得对某个特定问题的最佳解决方案。过分运用泛型程序设计技术,与过分运用面向对象技术一样,都是他不赞成的。”

还有关于指针的问题,“他(Stroustrup)通常把实际对象也放到容器里,然后再用一个容纳指针的容器 进行关键操作。他认为只要你仔细考虑,大多数资源都是有一个唯一的 owner 的。接着,他主动谈到智能指针,最有趣的东西就在这里了,他说,有很多人开发了类似 shared ptr 这样的东西,使事情看上去很漂亮。但是他不太喜欢智能指针。这个东西实际上是一种半吊子 GC ,它比手工管理自动化,又不如 GC自动化,高不成低不就。你同样不知道对象是什么时候被析构的,那为什么不直接用GC呢?在他看来,普通指针仍然有很大用处,不应该试图绕开它。”


当时,我们也关注一些诸如敏捷编程的时髦话题。孟岩曾经(02 年 10 月 24 日)转过一封 Bob 大叔 Robert Martin 给他的信,里面有一段话无关敏捷编程,但我觉得挺有趣,

It has been quite awhile since I have done any serious C++ work. Most of my work now is in Java, and is transitioning to C#. I'm not thrilled with either of these languages. They are OK, but not great. The languages that most pique my interest at the moment are Python and Ruby. I think the future likes in that direction.

是时候好好看看 python 了,不知不觉的公司里许多程序员中都开始出现学习 python 的势头。我第一次认真的审视这些动态语言,而不仅仅把它们当作一种嵌入式脚本使用。


叶航是在 02 年 10 月来公司报道的。以前我更熟悉他的网名:高铃响。我们在 sina 游戏制作论坛泡了好些年,是多年未见过面的网友。只听说他在深圳万智源做最初幻想,然后就被 dingdang 叫到了网易来。也有人叫他老高,不过我更多还是只呼其名了。

那天,我在天河跟 sina 论坛的坛友龙云峰喝酒。听说叶航过来了,打了个电话把他叫过去,大家版聚一下。就在一个很小的酒吧,为他接风。他是个好青年,时不时的接一下女朋友的电话。我们聊一些论坛上的旧事。叶航和我同届,真是奇怪的很,我认识的许多做游戏的同行,居然都是 2000 年大学毕业的,

叶航入职后进了大话组,不知道忙着什么。离他正式转入天下组做策划,随后升为主策划还有半年时间。不过我想 dingdang 早就想好了让他负责天下的吧。


大话一的玩家流失的很快,到了 03 年时,据说有的服务器上最少的时候只有两三个人,其中还有一个是在线的 GM 。不得不佩服这样忠实的玩家,即使把一个网络游戏玩成单机版,也要坚持下去。

徐波在那里摆弄大话一的新版本“仙履奇缘”,成天在论坛里跟玩家吵吵闹闹。同时, 大部分的大话一玩家被分流到这个使用大话二的新 client 以及从大话二服务器分支出来开发的服务器系统。这个服务器免费,聚集着上千个前大话一的玩家。我想那是一块实验田,可以不断的尝试加一些新的东西,对规则不断的修正,补充一些细节。我想,我们到现在为止,再没有一个项目可以这样。有稳定的程序,稳定且有一定数量的用户,没有项目时间的安排,只是不断的修改游戏设计,让它更好玩。

丁丁去而复返,dingdang 安排他做徐波的上司,在这个分不清是旧瓶装新酒还是新瓶装旧酒的项目里做主策划。作为外人,我对项目策划方面的进展了解不多,无法判断到底是丁丁的贡献更大,还是徐波的。但是我能肯定,不能否定他们任何一人为这个游戏,日后被称为《梦幻西游》的游戏,初期所做的一切。


03 年初,lua 第 5 版即将发布的消息从 lua 的邮件列表中传出。我饶有兴趣的查看了新特性列表,被深深吸引的是新加入的 coroutine 。直觉告诉我,这是一种用来描述游戏逻辑不错的工具。

coroutine 其实就是协作式多线程。在 windows 3.1 的年代就被用于多任务系统的开发。现在的 windows 也支持一个叫作 fiber 的特性。我想,其实用 C 语言也可以轻易模拟出这样的东西来。

之前,大话二的 client 一直在用类似状态机的方式控制屏幕上的角色。虽然 kyo dingdang 都觉得这样就够了,因为已经比大话一做的好。但是我始终不太满意。我想找到更自然的方法去描述画面行为。只有这样,程序员才好放手去描述更多的细节,游戏才能表现的更生动。

我花了许多时间来写一个 C 的 coroutine 库。事后发现完全可以用标准 C 语言(借助 longjmp) 来实现,但是当时还是采用了汇编。这样我能更精确的控制内存的布局(尤其是堆栈方面的处理),因为按我的想法,为每个控制序列附加一个线程控制,可能会达到千个这样的数量级。不仔细推敲是不行的。

郭老对这个东西很感兴趣,我给他演示了一些简单的例子,他觉得用起来很方便。

大约在 03 年的春天,郭老对我说,我这里风魂已经用 C++ 再次重写过了。我们这半年又弄出了许多好玩的东西,例如那个 coroutine 。不如大家用新的代码重新写一个游戏 client 吧。这次我用 coroutine 实现了新的网络底层接口,声音模块,还有对象的管理。一切都感觉比上次做大话二时舒服多了。

还有 python ,大家那时都认定它比 lua 更好用。

掌握了新的技术,总是能激发程序员们的斗志。就这样,我们再次开始从头开始写西游的客户端程序。目标是让《梦幻西游》可以用上新的技术。哦,那个时候还不叫《梦幻西游》,但不久就会换上这个留在无数玩家心里的名字了。

《梦幻西游》就这样兵分几路,独立的开发着。策划用着大话二的程序系统测试着玩法,并由服务器程序跟进。美术按照留下来的规范制作着新的资源,当然,我们的工具慢慢的也齐备了。我为之制作了可视化的编辑器,郭老做了一个魔法效果的编辑器。因为我们讨论的结果是,既然有时间,应该进一步的压缩 client 需要的美术资源,以后当以程序控制的动画为主。还有诸如更换武器,局部换色等等方案,都在有条不紊的制定出来。

而 Client 程序方面,由郭老和我一起制作。我还是写底层,除了重写了所有的 engine 代码外。还新增加了不少特性。比如图象动态缩放,这 RLE 压缩图片的实时缩放写起来相当麻烦,虽然最后我把它实现了,但因为换装拼接时,出现一些接缝问题效果不太满意,最终放弃未用。这会是名副其实的并肩作战,大家在发现潜在的问题时都可以当天解决。新的 client 质量得以提升就是理所当然的事了。

梦幻西游这个项目,悄然开始,顺利展开,正在于这种相互独立的开发。这个优势,在大话西游二的研发期间已经显露出来,但到梦幻西游,发挥的淋漓尽致。


大话二的收入不错,慢慢的大家的口袋里都富裕了起来。我不知道公司具体给开发组的提成是多少。从往日的一封邮件来模糊的揣测,应该不到 8% 。但是,这个游戏的收入总量是巨大的,而我们也没有投入太多的研发经费。连宣传都是少之又少。最终,大家拿到手的奖金自然是非常丰厚。这给了所有人一个非常宽松的开发环境。

没有多久,我们每个人都领到了一件纪念 T 恤,上面印了,十万人在线的大话西游。


如果要说点别的,在 02 年底,我突然爱上了 ps2 上的游戏。从最终幻想 X 开始。公司里有两台 ps2 ,就放在办公区的一角。每天下班后,大家都去玩一玩。一天,我看见麻雀在那玩最终幻想,这是个老游戏,但英文版出来不久。我帮他做翻译,一边看着他玩。然后自己就开始手痒了。由于不好霸占着公共的游戏机资源。周末立刻去买了一台回家。

之后一发不可收拾。我想我购买了几乎所有发行过的 ps2 游戏,数以千计。和许多游戏收藏爱好者不同,有一年的时间,我都是很认真的玩每个不那么垃圾的游戏。很多很多游戏都从头打到尾了。

那几年的业余生活很简单,健身,打游戏。当然后来还有更多的一些活动,比如骑车、攀岩、看卡通,这么看的话,不算宅男,嘿嘿。


谢绝转载

那些日子(目录)

May 16, 2008

那些日子(十七)

2002 年 9 月底,再次回到广州,仿佛一个新的开始。我想我要长住下来了。这次打算住在办公室附近,越近越好。

头几天,我住在安宁住的小屋子里。原来小蓝租下的,现在他已经离开公司。屋子很小,晚上我就睡在地板上。安宁给我看他写的一些小玩意,一个汇编写的软件 3d 渲染器,挺有意思。还有一个使用 d3d 做的简单引擎。公司的 3d 项目已经做了大半年了,一直没有定下一个技术方案,可能还想多一些技术尝试吧。

我也去公司转转,没有正式复职,只是跟朋友们打个招呼,我回来了。顺便向周围一个个小区问值勤的保安打探情况,看看有没有房子出租。这比找中介要划算一些。工业园还不太繁华,房源很多。没多久就找到一家,步行到公司才几百步(以前数过的确切的数字,后来又忘了),中间会路过一个中国银行,挺方便的。

只是屋里格局设计的不好,也没有家具。空空的有张木板床,床板裂开,躺上去有点硌。我也够能将就的,就在这张床上睡了几百个夜晚。我妈常说那间房临着马路,有点吵,担心我睡不好。我倒不觉得,心灵上的平静才是最重要的。接下来几年过的很舒服。因为没有书架,还像上学时那样,把书齐齐的码在床内侧,取起来容易。

偌大的客厅就那么空着,直到我妈说要过来住几天,才去超市买了台电视。我决定过一种有规律的生活,把自己的时间规划的好好的,一块块的用。所以已经不想在家拉网线,摆计算机了。宁愿过一种不插电的生活,家中只是睡觉看书而已。这个习惯一直保留到现在,我没有买过笔记本,住所没有计算机,没有网线,要写程序一律去办公室。慢慢的身体也养成一种习惯,做什么必须在特定场所才有灵感。如果离开办公室的那张椅子,高一些,低一些,硬一点,软一点,都会让写程序的兴致全无。

国庆去了趟深圳,见了许多沉浮于此的大学同学,看着大家都在为生活奔波忙碌,感慨万千。


长假过后,正式到公司报道。

公司冷清了许多,一问才知道,不少美术都休假了。是啊,他们非常辛苦,长期都是一周六天工作,晚上还有固定的加班时间。当然,每周多出的加班时间,都是累积到假期里的。所以那几年,美术都是把假积攒到一起,然后休上足月出去旅游。(现在好象已经不这样了,周六再很少见有部门要加班的)

刘琪说,大家商量着想把大话西游的美术重新做一次,以前的不太满意。这次新的想做的 Q 一点。我不太在意。反正到时候换换图片就够了。大话西游因石器时代的风靡而立项,或多或少受到它的后续版本魔力宝贝的刺激而向后发展吧。

郭伟已经在公司上班,坐在我的旁边。他在读大话西游的代码,我给他讲解引擎。他的任务暂时是给大话西游做一个较大分辨率的版本,因为这部分涉及地图预读策略的问题,所以我仔细的讲述了那块糟糕的代码。郭老倒不含糊,没用多久就让引擎支持了各种更高的分辨率。可惜这个改进并不受玩家欢迎。玩家更喜欢已有的 640 宽的小窗口,因为这样更流畅,还可以同时开几个 client 一起玩。同样,过大的分辨率,除了提高用户机器的需求外,也加大了服务器的负载(对每个玩家广播的信息量增加);整体来说,对我们和玩家都是极不划算的,这样的一个版本放出后不久,最终还是被取消掉了。

游戏部门开始筹备自己的市场部,想把游戏市场工作从公司的大市场部中独立出来。这个决策应该是对的,丁磊也有一种对老的公司部门精兵简政的想法。黄华逐步从策划转为产品经理,管的更多是市场方面的事儿。随着精灵的逐步没落,设在上海的精灵团队(主要是市场方面)被集体南迁广州。这次大迁徙,公司上海部门离开了许多人,很多人不愿意离开长三角。剩下的一批搬到广州住下来以后,也慢慢散去。当第二年工业园里多出一家网游企业:光通,许多人(我记得的有老刀)去了那儿。光通就开在我租的屋子前面,我总觉得他们的大门朝向不对,若拿伪科学来讲,就是风水有问题。呵呵,一家之言。

当大话西游二成了网易游戏唯一一个赢利产品时,黄华做到了市场部门总监。萝卜则从大话二的主策划变为项目负责人。说起这游戏市场部来,张金姐后来不无遗憾的跟我说,当时大家都是从零开始,原本她很想,也有能力和实力去带市场部这个新团队的,那样她可能会发展的更好。可惜正好生小孩去了,错过了时机。如今张金的娃娃该上小学了吧,很聪明,被他的妈妈成天的夸。这些年,看见张金每天很晚回家,没有那么多时间照顾自己的孩子。让我觉得公司一步步发展起来,真的是有无数人投入了太多心血,做出了极大的牺牲。

大话西游二收费后进展很顺利。但和一切一切的网络游戏第二版一样,同样遭到了第一版玩家的猛烈抨击。念旧,还真是人之常情呢。逝去的东西东西永远是最美的,无论它还在的时候给你带来多少烦恼。大家不再记得那些 bug 那些设计失误,只记得它的好。

徐波就是其中一个,他做大话一的 GM 有很长一段时间,自己也玩。记得有一次他对我说,其实大话一游戏做的还是满好的,如果 bug 少一点,可以做的很精彩。

今天我在旧信箱里翻出徐波 02 年 5 月中给我写了一封信,里面附了他对大话二的诸多意见。有两份很长的文档。当时我正忙于程序,没有回复和他讨论。不过这份文档,应该看起来算是狠狠的批判了当初大话二的设计。当他转给大话二的策划组看后。在讨论会上,自然招致一片反对声。徐波不是个容易与人相处的人,我没有参加那次策划讨论,但我能想象出当时的情景。一大组人被一个毫无经验的“外行”否定,从心理学上分析,就能知道那种集体而生的排斥心。策划组全体都觉得他在那信口开河,争吵中,脾气最好的萝卜居然都气的拍桌子。最终只得让 dingdang 来调停。

如此看来,徐波没能融入大话二的策划团队就是自然的事。dingdang 只好让他做点别的。游戏的 client 已经稳定,那么就可以尝试把原来的大话一搬到新的 client 上来运行(和大话二公用一份 C++ 代码,但重新编写逻辑脚本)。陈舟(舟字用了个同音字,原字生僻不好输入)负责移植服务器;徐波以一个大话一老玩家及资深 GM 的身份介入这个项目的策划。这个版本被内部命名为“仙履奇缘”。看过大话西游电影的同学当明白这个词的寓意。


我的生活变的很有规律。暂时不想做什么新项目,只想学点东西,做一些积累。重新上班第一天,我就开始筹备一个技术讨论的邮件列表。因为当时对 C++ 颇有兴趣,就叫作 C++ 邮件列表了。

这个邮件列表到今天还在活动中,用的开源软件和专门架设的服务器。但是最早的时候,我是在本机制作了一个收发邮件的脚本来完成订阅、转发等服务的。就是利用一个普通的 email 信箱,让大家把邮件发到里面,然后我收下来,用脚本分发处理,再转发给每个人。

我整理了通讯录中所有的程序员,邀请他们加入我这个邮件列表。一部分是公司同事,一部分是网友。包括了新认识的孟岩等人。大家聊的挺开心,我觉得挺有趣,也想把这个做下去。今天翻出最早的几封信,02 年 10 月里发的,谈到买的新书:The Art of Computer Programming 第 2 卷 的中文译本。想起那段时间,还在拼命的做书上的习题呢。

后来这个邮件列表随着人员的增加,出了许多问题。经常被 smtp 服务器误认为在群发 spam 。我用的 email 是 163.com 自己的。原以为问题很容易解决。也就是为了这个问题,开始和公司邮件组的同事进行交流。我总觉得,处理这个问题弄个白名单就 ok 了,对于长期群发邮件,但没有被任何人投诉的帐号,应该很容易纳入白名单。但接下来听了邮件组的同事倒的许多苦水。嗯、其实一些表面上容易做的事情,即使技术上也没有障碍,实际操作时还是有各式各样的困难的啊。

虽然一再被封帐号,甚至冻结 ip ,这个半人工的 maillist 还是开了一年多。只到 03 年 11 月底,我群发了最后一封邮件宣布它关闭。大家觉得可惜,不久以后,我从公司申请到服务器资源,又重新开起来。


另一件事情,我开始健身。一直坚持了近三年。这段经历让我明白了一个道理。别人能做的事情,自己也是能做到的。无论目标看起来多么遥不可及。关键还是看是否有决心坚持下去。而一件事情能坚持,往往看的并不是兴趣爱好,或是利益诱惑,更多的只是习惯。养成习惯才是最重要的。

我从小身体就非常瘦弱。到小学毕业时,一个引体向上都拉不起来。上学期间,我觉得自己天生在体育方面就比别人差。进高中前,还担心体育不达标会影响入学。到读大学期间,曾经被寝室的同学怂恿着去健身,但只去了几天,听了教练讲一些要领后就没怎么再去。毕业后,一米八多的个头,体重只有 130 。夏天脱了上衣就是一身排骨。

心一旦安定下来,我想试试能不能有所改变。

公司不远处(员村)有一间健身房,先去打探了一下,感觉设施很齐备。如果按次去,就比较贵,一次要十多块。而且容易荒废。比较了一下,办那种早卡比较划算,一个月才 100 多点,唯一的限制是在中午 12 点前进场。一咬牙,决定彻底一点,改掉晚睡晚起的习惯。每天七点起床,吃个早餐休息一下,就走过去(大约半小时路程)锻炼。

旁边是个电影院,只要是周末,训练完了还进去看场电影。电影业很萧条,好几次放映厅空空的就我一人。感觉是个人包场,非常的惬意。碰到滥片,窝在情侣座里小睡一会。那几年,真是贡献了不少银子给我们国家的电影事业呢。

健身房的器械区早上基本没人,教练也很无聊。几句话我们就聊上了。他乐得交个朋友,便帮我指定计划,一点点的开始练习。我想我就是那么下了个决定就开始了。一直坚持下去。一开始是隔天去一次(因为没有习惯大量肌肉练习的人,一开始必须保证每次之后 48 小时的休息),然后逐步增加频率,直到一周五次。

很辛苦,也很单调。每天一个半小时的训练,各个大肌肉群分开练习。全是各种器械的反复机械练习。一组组的做,直到压榨出肌肉中的每一点能量。还有每天 100 个的仰卧起坐(从平板到斜板再到几十千克的负重)。最初的那段时间,整天腰酸背痛,四肢无力。记得有天躺在床上,用手硬是撑不起身体坐起来,我知道那是肱三头肌脱力的现象。

唯一的乐趣,就是每天测量自己的各处肌肉的围度,以及称体重,看那些数字在小数点后的变化。神奇的是,晚上的睡眠也是相当的好。白天虽然没力气,但很有精神。每天都能吃上十多个白水煮鸡蛋。身体也就一天一天明显的膨胀起来。

一年之后,体重就从最初的 130 上升到了 156 。卧推从刚开始的不到 30 公斤,增加到接近 100 公斤,深蹲也达到了 140 以上。看着杠铃两端厚厚的哑铃片,心里特有成就感。

而引体向上慢慢的也可以做到 18 个(这个受体重增加影响,进展很慢),这都是以前不敢去想的事情。

一直以为,身体主要是父母给的,后天能改变的很少。当看见别人身材魁梧,总是很羡慕。小时候没注意锻炼,觉得大学毕业后就成年了,能改善的可能性不大。没想到,一切都不晚,只要去努力,依旧可以改变自己的。

只是这两年,项目实在太忙,主要是劳心。我中断了健身的习惯。感觉身体状态降了很多。体重也掉了下来。不过还是比大学时好一些。我想能够在这几年玩命去做新的项目,这身体基础跟前几年的坚持锻炼是分不开的。真所谓养兵千日,用兵一时啊 :D 。等现在手头的事情做完,一定要恢复这些好习惯。


谢绝转载

那些日子(目录)

May 15, 2008

那些日子(十六)

《大话西游二》是在 2002 年 8 月 15 日正式收费 的。而就在之前几天, 02 年 8 月 7 日,网易宣布股票发行以来,第一次实现赢利。这次赢利,净利润仅 3.8 万人民币,我在网上看到这条消息时,感觉太搞笑了。根据财报,一个季度的运营费用有 2719万,结果恰恰就赚了不到 4 万。这个数字若不是精心做出来的,而仅仅是一个巧合的话,我觉得那实在是太幸运了。

事后,我给后进来公司的新同事讲这个段子时开玩笑说:当时我的第一反应是,前段时间公司暂停了我们大家的办公文具申报,连以前每月发到个人桌上的卷纸也没有了。感情公司这历史上的第一次赢利,是大家坚持三个月,集体节约下那些铅笔、记事本和卷纸给省出来的。每个网易员工都是功不可没呀。

不过不管怎么说,从五月里开始,一切都朝着好的方向在发展。

但我并未在广州亲身经历这几个特殊的时刻。


2004 年以前,公司的劳动合同等管理并不严格。合同放在我的抽屉里,一放就是两三年,中间有人问过一次。我拖着没签,就再也没有人过问了。我想公司为了早日实现赢利,在运营成本上扣得很细。能不招人的岗位就不招人。尤其是行政财务等部门,长年都只有那么几个人在办公。有点什么事情都不敢轻易打搅那几个 mm 。早年,我的一些报销单能压上半年才处理完到帐。弄到后来,除了出差的飞机票和酒店住宿这些大额的做一下报销单外,小额日常的报销都是不想去做的。

研发部门中,直接开发人员之外的后勤管理人也出乎寻常的少。上百人的游戏部,就一个前台 Candy 忙内忙外,剩下的全是研发人员。后来调了张金姐过来,仍旧不堪重负。最后几乎所有的文职人员,都需要做一些内勤的工作,像做韩语翻译的金香兰,我们的法务顾问等等。

游戏部门人还远不如今天这样多的那时,办公室坐不满。泡泡组便搬到工业园一起办公。黄晓东(不久后离开,后去微软为移动做飞信)当时任泡泡的项目经理,我们也时常聊天。泡泡组的加入,也加大了许多后勤工作上的压力。

我想若不是靠大家的自律,这么大的团队无法自我组织起来,完成这样一个项目。

七月,眼见着大话二顺利收费已成定局,技术问题基本上全部克服了。dingdang 在考虑的是收费后要不要删档的问题;丁磊考虑的是收费维持一小时三毛的标准、还是提高到四毛一小时。很多人反对涨价,但丁自有他在精灵上五毛一小时的成功案例,固执的坚持要涨一毛钱。事实证明他的对的,除了那时候残留下来的极少数大话一玩家在网上闹闹外,大部分用户接受了这个价格。另一方面是因为几个月后增加的一个不起眼的小设计,点卡交易系统的成功。这段故事放在下回讲述。

我的工作,即那些代码的日常维护,同事全部可以轻松接下来。留在公司已经不是特别必要的事情了。这样说,我的初衷是完整的做成一件事,到这里、目的就已达到。至于成功的果实,由哪些人怎样去分享,已是微不足道。

一个周末,我去电脑城买了块移动硬盘。用它备份了一些代码,几篇业余写的策划稿,收集的一些资料,把家里的计算机送还给公司。这块硬盘质量不好,不久就坏掉了,那些文件从此消失,心痛了好久。

七月月中,我跟 dingdang 说,我想休假。好好想想再该去做什么。没有提辞职,其实我也拿不准是否真的想辞掉这份工作。只是说,把薪水停掉吧,可能我想多休息一段时间,领着薪水我心不安。dingdang 说,无论两个月还是三个月,随便休吧,完了再回来。

走的那个周末,下着瓢泼大雨。雨水一上午就积到了脚踝。我没太多行李,主要是书。可随身几大箱,也很难步行出院子。租的那个房子在一条很深的小巷子里,终于有个好心的出租车司机愿意进去接我出来。那个巷子真的是很窄,车进去都无地方掉头,倒着开出去的。

房东和邻居都有点舍不得我走,因为我的作息时间,我本不是个容易很邻里打交道的人。但母亲偶尔过来住,和街坊相处的很好。她很乐于助人。那栋楼的楼上原有个独居的老太太,儿女都定居在美国。有一次心脏病发作,母亲送她去的医院。房东一对老人,在我离开广州后还偶有联系,等我日后再次回到广州,母亲时常去看望。老人家一直唠叨,后来几任房客都不太合意,最后只好把房子低价贱卖了事。


就这样突然的决定离开广州,显得有些冲动了。其实当时我已经在武汉供房,为父母买一套新房子,让他们过的好一些,恐怕是所有儿女的心愿。

02 年初的房价还不高,只是人们看到的都是相对价格,而非绝对数字。从福利分房的年代过来,当时单位里的房子把产权卖给职工,不过几百块一平米。而福利房周边的商品房价已经是高达一千多了,不是很好卖。一开始我看上一处两百多平的复式,单价要 1200 。计算了一下,可以承担的起。不久又觉得小区设计的不太好,而旁边打算新开的楼盘感觉更好(还只是楼花,地基还没打,只有模型),但是单价要两千多了。这在那一片已是天价。父亲有些犹豫,因为按我的计划,贷款五年买下,每个月需要还贷 5600 。实在是贵了点。单靠父母微薄的工资,无论如何供不起的。而他们辛苦一辈子,有了钱都接济亲友,又没有丝毫积蓄。

我当时坚信,只有最好最有价值的东西,才有足够的升值空间。而且既然要买房给父母,就一定要最好的。在我的坚持下,买下了这套房子。同时也背上了六位数的债务。

有时候,我也怀疑自己是不是乐观的过了头。虽然明知道身上有几十万的负债,银行里的存款也都拿出去付了价格不菲的首期,但对于即将失去固定收入还是满不在乎。似乎自己从来没有思前想后的去考虑以后可能会面临的诸多困难。

不过,为了打消父母的担心,我还是在八月去了北京。毕竟在家混日子是赚不来钱的。


北京有家新开的网络游戏公司叫作侠客行。他们头儿董晓阳是我在网上认识的朋友。据说他在美国读书时,曾经和方舟子一帮人等开发过名为侠客行的 mud 。这次回国创业,就是想把这款 mud 图形化。

他在用“风魂”写 client ,想让我帮他做点东西。

当时我在心里认为,已经可以给网易公司一个交代了。大话这个项目圆满完成,对的起我过去拿的一年半的工资。我还没有跟网易在附有禁止竞争协议的劳动合同上签过字;已经中断了薪水,处于停薪休假中;而且这次也只是做一些底层技术工作,帮人解决问题而已。对于我来说,写程序和做游戏是分开的两件事。所以,我爽快的答应了。就算是兼职吧。

董晓阳给我开了一个比网易更高的薪资,希望我能全心加盟。我拒绝了,因为我不想再次重复做过的事情。侠客行的游戏看过,当时还很一般,我觉不出会比大话更好。某些方面做的跟大话一一样简陋。看的出来,很多模块是借用一些开源的东西东拼西凑出来的。

如果真的是我来接手的话,等于又重新做一遍大话二,这可受不了。人生不过数十年,重复自己有何乐趣。

他们的一大问题是缺少完好的 GUI 系统,有如大话一曾缺少的一样。我在北京干了不到一个月,挺自由的在他们的办公室出入,解决这个问题。这方面,已经积累了太多经验,去北京前在武汉家中,我已把 glow 全部完成,所做的只是一些整合工作。

最后董晓发了我一个月的兼职工资,大信封装的现金,厚厚的有一万。带回家中交给父母,让他们放心,儿子这辈子无论干什么,都是饿不着的。


在北京过的那个夏天,更多的还是拜访旧友。同时也结识了些新朋友。

一天,胖肖给我打电话。说黄晓东离开网易后一直在北京,大家可以出来聚一下。另外还可以叫上在联想工作的 孟岩 。我听到这个名字很耳熟,只花了几秒钟就想了起来。当时网上流传着一个帖子,关于配置 STL port 在 Windows 下编译并整合到 VC 中使用。此贴就是此人大作。我当时对 C++ 和 STL 兴趣浓厚,颇想结交一下玩 C++ 的同道。而且听说他正在和候捷合译 《C++标准程序库》,很是期待这本重要的译作。

我们四个人在一家川菜馆碰面吃的火锅,听说孟岩也是武汉人,相互感慨了一番。大家都非常健谈,边吃边聊,意犹未尽。并没有在晚饭后散去,而是转战一家茶馆继续。

程序员碰面,总是有聊不完的话题,很多不做此行的人很难理解。一开始大家还只是聊一些程序技术问题。C++ 语言方面,胖肖和晓东不是很有兴趣,就我和孟岩讨论甚欢。随便拿出个奇技淫巧来,都可以说上半天。而后,大家上升话题谈一些高屋建瓴的软件设计方面的学问,由于各自都有许多工程经验,自然故事连篇。记得,还聊了一段优化,最后胖肖总结,最大的优化手段,无非是一种广义的 cache ,即想办法避免重复的操作和运算。还有一些在实际工程中并不多见,即是数学上的算法改进。话题就这样扯到现代数学和物理的进展。当时我很着迷于超弦理论,看了不少科普书,当即吹了半天的牛。说着说着,不知怎么又扯到历史上去,难得孟岩也读爱读史书,我们从秦始皇一直聊到李秀成。

直到深夜,孟岩的 mm 不停的发来短信,他才不舍的离开。我和胖肖干脆跟着晓东去他住的地方彻夜长谈。

补充修正:后来翻出来一封老邮件,是胖肖约我出去吃饭的。时间是 2002 年 5 月 9 日,约在 12 日吃饭。所以上面这段故事记叙时间有误,应更早一些。7,8 月份的时候我再去北京,又去找过一次黄晓东。那天半夜,我被关在住所外面,进不了门。手机没电,幸亏有随身携带电话卡的习惯。身上摸出张黄晓东的名片。满大街找电话亭,把他从床上拉起来接我去他那过夜 :D 。


回到武汉后,我去了一趟庐山,风景很美,玩的挺开心。这也是我第一次自己跑出去游山玩水。大学时,假期都去写程序或做兼职去了,同时也没钱远游。工作后,一直很忙,即使出去玩,也是一大忙同事赶去景点转上两天。而这次,却有很多时间,慢悠悠的过。前面的事情做完了,后面还不确定做什么,觉得挺放松。那种感觉叫——自由。

接下来,在武汉家里待着。母亲早已退休,除了白天照顾我吃饭外,就是出门忙乎她的一些事情,照顾几位老人:她工作时的师傅;父亲还在上班,成天在单位里忙碌。我便去图书批发市场淘些折价书回来看,倒是特别清净。时常想想是不是应该继续一年前的想法做个有历史感的游戏。可越发研究历史,想的越多,越觉得自己的学识太浅薄。我想,即使转行不写程序,不做游戏了,这个世界上还是有很多有趣的事情可以去琢磨的。

网易的股价在我休假的日子里,随着大量的利好消息,玩命一样的向上疯长,不多久就六七块了。能和这成长速度媲美的是大话西游二的在线人数。我想,这次又被丁磊说对了,我们超过盛大,不过是时间问题。

在家里安定了一段时间之后,终于想明白。虽然不确定以后想再做什么,但自己想做的事情,自身的学识和能力还差的很远。提高自己,不一定要一个人独居在家中。有个好的环境,和人交流的环境,只会更好。网易是个好公司,现在也在迅猛发展。而自己是个有用的人,无论在哪里都有能力为别人做些事情。一旦有个好的平台,只会做的更多。

同事在网上问,休息够了没?赶快回来上班吧。在那金秋十月,我又回到了广州。


谢绝转载

那些日子(目录)

May 14, 2008

那些日子(十五)

大话西游 2.0 在 02 年五一封闭内测的时候,已经更名为大话二。因为丁觉得,反正是重新做的,就应该以新名字重新来推广。

由于先前的刘铁等几个策划离开,月心被调离大话组,转到 3d 项目中(这也一定程度的导致了这个 3d 项目最终被命名为天下二)。Micro 在他回加拿大前的一个月,开始重新为游戏策划招兵买马。

萝卜从大话西游的界面设计师改行做游戏策划,黄华被提升为大话西游的主策划。而丁丁(日后的《梦幻西游》产品经理)就是这个时候入职网易的。这是 2002 年四月间的事情。

按我讲述这个故事的前后习惯,所有提到的人均用我平时在公司对他们的称呼。那么就用丁丁代这么个人了(有人也把丁磊称作丁丁,不过不是我的习惯)。公司里也有人称他为老妖,那是他的一个网名吧。

丁丁总是带着一副彩色的眼镜,年龄看起来比实际上的小许多。在当时的游戏开发团队里,只有 dingdang 比他年长一点。他从学校里出来的早,所以工作经历比其他人要多许多。据说早年卖过花,早早的起来去花市里,把花架在自行车上运出去卖,收入还不错;后来手工焊过线路板,做数控机床的驱动电源,赚了不少钱 …… 也算是久经江湖了吧。

那一年末他又离开网易,但不久以后再次回来,一直做到现在,已经是游戏部门的领导了。

这段时间有前同事跟我在泡泡上聊,说怀念过去的工作经历,想再回来网易,但是又担心回去后受到不公正的评价,影响日后的发展。其实中途离开过公司,之后又回来的的例子很多很多。在这个故事里提到的人中就有 ruiheng 和丁丁。我现在也管理一个团队了,从内心中感到,其实用人往往还是希望更熟悉点,所谓知己知彼,百战不怠。大多数领导团队的人,还是希望那些自己离开的同事可以回来继续共事的。何况周而复返,更能说明经过了深思熟虑。

丁丁来的那一晚,Micro 叫我一起去吃饭,说要给新朋友接风。饭局不太隆重,我们就在工业园中的明记大排档吃的。天气开始有点热了,老板说屋子里有空调,大家就坐进去。我跟丁丁之前没有见过面,但是一聊起来发现还有点缘分。他是《古龙群侠传》的数值策划,那么就是郭伟的老同事了。我们立刻就有了共同话题。


大话二的 client 放出后,作为引擎开发者,我已经没太多事情。我给自己找了些事情做,那就是想方设法减少外挂和加速器对游戏的危害。

外挂问题,是一个长期的处理过程,前后持续投入了一两年。但都是断断续续的在做。灵感来了,添点东西,从来不是我的主要工作。相关的一些方面,前面已经谈起过,不再累赘技术细节。下面简单提一下加速器的监测。

所谓加速器,就是让 client 以高出常规频率向 server 发送一些指令包。早期的 MMORPG 服务器都是单纯的包驱动,即,根据 client 发送过来的指令,在检查了逻辑合法性后,做出相应的处理以及反馈。大多数网络服务都是这么做的,比如 web server 用的 http 协议就是这样。用户从浏览器发起一个请求,服务器就做出一个回应。普通的网络服务仅仅在防止恶意攻击时,才限制一下同一处来的并发请求数。但 MMORPG 则不够,因为时间信息也是影响游戏规则的一部分,我们需要保证时间间隔信息的合法,以此维护游戏公平。另一方面,也要阻止非法用户吃掉过多的 server 带宽和 cpu 资源。

今天看起来很简单的道理,当时我并不是一开始就意识到的(虽然着手处理加速器的工作更早就开始做了)。最早是 tarcy 给我讲的一件事,让我意识到这个问题的严重性。

tarcy 在九城测试《奇迹》时就开始为这个游戏写外挂了。我一开始很奇怪,不是说《奇迹》的战斗逻辑都放在服务器计算的吗?那么就不再会出现《精灵》那种修改 client 就能做到无敌天下的问题。使用外挂又有什么特别的好处呢?tarcy 说他们写的外挂很好用,可以让火球提高最高八倍的攻击力。一开始我不相信,他一解释就明白了。原来只是提高的发火球的频率而已。(btw ,tarcy 的奇迹外挂后来据说达到六位数的注册用户,还发展了海外代理,赚了个钵满盆盈 :D 如果单单是个人想赚点钱,这比为网游写程序要来的容易多了)

后来 wow 是用技能冷却 ( CD : Cool Down) 时间来回避这个问题的,这也是欧美系网游一贯传承下来的方法。今天被很多游戏学了去,但那个时候却不普遍。

最开始,我去解决加速器引起的问题,只是想阻止玩家用不合法的手段在虚拟场景中移动的比正常速度快,也就是避免玩家以非法的频率发送移动指令。玩家做到这一点,甚至不需要修改 client 程序。他只需要用一个小软件修改操作系统的时钟逻辑频率即可,这样的软件比比皆是,被称为变速齿轮。

我们的服务器程序设计的并不好,mudOS 的底层也没有精确控制时间的设计。在做这件事情时,和通讯加密一样,我尽量避免要求服务器做大的修改。

方法是很简单的,就是在通讯底层加上时间戳。也就是在时间流逝后,发送一个时间信息包,通知 socket 上的对方自己本地的时刻。理论上,socket 两端的时间流逝速度应该是一致的。假设一开始通讯时,client 和 server 的时刻校对一致,由于网络通讯需要消耗一段时间,所以,server 收到的 client 发送的时间戳时,时间戳表示的时刻都应该比本地时间慢一些。一旦快于本地时间,就可认为 client 在作弊。

这个方法很多游戏开发团队都想到了。

头一年(01 年)国庆的时候,我曾经去上海拜访过新浪游戏论坛上的一群网友。小箭2000 带着 freemind ,analyst ,softboy 等一帮人在上海为金智塔做《星河贝贝》。那是个下午,小箭的电话始终没有人接。analyst 说他就是这习惯,睡觉不关手机,也不接电话,等醒了会打回来。freemind 请我吃螃蟹,他说来到上海后,就开始喜欢吃这个东西了。还专门买了个蒸螃蟹的锅,周末从菜市场提上一串回家,放点冰糖一蒸,那可是人间美味。

吃完饭去他们办公室打星际。之后我们没交流太多技术问题,唯一印象深刻的一个就是谈这个加速器检测的方案。

这个方案从理论上看起来没错,但实际应用中,经常会发生误判。原因有二,一是准确对时非常困难 ,尤其在对时过程中 client 系统和通讯网络不稳定,会极大的影响后面的判定;第二是,PC 机的各钟主板,甚至运行的操作系统,都会导致时钟精度的不一致

所以在用时,这个方案还是有许多细节需要改进的。大话西游二的测试期间,不完善的检测手段,冤枉过不少可怜的玩家。kyo 的保守作风在这个问题上发挥了作用,原本我认为理论上完全可以判定出是否使用了加速器,但 kyo 一再坚持,即使检测到,也需要累积多次再做处理,这样大大减少了误判对玩家造成的影响。


2002 年的夏天,我基本脱离了《大话西游二》的开发。因为我总是自己找事情做,所以公司就没有指派给我任何任务。这期间读了几本书,影响了我好几年。

第一本书是著名的 C++ D&E :《C++语言的设计和演化》,我读了两遍,读的很快,但很透彻。这本书让我又一次重新认识了 C++ 。

第二本则是侯捷写的《STL 源码剖析》,我并没有读完。而是在实体书出版前, kyo 介绍我读了侯捷放出了前四章电子版。因为这本书,我把 STL 的源代码几乎浏览了一遍。发现 template 这个东西居然如此奇妙,从此陷入在把玩 template 的智力游戏中,一晃就是三年多。

02 年被我自己称为 C++ 年,C++ 的有关经典著作不断的被翻译,程序员杂志也在推波助澜。各大开发论坛的 C++ 版块都异常火爆。我在 csdn 注册了一个帐号,没发多少帖子,仅有的一些全在 C++ 版里了。我想我读了那几年翻译出版的所有的关于 C++ 的书,也为自己重新发现 C++ 这样一把无所不能的开发利刃而沾沾自喜。

ps. 通过 google 翻出当年的一个论战贴,讨论多重继承和组合模式的。我想很多同学在学习 C++ 时都有这类经历 :) 。

那些日子,不断的把自己学到的领悟到的新东西教给同事,我想,许多人都受到了感染。对于许多年轻的程序员,都会为找到一样可以证明自己比别人更聪明的玩具而兴奋不已。

在最为狂热时,我把 C++ 的字样印上了个人名片。和今天相比,当时的心境真是判若两人。

那段时间,我开始重新写 gui 的模块,想用“更 C++” 的方式来表达设计。编译期运算、(用 template)函数式编程、泛型抽象,无所不用之极。那套东西被我称之为 glow ( game library of windsoul) ,这名字还真是热情洋溢啊 :D 。

之后,便翻新重写“风魂”。不过鉴于 glow 开发时发现的一些问题,如编译速度过于迟缓、调试不便等,这个新版的“风魂”就不那么 C++ 了。也正庆幸这一点,这个版本可以一直用下去并被人持续维护,成为了后来《梦幻西游》以及其它几个网易产品的底层代码,甚至还用在了《天下二》的 GUI 模块中。

直到 2006 年,我开始对 C++ 开发项目进行反思。等到 2007 年写下 C 的回归 这篇颇有争议的 blog 时,我很能理解那些反对声音,如同理解当年的自己。


看到大话西游二顺利的发展,每天都能看到在线人数有新的突破,不多久就超过三万人在线了。我心里长舒了一口气,总算搞定了。

庞鑫离开后不久的一天,dingdang 把几个开发人员叫到了会议室。分别发给大家了一份文件。说是网易的期权。

所谓期权,就是一种在一段时间内,以一定价格买入指定股票的权利。这个价格往往就是制作期权文件那天的公开价位。虽然不是现金,但期权自有它的价值,这个在金融方面早有定论,不过当时我是没有太多概念。

简单的理解,就是当持有一支股票的期权,若它日后涨了,你可以以当初的价格买入。如果你在行使期权的当天再在公开市场上将股票卖出,其中的差价就是立刻能入手的获利了。而如果股价跌了,你可以放弃期权,也没有什么损失。在美国这样成熟的金融市场上,期权这种金融工具本身,甚至都可以被炒来炒去。

上市公司常常以颁发期权这种方式奖励员工,并鼓励员工努力工作,一同把公司发展的更好。一旦公司股价上涨,大家能有很大的收益。

直到 2004 年,网易每年都为所有正式员工颁发期权。无论是前台接待,还是仅入职几天的程序员,人人皆有。那一天,我手上的文件上写着 70 美分一股的价格,五年的有效期。等到 2006 年底即将过期时,我将这些期权全部行使,变成股票存放时,股价已经翻了一百多倍。

dingdang 向我解释说,本来我入职时间不长,可以拿到的数字比文件上的要少一些。但是由于一些同事的离开,大家商量后给我多一点。我所做的只需要签一个字了。

记得当时我很犹豫,迟迟不肯落笔。因为我觉得自己的事情都做完了,心里盘算着离开。


ps. 闲扯几句关于网易期权的事情吧。虽然公司里不让讨论大家各自期权多少和分配方案,但具体的情况,多少我还是有所耳闻的。当初那几年,我绝口不跟人谈这个,一是理解公司在这方面保密的苦心,二也是的确不太关心,否则也不至于每笔期权都到最后快过期的关头才着急行使,弄成每年都要做一次的大事。甚至感觉有些麻烦。

如今,公司已经不是人人发期权了,股价也涨到很高,我想再难有几十上百倍的收益。那些高收益的期权文件今天已经几乎都过了有效期限。有人在涨到 20 倍、30 倍时迫不及待的兑现,有人像我这样留到了最后,最终收益和当初期权数量反而关系不大。从金融角度看,当时的期权多少的差别其价值的绝对差距就不高。今天来谈这些,已经不太所谓了。

其实游戏部门的期权一开始总体不算多。这点我曾和其他部门一个头(已经离开网易)聊天时,他帮我打抱不平过。他说游戏部门为公司做出了很大的贡献,但在为自己部门谋福利这点上,dingdang 争取的太少。由于游戏部门人多,机构大,一平摊就没多少了。往往部门人一多,普遍级别就不高(官少),分期权的时候,级别又占了很大权重。他劝我去申请提一个级别,省得比别的部门干活少的多的人拿的还少。

利益分配真是个难题啊,共患难容易,共富贵难。

后来几年,让 dingdang 殚精竭虑的问题之一,就有如何奖励这个越来越大的团队中的每个成员。这绝不是一个写个程序,套个公式,就能完成的任务。它需要更多的智慧。


谢绝转载

那些日子(目录)

无言

这几天估计所有中国人都在关注一个共同话题。大家都自发的想做点什么。这两天谈论的太多,反而不想写啥了。

转个公司的内部公告:

心系四川灾区 员工募捐倡议

各位亲爱的兄弟姐妹:

看着四川地震灾难的图片,您一定已经默默地流过了泪,我们感受到了你的爱心,更加感受到了灾区人民的无助,是苍天无眼,但身为中国人,我们是一家人。现在就伸出您的双手,拉上身边的伙伴,虽然我们不能亲自去安慰他们,但我们一样可以支持他们。

已经三天了,全国上下在不断的献出爱心,现在就尽上我们的绵薄之力,去支持他们活下去,去支持他们重建家园。"家"是美好的,但他们失去了,就在一瞬间……让网易的全体员工,积极行动起来吧,让我们的爱去温暖他们受伤的心灵!

昨日公司已率先向灾区捐款500万人民币,并将视灾情考虑追加捐款。

同时,网易四地:北京、上海、广州、杭州今天中午12点起将开通"心系四川灾民--员工捐款箱",接受员工现场捐款,捐款时间截止2008年5月23日(下周五)18点。

此次募捐,因人力原因暂不接受物品捐物。所筹得四地捐款将与公司的捐赠集中统筹使用,灾区重建时公司将委派专人赴灾区,根据实际需要合理使用善款。

现在开始,请擦干心中的眼泪,勇敢些,让我们陪着他们一起努力!

天亮了,我们相信,有我们的爱心,明天会更好!

四地捐款地点如下:

(以下略)

另推荐:科学松鼠会之地震专辑

May 13, 2008

那些日子(十四)

让网易在网络游戏上看到希望的是《精灵》。这是个从韩国代理来的游戏。当时我们也有可能去谈 MU ,即《奇迹》。为什么定了精灵而不是奇迹呢?我听到的不确切的说法是,奇迹要价太高。

现在看起来,今天几家大的网游运营公司真的是特点明显啊。代理奇迹的九城,几个产品都敢花大价钱下注,先是奇迹,而后是魔兽世界。我想它的成功也绝非偶然了。

至于当时我看到的 RO ,其实也是个相当不错的产品。要价也不低,不过更重要的是 RO 制作完成的时间稍微晚一些,而精灵已经声称可以运营了。公司等不及,也是一方面原因吧。

在我的感觉里,从 01 年末开始,网易在各方面都是非常节省的。或许和丁磊的性格有关。也是这份节省,让公司在几家在 nasdaq 上市的中国网络公司中第一个起死回生。

《精灵》的市场部门放在了上海,办公室就设在人民广场边的高楼大厦中。西藏南路,楼下有家馆子叫作上海人家,味道不错。去上海出差时同事总是带我去吃。现在上海公司已经不在哪了,可能是因为人员增加,房租太贵吧。大猫猫就在《精灵》开始运营时,回了上海。

精灵的的技术支持部门以及机房设在广东。如果我没记错的话,机房租在佛山(ruiheng 提醒我说是在东莞,哈,还是记错了),这也是因为机位便宜的缘故了。小强从学校毕业没多久,便被指派到这个项目里做远程系统维护。

据说,当时公司为了节省开支,全部按普通家用 PC 的标准采购了一大堆的兼容机做服务器。4000 块一台的标准,甚至配的是 IDE 硬盘。可害苦了值守机房的同事(经 ruiheng 提醒,是 charles ,我没打过交道,没印象),时刻都有硬盘坏掉。守在机房,几天不能回家。后来精灵停止运营,这些机器淘汰下来,全部搬回办公室给大家办公用机更新换代。我做梦幻那会儿的机器就是精灵服务器呢,换下来的机器则交给策划写文档。策划再将淘汰的机器送去客服组监控游戏中的聊天频道,或是扔到 QC 部门做低端测试机。

任在服役的一台服务器,被我借了块空间存放个人主页了,一直到今天还在工作着。

精灵的收费标准是破天荒的五毛一小时。那个年代,大家都还摸不清玩家的心理底线和承受能力。居然这个价位游戏也依然火暴,真的是个奇迹。要知道当时玩的人最多的传奇要便宜很多,而且精灵相比传奇还缺少一个重要功能:PK 。

精灵大约是在 6,7 月开始收费的,没过多久就收回了成本。记看起来,小强也拿了不少奖金,刚毕业就能这样,自然是很高兴的。

从我的角度事后去看精灵,它更大的作用是推广开了网易一卡通,让网易的点卡顺利进入了各个渠道,为日后大话西游二的顺利收费铺平了道路。

那段时间,丁磊显得踌躇满志。一天晚上他到游戏开发组的办公室转悠,走到我的位置前要看看大话新的 client 。之后我们谈起游戏产品。他说,“我们的目标是做国内第一,盛大算不得什么。”我心里只嘀咕,现在我们离盛大还差一大截呢,就算在国内网游市场,前三都还排不上。精灵看起来是不错,但是比起传奇的用户来,远远不及。这大话,老实说,我愿意花心血投入做新版本,仅仅感觉前一版有自己参于但没做好,羞于见人。真正做出来,能不能抢占到最大的市场,还是个未知数呢?石器时代仍有人气,后续产品魔力宝贝已经上市。甚至国产的幻灵游侠也比我们之前做的好。


可惜,精灵的火暴没持续了几个月。毁掉这个游戏的居然不是游戏的设计,不是游戏的稳定性,而是外挂。

听到第一起相关报告时,我的脑子里只怀疑了几秒钟。居然有玩家用 FPE (当年很流行的一种单机游戏修改软件,可以锁定内存中的数值)就可以修改这个网络游戏。有玩家用 FPE 锁住血,就可以在游戏中获得不死之身。我立刻理解了这个游戏代理费为何如此便宜,还真是一分钱一分货啊。(虽然日后奇迹 MU 也饱受外挂之苦,可也没这么离谱的)

在网络游戏发展的初期,我想任何一家开发公司都是缺乏经验,需要一段时间积累的。早期开发出来的产品多半有些问题。据我个人猜测,精灵是从一个半成品的单机游戏中改动过来的。大部分设计都是单机模式。而做成网络版的好处是,可以省略单机游戏必须的一些要素,比如丰富的剧情,过场动画,等等。这个游戏只是在单机游戏的基础上增加了一点网络通讯功能,让玩家之间可以相互看见对方在干什么。所以也能想到,为何它们游戏中没有设定 PK (韩国官方的说法是,他们国家里网络游戏会被分级,PK 的设定会导致某个年龄以下的玩家不准来玩)。听说精灵后期的版本开放了 PK ,这我就不得而知了。

开发难度小,自然费用也就下来了。

还有几件事情可以看出精灵的程序之不成熟。

我们曾经向韩国公司反馈过 client 不能在 windows 98 下运行,他们说,他们没有考虑过支持 windows 98 ,因为在 2002 年,韩国人几乎全部升级到 windows 2000 了。我们很无奈,当时 windows 98 在国内的网吧还是主流操作系统。从我一个程序员的角度来看这个问题,兼容 windows 98 系统并不是什么困难的事情。可以在 windows 2000 下跑的游戏,如果在 98 下会出错,多半是一些 bug 导致的,而非用了什么专有 api 。(例外也是有的,有些因为 win98 早期版的一些 bug ,用户又不愿意更新系统。此类问题我在调试大话的兼容性时遇到过,解决起来也很快)

起初精灵的 Client 在没有声卡的机器上会挂掉。我用 ida pro 分析了一下,发现他们没检查声卡设备的初始化结果。Ali (精灵当时的产品经理)说,他找几个朋友搞一下就好了。我明白他的意思,他做游侠网,一定认识许多做破解汉化的朋友。对着二进制的程序做点这种小改动那是小菜一碟。其实甚至用不着他去欠朋友人情,我自己来弄也就是一天的事情。只是既然我们跟韩国公司是合作关系,他们有源代码,做起来也是快的很。可这件事,还是 ali 去找朋友搞定的。或许是沟通上的麻烦?

我们在精灵运营之前,派人去了趟韩国做技术上的交接。dingdang 带着 ruiheng 和 kyo 去的。大约是 2002 年 5 月的事。当时世界杯正准备召开,kyo 回来时还送了个一个世界杯的钥匙扣。本来我也要去的,因为筹备大话 2.0 的 beta 测试很忙,一直没能请假回家办护照。所以在韩国看见了什么,就都是 ruiheng 和 kyo 给我转述的了。

我们去只是去商量汉化以及登陆收费接口对接的事情。但 ruiheng 说了一些无关这些的见闻。对方是个小公司(接收了网易的版权费后才逐步扩大),几乎所有的程序都是一个人(CTO?)在做,当一个人急着赶产品时,版本控制这么关键的东西也被忽略掉了。所以精灵的代码管理很成问题。这也是我们几次三番要求他们改东西,对方都显得那么痛苦的缘故。

到 2002 年 9 月时,韩国方面按我们的要求做中秋活动,不小心弄出点 bug 。我们报告后,对方怎么也改不好。韩方的理由就是,正在做国庆活动呢,老代码已经找不回来了 :( 。代码管理之混乱,可见一斑。经过我们的强烈要求,他们才上了 vss 。

btw, 精灵的服务器也是架在 windows 上的,不是很稳定。

kyo 在韩国时跟我爆料,说韩国的网络条件很好呀,他们公司每台机器都有一个外部的固定 ip 。可他们的网络安全防范意识简直是太差了,在这些直接暴露给外网的机器上,居然开着文件共享。公司里也没有装防火墙。

那几天,大话西游新版上线,效果非常好。在主要开发人员都不在办公室的情况下,也基本没出什么问题。我们在之前测试的实在是太长时间了。我便买了台 GBA ,上班时坐在那里打黄金太阳和高级战争。一周就把两个游戏都翻版了。


精灵的外挂问题从软件设计角度看就是无法解决的。当然,如果精灵不那么设计(把绝大多数的运算放在客户端本地计算),它可能也做不到流畅的游戏感觉。

公司想了很多办法也无能为力,至少我是绝望的。韩国方面派了几个韩国人常驻我们公司,除了跟外国人交流一下让我觉得挺新鲜外,我觉得在外挂这件事上,他们起不到什么作用。倒是韩国朋友给我的印象还不错,相处很融洽。他们笑广东人吃不了辣的,我就带他们去吃正宗的川菜;我带他们去陈家祠转,介绍木门上的三国演义的雕刻。说起三国,他们也是知道的。大家英语都很一般,有时候说不清楚,写写汉字居然也有些效果。听说韩国人上学时要学千字文,还是识得许多汉字的。

最后他们留下来的一个计算机研究生,编程水平一般。就是很好强。有一次需要写一个统计精灵的数据库中数据的程序,他实现出来效率非常低。ruiheng 说不能这么慢的(跑一遍要几个小时),他硬是重写了一遍(减少到几分钟),声称不能更快了。我们都没再好意思去驳他的面子。

到 10 月的时候,精灵的产品组下了个无法判断对错的决定:把用程序检测出来数据异常帐号全部删去,号称删除了 10 万玩家帐号。一时间,骂声一片。现在想来,一定有误删的,无论相信自己的程序判断的多精确,都有可能有一些例外没有考虑到。这个错误,后来我在抓大话的加速外挂时也犯过。当和用户打交道时,毕竟不能太强势了。

至此之后,精灵开始走下坡路。丁磊曾经从雷军那里借了个人来,和金山联合开发反外挂软件。其实就是一个软件加壳监控系统。检测用户有没有非法修改内存。我对这种旁门坐道的玩意不以为然,实际上也的确没有什么效果了。

那段时间和 tarcy 喝酒时也聊过这个段子,tarcy 做这行的,对此非常不屑,举了很多手段来绕开这些监视系统。从这条路去堵住外挂,绝对是条死胡同。

再过了两年,我带了三个应届毕业生,想利用精灵的图片资源,重新实现一个《精灵》。(主要目的是想让新人练练手,重现精灵的辉煌倒没怎么想过)。之后,因为公司加大了天下二的投入,把这几个人全部编入天下组。重制《精灵》的项目也就取消,就这样不了了之。


从 2001 年底开始,随着短信收入的增加,丁磊在网易的地位就逐渐稳固了。董事会没有了那么多的反对声音。虽然游戏在 2002 年的开发尚未赢利,但老丁看准了这条道。dingdang 接手游戏部后,人员开始扩张。

程序方面,先有庞鑫和安宁的加入,打算开始制作 3d 项目。原本跟庞鑫一起过来的还有徐创,但因为一些原因,没多久就离开了。徐创跟丁磊起言语冲突的那个晚上我也在场,记忆尤新。不过扫兴的事情不想重提,谁是谁非也很难公断。倒最后剩庞鑫和安宁留下。

接下来几个月,庞鑫因为感情的问题,每个月都回一次北京。他笑称,赚的钱都贡献给中国民航了。他的前女友最终跟别人结婚我是知道的,甚至我还借了他几千块凑钱买结婚大礼。庞鑫在广州干的并不快乐,他走的也很突然。谁也没告诉,毫无征兆的连着两个月没来上班。安宁说他回了趟北京后就没再来广州。甚至在广州公司附近租的房子都没有退租,屋子里留下了新买的电器。

之后,我和庞鑫失去了联系。听说他回去后自己在做手机游戏,弄了个英文网站,把游戏卖给外国人。据说这种收游戏注册费的形式,做的还挺不错,口袋挺滋润的。

安宁留了下来安心做项目。3d 项目一直没定下来做什么,技术方案也不确定。早先想用 Torque 3d ,这个引擎一度在国内很有名气,因为它只售 100 美元。我甚至看到 3d 组的人搭了一个像模像样的一个场景出来,还倒入了许多西游中的人物模型,看起来就可以做个大话的 3d 版了。其间,曾为大话西游一写过几行代码的黄东海回来看过大家一次,对公司 3d 项目如火如荼的展开感叹不已。

可毕竟 Torque 这个东西是个七拼八凑起来的玩具,真应了我反复说的那句话:便宜没好货。(免费开源的不列入其中 :) )

这里就不仔细评论 Torque 引擎的好坏了,我没亲身用过,都是道听途说。想采购引擎的朋友别来问我。ps. 我说的也是 02 年的故事,至于 Torque 今天发展成什么样子,一无所知。

接下来,曾在鹰翔工作的小蓝也来了网易。不知道 dingdang 怎么和他搭上的线,反正不是我介绍认识的。dingdang 告诉我小蓝会过来时,我还楞了一下。那天我给小蓝接风,和 dingdang 一起陪他在 36 楼楼下的蓝与白快餐店喝粥。在广州的第一年,我最喜欢这家快餐店。就在我家对面,方便实惠,味道还不错。我恨不得把这家店写入游戏的感谢名单中。

小蓝在网易也没干多久,他的离开我没去问。我想他分到 3d 项目里,可能有些漫无目标的感觉。这个项目做了太久,实际上比我们当初能想象的都久。直到今天,也就是那个被称为“天下二”的游戏项目,尚未完成。

这真是个矛盾。一个成熟的游戏,包括它的各个部件,需要大量的时间来做。而参与项目的人,往往经受不了长时间的煎熬。开发人员很容易疲惫。而快速赶出来的东西,又很难做好,总是有太多的细节缺失。

或许抄袭是条捷径,但不甘心抄袭呢?都说当局者迷,旁观者清,可又有几个当局者真的是笨蛋?

每个成功都有其偶然性,也有其必然性。不可忽略两者其一。我们需要一些坚持,守着有一定概率发生的事情真的发生。


谢绝转载

那些日子(目录)

May 12, 2008

那些日子(十三)

这几天,许多同事 popo 上跟我聊天,谈及这段时间写的这个系列。老同事一刀(从大话一开始到现在一直在写游戏服务器),那是感慨万千,还帮我纠正了一处人名的错误;同样的有许多人,督促我修正一些小地方,我都一一改过了。有人聊起来,夸我记的好清楚,如同昨天才发生的一样。

真是不敢当,我的记性其实不好。记不清的人和事远比记下来的多,尤其容易忘记别人的名字,很惭愧啊。我只是写下那些能记住,可以理清前后因果脉络的故事;更多的人和事情,由于记忆残缺,分不清时间,不知道该放到故事的哪个角落。

我记得麻雀当年陪我选手机;记得美术部的一群长发帅哥集体去剃光头;记得给乌鸦夫妻参谋买房子;甚至记得牙牙来报道的那一天情景……

记得一刀他们在公司地板上过夜;记得 Mario 半夜里陪着 mm 在办公室里看流星花园;记得我们大家常去的大排档;记得凌晨两点干完活,一起打车去石牌东吃烤蚝,萝卜还一个劲的说没有他们家乡的好……

我只是记下自己的历程,但我不只是为自己写。我也为大家写,尽可能帮一起共事过的大家留下过去快乐的点点滴滴。美好的记忆不是什么可耻的事情 :) ,可耻的只是永远停留在回忆里的人,我想我们都不是这样的人。如果再有同行的朋友读过来,尽可以在留言中留下你的故事,或是提醒我一些被我遗漏的重大事件。

对于新加入网易的同事,据说有许多人是这个系列的读者,如果我写的能让迷茫的人看到一条模糊的路,那没有什么比这更能让我高兴的了。让我觉得在繁忙的工作之后,从每个晚上划出三个小时写这些很有价值。

网易之所以是一个好公司,正是因为不断的有同样信念的人聚集在一起。那些尚且不足的地方,需要大家一同努力。

以下是今天的正文:


说起国内自主研发的第一款商业上成功运营的 MMORPG,不应该算给《大话西游2》。

2000 年底,另一款网游悄然上线,并在 2001 年初成功收费,同时在线人数一度攀升到好几万,远超过当时失败的《大话西游》,它就是天晴数码的《幻灵游侠》。

我下载了一份《幻灵游侠》的 client ,发现居然是用 C++ Builder 做的,不由自主的想起了姚晓光。他 QQ 上的名字是 npc6 ,这个网名可能更多人熟悉一些。

2000 年在北京鹰翔的时候,我经常给林广利推荐一些写程序的网友过去工作,林广利不懂程序,也时常让我帮忙和一些来应聘的程序员谈,算是面试了。姚晓光和他的哥们陈晨就是那个时候进入的鹰翔。

加上在大学最后一年辍学的小蓝,和我的一个老朋友彭乐,他们一起做《碧雪情天》。一个单机游戏,后来也制作了同名的网络版。

姚晓光喜欢用 RAD 的工具做开发,所以尤喜 BCB 。我那时维护了一个风魂的 BCB 版,但之后由于 BCB 的一些 bug 把我弄的痛苦不堪,就放弃维护了。姚晓光就是给我 report 那些 BCB 版风魂 bug 的人。

他和陈晨不久后离开鹰翔,我没有打听去了哪里。直到《幻灵游侠》上线,好奇的网上一问,他还真的在天晴。

《幻灵游侠》运营的情况我不甚了解,但是半年后我和姚重逢在林广利的办公室里聊天时。我意识到这款游戏还是很成功的。姚晓光说他后来一个月能拿到三万的月奖金,让我心里暗暗惊叹。倒不是羡慕,只是觉得,网络游戏还真的能赚钱哪。

《大话西游一》的最后那几个月,公司给大家发了一次奖金,算是犒劳辛苦了快一年的兄弟们。我领到奖金时,古越和果子都走了,micro 还在,但没多少事做。那一次,似乎有几千块(或是一万?)的奖金。我总觉得我能拿这么多,是因为做 client 的人只剩下我一个。

两者一对比,足可见成功的项目与失败的项目之差别了。

不久以后,姚晓光和彭乐去了盛大制作《神迹》,小蓝来到了网易加入 3d 组(即以后的天下二),此是后话。


当《幻灵游侠》如火如荼之时,我们还在紧张制作这《大话西游 2.0》。当时国内市场上还有几款更为火暴的游戏,其中首推《传奇》。几乎占据了大半壁江山。《石器时代》的后续产品《魔力宝贝》也崭露头角。我几乎觉得形势已定,根本没想过产品日后要在商业上超过这些,但我单纯的想把大话2.0 做好。内心里,我把大话一的失败看成自己的一种耻辱。

前一次说了不少大话2 项目的好话,现在可以谈谈一些不足了。

其实大