Project1
标题: 让我们来制作一个简单的资源占有模拟 [打印本页]
作者: Mr.Jin 时间: 2021-2-5 09:55
标题: 让我们来制作一个简单的资源占有模拟
本帖最后由 Mr.Jin 于 2021-2-5 09:59 编辑
今天我们来做一个简单有趣的小试验吧!
Unit = Struct.new(:asset)
Unit = Struct.new(:asset)
首先我们来定义一个Struct,表示一个"单元",它占有一定量的资源
我们可以通过观察不同"单元"之间的互动关系(资源量的传递),得到一些有趣的现象……
那么,现在我们来设计一套"单元"互动的规则
为了观察"单元",我们可能需要把它们画在一个区域里,这样就可以直观地看到结果了
所以为此我们首先需要传入一个尺寸:
然后我们要设定每个"单元"初始拥有的资源量,这个量我们可以认为是随机的,所以也要设定一个上限
现在,我们就可以构建一个"单元"表了,你可以理解成它们就是一个小社会里的所有人。
考虑到完全的随机化可能会导致某些"单元"刚出生就陷入资源极度匮乏的情况,因此我们使其最少也可以拥有半数的初始资源量最大值
units = Array.new(width * height) do
init_asset = rand(unit_initval_max) / 2 + unit_initval_max / 2
Unit.new(init_asset)
end
units = Array.new(width * height) do
init_asset = rand(unit_initval_max) / 2 + unit_initval_max / 2
Unit.new(init_asset)
end
好!布置完成了,我们现在来设计一轮游戏的规则,首先来搞一个循环吧。
我们现在要遍历所有的"单元"去和其它"单元"进行交互,所以来用一个双重循环编写
注意,为了不让id优先的"单元"获得先天优势,我们可以特意用shuffle把这个顺序给随机化
这是外层循环:
(0...units.size).to_a.shuffle.each do |i|
(0...units.size).to_a.shuffle.each do |i|
这是内层循环,代表着每个i去向其它的j发起互动:
(0...units.size).to_a.shuffle.each do |j|
(0...units.size).to_a.shuffle.each do |j|
接下来编写循环的内容,也就是交互的规则
首先写这样的一个东西避免自己跟自己交互(虽然交互规则大致决定了自己跟自己交互也没什么关系,但至少可以让你的程序跑的快一点点点点)
我们设定一个交互值,使得i"单元"的资源转移给j"单元",这个转移也是有限度的,不能超过i"单元"已有的资源量
(另外在i已经耗尽所有资源的情况之下,就不必再继续和其它的"单元"进行互动了,因此可以用break提前结束内层循环来让你的程序跑的快一点)
interact = [units[i].asset, rand(unit_initval_max)].min
units[i].asset -= interact
units[j].asset += interact
break if units[i].asset <= 0
interact = [units[i].asset, rand(unit_initval_max)].min
units[i].asset -= interact
units[j].asset += interact
break if units[i].asset <= 0
好,简单的规则完成了,我们来把这一切呈现出来,回到我们的loop循环之外去写几个熟悉的RGSS对象吧
sprite = Sprite.new
canvas = sprite.bitmap = Bitmap.new(width, height)
sprite.zoom_x = sprite.zoom_y = 16
sprite = Sprite.new
canvas = sprite.bitmap = Bitmap.new(width, height)
sprite.zoom_x = sprite.zoom_y = 16
搞出一个精灵,上面挂一个Bitmap作为我们的画布,画布的长和宽自然就是我们传入的长和宽了
当然我们做的实验可能会把长和宽做得很小,因此请用zoom把显示结果放大一些,我这里是16x
然后,我们需要在loop循环内,双层循环之后(也就是游戏逻辑处理完毕)的部分,写上我们呈现结果的部分:
先清空画布:
为了观察每个"单元"的资源占有情况,我们可以把代表"单元"的点绘制成红色的,越亮的点越富有,越暗的点越贫穷
这个亮度的计算,自然是以 [资源占有量 / 资源占有的理论总量(也就是所有单元的初始财富之和) * 100%] 来计算的,但是考虑到这样的话可能大多数的"单元"都会显示不清,
因此我们把这个总量乘以10%(当然你想更少或更多都可以)
unit_display_max = width * height * unit_initval_max * 0.1
unit_display_max = width * height * unit_initval_max * 0.1
把每个"单元"画到画布上的对应位置去:
(0...units.size).each do |i|
c = units[i].asset / unit_display_max
canvas.set_pixel i % width, i / height, Color.new(c * 255, 0, 0)
end
(0...units.size).each do |i|
c = units[i].asset / unit_display_max
canvas.set_pixel i % width, i / height, Color.new(c * 255, 0, 0)
end
最后更新画面显示:
好!现在来到def外面,我们来跑一下这个模拟:
(为了节省性能,开个8x8的就可以了)
我们可以看到,这些点的闪烁非常地频繁,呈现一种比较混乱的状态:
现在,我们来更改一下两个"单元"之间交互的规则:
我们不再保护i"单元"了,就算使其资源量变为负值(是负债吗?),也可以让它继续参与和其它"单元"的交互当中:
interact = rand(unit_initval_max)
units[i].asset -= interact
units[j].asset += interact
interact = rand(unit_initval_max)
units[i].asset -= interact
units[j].asset += interact
结果会如何呢?
我们可以看到,这次的结果呈现出了完全不一样的局面:有一些点似乎变成了"常亮"的!只有其它的一些点处于类似于上图的闪烁状态。
考虑到我们曾经在计算unit_display_max来观测显示结果时,为它乘以了10%,可能会使得一些超出该资源值的"单元"显示地过于亮,而没有办法显示比较"富有"的"单元"之间的差距
现在我们把这个10%去掉,让它以100%显示:
unit_display_max = width * height * unit_initval_max * 1.0
unit_display_max = width * height * unit_initval_max * 1.0
可以看到,情况变得类似允许"负债"之前那样了,不过你还是可以很容易分辨出来一些"常亮"的点。
实际上,我们可以把亮度的显示曲线用pow函数操作一下,你可以更清楚地看到那些"常亮"的点。
好啦,胡扯就到这里,简单粗糙的代码放上:
试验代码
-
sim3b.gif
(308.27 KB, 下载次数: 25)
作者: 百里_飞柳 时间: 2021-2-5 10:56
这是要做甚么.jpg
作者: 89444640 时间: 2021-2-5 11:07
楼主的意思是,不进行宏观调控,资本总会集中到少数点手中?
作者: Im剑侠客 时间: 2021-2-5 15:33
是否也在暗示着,随机化不能单纯地依赖rand本身。
欢迎光临 Project1 (https://rpg.blue/) |
Powered by Discuz! X3.1 |