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; }
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; }