delete[]choices[i];
delete[]choices;
}
}
}*ENTRY_RULE_PTR;
//============================================================================
//Structurethatstoreasingleaction.
//============================================================================
typedefstructACTION
{
longindex;//actionindex[0,numberofaction-1]
chartext[256];//actiontext
shortnum_entries_rule;//numberofentriesinaction
ENTRY_RULE_PTRentries_rule;//arrayofentrystructures
ACTION*next;//nextactioninlinkedlist
ACTION()
{
memset(this,0,sizeof(*this));
}
~ACTION()
{
delete[]entries_rule;
deletenext;
}
}*ACTION_PTR;
行为模板被存储为文本文件,同时每个行为的文本被包括在括号中。
每个包含条目的行为(标记为文本中的波浪字符)紧跟着是条目数据的列表。
每个条目由一个描述条目类型(文本型、布尔型、整型、浮点型或选项型)的单词开始。
对于文本类型而言并没有更多的需要信息,对于布尔类型来说也是如此。
而作为整数和浮点型,则要求一个最小值和最大值。
最后,选项类型条目后跟着的是可供选择的编号以及每个选项的文本(包括在引号里)。
如下所示:
"Ifflag#~is~then"
INT0255
BOOL
"Else"
"Endif"
"Setflag#~to~"
INT0255
BOOL
"Print~"
TEXT
"Movecharacterto~,~,~"
FLOAT0.02048.0
FLOAT0.02048.0
FLOAT0.02048.0
"Character~~~~points"
CHOICE3
"MainCharacter"
"Caster"
"Target"
CHOICE2
"Gains"
"Looses"
INT0128
CHOICE2
"Hit"
"Magic"
"Engageinbattlesequence#~"
INT065535
"EndScript"
第二篇
脚本条目的创建
因为ENREY_RULE结构仅包含了行为和条目的规则,所以需要另外的结构数组去存储每个条目的数据。
这些新的结构包括了在条目中所使用的文本、布尔值、多重选项,我们使用结构体ENTRY来表示。
//============================================================================
//structurethatstoreallentriesfactinformation.
//============================================================================
typedefstructENTRY
{
longtype;//typeofblankentry(ENTRY_TEXT,ENTRY_BOOL,
)
union
{
longio_value;//usedforsaving/loading
longlength;//lengthoftext(0terminator)
longselection;//selectioninchoice
BOOLbool_value;//BOOLvalue
longlong_value;//longbalue
floatfloat_value;//floatvalue
};
char*text;//entrytextbuffer
ENTRY()
{
memset(this,0,sizeof(*this));
}
~ENTRY()
{
delete[]text;
}
}*ENTRY_PTR;
在处理脚本条目的过程中,当一个脚本出现了许多条目时,最麻烦的问题也就接踵而来。
脚本中的每个行为都要求一个相匹配的ENTRY_RULE结构,其依次包含了一定数量的ENTRY结构。
为了更好地处理一个脚本的结构,还需要其他的结构来记录属于脚本行为的每个条目,我们将它命名为SCRPT。
//============================================================================
//structurethatstoreall
//============================================================================
typedefstructSCRIPT
{
longaction_index;//[0,numberofactions-1]
longnum_entries;//numberofentriesinthisaction
ENTRY_PTRentries;//arrayofentries
SCRIPT*prev;//previousinlinkedlist
SCRIPT*next;//nextinlinkedlist
SCRIPT()
{
memset(this,0,sizeof(*this));
}
~SCRIPT()
{
delete[]entries;
deletenext;
}
}*SCRIPT_PTR;
prev和next维护了整个脚本的连接列表,为了构造SCRIPT结构的连接列表,从代表脚本的第一个行为的根结构开始,然后使用next和prev将SCRIPT结构连接起来,如下图所示:
ACTION_TEMPLATE类的整合
理解了行为模板所使用的结构以及所容纳的脚本后,现在开始将它们整合到一起创建一个加载并处理脚本的类。
//============================================================================
//Thisclassencapsulatescriptsaveandload.
//============================================================================
typedefclassACTION_TEMPLATE
{
private:
longm_num_actions;//numberofactionsintemplate
ACTION_PTRm_root_action;//listoftemplateactions
public:
ACTION_TEMPLATE();
~ACTION_TEMPLATE();
BOOLload_actions(constchar*filename);
voidfree();
longget_num_actions();
ACTION_PTRget_root_action();
ACTION_PTRget_action(longact_index);
SCRIPT_PTRcreate_script(longact_index);
longget_num_entries_rule(longact_index);
ENTRY_RULE_PTRget_entry_rule(longact_index,longentry_rule_index);
voidexpand_default_action_text(char*buffer,ACTION_PTRaction);
BOOLexpand_action_text(char*buffer,SCRIPT_PTRscript);
}*ACTION_TEMPLATE_PTR;
实现:
//------------------------------------------------------------------------
//Getquotedlinefromfile.
//------------------------------------------------------------------------
staticBOOL_get_quoted_line(FILE*fp,char*data,longmax_data_size)
{
intc;
longpos=0;
//readuntilaquoteisreached(orEOF)
while
(1)
{
if((c=fgetc(fp))==EOF)
returnFALSE;
if(c=='"')
{
//readuntilnextquot(orEOF)
while
(1)
{
if((c=fgetc(fp))==EOF)
returnFALSE;
//returntextwhen2ndquotefound
if(c=='"')
{
data[pos]=0;
break;
}
//addacceptabletexttoline
if(c!
=0x0a&&c!
=0x0d)//ifcharacterisnotlinefeed,notcarriage.
{
if(posdata[pos++]=c;
}
}
break;
}
}
returnTRUE;
}
//------------------------------------------------------------------------
//Getwordfromfile.
//------------------------------------------------------------------------
staticBOOL_get_word(FILE*fp,char*data,longmax_data_size)
{
intc;
longpos=0;
//resetwordtoempty
data[0]=0;
//readuntilanacceptablecharacterfound
while
(1)
{
if((c=fgetc(fp))==EOF)
{
data[0]=0;
returnFALSE;
}
//checkforstartofword
if(c!
=32&&c!
=0x0a&&c!
=0x0d)//ifcharacterisnotblank,notlinefeed,notcarriage.
{
data[pos++]=c;
//loopuntilendofword(orEOF)
while((c=fgetc(fp))!
=EOF)
{
//breakonacceptablewordseperators
if(c==32||c==0x0a||c==0x0d)
break;
//addifenoughroomleft
if(posdata[pos++]=c;
}
//addendoflinetotext
data[pos]=0;
break;
}
}
returnTRUE;
}
//------------------------------------------------------------------------
//Constructor,zeromemberdata.
//------------------------------------------------------------------------
ACTION_TEMPLATE:
:
ACTION_TEMPLATE()
{
memset(this,0,sizeof(*this));
}
//------------------------------------------------------------------------
//Destructor,releaseallocatedmemory.
//------------------------------------------------------------------------
ACTION_TEMPLATE:
:
~ACTION_TEMPLATE()
{
free();
}
//------------------------------------------------------------------------
//Releaseallocatedmemory.
//------------------------------------------------------------------------
voidACTION_TEMPLATE:
:
free()
{
deletem_root_action;
m_num_actions=0;
}
//------------------------------------------------------------------------
//Loadanactiontemplate.
//------------------------------------------------------------------------
BOOLACTION_TEMPLATE:
:
load_actions(constchar*filename)
{
constintsize=256;
//freepreviousactionstructures
free();
FILE*fp;
//opentheactionfile
if((fp=fopen(filename,"rb"))==NULL)
returnFALSE;
ACTION_PTRact_ptr=NULL;
//keeploopinguntilendoffilefound
while
(1)
{
chartext[size];
//getnextquotedaction
if(!
_get_quoted_line(fp,text,size))
break;
//quitifnoactiontext
if(text[0]==0)
break;
//allocateonactionstructureandappendittolist
ACTION_PTRact=newACTION;
act->next=NULL;
if(act_ptr==NULL)
m_root_action=act;
else
act_ptr->next=act;
act_ptr=act;