最近在学游戏开发,尝试开发一个经营类游戏,其中有个点子就是:在游戏的过程中,会不时的发生一些突发事件,可能是任务,可能是天灾人祸等,当然,要有趣,那么这个事件就得是随机的,不能是一成不变的。

我的想法是设计一个表达式,使用表达式形成事件的多样化,表达式里的词缀够多,用词缀来实现随机化,这样添加足够多的词缀和表达式就能有足够多的随机事件。最后实现的效果应该是这样:

$charactor 很喜欢您的弟子 #disciple ,对他 $act ,获得奖励 #prize
王重阳很喜欢您的弟子王铁锤,对他千锤百炼,获得奖励一件衣服
乔峰很喜欢您的弟子王铁锤,对他千锤百炼,获得奖励领悟一个技能

其中$开头的词语,代表随机词缀;#开头的词语代表编程表达,也就是需要代码实现功能的词缀;获得的奖励,将与词缀进行挂钩。

为了快速实现原型,先采用python来完成demo,其他语言都能够实现相同效果。

第一步,先解析表达式。首先使用空格对整个表达式split,拆分出来所有的token:

token = expression_str.split(" ")
token
# ['$charactor', '很喜欢您的弟子', '#disciple', ',对他', '$act', ',获得奖励', '#prize']

遍历tokens,如果是$开头则代表词缀,#开头则代表编程表达,其实也可以直接用token来对比词缀表实现匹配,可是这样效率较低,所以加上了前缀来方便判断。

total_text = []
for i in token:
    if i.startswith("$"):
      pass
    elif i.startswith("#"):
      pass
    else:
      total_text.append(i)

在处理词缀之前,首先要定义好词缀表:

store_data = {
    'charactor': { 'text': ["令狐冲", "林平之", "王重阳", "乔峰", "段誉", "段誉姑姑的弟弟的儿子的同学的妈妈"] },
    'act': { 'text': ['一番把玩', '千锤百炼', '打情骂俏', '拳打脚踢'] },
    'place': { 'text': ['泰山', '黄山', '茅厕', '草丛', '房顶'] }
}

定义好词缀表之后,在遇到$开头的词缀的时候,进行词缀随机匹配:

total_text = []
for i in token:
    if i.startswith("$"):
      name = i[1:] # 去除前缀的$
      rand_i = random.randint(0, len(store_data[name]['text']) - 1) # 随机获得词缀中的一个
      total_text.append(store_data[name]['text'][rand_i])
    elif i.startswith("#"):
      pass
    else:
      total_text.append(i)

第二步,计算奖励,在这里为了简便,我直接定义为了#prize,并且一定要是表达式的最后一个词缀,至于为什么往下看就知道了。而#disciple我会获取到游戏中我所拥有的弟子中的一个,那首要一步是定义弟子数据。

disciple_data = ["王铁锤", "谢帅逼"] # 简单定义

当碰到#disciple的时候,直接进行随机选取弟子:

total_text = []
for i in token:
    if i.startswith("$"):
      name = i[1:] # 去除前缀的$
      rand_i = random.randint(0, len(store_data[name]['text']) - 1) # 随机获得词缀中的一个
      total_text.append(store_data[name]['text'][rand_i])
    elif i.startswith("#"):
      name = i[1:]
      if name == "disciple":
        rand_i = random.randint(0, len(disciple_data) - 1)
        total_text.append(disciple_data[rand_i])
    else:
      total_text.append(i)

这个时候词缀的填充大致完成了,那是时候计算整个事件带来的奖励了,大致思路是每个词缀都有一个价值,当词缀完成整个句子的时候,整个句子的价值决定了获取到的奖励,这个时候就需要给词缀表增加价值字段:

store_data = {
    'charactor': { 'text': ["令狐冲", "林平之", "王重阳", "乔峰", "段誉", "段誉姑姑的弟弟的儿子的同学的妈妈"], 'value': [5, 3, 5, 4, 3, -1] },
    'act': { 'text': ['一番把玩', '千锤百炼', '打情骂俏', '拳打脚踢'], 'value': [1, 5, 1, -2] },
    'place': { 'text': ['泰山', '黄山', '茅厕', '草丛', '房顶'], 'value': [3, 3, -1, 0, 1]}
}

第三步就是把整个句子的价值算出来:

total_value = 0 # 用来计算整个句子价值
total_text = []
for i in token:
    if i.startswith("$"):
      name = i[1:] # 去除前缀的$
      rand_i = random.randint(0, len(store_data[name]['text']) - 1) # 随机获得词缀中的一个
      total_text.append(store_data[name]['text'][rand_i])
      total_value += store_data[name]['value'][rand_i] # 加上词缀对应的价值
    elif i.startswith("#"):
      name = i[1:]
      if name == "disciple":
        rand_i = random.randint(0, len(disciple_data) - 1)
        total_text.append(disciple_data[rand_i])
    else:
      total_text.append(i)

这样价值就计算出来了,并且“ 令狐冲 ”、“ 王重阳 ”比“ 林平之 ”、“ 段誉 ”词缀的价值要高,“ 千锤百炼 ”比“ 一番把玩 ”价值要高,“ 拳打脚踢 ”甚至会产生负效果。

对应价值,设计一个简单的奖励表:

prize_data = {
    -4: "失去10声望",
    -3: "失去2000块钱",
    -2: "失去1000块钱",
    -1: "失去100块钱",
    0: "0块钱",
    1: "100块钱",
    2: "1000块钱",
    3: "2000块钱",
    4: "随机道具",
    5: "10声望",
    6: "20声望",
    7: "50声望",
    8: "一件衣服",
    9: "一把武器",
    10: "领悟一个技能",
    11: "资质提升",
    12: "领悟两个技能"
}

当然,如果算出来的奖励是多少,就获得对应等级的奖励,游戏也太无趣了,让获取奖励也多一些随机性,使用正态分布来处理获取奖励的概率,如果表达式的价值是8,那么应该是6、7、8的等级概率高,同时往两边扩散概率变低。

那么就进行最后一步,处理prize词缀,并且封装成方法,因为处理prize的时候直接使用了total_value的值,并没有检查之后是否还有词缀,所以为了计算奖励更加准确,需要将prize放在所有词缀的后面,以保证词缀都计算完成:

def random_event(expression_str):
  token = expression_str.split(" ")

  total_value = 0
  total_text = []
  for i in token:
    if i.startswith("$"):
      name = i[1:] # 去除前缀的$
      rand_i = random.randint(0, len(store_data[name]['text']) - 1) # 随机获得词缀中的一个
      total_text.append(store_data[name]['text'][rand_i])
      total_value += store_data[name]['value'][rand_i]
    elif i.startswith("#"):
      name = i[1:]
      if name == "disciple":
        rand_i = random.randint(0, len(disciple_data) - 1)
        total_text.append(disciple_data[rand_i])
      elif name == 'prize':
        rand_i = round(random.gauss(total_value - 1, (total_value - 1) / 10))
        total_text.append(prize_data[rand_i])
    else:
      total_text.append(i)
    
  return "".join(total_text)
random_event("$charactor 很喜欢您的弟子 #disciple ,对他 $act ,获得奖励 #prize")
# 段誉姑姑的弟弟的儿子的同学的妈妈很喜欢您的弟子谢帅逼,对他打情骂俏,获得奖励失去100块钱
random_event("$charactor 从 $place 到您的门派求学,是否接纳")
# 王重阳从泰山到您的门派求学,是否接纳

这样就可以通过编写不同的表达式,添加不同的普通词缀,编写更丰富的编程表达,来丰富整个事件系统,事件系统的能力也会成倍数增长。当然,这只是个思路,要真正做出这个事件,还有很多的概率需要计算。


0 条评论

发表回复

Avatar placeholder

您的电子邮箱地址不会被公开。 必填项已用 * 标注