tankant 发表于 2012-9-9 19:50:41

AI脚本生成器设计文档..........进行当中.....

本帖最后由 tankant 于 2012-9-10 20:06 编辑

需求方面,我貌似看不到太多的建议。那么我根据自己的理解开始设计一个设计文档。大家可以看看我的想法是不是已经都被人实现过。如果是那样的话,我就放弃。

实现语言:Python
GUI类库:PySide
数据库:SQLite

功能模块:
I.读取文件。读取per文件作为内容,并判断语法错误,识别规则、条件、动作等信息表现在GUI上。
II.编辑AI。点击鼠标完成所有的设计。当然也可以直接对代码进行修改
III.写文件。检查代码,如果代码语法没有错误,根据鼠标的修改把结果保存到per文件去。
IV.版本切换。可以在1.0C版本和其他MOD转换。可以新建MOD脚本规则。比如新建单位和对应的代码。

我对一些概念的理解和设计如下:

条件:全是返回值为bool类型的函数
分为三种:
1.固定条件。就是没有参数的函数
2.自定义条件。就是有一个或多个参数的函数
3.组合条件。可以把任何多个条件(固定条件、自定义条件、组合条件)进行组合成一个组合条件,逻辑组合方式分为and和or组合。

动作组:多个动作的序列(包括一个动作)

规则:一个条件+动作组的组合

GOAL:变量

希望我在文档设计阶段出现的错误,大家不要吝惜笔墨,请指出来。
感谢大家的鼓励与支持!感谢剧情狂的共同讨论!

个人主页www.orayes.com

tankant 发表于 2012-9-9 19:51:04

本帖最后由 tankant 于 2012-9-10 18:14 编辑

############################################
#读取脚本设计方案:
#I.逻辑步骤:
#读取文件(已完成)
#识别注释和字符串(已完成)
#定位所有的load
#定位所有defcon的位置,识别出常量和GOAL
#定位所有的#load-if-defined和#load-if-not-defined语句与其各自的#end-if、#else语句
#定位所有(defrule的位置和对应的右括号、=>符号,划分出条件部分和动作部分
#分析条件部分,划分出条件类型(我这个算法可能不好,肯定有更有效率的算法)
    #找到(or和对应的右括号,作为或类型的组合条件
    #找到(and和对应的右括号,作为与类型的组合条件;
    #找到连续两个的(和与之对应的右括号,作为与类型的组合条件;
    #找到最内侧的括号对,作为普通条件
#分析动作部分,定位所有动作部分的括号对,作为动作序列


#II.待写类:
#很多,最后列举

#III对应数据库相关的表设计:

#注释表(注释id,起始位置,结束位置)
#字符串表(字符串id,起始位置,结束位置)
#load表(load_id_PK,起始位置,导入的文件)
#常量和GOAL表(conid_PK,name,value)
#分支判断表(分支id,if位置,if类型,else位置,end位置)

#规则表(规则id,起始位置,结束位置,条件部分id,动作部分id)
#条件部分表((条件部分id,包含条件id)_PK)
#((条件id,包含条件id)_PK,逻辑组合类型,起始位置,结束位置)
#普通条件表((条件id)_PK,起始位置,结束位置)
#动作部分表((动作部分id,动作id)_PK)
#动作表(动作id_PK,动作次序)

#www.orayes.com

tankant 发表于 2012-9-9 19:51:16

本帖最后由 tankant 于 2012-9-10 02:37 编辑

成功读取了AI脚本到数据库后,则开始把内容显示到GUI上。如何布局GUI,既能满足所有的AI编写需要,有能有较好的用户体验,这是我一直苦苦思索的问题。作为程序设计者的我,思考更多的是满足所有AI编写的需要,而不是用户体验;而AI设计者是我的需求客户,所以大家应该在这个问题上好好探讨,多多提出意见。大概看了下卧龙先生的程序,否定了N多个方案后,以下是我的设计方案:

1.文件读取
    读取PER或者ZYP文件
2.文件保存
    2.1另存为PER脚本
    2.2另存为ZYP插件
3.添加状态(其实就是定义常量和GOAL)_QButton-->QWindow
    状态名称_QLineEdit
    状态值_QLineEdit
3.逻辑分支--逻辑分支列表_QListView
    3.1添加逻辑分支_QButton
      选择条件_QTreeView
      选择满足后的动作_QTreeView
      选择不满足后的动作_QTreeView
      确认添加_QButton
    3.2删除逻辑分支_QButton
4.规则--规则列表_QListView
    4.1.添加规则_QButton
      4.1.设置条件部分_QButton-->条件列表_QTreeView

            4.1.1.添加普通条件_QButton
                选择条件主语_QTreeView
                选择条件谓语_QListWidget
                选择条件宾语_QTreeView
            4.1.2.删除普通条件_QButton

            4.1.3.添加组合条件_QButton-->组合条件列表_QListView
                选择组合逻辑_QCheckBox

                4.1.3.1.添加普通条件_QButton
                  选择条件_QTreeView
                4.1.3.3.删除普通条件_QButton
                  选择条件_QTreeView

            4.1.4.重设条件部分_QButton

      4.2.设置动作部分_QButton--动作列表_QTreeView
            4.2.1.添加动作_QButton
                选择动作主语_QTreeView
                选择动作谓语_QListWidget
                选择动作宾语_QTreeView
            4.2.2.重设动作部分_QButton
    4.2.删除规则_QButton

5.格式化脚本
    5.1规范脚本的书写_QButton
    5.2自动添加注释_QButton

数据库需要建立的表:所有参数分门别类建立各自的表(很多,数据量很大,我录入都恶心了;另外这一步表名太多,需要有个命名规范,求资料!!!!!)

利用GUI保存数据后,再把数据写到per文件的实现就很简单了
#www.orayes.com

tankant 发表于 2012-9-9 19:51:47

本帖最后由 tankant 于 2012-9-10 19:01 编辑

开始实现一些方法
#www.orayes.com########################################
#www.orayes.com########################################
#www.orayes.com########################################
#www.orayes.com########################################
#www.orayes.com########################################

#./t/public.py
#encoding:utf8
#公共方法


#设置测试字符串
#script = open ('./data').read()
#len_script=len(script)

###########################################
#方法1:定位第一个指定文本的位置
def first_fuhao(s,text,start,end):
    fuhao=range(start,len(s))
    for i in fuhao:
      if s==text:
            idx=i
            break
      else:
            None
    else:
      idx=-1
    return idx

#print '定位第一个(: '.decode("utf8"),first_fuhao(script,'(',0,len_script)
#################################################



#################################################
#方法2:定位所有指定文本的位置
#依赖方法1
def all_fuhao(s,text,start,end):
    next_search=0
    positions=[]
    len_text=len(text)
    while 1:
      pos=first_fuhao(s,text,next_search,end)
      if pos==-1:
            break
      positions.append(pos)
      next_search=pos+len_text
    return positions
#print '定位所有(: '.decode("utf8"),all_fuhao(script,'(',0,len_script)
#################################################


################################################
#方法3:定位第一个"对的位置
#依赖方法1
#前提是"必须是偶数个
def first_fenhao_pair(s,start,end):
    pos1=first_fuhao(s,'"',start,end)
    pos2=first_fuhao(s,'"',pos1+1,end)
    return

#pair=first_fenhao_pair(script,0,len_script)
#print '定位第一对": '.decode("utf8"),pair,pair

#www.orayes.com########################################
#www.orayes.com########################################
#www.orayes.com########################################
#www.orayes.com########################################
#www.orayes.com########################################   

#./read.py
#encoding:utf8


import sys
sys.path.append("./t")
import public

#测试字符串
cur_line='aasdf"afd"awe"as;df"asf'#假设这是脚本的一行







def abc(line):
    ########识别当前行分号和双引号哪个是有效的
    len_line=len(line)

    #定位第一个;的位置
    first_fenhao=public.first_fuhao(cur_line,';',0,len_line)
    #print 'first_fenhao ',first_fenhao

    #定位第一个"的位置
    first_yinhao=public.first_fuhao(cur_line,'"',0,len_line)
    #print 'first_yinhao',first_yinhao

    #定位所有"的位置
    all_yinhao=public.all_fuhao(cur_line,'"',0,len_line)
    #print 'all_yinhao',all_yinhao
    #active_yinhao=all_yinhao#初始化有效"
    active_yinhao=public.all_fuhao(line,'"',0,len_line)
    #print 'active_yinhao',active_yinhao

    #定位所有;的位置
    all_fenhao=public.all_fuhao(line,';',0,len_line)
    #print 'all_fenhao',all_fenhao
    #active_yinhao=all_yinhao#初始化有效"
    active_fenhao=public.all_fuhao(line,';',0,len_line)

    start_pos=0
    active_yinhao_pairs=[]
    while 1:
      #print '==========='
      if first_fenhao==-1:
            #print '没有注释'.decode("utf8")
            #把有效引号序列变成有效引号对序列
            len_active_yinhao=len(active_yinhao)
            num=0
            active_yinhao_pairs=[]
            while num<len_active_yinhao:
                active_yinhao_pairs.append(,active_yinhao])
                num+=2
            active_fenhao.append(-1)
            break
      if first_yinhao==-1:
            #print '剩余没有引号了'.decode("utf8")
            break
      if first_fenhao<first_yinhao:#假设第一个;在第一个"前面
            #print first_fenhao,'之后所有"将失效'.decode('utf8')
            #print active_yinhao
            len_active_yinhao=len(active_yinhao)
            #print range(len_active_yinhao),'-----------'
            num=0
            for cur_yinhao in active_yinhao:
                if cur_yinhao>first_fenhao:
                  start_del_yinhao=active_yinhao.index(cur_yinhao)
                  for i in range(num,len_active_yinhao):#把当前分号之后所有引号全部设置为无效
                        del active_yinhao
                        #print active_yinhao
                  break
                else:
                  None
                num+=1
            #print '=================='
            #把有效引号序列变成有效引号对序列
            len_active_yinhao=len(active_yinhao)
            num=0
            active_yinhao_pairs=[]
            while num<len_active_yinhao:
                active_yinhao_pairs.append(,active_yinhao])
                num+=2
            break
      if first_yinhao<first_fenhao:#假设第一个"在第一个;前面
            #print '第一个"对之间的;将失效'.decode('utf8')
            #print 'all_fenhao',all_fenhao
            #print 'active_fenhao',active_fenhao
            pair=public.first_fenhao_pair(line,start_pos,len_line)
            #print '定位第一对": '.decode("utf8"),pair,pair
            for cur_fenhao in all_fenhao:
                if cur_fenhao>pair and cur_fenhao<pair:
                  #print cur_fenhao,'分号失效'.decode("utf8")#当前没有用的分号
                  active_fenhao.remove(cur_fenhao)
                  #print '剩余有效分号'.decode("utf8"),active_fenhao
            #print '剩余有效分号: '.decode('utf8'),active_fenhao
      if pair==-1:
            #print "语法错误-1:一行内有效引号不成对".decode("utf8")
            active_yinhao_pairs.append([-1,-1])
            break
      start_pos=pair+1#新循环的开始位置
      #print 'start_pos :',start_pos
      if start_pos==-1:
            #print '=================='
            #把有效引号序列变成有效引号对序列
            len_active_yinhao=len(active_yinhao)
            num=0
            
            while num<len_active_yinhao:
                active_yinhao_pairs.append(,active_yinhao])
                num+=2
            break
      all_fenhao=active_fenhao
      first_fenhao=public.first_fuhao(line,';',start_pos,len_line)
      first_yinhao=public.first_fuhao(line,'"',start_pos,len_line)

    print '所有有效的引号对'.decode("utf8"),active_yinhao_pairs
    print '注释开始位置:'.decode("utf8"),active_fenhao
    return ]
print abc(cur_line)
#www.orayes.com


以下是./read.py的测试用例:

情况1:有效引号不成对(语法错误)
aa"bb"c";cdd;eeff

所有有效的引号对 [[-1, -1]]
注释开始位置: 8
[[[-1, -1]], 8]

情况2:没有有效引号
asdf;asdf"asdf";asdfasf

所有有效的引号对 []
注释开始位置: 4
[[], 4]

情况3:有成对有效引号,有注释
aa"bb"c";c"dd;"ee"ff

所有有效的引号对 [, ]
注释开始位置: 13
[[, ], 13]

情况4:有成对有效引号,无注释
aasdf"afd"awe"as;df"asf

所有有效的引号对 [, ]
注释开始位置: -1
[[, ], -1]


#www.orayes.com

sulfurliuz 发表于 2012-9-9 23:13:25

回复 tankant 的帖子

楼主加油,如果能够将AI的编辑智能化,将是一大壮举

得闲人 发表于 2012-9-10 00:44:23

本帖最后由 得闲人 于 2012-9-10 11:38 编辑

建议增加插件(例如不动AI数字AI等)
-------------------------------
是否能做到给出一个AI就知道它是什么意思

tankant 发表于 2012-9-10 19:32:52

本帖最后由 tankant 于 2012-9-10 20:06 编辑


累死我了,我得休息会儿。。。。。

tankant 发表于 2012-9-11 10:07:22

本帖最后由 tankant 于 2012-9-11 10:10 编辑

回复 得闲人 的帖子

1.插件。。。这种东西也计划可以用这个程序生成、读取。你指的是ZYP文件吗?
2.你是说直观性。。。能做到。关键是参数太多,需要时间整理录入。录入完后才能进行下一步GUI的设计。

tankant 发表于 2012-9-29 21:07:01

本帖最后由 tankant 于 2012-11-2 16:42 编辑

我已经把剧情狂翻译的那个AI帮助手册的数据输入到数据库中了。最近编写了无数脚本,积累了许多经验,提高了许多认识。感觉这里面的讲究很多,比较复杂。不过思路理清了许多。知道怎样入手了。希望写脚本的朋友能给我提出更多建议。


已经做出一个初步的样子,目前只能生成AI脚本,保存按钮不知道放在哪里合适:
https://www.hawkaoe.net/bbs/thread-95096-1-1.html
页: [1]
查看完整版本: AI脚本生成器设计文档..........进行当中.....