新版太阳神三国杀武将技能AI设计概要.docx

上传人:b****5 文档编号:6704301 上传时间:2023-01-09 格式:DOCX 页数:24 大小:30.18KB
下载 相关 举报
新版太阳神三国杀武将技能AI设计概要.docx_第1页
第1页 / 共24页
新版太阳神三国杀武将技能AI设计概要.docx_第2页
第2页 / 共24页
新版太阳神三国杀武将技能AI设计概要.docx_第3页
第3页 / 共24页
新版太阳神三国杀武将技能AI设计概要.docx_第4页
第4页 / 共24页
新版太阳神三国杀武将技能AI设计概要.docx_第5页
第5页 / 共24页
点击查看更多>>
下载资源
资源描述

新版太阳神三国杀武将技能AI设计概要.docx

《新版太阳神三国杀武将技能AI设计概要.docx》由会员分享,可在线阅读,更多相关《新版太阳神三国杀武将技能AI设计概要.docx(24页珍藏版)》请在冰豆网上搜索。

新版太阳神三国杀武将技能AI设计概要.docx

新版太阳神三国杀武将技能AI设计概要

新版太阳神三国杀武将技能AI设计概要

第一章:

AI概述

第二章:

触发技与响应询问

一、响应技能发动询问

二、响应卡牌使用询问

三、响应卡牌打出询问

四、响应选择询问

五、响应角色选择询问

六、响应卡牌选择询问

七、响应五谷丰登选牌询问

八、响应卡牌展示询问

九、响应花色询问

十、响应遗计询问

十一、响应拼点询问

十二、响应弃牌询问

第三章:

视为技与技能发动

一、一般视为技与卡牌使用

二、一般视为技与卡牌响应

三、判定锁定视为技

四、使用技能卡

第四章:

AI特征信息

一、使用价值与使用优先级

二、相合花色与相合卡牌

三、武将嘲讽值

四、仇恨值与角色关系

第五节:

常用AI函数

 

第一章AI概述

正如《新版太阳神三国杀武将扩展学习手册》所描述的那样,太阳神三国杀的AI系统还是有一定章法可循的。

武将技能AI作为AI系统的重要组成部分,自然也不例外。

手册第八章里简单介绍了AI的概念和作用,给我们留下了一个初步的印象;这里将更进一步,感受一下更具体的武将技能AI设计工作。

说起来,武将技能AI还是与具体的武将技能有着密不可分的联系。

技能的种类、传递数据的方式,许多因素都影响着武将技能AI的设计。

触发技有触发技的AI策略,视为技也有自己的一套AI实现方法。

具体到技能上,更是花样百出,各有不同。

不过,掌握了武将技能AI的工作方法,再进行具体的设计,就容易很多了。

一般而言,距离修改技、手牌上限技之类的技能,在游戏里以锁定技的样貌出现,不需要玩家干预。

不论操作者是人类玩家还是电脑玩家,都是同样的效果,所以这些技能理论上是不需要AI支持的。

对于触发技来说,电脑玩家只需要知道在需要作出选择的时候,如何找出正确的答案即可。

为此,AI系统提供了一系列的决策表和决策函数。

每当遇到触发技询问时,首先查阅决策表中是否有对应的决策函数。

若找到这样的函数,就根据函数的结果作出选择;若没有找到,就交给AI系统统一处理,得出一个一般情形下的选择结果。

所以,触发技AI的设计,其实就是针对技能中出现的各个询问场景,编写对应决策函数的过程。

每个询问场景都会有自己特定的决策函数格式,按照这些格式写决策函数,就会很容易设计出触发技的AI了。

而对于视为技来说,情况又有所不同。

视为技没有特定的触发时机,需要玩家主动选择发动。

这需要考虑两个方面:

什么时候发动,以及要以怎样的方式发动。

在这个过程中,AI系统会依次检查玩家拥有的卡牌,判断哪些卡牌可用,并参照可用卡牌的优先级、使用价值等特征信息,选出当前最应使用的卡牌(包括技能卡和实际的卡牌),按照对应的卡牌使用方式使用它。

每当使用完一张卡牌,再重复这个过程,直到不再有卡牌可用。

这样,视为技的AI设计,一方面要提供判断卡牌是否可用的检测函数,一方面要提供包含了卡牌使用方式的执行函数。

此外,还要提供一些相关的特征信息,以决定在所有卡牌使用过程中的出场顺序。

除了武将技能AI以外,AI系统还包括了身份识别等更为丰富的内容,这里就不再关注了。

关于AI系统的更为详尽的介绍,可以参考太阳神三国杀extension-doc文件夹中的11-Fundamentals.lua~18-Beta.lua等文档。

第二章触发技与响应询问

一、响应技能发动询问

技能代码中出现askForSkillInvoke()函数的地方就是询问是否发动技能的场景了。

它的函数原型是:

Room:

askForSkillInvoke(player,skill_name,data)

其中:

player:

ServerPlayer类型,表示被询问发动技能的当前角色。

skill_name:

string类型,表示技能的名字。

data:

QVariant类型,表示传递给AI系统的参考数据。

另一个函数原型是:

ServerPlayer:

askForSkillInvoke(skill_name,data)

参数skill_name和data的涵义与第一个原型中的同名参数是相同的。

对于这个场景,AI系统的处理函数是:

SmartAI:

askForSkillInvoke(skill_name,data)

这个函数首先将通过表sgs.ai_skill_invoke查找对应的决策函数,而这个决策函数正是我们要具体设计的内容。

响应技能发动询问的决策函数原型是:

function(self,data)

其中:

self:

表示表SmartAI,由AI系统提供。

data:

表示参考数据,其实就是技能代码中传递过来的data参数了。

它的执行结果是bool类型的。

如果为true,表示发动技能;为false的话,则不发动这个技能。

这个表self(或者说表SmartAI)提供了许多有用的信息,比如:

self.player就是Room:

askForSkillInvoke(player,skill_name,data)中的第一个参数player,ServerPlayer类型,表示当前响应询问的角色。

self.room表示当前所在的游戏房间,Room类型。

self.friends表示当前角色的所有友方角色,也包括自己在内,table类型。

这里的友方不一定意味着身份的相同,主公与忠臣、忠臣与内奸、主公与内奸、内奸与反贼之间在一定时段內都可能会是友方关系。

self.friends_noself表示当前角色的除自身以外的所有友方角色,table类型。

self.enemies表示当前角色的所有敌方角色,table类型。

同self.friends的情形一样,身份的差异也不一定意味着阵营的对立。

将我们的决策函数写入表sgs.ai_skill_invoke的方法是:

sgs.ai_skill_invoke[skill_name]=function(self,data)

这就将技能名skill_name与特定的决策函数对应起来了。

如果技能是否发动与决策无关,那么决策函数可以简化成一个对应的bool值,比如:

sgs.ai_skill_invoke[skill_name]=true

就表示技能skill_name始终发动。

如果SmartAI:

askForSkillInvoke(skill_name,data)函数没有找到所需要的决策函数,那么它将按照默认的方式处理这个场景。

即,如果技能skill_name的触发频率是sgs.Skill_NotFrequent,那么产生一个false结果,不发动这个技能;如果触发频率是sgs.Skill_Frequent,那么产生一个true结果,发动技能。

对于其它场景,AI系统也是大体依照这样的流程进行处理的,后文不再赘述。

二、响应卡牌使用询问

技能代码中出现askForUseCard()函数的地方就是询问使用卡牌的场景了。

函数原型是:

Room:

askForUseCard(

player,pattern,prompt,notice_index=-1,method=sgs.Card_MethodUse

其中:

player:

ServerPlayer类型,表示被询问使用卡牌的当前角色。

pattern:

string类型,表示卡牌应符合的条件。

prompt:

string类型,表示询问时出现的提示信息。

notice_index:

number类型,表示提示信息的编号,默认为-1。

method:

sgs.Card_HandlingMethod类型,表示卡牌的处理方式,默认是sgs.Card_MethodUse。

对于这个场景,AI的处理函数是:

SmartAI:

askForUseCard(pattern,prompt,method)

三个参数pattern、prompt、method和技能代码中的同名参数是相同的。

这个函数通过表sgs.ai_skill_use来查找决策函数。

响应卡牌使用询问的决策函数原型是:

function(self,prompt,method)

它的执行结果是一个string,表示卡牌的使用方式。

具体的格式是:

#N:

C:

->U

#N[S:

P]:

C:

->U

@N=C->U

@N[S:

P]=C->U

其中:

N表示卡牌的对象名(objectName())。

S表示卡牌的花色字符串(getSuitString())。

P表示卡牌的点数(getNumber())。

C表示卡牌的子卡构成,是由一系列通过“+”连接的卡牌编号(getId())组成的字符串。

”.”表示没有子卡。

U表示卡牌的使用对象构成,是由一系列通过“+”连接的角色的对象名(objectName())组成的字符串。

”.”表示不指定使用对象。

以“#”开始的string结果表示Lua卡牌的使用方式,而以“@”开始的string结果表示C++卡牌的使用方式。

因此我们在设计武将技能AI时,写出的卡牌的使用方式,都是以“#”开始的。

将决策函数写入表sgs.ai_skill_use的方法是:

sgs.ai_skill_use[pattern]=function(self,prompt,method)

如果SmartAI:

askForUseCard(pattern,prompt,method)函数没用找到这个决策函数的话,默认产生的结果是”.”,表示不使用任何卡牌。

三、响应卡牌打出询问

技能代码中出现askForCard()函数的地方就是询问打出卡牌的场景了。

这个函数的原型是:

Room:

askForCard(player,pattern,prompt,data,skill_name)

以及

Room:

askForCard(

player,pattern,prompt,data,method=sgs.Card_MethodDiscard,

to=NULL,isRetrial=false,skill_name

其中:

player:

ServerPlayer类型,表示被询问打出卡牌的当前角色。

pattern:

string类型,表示卡牌应符合的条件。

prompt:

string类型,表示询问时出现的提示信息。

data:

QVariant类型,表示参考数据,还是从技能代码里传递过来的。

skill_name:

string类型,表示技能的名字。

method:

sgs.Card_andlingMethod类型,表示对卡牌的处理方式,默认是sgs.Card_MethodDiscard。

to:

ServerPlayer类型,默认为nil。

isRetrial:

bool类型,表示是否用于改判,默认为false。

对于这个场景,AI的处理函数是:

SmartAI:

askForCard(pattern,prompt,data)

这个函数通过表sgs.ai_skill_cardask来查找决策函数。

响应卡牌打出询问的决策函数原型是:

function(self,data,pattern,target,target2)

和响应卡牌使用询问的决策函数一样,它的结果也是string类型的,表示卡牌的使用方式。

将决策函数写入表sgs.ai_skill_cardask的方法是:

sgs.ai_skill_cardask[prompt]=function(self,data,pattern,target,target2)

如果SmartAI:

askForCard(pattern,prompt,data)函数没有找到这个决策函数,AI系统会尝试着按照pattern和prompt决定打出哪些卡牌。

如果仍然找不到符合条件的卡牌,那么将产生”.”的结果,表示不打出任何卡牌。

四、响应选择询问

技能代码中出现askForChoice()函数的地方就是询问选择的场景了。

这个函数的原型是:

Room:

askForChoice(player,skill_name,choices,data)

其中:

player:

ServerPlayer类型,表示被询问选择的当前角色。

skill_name:

string类型,表示技能的名字。

choices:

string类型,表示各个选项,是由一系列通过”+”连接的选项字符串组成的。

data:

QVariant类型,表示要向AI传递的参考数据。

对于这个场景,AI系统的处理函数是:

SmartAI:

askForChoice(skill_name,choices,data)

这个函数通过表sgs.ai_skill_choice来查找决策函数。

响应选择询问的决策函数原型是:

function(self,choices,data)

它将产生一个string类型的结果,表示选出的那个选项。

将决策函数写入表sgs.ai_skill_choice的方法是:

sgs.ai_skill_choice[skill_name]=function(self,choices,data)

如果选择的结果与决策无关,那么决策函数可以直接简化成这个结果,比如:

sgs.ai_skill_choice[skill_name]=“choiceA”

就表示技能skill_name询问选择时,始终选择choiceA。

如果SmartAI:

askForChoice(skill_name,choices,data)函数仍然没有找到这个决策函数,那么AI系统首先将检查这个技能是否有默认的选择,如果有,就直接用默认的选择作为结果。

否则,AI系统将从choices里随机选出一个选项,作为最终的结果。

五、响应角色选择询问

技能代码中出现askForPlayerChosen()函数的地方就是询问选择一名角色的场景了。

这个函数的原型是:

Room:

askForPlayerChosen(player,targets,reason)

其中:

player:

ServerPlayer类型,表示被询问选择角色的当前角色。

targets:

QList类型,是一个列表,表示各个备选的角色。

reason:

string类型,表示询问角色选择的原因。

对于这个场景,AI系统的处理函数是:

SmartAI:

askForPlayerChosen(targets,reason)

这个函数通过表sgs.ai_skill_playerchosen来查找决策函数。

响应角色选择询问的决策函数原型是:

function(self,targets)

它将产生一个ServerPlayer类型的结果,表示被选出的角色。

将决策函数写入表sgs.ai_skill_playerchosen的方法是:

sgs.ai_skill_playerchosen[reason]=function(self,targets)

如果SmartAI:

askForPlayerChosen(targets,reason)找不到这样的决策函数,那么AI系统将从这些备选角色中随机选择一名,作为最后的结果。

六、响应卡牌选择询问

技能代码中出现askForCardChosen()函数的地方就是询问选择一张卡牌的场景了。

这个函数的原型是:

Room:

askForCardChosen(player,who,flags,reason)

其中:

player:

ServerPlayer类型,表示被询问选择卡牌的当前角色。

who:

ServerPlayer类型,表示待选卡牌所属的目标角色。

flags:

string类型,表示待选卡牌的位置标志。

由”h”(表示手牌区)、”e”(表示装备区)、”j”(表示判定区)组合而成。

reason:

string类型,表示询问卡牌选择的原因。

对于这个场景,AI系统的处理函数是:

SmartAI:

askForCardChosen(who,flags,reason)

这个函数通过表sgs.ai_skill_cardchosen来查找决策函数。

响应卡牌选择询问的决策函数原型是:

function(self,who,flags)

它将产生一个number类型的结果,表示选出的卡牌的编号。

将决策函数写入表sgs.ai_skill_cardchosen的方法是:

sgs.ai_skill_cardchosen[reason]=function(self,who,flags)

如果选择的结果与决策过程无关,那么可以决策函数可以简化为具体的卡牌编号。

比如:

sgs.ai_skill_cardchosen[reason]=23

就表示在响应原因为reason的卡牌选择询问时,始终选择编号为23的卡牌(杀[♥10])。

如果SmartAI:

askForCardChosen(who,flags,reason)找不到这个决策函数,那么AI系统将根据who是否为友方、flags包含的区域以及具体的reason作出一般情形下的选择。

这个选择的过程较为复杂,具体可参考smart-ai.lua中该函数的具体代码。

七、响应五谷丰登选牌询问

技能代码中出现askForAG()函数的地方就是询问从五谷丰登界面选择一张卡牌的场景了。

这个函数的原型是:

Room:

askForAG(player,card_ids,refusable,reason)

其中:

player:

ServerPlayer类型,表示被询问五谷丰登选牌的当前角色。

card_ids:

QList类型,表示五谷丰登界面中所有备选卡牌的编号列表。

refusable:

bool类型,表示是否可以拒绝响应此询问。

reason:

string类型,表示询问选择的原因。

对于这个场景,AI系统的处理函数是:

SmartAI:

askForAG(card_ids,refusable,reason)

这个函数通过表sgs.ai_skill_askforag来查找决策函数。

响应五谷丰登选牌询问的决策函数原型是:

function(self,card_ids)

它将产生一个number类型的结果,表示选出的卡牌的编号。

将决策函数写入表sgs.ai_skill_askforag的方法是:

sgs.ai_skill_askforag[reason]=function(self,card_ids)

如果SmartAI:

askForAG(card_ids,refusable,reason)找不到这样的决策函数,那么AI系统将根据refusable、reason以及self.player自身的技能和对卡牌的需求程度作出一般情形下的选择。

这个选择的过程同样较为复杂,具体可以参考smart-ai.lua中该函数的具体代码。

八、响应卡牌展示询问

技能代码中出现askForCardShow()函数的地方就是询问展示一张卡牌的场景了。

这个函数的原型是:

Room:

askForCardShow(player,requestor,reason)

其中:

player:

ServerPlayer类型,表示被询问展示卡牌的当前角色。

requestor:

ServerPlayer类型,表示发起询问的源角色。

reason:

string类型,表示询问卡牌展示的原因。

对于这个场景,AI系统的处理函数是:

SmartAI:

askForCardShow(requestor,reason)

这个函数通过表sgs.ai_cardshow来查找决策函数。

响应卡牌展示询问的决策函数原型是:

function(self,requestor)

这个函数将产生一个Card类型的结果,表示将展示的卡牌。

将决策函数写入表sgs.ai_cardshow的方法是:

sgs.ai_cardshow[reason]=function(self,requestor)

如果SmartAI:

askForCardShow(requestor,reason)没用找到这样的决策函数,那么AI系统将从当前角色的手牌中随机选择一张作为结果以进行展示。

九、响应花色询问

技能代码中出现askForSuit()函数的地方就是询问选择一种花色的场景了。

这个函数的原型是:

Room:

askForSuit(player,reason)

其中:

player:

ServerPlayer类型,表示被询问选择花色的当前角色。

reason:

string类型,表示询问花色的原因。

如果reason缺失的话,AI系统会将其补全为”fanjian”,并依照反间选择花色的情形处理。

对于这个场景,AI系统的处理函数是:

SmartAI:

askForSuit(reason)

这个函数通过表sgs.ai_skill_suit来查找决策函数。

响应卡牌展示询问的决策函数原型是:

function(self)

这个函数将产生一个number类型的结果,表示选出的花色编号。

其中,0、1、2、3分别表示黑桃、红心、草花、方块花色。

将决策函数写入表sgs.ai_skill_suit的方法是:

sgs.ai_skill_suit[reason]=function(self)

如果SmartAI:

askForSuit(reason)没用找到这样的决策函数,那么AI系统将从0~3中随机选出一个数字作为最后选择的结果。

十、响应遗计询问

技能代码中出现askForYiji()函数的地方就是询问遗计分牌的场景了。

这个函数的原型是:

Room:

askForYiji(guojia,cards,is_preview=true,visible=false)

其中:

guojia:

ServerPlayer类型,表示被询问遗计分牌的当前角色。

cards:

QList类型,表示待分配的卡牌的编号列表。

is_preview:

bool类型,默认为true。

visible:

bool类型,表示卡牌在分配过程中是否对所有角色可见,默认为false。

原本这个函数只是技能“遗计”专用的,后来随着“礼让”等技能的出现,才开放出来,有了进行额外的AI设计的可能。

对于这个场景,AI系统的处理函数是:

SmartAI:

askForYiji(card_ids,reason)

这个函数是通过表sgs.ai_skill_askforyiji来查找决策函数的。

响应遗计询问的决策函数原型是:

function(self,card_ids)

这个函数将产生两个结果,依次是ServerPlayer类型(表示分牌的目标角色)和number类型(表示分给目标角色的卡牌的编号)的。

将决策函数写入表sgs.ai_skill_askforyiji的方法是:

sgs.ai_skill_askforyiji[reason]=function(self,card_ids)

如果SmartAI:

askForYiji(card_ids,reason)没有找到这个决策函数,那么AI系统将根据self.player自身存在的标志,采用“礼让”或“遗计”的策略产生分牌的结果。

这部分内容较为复杂,具体可以参考smart-ai.lua中此函数的相关代码。

十一、响应拼点询问

技能代码中出现askForPindian()函数的地方就是询问打出一张卡牌拼点的场景了。

这个函数的原型是:

Room:

askForPindian(player,from,to,reason)

其中:

player:

ServerPlayer

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 医药卫生 > 基础医学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1