bool	Satori::load(const string& iBaseFolder)
{
	GetSender().next_event();

	setlocale(LC_ALL, "Japanese");
#ifdef _WINDOWS
	_setmbcp(_MB_CP_LOCALE);
#endif

	mBaseFolder = iBaseFolder;
	GetSender().sender() << "■SATORI::Load on " << mBaseFolder << "" << std::endl;

#if POSIX
	// 「/」で終わっていなければ付ける。
	if (mBaseFolder[mBaseFolder.size() - 1] != '/') {
	    mBaseFolder += '/';
	}
#else
	// 「\」で終わっていなければ付ける。
	if (mBaseFolder[mBaseFolder.size() - 1] != '\\') {
	    mBaseFolder += '\\';
	}
#endif


#ifdef	_MSC_VER
	// 本体のあるフォルダをサーチ
	{
		TCHAR	buf[MAX_PATH+1];
		::GetModuleFileName(NULL, buf, MAX_PATH);
		char*	p = FindFinalChar(buf, DIR_CHAR);
		if ( p==NULL )
			mExeFolder = "";
		else {
			*(++p) = '\0';
			mExeFolder = buf;
		}
	}
	GetSender().sender() << "本体の所在: " << mExeFolder << "" << std::endl;
#endif // _MSC_VER

	// メンバ初期化
	InitMembers();

#ifdef	_MSC_VER
	// システムの設定を読んでおく
    OSVERSIONINFO	ovi;
    ovi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
	::GetVersionEx(&ovi);
	string	os;
	if ( ovi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ) {
		if ( ovi.dwMinorVersion == 0 ) { mOSType=SATORI_OS_WIN95; os="Windows 95"; }
		else if ( ovi.dwMinorVersion == 10 ) { mOSType=SATORI_OS_WIN98; os="Windows 98"; }
		else if ( ovi.dwMinorVersion == 90 ) { mOSType=SATORI_OS_WINME; os="Windows Me"; }
		else { mOSType = SATORI_OS_UNDEFINED; os="undefined"; }
	} else {
		if ( ovi.dwMinorVersion == 0 ) {
			if ( ovi.dwMajorVersion == 4 ) { mOSType=SATORI_OS_WINNT; os="Windows NT"; }
			else if ( ovi.dwMajorVersion == 5 ) { mOSType=SATORI_OS_WIN2K; os="Windows 2000"; }
		}
		else { mOSType = SATORI_OS_WINXP; os="Windows XP or later"; }
	}
	GetSender().sender() << "OS種別: " << os << std::endl;
	if ( mOSType==SATORI_OS_WIN95 ) {
		is_single_monitor = true;
	} else {
		BOOL (WINAPI* pEnumDisplayMonitors)(HDC,LPRECT,MONITORENUMPROC,LPARAM);
		(FARPROC&)pEnumDisplayMonitors = ::GetProcAddress(::GetModuleHandle("user32.dll"), "EnumDisplayMonitors");
		if ( pEnumDisplayMonitors==NULL ) {
			is_single_monitor = true;
		}
		else {
			RECT rectData[2];
			memset(rectData,0,sizeof(rectData));
			(*pEnumDisplayMonitors)(NULL,NULL,(MONITORENUMPROC)MonitorEnumFunc,(LPARAM)(rectData));

			max_screen_rect = rectData[0];
			desktop_rect = rectData[1];

			RECT*	rect;
			rect = &desktop_rect;
			GetSender().sender() << "プライマリデスクトップ: (" << 
				rect->left << "," << rect->top << "," << rect->right << "," << rect->bottom << ")" << std::endl;
			rect = &max_screen_rect;
			GetSender().sender() << "仮想デスクトップ: (" << 
				rect->left << "," << rect->top << "," << rect->right << "," << rect->bottom << ")" << std::endl;
			is_single_monitor = ( ::EqualRect(&max_screen_rect, &desktop_rect)!=FALSE );
			GetSender().sender() << (is_single_monitor ? 
				"モニタは一つだけと判断、見切れ判定を呼び出し元に任せます。" : 
				"複数のモニタが接続されていると判断、見切れ判定は里々が行います。") << std::endl;
		}
	}
#endif // _MSC_VER

	// 置換辞書読み取り
	strmap_from_file(replace_before_dic, mBaseFolder+"replace.txt", "\t");
	strmap_from_file(replace_after_dic, mBaseFolder+"replace_after.txt", "\t");

	// キャラデータ読み込み
	mCharacters.load(mBaseFolder + "characters.ini");
	for ( inimap::const_iterator i=mCharacters.begin() ; i!=mCharacters.end() ; ++i ) {
		const strmap& m = i->second;
		strmap::const_iterator j;

		// 置換辞書に追加
		j = m.find("popular-name");
		if ( j != m.end() && j->second.size()>0 ) 
			replace_before_dic[j->second + ":"] = string("\xff\x01") + zen2han(i->first); //0xff0x01はあとで変換
		j = m.find("initial-letter");
		if ( j != m.end() && j->second.size()>0 ) 
			replace_before_dic[j->second + ":"] = string("\xff\x01") + zen2han(i->first); //0xff0x01はあとで変換

		j = m.find("base-surface");
		if ( j != m.end() && j->second.size()>0 )
			system_variable_operation( string("サーフェス加算値") + i->first, j->second);
	}

	//for ( strmap::const_iterator j=replace_before_dic.begin() ; j!=replace_before_dic.end() ; ++j )
	//	cout << j->first << ": " << j->second << endl;

	// ランダマイズ
	randomize();


	//------------------------------------------

	// コンフィグ読み込み
	LoadDictionary(mBaseFolder + "satori_conf.txt", false);

	// 変数初期化実行
	GetSentence("初期化");	

	// SAORI読み込み
	Family<Word>* f = words.get_family("SAORI");

	mShioriPlugins->load(mBaseFolder);
	
	if ( f != NULL )
	{
		std::vector<const Word*> els;
		f->get_elements_pointers(els);

		for (std::vector<const Word*>::const_iterator i=els.begin(); i!=els.end() ; ++i)
		{
			if ( (*i)->size()>0 && !mShioriPlugins->load_a_plugin(**i) )
			{
				GetSender().sender() << "SAORI読み込み中にエラーが発生: " << **i << std::endl;
			}
		}

	}
	mShioriPlugins->load_default_entry();

	talks.clear();
	words.clear();

	//------------------------------------------

	// セーブデータ読み込み
	//bool oldConf = fEncodeSavedata;

	bool loadResult = LoadDictionary(mBaseFolder + "satori_savedata." + (fEncodeSavedata?"sat":"txt"), false);
	GetSentence("セーブデータ");
	bool execResult = talks.get_family("セーブデータ") != NULL;

	if ( ! loadResult || ! execResult ) {
		loadResult = LoadDictionary(mBaseFolder + "satori_savebackup." + (fEncodeSavedata?"sat":"txt"), false);
		GetSentence("セーブデータ");
		execResult = talks.get_family("セーブデータ") != NULL;
	}

	talks.clear();
	
	reload_flag = false;

	if ( variables.find("ゴースト起動時間累計秒") != variables.end() ) {
		sec_count_total = zen2ul(variables["ゴースト起動時間累計秒"]);
	}
	else if ( variables.find("ゴースト起動時間累計ミリ秒") != variables.end() ) {
		sec_count_total = zen2ul(variables["ゴースト起動時間累計ミリ秒"]) / 1000;
	}
	else {
		sec_count_total = zen2ul(variables["ゴースト起動時間累計(ms)"]) / 1000;
	}
	variables["起動回数"] = itos( zen2int(variables["起動回数"])+1 );

	// 「単語の追加」で登録された単語を覚えておく
	const std::map< string, Family<Word> >& m = words.compatible();
	for (std::map< string, Family<Word> >::const_iterator it = m.begin() ; it != m.end() ; ++it )
	{
		std::vector<const Word*> v;
		it->second.get_elements_pointers(v);
		for (std::vector<const Word*>::const_iterator itx = v.begin() ; itx < v.end() ; ++itx ) {
			mAppendedWords[it->first].push_back(**itx);
		}
	}

	//------------------------------------------

	// 指定フォルダの辞書を読み込み
	int loadcount = 0;
	strvec::iterator i = dic_folder.begin();
	if ( i==dic_folder.end() ) {
		loadcount += LoadDicFolder(mBaseFolder);	// ルートフォルダの辞書
	} else {
		for ( ; i!=dic_folder.end() ; ++i )
			loadcount += LoadDicFolder(mBaseFolder + *i + DIR_CHAR);	// サブフォルダの辞書
	}

	is_dic_loaded = loadcount != 0;

	//------------------------------------------

	secure_flag = true;

	system_variable_operation("単語群「*」の重複回避", "有効、トーク中");
	system_variable_operation("文「*」の重複回避", "有効");
	//system_variable_operation("単語群「季節の食べ物」の重複回避", "有効、トーク中");

	GetSentence("OnSatoriLoad");
	on_loaded_script = GetSentence("OnSatoriBoot");
	diet_script(on_loaded_script);

	GetSender().sender() << "loaded." << std::endl;

	GetSender().flush();
	return	true;
}
Beispiel #2
0
bool	Satori::Translate(string& ioScript) {

	if ( ioScript.empty() )
		return	false;

	const bool is_OnTranslate = (mRequestID=="OnTranslate");

	// さくらスクリプトとそれ以外を分割して処理を加える
	vector<string>	vec;
	string	acum;
	bool	content=false;	// 文に中身があるのか
	bool	is_first_question = true; // 選択分岐記録の消去処理用。
	int	last_speaker=0;
	const char* p = ioScript.c_str();
	while (*p) {
		string	c=get_a_chr(p);	// 全角半角問わず一文字取得し、pを一文字すすめる
		
		if ( c=="\\" || c=="%" ) {
			if (*p=='\\'||*p=='%') {	// エスケープされた\, %
				acum += c + *p++;
				continue;
			}
			
			const char*	start=p;
			string	cmd="",opt="";
	
			while (!_ismbblead(*p) && (isalpha(*p)||isdigit(*p)||*p=='!'||*p=='*'||*p=='&'||*p=='?'||*p=='_'))
				++p;
			cmd.assign(start, p-start);
	
			if (*p=='[') {
				const char* opt_start = ++p;
				while (*p!=']') {
					if (p[0]=='\\' && p[1]==']')	// エスケープされた]
						++p;
					p += _ismbblead(*p) ? 2 : 1;
				}
				opt.assign(opt_start, p++ -opt_start);
			}
			
			// 選択分岐ラベルに対する特殊処理
			if ( !is_OnTranslate && 
				cmd=="q" && opt!="" && count(opt, ",")>0 && 
				mRequestID!="OnHeadlinesense.OnFind") {

				// 選択分岐があるスクリプトであれば、その初回で選択分岐記録をクリア
				if ( is_first_question ) {
					question_record.clear();	
					is_first_question = false;
				}

				// 選択分岐を記録
				{
					strvec	vec;
					split(opt, ",", vec);
					if ( vec.size()==1 )	// countとsplitの罠。
						vec.push_back("");	// 
					string	label=vec[0], id=vec[1];

					if ( false == compare_head(id, "On") )
					{ 
						// Onで始まるものはOnChoiceSelectを経由されないため、対象外とする

						int	count = question_record.size()+1;
						question_record[id] = pair<int,string>(count, label);

						// ラベルIDに書き戻し
						opt = label+","+id+byte1_dlmt+label+byte1_dlmt+itos(count);
						for (int i=2;i<vec.size();++i)
							opt += string(",") + vec[i];
					}
				}
			}
			else if ( cmd=="0" || cmd=="h" ) { last_speaker=0; }
			else if ( cmd=="1" || cmd=="u" ) { last_speaker=1; }
			else if ( cmd=="p" && aredigits(opt) ) {
				last_speaker=stoi(opt);
				if ( mIsMateria || last_speaker<=1 ) {
					cmd = (opt=="0") ? "0" : "1";
					opt = "";
				}
			}
			else if ( cmd=="s" && !opt.empty() ) {
				last_talk_exiting_surface[last_speaker]=stoi(opt);
			}
			else if ( cmd.size()==2 && cmd[0]=='s' && isdigit(cmd[1]) ) {
				last_talk_exiting_surface[last_speaker]=cmd[1]-'0';
			}
						
			if ( !acum.empty() )
				vec.push_back(acum);

			if ( opt=="" )
				vec.push_back(c + cmd);
			else
				vec.push_back(c + cmd + "[" + opt + "]");
			acum="";

			static	set<string>	nc_cmd;	// 有効と数えないさくらスクリプト群
			static	bool	initialized=false;
			if (!initialized) {
				initialized=true;
				nc_cmd.insert("0"); nc_cmd.insert("1"); nc_cmd.insert("h"); nc_cmd.insert("u"); nc_cmd.insert("p");
				nc_cmd.insert("n"); nc_cmd.insert("w"); nc_cmd.insert("_w"); nc_cmd.insert("e");
			}
			if ( nc_cmd.find(cmd)==nc_cmd.end() )
				content = true;

		}
		else {
			content = true;
			acum += c;
		}
	}
	if ( !acum.empty() )
		vec.push_back(acum);

	if (!content)
		return	false;	// 中身の無いスクリプト(実行してもしなくても一緒)と判断。

	ioScript="";

	for (vector<string>::iterator i=vec.begin() ; i!=vec.end() ; ++i) {
		if ( i->at(0)!='\\' && i->at(0)!='%' ) {
			// さくらスクリプト以外の文への処理

			// アンカー挿入
			if ( !is_OnTranslate )
				for ( set<string>::iterator j=anchors.begin() ; j!=anchors.end() ; ++j )
					replace(*i, *j, string("\\_a[")+*j+"]"+*j+"\\_a");
		}
		ioScript += *i;
	}


	// 事後置き換え辞書を適用
	if ( !is_OnTranslate )
		for ( strmap::iterator di=replace_after_dic.begin() ; di!=replace_after_dic.end() ; ++di )
			replace(ioScript, di->first, di->second);

	diet_script(ioScript);	// ラストダイエット

	// エスケープしてあった文字を戻す
	m_escaper.unescape(ioScript);

	return	true;
}