« December 2007 | Main | February 2008 »

January 29, 2008

辟谣

今天在 popo 上有则可笑的消息传播开,居然连刚离开公司的同事们也将信将疑。鉴于过往的一些事情,我想对于澄清谣言还是及早做点贡献比较好。

关于今天坊间盛传的“传网易人事变动:丁磊将亲掌游戏业务”这则新闻,提到 dingdang 将离职的消息,完全是一则谣言。

圈内的朋友也不要再来向我求证了。我这人从来凭内心说话,大家可以不认同我的观点不相信我的判断,但绝对值得相信我这个人。至于散布谣言的所谓“知情人士”是何居心,这里就不妄加揣测了。

dingdang 可以说是网易游戏部门的灵魂人物,也是许多人的精神支柱。他的贡献和付出所有网易人有目共睹,我相信绝大多数人是认可的。即使有人不认可他的工作和做法,但绝对认可这个人。

我跟 dingdang 有相当不错的私交。他在交接工作的前不久,也就是不到一个月前,专程来我这里。我请他吃饭喝咖啡,两人长聊了一个晚上。我想我了解他的想法,也理解他为什么这次脱离游戏部门的最高管理岗位。这里有很复杂的因素在里面,我想不是三言两语可以解释清楚的。也不必在公开场合多解释了。

January 28, 2008

安全的提交密码

这篇 blog 的内容原本是去年 10 月写的,当时正在看《24小时反恐》,脑子里涌现出无数古怪的想法,觉得这个世界到处都是特工,什么通讯手段都不可靠。在我们还没有能力获得量子加密需要的硬件前,能有限依靠的恐怕只有数学能保证的加密技术。

当时那篇 blog 写了一大篇,自己都觉得太过于天马行空的乱扯,就没有公开。

不过今天开周会,我们又提到游戏 client 提交密码的安全性问题,指派了一个同事最近在这方面做些工作,这里也写点以前研究的东西,留点记录吧。

简单说,我们应该避免在一次登陆过程中从互联网连接中传递明文的用户名密码信息。这是一个起码的要求,但是我们以往的产品做的并不好。很多时候都是伪加密。就是 client 用个私有算法将密码信息编码后传送,再由 server 用相同的算法还原。

这个安全性极度依赖 client 的程序不被逆向工程。一旦有人完全逆向工程后,只需要他监听到通讯,就可以还原出用户的密码。

物理上防止通讯被监听的技术在可见的时间内几乎不可能被大众使用,我们现在即使能保证自己的 client 机器没有被人动过手脚,还是无法知道自己的通讯数据是否被监听。只能寄希望于数学的加密技术了。

SSL 就是干这个的,但是由于种种原因,暂时我们还不能在游戏 client/server 中推行使用。那么,现在是不是可以抽出一些东西来,自己先在程序中实现出来用着。其实,优先要做到的,无非是安全的让用户提交用户名密码而已。

最著名的算法莫过于 RSA 。我想任何一个理工科跟计算机沾点边的大学生都应该了解那么一点。

知道 RSA 算法大约是在高考前夕。当时读到了 Gates 先生写的一本书《未来之路》。让我尤为感兴趣的是其中介绍的非对称公私匙加密算法。进了大学后,当拥有很多的时间时,我去校图书馆翻阅了一些论文,了解了最著名的 RSA 。

简单来说,RSA 算法可以看成一个带锁的箱子。只有箱子制造者可以打开这把锁。而箱子上有条缝,别人没有钥匙也可以往里面塞东西。

如果 A 和 B 想交换保密信息的话,那么由 A 做一个 RSA 箱子交给 B 。B 把东西塞进箱子送还给 A 。这时,A 就可以自己把箱子打开,拿到 B 给他的东西了。

RSA 的问题在于计算速度。RSA 需要做大数的幂运算,这需要消耗大量的计算资源。所以直接对信息做 RSA 加密不太适合高带宽的通讯。继续上面那个直观的比喻:RSA 固然是个不错的箱子,但无论是打开它还是向里面塞东西,都颇费周折。所以,作为 B ,通常是配一对普通锁的钥匙。把钥匙而不是东西本身塞进 RSA 箱子。然后再用轻巧(但同样坚固)的锁来运送货物。

现在的问题是,直接拿 RSA 来加密用户登陆信息是否合适?

看起来是满不错的,用户登陆无非一个用户名一个密码,符合上面轻巧的定义。如果我们不要求特别高的安全性是完全可行的。不过这里我们想讨论一下别的算法方案。


关于 RSA 的问题。

如果有足够的计算能力,和足够的时间,理论上我们可以从 RSA 的 public key 中提取出 private key 来。所以,基于 RSA 的加密系统都会在生成 key pair 时给它签上一个过期时间。

假设我们每次通讯都用 RSA 加密当次通讯用的随机 key ,再用这个随机 key 做传统对称加密(比如 DES),那么在一定时间内,这些通讯数据我们都可以认为是安全的。

可是,如果有不怀好意的人从一开始就监听了你的所有通讯数据流并记录下来会怎样?虽然他一开始并没有能力解密里面的数据,但是他可以昼夜不息的去分解那个大素数,直到有一天提取出你的 private key 为止。即使你在 key pairs 过期之前更换了新的钥匙,但是,你曾经的所有通讯数据都会在老的 key 被解密那天同时变成明文。

而且,如果你是用私人途径发布 public key 来防止恶意监听者拿到可供分析的材料。那么你用这个 key 次数越多就越容易暴露。

怎么办?如果想避免大量历史信息同时被解密,难道我们每隔几次通讯就换一对钥匙吗?RSA 的钥匙生成代价可是很大的。

伟大的数学家们自然有好方法来解决这个问题,其中最著名的某过于 Diffie Hellman 密匙交换协议。


简单说来 Diffie Hellman 协议可以干这么一件事:A 拿到一个神奇的 Diffie Hellman 箱子,随便找把锁(选择一个随机数)锁起来,发给 B 。这个箱子的神奇之处在于,一旦上两次锁,它内部的机关就会根据这两把锁在内部制造出一个随机的钥匙。只要每次上的锁不一样,制造出来的钥匙就不一样。当 B 收到这个箱子后,加上第二把锁。打开箱子,取到随机钥匙配上一把,然后把箱子送还给 A 。

这个时候,A 和 B 都是箱子的主人。而当 A 也打开箱子,就取到了 B 已有副本的那把钥匙。今后,A 和 B 就可以用这对相同的钥匙来加密传送信息了。

和 RSA 箱子不同,每个 RSA 箱子和锁是一体的。而 Diffie Hellman 箱子可以配许多把普通的锁。每一个独特的 Diffie Hellman 箱子的制造成本虽然相对比较高(要生成素数的原根还是很麻烦的)。但因为锁上它的锁成本却很低。每次 A 和 B 想交换钥匙,都可以换新的锁。这样,每次通讯都可以看成是独立的,一组通讯被破解,并不影响其它通讯的安全性。只是 RSA 箱子虽然繁杂,理论上却可以装任何东西。Diffie Hellman 箱子固然神奇,但它却放不了指定的物品,只能自己生成钥匙罢了。

btw, 以上的比喻只是方便理解,可能并不太准确。有兴趣想了解的朋友可以自己去 google 资料。

我们很容易想到, Diffie Hellman 协议也有天生的缺陷。随机生成的密码不能携带双方的身份信息(因为不能人为指定)。这样容易被中间人攻击。如果需要,我们就得进一步改进它。联合使用 DH 和 RSA 可能是个好主意,今天就不展开讨论了。也有对 DH 改进的协议如 OAKLEY 协议 用来解决用户身份认证的问题。


前两年刚玩 palm 手机时有个有趣的想法,就是做一个加密短信发送软件。不用太复杂,用类似 DES 的对称加密算法就可以了。如果两个朋友有见面的机会,用红外传输约定一个密钥,以后可以用这个密钥加密发送短信。由于密钥没通过无线网络传输,仅限于面对面红外约定,我们可以认为密码交换是安全的。

如果简单的每次都用那个约定的密钥加密,一旦有一天有一方的手机本身落入“老大哥”手里,那么由于以前所有的加密通讯都可能被记录,也就意味着所有以往的秘密都被公开了。这对另一方非常不利。

我想了个简单的方法避免陷入这种尴尬的局面。那就是每次加密短信发完后,都将密钥 hash ( md5 ) 一次生成下一个版本。发送加密短信时,将密钥版本号明文附在信息前面,防止中途丢失信息导致的密钥不同步。由于 hash 函数的不可逆性,我们就可以建立起一个有相对隐私的 p2p 短信平台了 :)

January 25, 2008

版本控制系统再考察

鉴于迁移版本控制系统的工作量比较大(主要是培训成本),这几天我们工作室重新调整了下各自对 svn 仓库的管理权限,理了下以后的开发管理流程。最终决定继续把 svn 用下去(至少到项目第一阶段完成),希望比以前用的更好。

但出于个人兴趣,我继续考察了几个分布式 VCS/SCM ,并装了其中几个玩。个人直觉 Darcs 最好。不过从流行度讲,或许 Mercurial 更佳。

虽然近期网上似乎支持 Mercurial 的最多(包括乌龟版也做的最全面),但我还是找到一篇文章支持我的直觉。

Whose Distributed VCS Is The Most Distributed?

他写的算是有理有据了。

不过这篇 blog 成文于 2006 年 8 月,离现在已有些年头,在这个讯息万变的今天,每个活跃的开源软件都会不断的发展,大家姑且看之。至于我的个人意见,只是出于直觉,没什么可参考性。

作者提出了理想的分布式版本控制系统的八点要求,这也正是我想要的:

  1. 协作的基本模式必须是基于分支。

  2. 做分支必须很廉价。

  3. 可以智能的合并分支。

  4. 每组更改集都不必通过整个更新历史就能和其他部分合并。

  5. 分支既是仓库的副本,分支操作保持有全部的历史。

  6. 合并操作也不损失更新历史。

  7. 提交、分支、合并操作都可以离线完成。

  8. 针对大多数应用都尽可能的快。

关于这 8 点的具体解释,有兴趣的朋友可以去读原文,写的很清楚。其实对于我,没必要分这么细。我需要的就是,大家可以基于分支来协作工作,而不是基于单次提交。我每次向大家工作的集合(主干)做合并操作,应该包含一系列的本地提交。在完成这个功能的基础上,VCS 应该用起来足够简单(简单的用 pull/push 取代 update/commit),不损失我的工作流程包含的信息(从何时分支,何时合并,中间做了一系列什么修改),且跑起来足够快。

作者的结论是明显偏向 Darcs 的,这个观点倒是可以商榷。不过 svn 显然达不到大多数要求。这几天我在 svn 上做了许多分支合并的试验,发现 svn 很不人性(相比更人性的分布式设计而言)。为什么会这样?因为 svn 设计之初本就不是基于分支来解决大家的协作问题的。

btw, Darcs 对中文支持可能会有问题,但是可以通过设置环境变量绕开。请参考 Darcs 的手册中 Character escaping and non-ASCII character encodings 一节设置。

January 22, 2008

分布式的版本控制工具

我最早接触的 SCM 工具是 vss ,但是没用几天(换工作到网易后)就迁移到了 cvs 。我自己大约用了一年后,公司集体从 cvs 迁移到了 svn 。领导这次大迁徙的大大说, svn 是一个更好的 cvs (确实是这样吗?据说有争议,但至少我感觉在多文件版本控制上 svn 比 cvs 方便,因为 cvs 无法保证多个文件同时提交的原子性)。

前几年,有人跟我争论过到底 vss 的加锁模式好,还是 cvs 的合并模式好。我觉得答案是不言而喻的,懒得争论。虽然在某些特殊环境上,我们偶尔需要加锁模式协同工作,但对于程序员的协作来说,无疑我们需要并行的工作。

我们在若干年前曾经淘汰过一次加锁的协作编码方式,而到了今天,是时候再做一些改变了。或许,分布式的版本控制工具才是未来的发展方向。我想,总有一天,cvs/svn 这类集中式版本控制工具会被淘汰掉的。

说说我的困扰吧,可能很多开发小组也遇到过。

  1. 我们禁止提交不能编译通过的代码,尽量不提交不能测试通过的代码。结果,对于很复杂的模块,有人几乎一个月都没提交过一次。他总是觉得程序还不太成熟,但几经修改的代码其实从来没有作版本控制。

  2. 有些模块由两个人合作编写,关系非常紧凑。有时候需要在两人之间交换一些代码,为了方便,大家通过代码仓库中转,结果在仓库中留下许多未完成的版本。

  3. 代码被用笔记本带回家,结果在家完成的部分无处可以提交。(为了安全,我们的代码仓库不能从外网访问)

  4. 某人写了一个模块,总是有 bug 没有修改完,而不敢提交。这个时候,另一个人希望协助他找问题,却没有合适的途径 share 那段完成了一半的模块。跑过去 XP 一下么?天哪,为什么我们这里每个人用的编辑器都不一样,还都爱用些特别个性的配色方案呢?

我们尝试过一些 work around 的解决方法,比如在本地自己创建仓库。托 TortoiseSVN 的福,这件事在 Windows 下做起来还是很简单的。可终归是多个仓库的管理,用的人始终感觉麻烦,而没有贯彻下去。

今天有同事问我,分布式版本控制工具到底跟我们现在在用的系统有什么区别。我想了一下回答说:它的本质就是在原有工具的基础上增加了一种方便的仓库合并功能。(哈,我接触这类东西时间不长,大家就当我胡说)

集中式版本控制工具,总要求你有一个中心服务器,提供一个项目仓库。每个人都必须严格保持跟仓库的内容一致。当项目大于等于 2 人时,往往都会指定一些规则,比如不要提交写了一半的代码到仓库去等等。结果,这些规则导致了上面我提到的问题。

即使是一个人自己用,有时候也会碰到问题。有一次我回到家,看到老爸(一个老程序员)在家做一个自己的小东西。因为我们家有两台电脑,我看见两台机器上有若干份不同的版本,我便推荐他用 svn 。因为两台机器都不是 24H 开机,我便选择了在 U 盘上创建仓库。可以设想的到,两台机器的 U 盘插入后盘符是不同的,这可真是一场灾难啊。

其实大多数情况下,我们要的仅仅是 版本管理 ,并不要求通过这类工具协同很多人修改同一份代码。在我们公司,修改别人的代码是要通知文件创建人的。大家都尽量在自己的工作目录下写东西。我并不要求分布式的版本控制工具帮我解决开发人员分布在不同地方的问题,我需要的仅仅是可以更方便的创建私人(或小团体)的分支,可以局部的提交的问题。这些,只需要一个仓库合并的特性就做到了。


我比较孤陋寡闻,知道有分布式版本控制工具是从 git 发布的消息开始的。有 Linus 的鼎鼎大名在那,应该是个好东西。我想还会有一些跟我一样,一进入项目开发就两耳不闻窗外事的朋友,不知道 git 是何物的话,不妨看看 Git 中文教程

可惜的是,git 对 Windows 支持的并不好。我们至少还有一半的项目跑在 Windows 下,开发人员则超过一半在用 windows 平台。听说其原因是 git 非常依赖文件系统的一些特性,这些在 Linux 下表现的很好,而 Windows 下特别糟糕。不管具体原因是这个还是别的,我对在公司推广 git 没有多少信心。

另一个选择是 Monotone ,但听说跟 git 有同样的问题(对 windows 的支持问题)。毕竟 git 本身就受了 monotone 的很大影响吧(我猜的)。有趣的是,和 Git 一样 Monotone 也是用 C 写的。当然这句话其实应该倒过来说,因为 Monotone 是从 2003 年开始的,比 Git 早多了。

关于 Git 和 monostone 对 windows 支持不太好的说法,可以参考这一篇: Mozilla: Version Control System Shootout Redux Redux ,Mozilla 的大大这样评价:Git is inappropriate for cross-platform projects due to its UNIX-centric nature; same goes for Monotone.

嗯,既然 Mercurial 是 (Mozilla 的) current favorite (but not the winner) ,我们也可以关注一下。说起来,Mercurial 的命令名很有趣,是 hg 。我花了几秒钟才反应过来,Hg 就是汞嘛 :D 。

下面再让我们看看几个候选人,Bazaar 的网站上有它和其它几种工具的比较。虽然有人说它性能不行,但我想那是针对 Mozllia 这种超级项目说的,我想对我们这样的小东西不会有什么影响。别的方面看起来很不错哟。尤其是它宣称的智能 rename ,真是太有爱了。

svn 下给目录 rename 绝对是场灾难。如果你不小心没有直接去仓库中 rename ,那么就意味着目录下所有文件的 del / add 。而即使你在仓库上直接操作,所有 client 都会大量的做 del / add 操作。每当这个时候,我都超心痛我的硬盘。

darcs 看起来也不错,我对 Haskell 本身就有莫名的好感,用 Haskell 写出来的软件对我就意味着稳定。虽然我自己不怎么玩 Haskell 也不太用 Python ,但是若让我花时间选一门语言玩的话,我会优先试试 Haskell 的。

作为 svn 的老用户,或许应该多关注一下 svk ,它在 svn 的基础上增加了一些分布式管理的东西。但是我不太喜欢这种补丁式的解决方案,因为设计总会随着需求而改变。若是背上太多历史包袱会让我有些不详的预感。

最后可以看看 GNU Arch 。我浏览了 arch 的 wiki 中 WhyArch 这一页,吸引我的是最后两条:

  1. Arch is lightweight

  2. Arch has a clean and transparent design

不过从 google 搜索结果来看,我没觉得 GNU Arch 是个有前途的项目(相比前面几个而言)。


对于我这样依然有部分时间在 Windows 环境下苟延残喘的程序员来说,有个好消息。那就是托开源的福,可爱的小乌龟无处不在。

  1. Mercurial 的乌龟版:TortoiseHg

  2. Bazaar 的乌龟版: TortoiseBZR

  3. Darcs 的乌龟版: TortoiseDarcs

不过就我的历史经验,只有 TortoiseSVN 是正宗乌龟,最好用。不用对其它版本乌龟的操作手感抱太大希望。


1 月 23 日 补充:

下面很多朋友谈到,合理的使用 branch 的功能就能解决我碰到的大多数问题。

没错,的确是这样。但是我们现在使用的 svn ,由于各种原因开 branch 都是件很麻烦的事。并不是指操作麻烦,而是管理麻烦。我们没有专门的代码仓库管理人员,大家比较松散。另外,在经过一次安全事故后,公司要求严格控制代码树上每个分支的读写权限。最终导致开 branch 成本过高,而很少有人日常使用。

前面提到分布式版本控制工具提供了方便的仓库合并功能,这个仓库合并其实就是分支合并。并非 svn 没有,而是做的不方便。这一点正如 cvs 的一个老问题:如何方便的确定一组文件的版本,我们可以用 tag 来解决,但终究不如 svn 那样每次多文件提交都是单一原子操作来的方便。

January 21, 2008

周末过了两天黑白颠倒的日子

都是游戏给害的。

一开始迷上 Puzzle Quest ,装了个 PSP 版玩,一发不可收拾。初看起来就是一个 Bejeweled (钻石迷情) 的改版,很多手机上都装的小游戏,我见过许多 mm 喜欢玩。但是这次人家硬是做了极大的创新,变成了一个 RPG 。

职业、魔法、任务、升级、打怪、抓宠、合成装备,一个都没少。甚至战斗起来比大部分粗制滥造的网游有趣多了。消除方块也变的有意义,不再是比谁消的快,而是给不同的方块赋予了四系魔力、经验、金钱、攻击等不同含义。在对战的环境下,可以发挥更多的策略。与传统 RPG 不同,在 Puzzle Quest 里低等级玩家打败高等级玩家也是有可能的,即使级别相差很大而 RP/技术 足够好的话,总能有一丝胜利的希望。

把方块游戏玩出这种花样来,就不简单的等同于 PUZ+RPG 的组合了。相比我这几年经常听到的,“让我们把 XXX 类型 和 RPG 结合起来放到网游中”,“在 MMORPG 中加几个小游戏吧”,这才是真正的创新。而为啥我们的策划就如此没想象力呢?

好吧,没想象力就没想象力,退一步那就抄去吧。其实这个游戏抄到任何一个休闲游戏平台上都是绝对大作了。鉴于它拥有无数 RPG 元素,可以做角色培养,应该是很好赚钱的呢。:)

就这样,我用 Puzzle Quest 打发了周五的夜晚,一直睡到周六下午。


给同事推荐 Puzzle Quest 的同时,也有人给我推荐了 PSP 上新出的《勇者别嚣张》。从画面初看起来就是一个简化版的《地下城守护者》,但玩起来感觉却不太一样,只能说游戏目的类似吧:扮演魔王驱使怪物杀掉来进犯的勇者。

《勇者别嚣张》是全日文的,还尽是假名。(其实学过几天日语的人就该知道,其实片假名的词大多数就是对英文单词的音译,花两天时间背一下,外加日语中大量出现的汉字,玩日文游戏其实没多少语言障碍。)不要被菜单和游戏对白吓到。其实这个游戏的操作极其简单,就是方向键加一个挖掘键便可以玩了。

在今天,游戏/软件菜单越来越复杂的今天,我们这些游戏制作人应该好好反思了。复杂的游戏规则应该隐藏在背后,交给玩家用户的应该是最简单的交互接口。

这个游戏也非常耐玩,我周末打了一天,到第八关那个金色的勇士冲起来后就抗不住了。这激起我无比的好胜心,计划在下个周末通关。


《勇者别嚣张》的画面非常复古,不仅是基于 2d 平面 Tile 的,精灵的形象也是极其简陋的像素图。那个主角魔王的造型,立马让我联想到 FC 上的最终幻想一。勇者则是经典的 DQ 里的风格。

这个画风让我想起前些年有朋友推荐我玩的 NetHack 。一个发展了 20 多年,在今天仍旧在向我们展示 Ascii Art 的游戏。

当时我正着迷于《不可思议的迷宫》,有朋友建议我看看 NetHack 。NetHack 的前身是 rogue ,rogue 在《Unix 编程艺术》上也提到过,就是一个迷宫探险游戏。这个游戏影响之深远,以至于大量使用键盘热键交互控制的 console 软件都被称之为 roguelike 。

《不可思议的迷宫》应该就是这类游戏的直系后代。另外一些著名的游戏,如《Diablo》应该也算远亲,不过 Diablo 的自动生成迷宫表现的就远没它的祖先好了。

当年我没太把 NetHack 玩进去,今天心血来潮又当了一个试试。其实我的主要目的是想读一下源码,看看它如何自动生成随机迷宫和迷题的。这些代码早在 1985 年就成型了,还是很古老的 C 语言风格。但是设计人员的想象力却不比今人差。今天还有多少游戏程序员把心思放在“如何随机生成更好玩的迷宫”这样的题目上?

可惜 NetHack 的源码写的时候没考虑过支持中文,它的底层 API 是硬把字符一个字节一个字节写到 console 屏幕上的。中文一个需要两个字节,自然就不能正确显示了。

不支持中文可能是这个游戏一直没有爱好者去汉化的原因之一。另一个原因是其中有数以十万字的英文文本,用到大量普通字典也查不到的奇幻小说中才会出现的名词或缩写,工作量太大吧。

我试着做了下程序上的汉字支持,第一步是让其可以显示汉字出来。这里用了个 work around 的方法,因为字符串显示肯定是依次调用 xputc_core 函数。我在函数里检测字符的 ascii 值,一旦大于 128 就记录下来暂时不于显示。等下一次调用时,把两个字符连接起来一次调用 write console 的 api 。

第二步是做字符串替换。因为游戏逻辑都直接写到了源文件里,或是用一些代码生成数据。所以许多地方做一下字符串的汉化即可。我原本想把一些不熟悉的名词替换成汉字以便自己游戏时不用再查字典。后来发现,NetHack 里大量使用自生成代码,有的串该成非字母后会不太正常。这个时候就需要改些代码了,不过也不算太麻烦,毕竟人家程序写的很清晰,注释也很详细。

还有一些地方会成字符串中提取字母做游戏里用到的热键,直接换成汉字,游戏中就激活不了热键了。最终我保留了英文字符串,在数据结构中增加了中文字符串的字段,修改源码,让其在显示的时候调用中文信息。开源还真是个好东西啊!:D


不过以上也只是一些业余爱好,我已不是学生时代的我。那个时候有大量闲余时间做这些。

对 NetHack 有兴趣,并想继续汉化的朋友可以和我联系。我可以私下讲述一下自己对 NetHack 源码的理解,和做汉化的思路,节省汉化爱好者们的时间。

btw, 假如能把 NetHack 套上一个现代游戏的漂亮外壳,并修改操作方式让其适应现代玩家,我想它依旧拥有万人迷的魅力。

January 17, 2008

给大家做个交代吧

这几天收到了很多朋友的 email ,许多朋友附了简历。非常感谢大家的信任。因为大家都花了心思写 email ,所以我也很努力的回复。和一些朋友做一些交流。不过毕竟精力有限,可能还是无意中怠慢了一些朋友,这里一并说一声抱歉。

加上前几天感冒了,大约花了一周时间到今天才基本转好。身体不太舒服的时候,人也懒懒的。拖到今天终于把人选定下来了。要知道,做选择总是件艰难的事儿。很想和大家以朋友论交商量这件事情,以朋友之礼婉拒大家的盛情。我想我也是这么在做的。

毕竟我们这里只是一个小团队,暂时也不想扩张的太大。前几年给公司做技术招聘的时候,我们一下子从高校毕业生中招了上百个程序员,至今还有消化不良的感觉。不能让每个人都发挥出自己全部的能力时,埋没人才是极大的浪费。

这次大多朋友是冲着我个人来的,水平能力都很高。我会把大家给我发送过的简历放在私人信箱中,毕竟我还没有开猎头公司的打算。:)

还有一些朋友可能更想的是在游戏行业发展,而不一定在哪里。那么,如果有需要的话,可以告诉我,我能够帮大家推荐简历到我们公司其他的项目组,或者一些朋友所在的游戏公司。


另外,这次没有做美术的朋友和我联系比较遗憾。当然我也有自知之明,这个 blog 的读者几乎都是程序员这个小圈子里的。

January 15, 2008

随便写写

最近把 Asimov 的《基地》系列中,正传三本看完了。算是补课也好,没有辜负我专门去邮购这些书。买书真是件奢侈的事儿,以前是因为书贵,现在是因为时间和精力。

初翻此书,没有我当年期待的那么好。在那个没有网络的年代,读到这些科幻名著是件很难的事情。Asimov 也被神化了,这里面老爸对此亦有贡献。在我还刚认识几个字,是本书就想拿来读的年龄段,他就向我兴致勃勃的介绍 Verne ,Asimov 。弄的我小时候以为这两个就是世界上最伟大的作家。

不过,把这几本读完后,也不算太糟糕。或许有些翻译质量的不适应,故事还是高潮迭起的。毕竟是数十年前的科幻了,幻想中的科学总有那么一点怪怪的。当我在第一本中看到“电算板”时,心里只有一个念头,这不就是笔记本电脑么?功能好象还抵不上我现在用的 palm 手机 :)

抛开想象中的落伍科技之外(YY 方面自然比不过如今流行的玄幻小说),情节方面的构思还是颇为引人入胜的。即使许多情节的设计以今天的眼光看来不算新鲜。但我们应该考虑到这么多年来,总有新的作者不断仿效加工,才使得我们有了审美疲劳。

总之,向没看过的此书的科幻迷推荐一下。


周末偶然发现,我们的 3d client 在我的 freeBSD 的 X 下表现有 bug 。中文输入的消息处理有问题。据用 Ubuntu 的同学说,Linux 下又是好的。我检查后发现,原来是 XwcLookupString 这个 api 的问题。

前几年 Windows 下程序写多了,想当然以为接收 wide char 的 api 一定会以 unicode 编码,结果这次发现不是的。我的程序收到的消息都是 gbk 编码的汉字。wide char 仅仅是宽字符而已。当然这是因为我的 locale 设置问题,跟是 freeBSD 还是 linux 无关。

man 了一下,看到这组 XIM 的 相关 API 一共 3 个: XmbLookupString ,XwcLookupString 和 Xutf8LookupString 。 改用 utf8 版本后,再把取到的 utf8 字符串转换为 UTF-16 编码,结果就正常了。

btw, 以前没用过 XIM 接口,刚开始用还是有点困扰,主要是中文资料比较少,英文的也不算多。问了几个同事,有一人推荐我试试 IIIFM 接口,据说设计的比 XIM 好。又有一同事说 IIIFM 设计的比较失败,还是 XIM 用的人多。google 了一下,确定支持 XIM 比较安全。其实搞明白之后,也就那么回事,无非初始化繁琐一点。

之所以解决中文输入问题,X 看起来比 Windows 麻烦那么一点点,实在是因为 Windows 提供了统一的接口,而 X 比较开放,可以给用户更多选择。

说实话,Windows 那种输入法注入用户进程的实现方法,我觉得满恶心的。居然输入法的 bug 可以导致用户程序崩溃。不信的话,切到智能 ABC 试试依次按这些键: V 、方向键上、Del 、回车。


说点游戏有关的事情。

今天收到公司研究部门的工作报告,他们翻译了 2007 年 GDC 上许多重要的 session 的录音。我看了一晚上了,由于有原文对照,倒不是很在意译文质量。不过看的出来,同事们都很用心在做这个事。恐怕这也是大公司好处之一,老板可以出钱雇人做这种需要很大精力完成的工作。

鉴于这些是公司内部资料,我就不外贴了。随便说说,其中有几篇满有意思的 :)

  1. 《恶魔城》系列游戏的制作人五十岚浩司谈了下他为什么坚持做 2d 游戏。一个重要观点是, 2d 游戏有目前 3d 游戏所不能达到的地方。比如说精确距离判定,这在动作游戏中对玩家非常重要。还有技术上的区别对程序员对团队的影响等,都是满深刻的。(这里我们不能肤浅的把技术理解为 3d api 的掌握,3d 建模技术的掌握,或是编写 shader 程序的能力等等)

  2. 有一份研究报告(对 wow 的调查研究)表明:“网络游戏中玩家的社会性并没有表面看起来那么强。玩家更看重多个玩家同时在玩的事实本身,而少在乎到底有多少直接的互动。” 这就是说,玩家们只要知道有人在跟他一样玩着游戏就好,这就足够成为他们的“群体经验”了。这一点跟我这两年的看法一致,我们现在正在做的游戏就致力于实现在更大的集体中,单独的玩游戏。

  3. 还有一篇颇有启发的。他谈到,“游戏的意义不在于游戏本身,也不在于游戏中的图像,而在于游戏创造的情感体验。”。无论什么类型的游戏,最后给人以愉悦的都是其能够激发我们的某种情感。我想这个论题能够迅速引起我的兴趣,恐怕也跟我这几天在看《基地》有关。当然即使没有这个背景,演讲者也是讲的满好的。电影的出现,可以超越书籍这些传统媒体给人带来更多的情感体验,而游戏甚至可以比电影带来更多。比如有这样一些体验,是游戏独有的。例如:“憋了许久,突然爆发的感觉”,比如终于干掉了 boss ,升到了一个特定的级别,掉落一个稀有装备等等;“当竞争对手陷入窘境时你的感受”,也就是有点邪恶的快乐或是比他人强的骄傲;还可以供人消遣娱乐。

  4. 还有一些,今天时间有限,不多写了。


最近收到了不少信,大多跟我前几天写的 这篇 有关。继续感谢大家。不过我这次不想增加太多人了,程序的话,一人足可。还是前几天说的,主要是缘分。请大家莫以为云风轻慢大家。

最后推荐一篇文章:有那么一群天真的波兰人—— 一个关于Witcher的童话故事

January 08, 2008

163 邮箱终于支持 opera 了

每当同用 opera 的朋友问起我们公司的各种 web 服务时,我都很惭愧。做为网易的老员工,居然无力推动各种 web 服务对 opera 的支持度。以前还只是一个页面美观度的问题,后来 ajax 的流行,干脆许多东西都用不了了。

其实,在支持 opera 这个方面,我已经很卖力了。抓到机会就在那些同事的耳根子底下叨叨,直到他们怕了我 :)

一些简单的活,我倾向于自己来做。比如去年帮 URS 的页面抓到了几个 opera 下的显示 bug (HTML 写的不标准造成的)。popo 对 opera 支持的不好的问题 现在也官方解决了。

但是,更多产品更全面的支持 opera 还是需要大家的努力。今天,终于发现邮件组的同事将产品完美支持 opera 9.25 了(以前用 opera 登陆 web 邮箱,需要选择非 ajax 的界面,而不能用极速版)。这下终于敢对人说,网易电子邮箱 是国内做的最好的了 :D

ps. 我们的博客系统 对 opera 支持的还是不太好。倒是 firefox 支持度不用人操心的,因为知道他们开发就是在 firefox 下,这 opera 支持度还是得多唠叨一下的 :D


最后加一则八卦,前段在软件2.0大会上听来的。不知道靠不靠谱,我也没向邮件组的同事确认。当时讲这则八卦的朋友跟我感叹说,原来墙角可以这么挖的 :D

话说网易的邮件组想挖人,找到某知名网络公司(隐去名字)做邮件一块的人,拉出来吃饭。不谈待遇前途,只谈邮件系统技术构架。说的唾沫横飞。听者有意,比较了下自己公司的邮件系统,感觉做下去没意思,随即拟好了辞职报告。

感谢大家

承蒙大家信任,这两天收到好多邮件。比我预期的多,非常的高兴。我相信各位朋友是真诚想一起共同做一件有意思的事情,看的出来,很多人都是自己圈子里的高手。相信也是各个猎头公司的重点目标。许多人都没有事先准备好的简历,直接冲着我的这篇 blog 而来。

因为我是真诚想个合作伙伴,所以这次收到的邮件,都不会按以前的惯例转发给公司其他部门。毕竟,我不想利用私人 blog 给公司发布招聘广告。每封邮件我都会站在朋友立场认真回复的。

January 07, 2008

想找个朋友

这两个月我为我们小组申请了个名额,可由于诸多原因,来来去去几个人都没能长期留下来。总觉得有点遗憾,想把这个空缺补上。

在 blog 上发告示好象挺俗的,可是这两年闭门造车,没积累多点人脉,也只好出此下策了。可能我的要求还有那么一点点高,公开场合下写下这些,也担心被人唾骂:又想马儿好,又想马儿不吃草。毕竟,我还是想找多一个志同道合的朋友,一起把游戏做好。要求也会是相互的。

OK 。正经点说,我们谋求一个伙伴,大家一起做一个与众不同的网络游戏。目前引擎的基础构架已经完毕,但还有许多工作需要在项目开展期间完善。游戏的设计案已经基本定下来,有了个大家确定可以完成的蓝图,但尚未细致的文挡化。

希望能找到一个朋友,真心喜爱游戏,有积极向上的人生观,想自己参与到一款并非抄袭现有模式的网络游戏制作中来。暂时我们只想增加一个人,目前不考虑专职策划人员。希望这个朋友是程序或美术的身份,并可以提供自己对游戏设计的想法。


除了以上热爱游戏这个基本点之外,

对于有兴趣的程序员,我们希望:

  1. 年轻,没有太多生活负担,肯和大家一起奋斗至少两年。在年轻和奋斗这两点上,尽管以我自己为参考:本人 29 岁(自以为很年轻),每周工作 40 小时以上(工作负荷感觉不大),正常休息。除去目前在做的游戏项目,没有什么杂念,休闲时间也多有思考如何把这件事情做好。我个人作为团队领袖,不会给团队成员高于对自己的要求。

  2. 有编程经验至少 5 年以上。可以独立解决问题。善于查找资料,阅读源代码。有软件行业工作经验(不限于游戏行业),至少参加过一个完整的软件开发,对参与的软件的构架有清晰的认识。

  3. 有混合语言编程经验,不仅熟悉 C 或 C++ 这样的静态类型语言,又使用过 Python ,Lua ,Ruby 这样的动态语言编写实用的代码。对编程语言没有明显的偏见。对计算机体系结构有自己的认识,善于用 C 语言这样的工具实现高性能的模块,又不固定于 C 语言思维,可以活用动态语言解决问题。

  4. 思维缜密,追求但不苛求完美。不把任何一个功能模块只当作任务完成。能够在编码中自我发现需求和设计不足。

  5. 善于交流。希望与更多的有创造力,独立思考的程序员们一起工作,激发更多的灵感。


对于有兴趣的美术人员,我个人不做这一行,只能随便写写我个人的看法:

  1. 同上关于程序员的第一条。

  2. 能够熟练使用 3d 建模工具,例如 Maya 3d Max 等。熟练使用 2d 平面设计工具,如 Photoshop 等。能够独立完成建模(不限于高面模型或低面模型),绘制贴图,调整角色动作等工作。

  3. 有一定的手绘能力,科班出身为佳。有想象力,能够自己做场景和角色形象的设计。

  4. 有游戏行业从业经历至少 3 年以上。游戏涉猎面广,善于分析其他游戏中美术的技巧和制作方法。对计算机和网络皆能熟练运用。


我们能提供的有:

  1. 激动人心的游戏项目。可以保证技术上可以实现(我个人做了多年的程序员,目前兼做策划,绝对不会提出空中楼阁的案子),玩法上有所创新(一个 20 多年游戏龄的老玩家做出的承诺)。

  2. 舒适宽松的工作环境,稳定的资金支持。办公室坐落在著名风景区中闹中取静的一角,生活便利。我们的公司网易,有坚实的资金储备。我个人为这家公司服务了七年,得到公司各级领导和同事的信任。

  3. 一群友好且有创造力的同事朋友。人数不多,大家相处非常愉快。

  4. 已有两年多的工作积累,技术方面一直追求尽善尽美,以作为后期游戏搭建坚固的积石。

  5. 待遇不是很高,但处于业内中等水平。项目完成后,会有一定比例的分红。不敢做预期,因为创新的项目必然有市场风险。


有兴趣的朋友,可以给我发 email 。email 地址在 http://www.codingnow.com 可以找到。如果是已经认识的朋友有这个意向,直接用联系到我的方式联系我即可 :D

能在一起做点事情是种缘分。

ps. 我们待遇真的不高,尤其对于我们想找的这种有经验,能够独挡一面的人才。当初我选择做这件事,也是各种机缘巧合,想给自己的生活和未来有点改变。这次能不能找到合适的朋友,恐怕也只能看缘分了。


1 月 17 日:

这件事情告一段落,云风在这里给大家一个交代

January 05, 2008

C 语言(C99) 对 64 位整数类型的支持

前几天跟同事闲聊 64 位操作系统时,有人问起 64 位平台上,C 语言的数据类型如何确定的问题。以及跨平台(跨 16 位、32 位和 64 位平台)程序如何选用合适的数据类型。

我查了一下资料,记录如下:

char 通常被定义成 8 位宽。

int 通常被定义成 16 位或 32 位宽(或更高),它取决于平台。编译器将在这两者间选择最合适的字宽。

short 通常被定义成 16 位宽。

long 通常被定义成 32 位宽。

C99 为 C 语言扩展了新的整数类型 long long ,通常被定义成 64 位宽。(GNU C 亦支持)

但是 C 标准并没有定义具体的整数类型的宽度,只定义了 long long 的级别高于 long ,long 的级别高于 int ,int 的级别高于 short ,short 的级别高于 char 。(另外有 _Bool 永远是最低级别)。级别高的整数类型的宽度大于等于级别较低的整数类型。

char 的宽度用宏 CHAR_BIT 定义出来,通常为 8 ,而除了位域类型外,其它所有类型的位宽都必须是它的整数倍。

如果需要精确确定整数类型的宽度,在 C99 以及 GNU C 中,需要包含 stdint.h ,使用其中几种扩展的整数类型。

int16_t 可以保证整数长度为精确的 16 位。同样,int8_t 可以保证整数长度为精确的 8 位。类似的还有 int32_t int64_t 以及无符号类型 uint8_t 等等。

int_least16_t 可以得到一个当前平台所支持的至少有 16 位宽的最短整数类型。(其它同类型的可以类推)

int_fast32_t 可以得到当前平台下得到处理速度最快的至少为 32 位的整数类型。

intmax_t 可以获得当前平台所支持的最大宽度的整数类型。

在书写整数常数时,在数字后加上 L 表示是一个 long 类型的整数,加上 U 表示是一个 unsigned 整数,加上 LL 表示是一个 long long 类型整数。但是由于 long long 这些并不能确定准确字宽,有此需求时,可以借助宏 INTn_C(value) 来转换。例如,想指定一个 64 位整数常数 0x1234 ,可以写成 INT64_C(0x1234) 。若在当前平台上 int_least64_t 就是 long long int 的话,这个宏会被展开成 0x1234LL 。

最后再提一个很重要的扩展类型:intptr_t (无符号版本写成 uintptr_t)这个类型可以被安全的在 void * 和 整数间转换,对于写跨 64 位平台的程序非常重要。也就是说,当你需要把指针作为一个整数来运算时,转换成 intptr_t 才是安全的,可以在运算完毕安全的转回指针类型。

C 语言中,指针和整数之间的转换经常用到(多用于需要精确控制数据在内存中的精确布局时),在 32 位平台上,由于指针类型的字宽和 int 相同,所以我们不太在意这个问题。但是到了 64 位平台上,由于目前几乎所有 64 位系统都采用 LP64 模型,既整数依旧是 32 位,而指针是 64 位的。intptr_t 这个数据类型就成了安全跨平台编程的保证。

最后,附上 C99 标准文档技术修正第三版 ISO/IEC 9899:TC3

January 02, 2008

新年快乐

元旦放了三天假,我基本都在打游戏。

Wii 买来有一段时间了。因为工作上费心的事情太多,所以邮寄来以后,包装都没拆,就那么在办公室的书柜上摆了一个月。有了这么几天假期,我终于决定玩一下游戏,放松下心情。

选的游戏是《塞尔达传说:黎明公主(The Legend of Zelda: Twilight Princess)》,美版的。这个游戏 05 年(或是 04 年?)在 GDC 上看过,据说那是第一次在公开场合展示这个版本。平原马战的那一场,当时看的会场上所有人热血沸腾。今天,终于亲身体验了一把,果然味道不错。

马战这个段子连旁边看的老爸都感叹说,没想到游戏可以做到今天这个程度。我知道他指的是互动情节和人物刻画,而不是 3d 渲染技术。不错,游戏做到这种程度,第九艺术的名号当之无愧。虽然表现力还是有限,可已经超过许多平庸的电影了。加上玩家在玩游戏时的代入感远远大于电影的观众,这是由于玩家需要更多的时间完成故事,把情节穿插在游戏进程中,逐步的在细微处感染人。

今天上班时,一个同事告诉我他在玩 PSP 上的《最终幻想7》,感觉不错。这个我前几天曾强烈推荐过。《最终幻想 10》开始,游戏制作人就开始寻求更好的方式,用 3d 互动的方式来演绎一个编好的故事。在我接触的游戏中,就是从它开始,游戏中大量采用电影里的镜头运用手法。并用实时渲染的技术来表达人物的面部表情,而不仅仅是肢体语言。在这个方向上,新版的 7 代前传更是发挥到了极至。并在游戏中简化游戏操作以及降低谜题的难度(把消耗时间迎合骨灰玩家的部分扔到了支线上)。让玩家可以顺利的欣赏完整个故事。我没有看任何功略,完成核心危机只用了大约 17 小时。如果不是刷那些支线任务找乐子的话,估计 15 小时就能爆机。目前二周目玩了一半还放着呢。

不过这次这版塞尔达可没走“简单化”的路线。它延续了此系列的一贯作风:强调迷题和于场景互动的动作性。对于吃惯“现代”游戏快餐的急性子玩家,这个游戏还是颇有难度,需要一些耐心的。

不过还好,我还是没有借助攻略,已经顺利进行了游戏流程的一半了。这个一半当然是自己估计的,靠的是个人多年 RPG/AVG 游戏的经验。目前游戏进程已经大地图全开,剑技学会了 4 招,取得了 The Master Sword 并可以自由变狼。进行到这里,游戏时间是 38 小时。看来,整个游戏的基本流程会在 70 小时+ 了。这倒合符合传统日式 RPG 的惯例。

游戏的谜题都设计的恰到好处,绝大多数都是靠画面和镜头的提示,绝少依赖文本,并做足了情节引导以及嵌入故事中的教学。游戏几乎没有什么地方会卡住很久,标出所有隐藏宝箱位置的指南针道具,动作失败后可以无限重来的设计都非常贴心。那些谜题只要肯细心琢磨,通常都会在半分钟到半小时之间想到线索。这个难度不至于让玩家过于受挫,又可以在解决问题后激发出成就感。

我想,好的游戏就应该是这个样子:别为难玩家,也不要侮辱玩家的智商 :D