“史诗”级宇宙科幻大型多人在线网络游戏:《黑暗森林》

之前有不少大佬编制模拟黑暗森林的程序,我也来凑个热闹。但是与“文明分类、物竞天择”的思想不同,楼主直接采用用户操控文明,一举解决了“人工智能文明决策系统僵硬”的问题。同时也供广大吧友茶余饭后消遣之用


楼主 Andy18650  发布于 2019-05-27 11:39:00 +0800 CST  
游戏整体理念参考《三体I》中的思想,将尽量大的信息量压缩在精简的规则系统中。游戏规则将在稍后放出。

楼主 Andy18650  发布于 2019-05-27 11:40:00 +0800 CST  
(这是游戏核心算法的一部分,控制舰队搜索敌方单位)

楼主 Andy18650  发布于 2019-05-27 11:41:00 +0800 CST  
@[url]http://某叶怕怕[/url],目前游戏“核心算法”(话说这是我在体吧看到的一篇文的名字)已经全线竣工,C/S结构(客户端/服务器结构)的通信也可以运行,但是仍然存在很多问题和Bug。最关键的,在于服务器和客户端的操作都使用命令行,难看也就罢了,美其名曰“简洁冷峻”,关键java的命令行程序不能双击运行。。。而且输出会打断指令输入
不过,楼主当年第一代黑暗森林游戏的时候,客户端用上了swing(小声:通过swing做了个输入输出分开的命令行。。。),这次在学习Unity3D,相信不久的将来就能用上。

楼主 Andy18650  发布于 2019-05-27 21:18:00 +0800 CST  




这是目前游戏“界面”的样子,未来肯定会有极大的改观。。。
第一、第三张是客户端,中间是服务器。

楼主 Andy18650  发布于 2019-05-27 21:24:00 +0800 CST  
为了做到“把复杂的游戏内涵压缩在尽量简单的规则中”楼主在规则的设定上下了一番功夫。先总结如下
(用方括号[]括起来的是java有关的内容,不影响阅读):
游戏基本单位——文明单位(Civilization_Unit):
文明单位是游戏的基础,[是下面两个关键单位的父类,它是“抽象”的,所以本身并不可以创生]。它有三大基本属性:科技(technology),资源(resource)和人口(population),简称“TRP”。这三个简单的[双精度浮点]变量以一种复杂的方式互相关联,具体方式在以后会讲到。总之,这三个属性是游戏的核心。

楼主 Andy18650  发布于 2019-05-27 21:33:00 +0800 CST  
游戏的关键单位——星球(Planet):
星球是玩家的“基地”,[是文明单位的子类,所以]也具有“TRP”三个属性。每一刻(tick),资源会消耗,消耗量正比于人口,科技也会发展,发展量也正比于人口。当资源小于等于零,星球会进入休眠,资源不会消耗,科技也不会发展(科技支援——一个以后会讲到的机制——除外)。

楼主 Andy18650  发布于 2019-05-27 21:38:00 +0800 CST  
@某叶怕怕

楼主 Andy18650  发布于 2019-05-27 21:39:00 +0800 CST  
游戏的另一个关键单位——舰队(Fleet):
舰队[是文明单位的另一个子类,所以]也具有TRP(科技、资源、人口)三大属性。同时,舰队具有星球所不具有的一大特点:可以移动。(星球是不可移动的),舰队的移动用xyz三个方向的[双精度浮点]分量表示。每一个tick,游戏将xyz三个坐标分别加上三个速度分量。
当舰队的速度(矢量)改变时,系统会计算改变所需要的速度变化量(delta-v),这个变化量乘上舰队的人口就是所需的冲量(假设无论科技等等,舰队的质量正比于人口)。这个冲量再乘上一个常数,就是舰队变轨所需要的资源。这个资源将在舰队的资源中减去。如果舰队资源不够,[方法会抛出一个FleetTransferException],舰队不会尝试变轨并保持原轨道。

楼主 Andy18650  发布于 2019-05-28 20:00:00 +0800 CST  
然而,要注意到一个顺序:科技先同化,人口再降低。那么存在这样一种极端情况:一支科技为1,人口为1000的舰队打败了一支人口为1,科技为999的舰队,那么胜利者首先将科技同化为999,变为科技999,人口1000。然后人口减少(1*999/999=1),变为科技999,人口999的“无敌舰队”。这个案例证明了,在允许科技同化的情况下,舰队的战斗力不一定是单向减少的。但是考虑另一个案例:一个人口为80,科技500的舰队打败了人口为60,科技600的舰队,同化科技为600,然后人口减少(60*600/600=60)变为人口20,科技600的舰队,战斗力降低2800。所以,不一定发生了科技同化,就一定会有“舰队战斗力增长”的反常事件发生。

楼主 Andy18650  发布于 2019-05-28 21:01:00 +0800 CST  
楼主刚才证明了,如果要产生“战斗力增加”的情况,至少要满足这么些个条件(下标1表示自己,下标2表示对方)。容易证明:在发生科技同化的情况下,人口减少量一定等于对方人口,所以有:
t2*(p1-p2)>t1*p1(战斗力增长)>t2*p2(胜利判定)
t2*p1>t1*p1+t2*p2>2t2*p2(展开并移项)
p1>2p2(由1,3约去t2可知,必要但非充分)
t1*p1+t2*p2-t2*p1-t1*p2<-t1*p2(由1,2可知,添项t1*p2)
(t1-t2)(p1-p2)<-t1*p2(因式分解

楼主 Andy18650  发布于 2019-05-29 14:44:00 +0800 CST  
宇宙“聊天室”——信号(Signal):
为了满足猜疑链的基本公理,游戏不允许超距通讯。所以发出信号是玩家间唯一的通讯方式。信号只能由星球发出,信号的内容由玩家在发出时声明,并不可改变。发出后,信号以光速传播。当信号遇到星球或舰队时,该星球或舰队的拥有者[Player]的用户[Client]会受到这条信息,除了信息内容以外,这个用户还会收到精确的接收时间[一个双精度浮点的tick数据,实际上是单独计算出来的,而不是主类中的TICK变量]和接收到这个信号的文明单位(星球或舰队)。注意,接收到信号不代表能定位到对方,甚至,游戏设定为连对方的大致方向也不知道(虽然在现实中这是可以做到的)[因为算法需要反三角函数,比较困难]。然而,根据距离几何学,如果一个文明有两个单位,就可以得到一个距离差(时间差*光速),从而把对方的位置缩小到一个双曲面上,如果有三个单位,就可以得到一条双曲线,如果有四个单位,那么就可以精确地定位到一个点。不过,系统的计算精度[双精度浮点数的精度]是有限的,所以这个点的坐标也可能有误差。增大接收信号的文明单位之间的距离可以减小这一误差,这就鼓励文明尽量扩大自己的疆域。或者,对于规模较小的文明,可以采用派出舰队的方式增长测量基线。

楼主 Andy18650  发布于 2019-05-29 15:08:00 +0800 CST  
光锥之外,就是命运——影子单位(ShadowUnit)与“历史”系统:
说实话,当年想出这一系统时,我甚至怀疑我违背了“简单的规则”的初衷。但是回想起来,这个规则还是比较简单的,复杂的只是其中派生出来的各种不确定性与对逻辑的高度要求。这么看来,也符合《三体I》中的“理想游戏”模型。
这个系统的本质,仍然是狭义相对论。一个简单的事实:当你仰望星空时,你正在沿时间之河逆流而上。半人马座是四年前的半人马座,巴纳德星是6年前的巴纳德星。。。同理,当你发现一支敌方星球或舰队时,你发现的是它的过去。。。这里必须连带提一下发现的判定:如果一个文明单位自身的科技乘以对方的人口,大于一个常数[FINDING_CONSTANT]那么即判定为发现。但是要注意,这里的“科技”是这个单位现在的科技,对方的“人口”却是过去的人口。从光锥的角度,这很好理解。[但是从算法的角度就不一样了,下面大量暴力算法预警:]
[首先,每一个文明单位都有自己的“历史”——一个HashMap表。这个表的Key是时间,Long类对象,其实就是一个长整型,自动装箱,Value是一个单独的ShadowUnit类对象,当然,分为Shadowplanet和Shadowfleet两个子类。每一个回合(TICK),单位就往自己的历史中写入自己当前状态的镜像,这个镜像有点类似于C语言的结构体,本职工作就是记录数据,Key就是当前的TICK。那么,既然Key是连续的,为什么不使用ArrayList这样的可变数组呢?我只想说:我也希望啊!ArrayList的遍历只需要foreach即可,而HashMap则需要重量级的Iterator。可是舰队不一定是从0开始生成,使用ArrayList会产生大量无用的空间,而且,TICK是long,而ArrayList的索引是int,向下转型总是让人心里发慌,要是这个游戏时间太长int溢出了捏?。。。]

楼主 Andy18650  发布于 2019-05-30 11:42:00 +0800 CST  
这样一来,对方的行动,就不太在己方的掌控之内,虽然客户端提供了planetpredict和fleetpredict两个指令用来预测对方星球和舰队目前的状态,但是注意:这个预测是建立在对方完全不操作的基础上的,如果对方在这段时间内突然增加星球人口,或是将舰队变轨,己方是不知道的。这样一来,盲目相信predict给出的结果反而会让人步入陷阱。

楼主 Andy18650  发布于 2019-05-30 19:02:00 +0800 CST  
共同发展——科技支援:
同一个文明的星球,自然要互帮互助。但是,由于人口可以由玩家直接指定(假设星球上的人都是机器人。。。可以工业化生产和封存),传输人口没有必要,传输资源的话,需要用到舰队“显式”传递,即派遣一支“资源运输队”前往支援,当然,这支舰队自己也要消耗资源。但是,科技是可以自动支援的。但是光速的壁垒在这里仍然有效:如果一个星球离另一个较远,那么那个星球接收到的就是另一个星球很多TICK以前的科技。这个延迟不仅仅是简单的线性落后多少点的科技的问题,关键在于,如果科技的“源星球”发生技术爆炸(注意这个爆炸可以由玩家随时引起,只要把人口调至极高,但是后果是资源的大量消耗),那么远处的星球很久以后才会收到这一红利。而且,这种资源是不叠加的,即如果一颗星球的科技发展速度低于“源星球”,那么它的科技发展速度只会跟上“源星球”而不会两者叠加。
这个规则的另一个重要意义在于,如果没有它,那么所有星球的科技总和是有着最大值的(资源总和/资源-人口系数*资源-科技系数)有了这一条规则,那么就可以通过以下方法打破这一定律:
把一颗星球的人口设高,然后其他星球的人口设低,然后将资源用舰队送往这一颗星球,就像设立首都。然而这个“首都”的选址是个技术活。因为它聚集了大部分的科技与资源,如果被占领,那就亏大发了,所以不能在前线。那大后方呢?也不行,这样前线的“钢铁长城”(星球组成的防御带)就只能接受到很久以前的科技,效率太低。所以这个选址要像明成祖一样,靠前而不是“战斗区域”。

楼主 Andy18650  发布于 2019-05-30 19:27:00 +0800 CST  
这里来讨论另一个可能性:双首都。这是一个历史上经常发生的情况。理论上,这样可以避免“把鸡蛋放在一个篮子里”,但是双首都的代价是科技的转化效率打折。然而,具体问题具体分析。当游戏进行到后期,少数寡头玩家博弈时,文明的范围会很大,而且会遇到“腹背受敌”的情况。这时双首都甚至多首都就很有用了。一个前线一个。
另一个可能是首都的资源不高,资源全部存在首都附近的一个星球上,这样,即使首都被占领,立马带着资源跑路。但是,由于要求自身消耗资源尽量少,“首都粮仓”的人口也要很小,这样就很容易被人“火烧乌巢”,把资源卷走,给首都来一招“釜底抽薪”,那么高人口的首都就会很快耗尽资源休眠(休眠以后战斗力强制为0),这是再趁火打劫,一个超级文明没准这样就凉了。

楼主 Andy18650  发布于 2019-05-30 19:54:00 +0800 CST  
鉴于度娘经常吞楼,链接就不再发了。感兴趣的可以在本楼回复区留下邮箱,单独发。

楼主 Andy18650  发布于 2019-05-31 09:49:00 +0800 CST  
不可靠的联盟——文明结盟系统:
在游戏中,文明的结盟是有向的,即文明A可以和文明B结盟,但文明B不与文明A结盟,所谓“同床异梦”是也。[这是因为我给每个玩家都设置一个可变数组存储盟友,而不是在主类中储存“盟友对”]与一个文明结盟,只需要知道对方的玩家名称[Playername],然后makeally即可。结盟后,己方的舰队会强制不与盟友的舰队交战,同时也不可以占领盟友的星球,只会像遇到己方星球一样发生支援(相当于强制战败)。同时,双方也可以共享数据。目前,可以共享发现的敌方星球与舰队数据。不过,这一条规则可能在未来的更新中修改。

楼主 Andy18650  发布于 2019-05-31 09:59:00 +0800 CST  
楼主放弃Unity3D了,上马大名鼎鼎的轻量级JAVA游戏开发库(LWJGL,就是这货编出了Minecraft),目前正在疯狂学习中。。。

楼主 Andy18650  发布于 2019-05-31 20:51:00 +0800 CST  
汇报一下最新进展:下面这个窗口看起来什么都没有(反动透顶),还不如cmd的命令行。但是!它是L!W!J!G!L!生成的窗口!楼主曾经用swing达成过这个效果,还做出过登录界面(包括文本框、按钮和——一个用swing实现的命令台)。但是swing的致命问题在于无法生成3D图像。所以鲁迅没有说过:“学医救不了中国”,但楼主说过:“Swing做不出《黑暗森林》。”事故转攻LWJGL2.9.3。然久寻国内优秀教程而不得,最后照着一个搬运的油管视频开做。那个语速把楼主一个雅思听力8.0虐得不要不要的。。。


可以看见一个有趣的事实:虽然Dark Forest Client Graphical项目已经建立(实际上还加好了API)但是这个窗口是在GameEngine项目下运行的。这是因为教程上面取了这个名字。。。以及不可能一开始就直接编出那个客户端来,所以索性开一个新project,学会了再编《黑暗森林》

楼主 Andy18650  发布于 2019-05-31 23:45:00 +0800 CST  

楼主:Andy18650

字数:13774

发表时间:2019-05-27 19:39:00 +0800 CST

更新时间:2019-07-08 18:34:45 +0800 CST

评论数:253条评论

帖子来源:百度贴吧  访问原帖

 

热门帖子

随机列表

大家在看