最近在学游戏开发,尝试开发一个经营类游戏,其中有个点子就是:在游戏的过程中,会不时的发生一些突发事件,可能是任务,可能是天灾人祸等,当然,要有趣,那么这个事件就得是随机的,不能是一成不变的。
我的想法是设计一个表达式,使用表达式形成事件的多样化,表达式里的词缀够多,用词缀来实现随机化,这样添加足够多的词缀和表达式就能有足够多的随机事件。最后实现的效果应该是这样:
$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 条评论