複雑なデータの取得
複雑なものをC++で直接相手にせず、Luaで平らにして取り扱いやすくする
Lua側で複雑な入り組んだデータを定義し、これをScenarioModで取得する場合、
複雑なデータのまま、画用紙に書いてしまうと、SceanrioMod側の負担が高まります。
なぜなら、ScenarioModで簡単に画用紙から取得できるのは、「少数」もしくは「文字列」であり、
複雑なデータ構造となると、素のLuaの比較的複雑で取り回しにくいAPIを直接扱うことになるからです。
今回は、以下のようなデータが、個数不明のまま定義されたとしても、問題なくSceanrioModで取得する
ということを目指します。
ファイルの読み込み部
以下のように対象となるtxtファイルを「天翔記フォルダ」に用意します。
-
BushouData.txt
local data_list = {
{['名前']="武田信玄" , ['政治']=100, ['戦闘']= 90, ['智謀']=80},
{['名前']="上杉謙信" , ['政治']=70, ['戦闘']=120, ['智謀']=70},
{['名前']="北条氏康" , ['政治']=105, ['戦闘']= 80, ['智謀']=90},
}
-
カスタム駆動関数.cpp
void 複雑なパラメータの取得() {
try {
// ファイル存在簡易チェック。win32api
if ( PathFileExists( "BushouData.txt" ) ) {
LUA::Do_ファイル("BushouData.txt");
}
} catch(...) {
デバッグ出力 << "LUAファイル実行エラー" << endl;
return; // このレベルでエラーはヤバイ。パラメタ読み取りはしない。
}
}
void カスタム::On_起動時() {
複雑なパラメータの取得()
}
Luaで値を返す関数を作成
先述のBushouData.txtのデータは、「テーブルのなかに、さらにテーブル」が入っており、入り組んでいますので、
画用紙に書かれているこのままの形だと、C++側で値を取得するのは、とても大変です。
そこで、Luaで、以下のような関数を作り、
「Get_グローバル数値」や「Get_グローバル文字列」で値を引き出せるような形で取れる準備をします。
dprintしてみると、その様子がわかります。
-
BushouData.txt
local data_list = {
{['名前']="武田信玄" , ['政治']=100, ['戦闘']= 90, ['智謀']=80},
{['名前']="上杉謙信" , ['政治']=70, ['戦闘']=120, ['智謀']=70},
{['名前']="北条氏康" , ['政治']=105, ['戦闘']= 80, ['智謀']=90},
}
-- とある ix 番目のデータを、平べったく値だけ並べて返す。
-- もし ix 番目がデータの終わりなら、'終了' という文字列を返す。
function GetNextDataList(ix)
-- ix番目のデータに別名「p」を付ける。(コピーではない、別名)
local p = data_list[ix]
if p then
-- luaは複数の値を並べて返すことが出来る。
return '続く', p['名前'], p['政治'], p['戦闘'], p['智謀']
else
return '終了'
end
end
dprint( GetNextDataList(1) )
dprint( GetNextDataList(2) )
dprint( GetNextDataList(3) )
dprint( GetNextDataList(4) )
dprint( GetNextDataList(5) )
さて、直接ベタ書きした部分は、 具体的なデータ数を指定せずとも、for ループにできるでしょう。
又、次のように 一端グローバル変数に受け取って画用紙へと書き 画用紙経由で取り扱うことが可能だと気づくでしょうか。
-
forループにする実験
local data_list = {
{['名前']="武田信玄" , ['政治']=100, ['戦闘']= 90, ['智謀']=80},
{['名前']="上杉謙信" , ['政治']=70, ['戦闘']=120, ['智謀']=70},
{['名前']="北条氏康" , ['政治']=105, ['戦闘']= 80, ['智謀']=90},
}
function GetNextDataList(ix)
local p = data_list[ix]
if p then
return '続く', p['名前'], p['政治'], p['戦闘'], p['智謀']
else
return '終了'
end
end
for i=1, 10000 do
_is_end, _pname, _pgov, _pbat, _pint = GetNextDataList(i)
if _is_end == '終了' then
break;
else
dprint(_pname, _pgov, _pbat, _pint)
end
end
ということは、C++側から、この for ループのような処理をしてやれば、値を受け取れそうだ、ということがわかります。
-
最終的なBushouData.txt
local data_list = {
{['名前']="武田信玄" , ['政治']=100, ['戦闘']= 90, ['智謀']=80},
{['名前']="上杉謙信" , ['政治']=70, ['戦闘']=120, ['智謀']=70},
{['名前']="北条氏康" , ['政治']=105, ['戦闘']= 80, ['智謀']=90},
}
function GetNextDataList(ix)
local p = data_list[ix]
if p then
return '続く', p['名前'], p['政治'], p['戦闘'], p['智謀']
else
return '終了'
end
end
-
最終的なカスタム駆動関数.cpp
struct myパラメタ型 {
int 番号;
string 名前;
int 政治;
int 戦闘;
int 智謀;
};
vector<myパラメタ型> v_data_list;
void 複雑なパラメータの取得() {
try {
// ファイル存在簡易チェック。win32api
if ( PathFileExists( "BushouData.txt" ) ) {
LUA::Do_ファイル("BushouData.txt");
}
} catch(...) {
デバッグ出力 << "LUAファイル実行エラー" << endl;
return; // このレベルでエラーはヤバイ。パラメタ読み取りはしない。
}
// luaの配列の添え字は「1」からスタートする。「i」を増やしながら無限ループ
for (int i=1; true; i++) {
// 1人分読み取って、画用紙へと受け取る。
try {
stringstream cmd;
cmd << "_is_end, _pname, _pgov, _pbat, _pint = GetNextDataList(" << i << ")";
LUA::Do_コマンド(cmd.str()); // _ret_en, _pname, ... というように、ScenarioMod側で好きな変数を指定して、画用紙へと書く。
} catch(...) {
break; // 関数実行のエラーがあれば、読み取り終了。forを抜ける
}
// もう「データ読み取りが既に終了」というシグナルが返ってきてるようなら、forループを抜ける
try {
// リストが終わりというシグナルが返ってきたなら、読み取り終了。forを抜ける
if ( LUA::Get_グローバル文字列("_is_end") == "終了" ) {
break; // 読み取り終了
}
} catch(...) {
// _is_endの処理でエラーが起きるようでは、無限ループに陥る可能性がある。
// パラメタ読み取りを即座に終了する。
return;
}
// 画用紙から読み取って、C++内の変数へと追加保存する。
try {
// 画用紙からの現在の値の読み取り。
myパラメタ型 data;
data.番号 = i;
data.名前 = LUA::Get_グローバル文字列("_pname");
data.政治 = (int)LUA::Get_グローバル数値("_pgov");
data.戦闘 = (int)LUA::Get_グローバル数値("_pbat");
data.智謀 = (int)LUA::Get_グローバル数値("_pint");
// ScenarioMod側で用意したパラメタリストへと追加する。
v_data_list.push_back(data);
} catch(...) {
// 例外が起きてもとりあえずスルーして次のデータを読み込む。
}
}
}
void カスタム::On_起動時() {
複雑なパラメータの取得();
for each(myパラメタ型 data in v_data_list) {
デバッグ出力 << data.番号 << endl;
デバッグ出力 << data.名前 << endl;
デバッグ出力 << data.政治 << endl;
デバッグ出力 << data.戦闘 << endl;
デバッグ出力 << data.智謀 << endl;
デバッグ出力 << string(20, '-') << endl;
}
}
|