festring material::GetName(truth Articled, truth Adjective) const { static festring Name; Name.Empty(); AddName(Name, Articled, Adjective); return Name; }
festring::sizetype festring::IgnoreCaseFind(const festring& Where, const festring& What, sizetype Begin) { if(What.IsEmpty()) return Begin; for(; Where.GetSize() >= What.GetSize() + Begin; ++Begin) if(::Capitalize(Where[Begin]) == ::Capitalize(What[0])) { truth Equal = true; for(sizetype c = 1; c < What.GetSize(); ++c) if(::Capitalize(Where[Begin + c]) != ::Capitalize(What[c])) { Equal = false; break; } if(Equal) return Begin; } return NPos; }
festring id::GetName(int Case, int Amount) const { static festring Name; Name.Empty(); AddName(Name, Case, Amount); return Name; }
inputfile::inputfile(const festring& FileName, const valuemap* ValueMap, truth AbortOnErr) : Buffer(fopen(FileName.CStr(), "rb")), FileName(FileName), ValueMap(ValueMap) { if(AbortOnErr && !IsOpen()) ABORT("File %s not found!", FileName.CStr()); }
void festring::SearchAndReplace(festring& Where, const festring& What, const festring& With, sizetype Begin) { for(sizetype Pos = Where.Find(What, Begin); Pos != NPos; Pos = Where.Find(What, Pos)) { Where.Erase(Pos, What.GetSize()); Where.Insert(Pos, With); } }
void festring::SearchAndReplace(festring& Where, cfestring& What, cfestring& With, sizetype Begin) { if(What.IsEmpty()) ABORT("Infinite loops in SearchAndReplace detected!"); for(sizetype Pos = Where.Find(What, Begin); Pos != NPos; Pos = Where.Find(What, Pos)) { Where.Erase(Pos, What.GetSize()); Where.Insert(Pos, With); Pos += With.GetSize(); } }
void festring::ExtractWord(festring& To) { for(sizetype c = 0; c < Size; ++c) if(Data[c] == ' ') { To.Empty(); To.Append(&Data[c + 1], Size - c - 1); Erase(c, Size - c); SwapData(To); return; } To = *this; Empty(); }
bool festring::IgnoreCaseCompare(const festring& First, const festring& Second) { for(sizetype Pos = 0; Pos < First.GetSize() && Pos < Second.GetSize(); ++Pos) { char Char1 = ::Capitalize(First[Pos]); char Char2 = ::Capitalize(Second[Pos]); if(Char1 != Char2) return Char1 < Char2; } return First.GetSize() < Second.GetSize(); }
void febot::Reply(festring& String) const { String.Empty(); if(GetControlWordChain()->Link.empty()) return; wordchain* WordChain = GetControlWordChain()->GetRandomLink(); String << WordChain->String.back(); for(WordChain = WordChain->GetRandomLink(); !WordChain->String.back().IsEmpty(); WordChain = WordChain->GetRandomLink()) String << ' ' << WordChain->String.back(); String.PostProcessForFebot(); }
void febot::BeTalkedTo(festring String) { String.PreProcessForFebot(); if(!String.IsEmpty()) { festring Word; wordchain* OldChain = GetControlWordChain(); for(String.ExtractWord(Word); !Word.IsEmpty(); String.ExtractWord(Word)) { wordchain* NewChain = CreateWordChain(OldChain, Word); OldChain->Link.push_back(NewChain); OldChain = NewChain; } OldChain->Link.push_back(GetControlWordChain()); } }
void inputfile::ReadWord(festring& String, truth AbortOnEOF) { int Mode = 0; String.Empty(); for(int Char = fgetc(Buffer); !feof(Buffer); Char = fgetc(Buffer)) { if(isalpha(Char) || Char == '_') { if(!Mode) Mode = MODE_WORD; else if(Mode == MODE_NUMBER) { ungetc(Char, Buffer); return; } String << char(Char); continue; } if(isdigit(Char)) { if(!Mode) Mode = MODE_NUMBER; else if(Mode == MODE_WORD) { ungetc(Char, Buffer); return; } String << char(Char); continue; } if((Char == ' ' || Char == '\n') && Mode) return; if(ispunct(Char) && HandlePunct(String, Char, Mode) == PUNCT_RETURN) return; } if(AbortOnEOF) ABORT("Unexpected end of file %s!", FileName.CStr()); if(Mode) clearerr(Buffer); }
void logentry::WriteLog(const festring& FileName) { FILE* LogFile = fopen(FileName.CStr(), "a"); if(!LogFile) return; festring Sep = CONST_S(":"); festring Subst = CONST_S("_"); festring::SearchAndReplace(Name, Sep, Subst); festring::SearchAndReplace(Ktyp, Sep, Subst); festring::SearchAndReplace(Kaux, Sep, Subst); festring::SearchAndReplace(Killer, Sep, Subst); festring::SearchAndReplace(Msg, Sep, Subst); festring::SearchAndReplace(Place, Sep, Subst); // XXX duplicating game::GetTime() int Hour = 12 + Tick / 2000; int Day = Hour/24 + 1; Hour %= 24; int Min = Tick % 2000 * 60 / 2000; fprintf(LogFile, "name=%s:start=%ld:end=%ld:hp=%d:mhp=%d:ktyp=%s:kaux=%s" ":killer=%s:msg=%s:place=%s:sc=%d" ":turn=%d:dur=%ld:time=Day %d, %d_%02d\n", Name.CStr(), (long)Start, (long)End, Hp, Mhp, Ktyp.CStr(), Kaux.CStr(), Killer.CStr(), Msg.CStr(), Place.CStr(), Score, Turn, (long)Dur, Day, Hour, Min ); if(fclose(LogFile)) { // error: cannot write to log } }
void festring::SplitString(festring& Source, festring& Result, sizetype Length) { if(Source.GetSize() <= Length) { Result << Source; Source.Empty(); return; } sizetype Pos = Source.FindLast(' ', Length); if(Pos != NPos) { Result.Append(Source, Pos); Source.Erase(0, Pos + 1); } else { Result.Append(Source, Length); Source.Erase(0, Length); } }
int inputfile::HandlePunct(festring& String, int Char, int Mode) { if(Char == '/') { if(!feof(Buffer)) { Char = fgetc(Buffer); if(Char == '*') { long StartPos = TellPos(); int OldChar = 0, CommentLevel = 1; for(;;) { if(feof(Buffer)) ABORT("Unterminated comment in file %s, beginning at line %ld!", FileName.CStr(), TellLineOfPos(StartPos)); Char = fgetc(Buffer); if(OldChar != '*' || Char != '/') { if(OldChar != '/' || Char != '*') OldChar = Char; else { ++CommentLevel; OldChar = 0; } } else { if(!--CommentLevel) break; else OldChar = 0; } } return PUNCT_CONTINUE; } else { ungetc(Char, Buffer); clearerr(Buffer); } } if(Mode) ungetc('/', Buffer); else String << '/'; return PUNCT_RETURN; } if(Mode) { ungetc(Char, Buffer); return PUNCT_RETURN; } if(Char == '"') { long StartPos = TellPos(); int OldChar = 0; for(;;) { if(feof(Buffer)) ABORT("Unterminated string in file %s, beginning at line %ld!", FileName.CStr(), TellLineOfPos(StartPos)); Char = fgetc(Buffer); if(Char != '"') { String << char(Char); OldChar = Char; } else if(OldChar == '\\') { String[String.GetSize() - 1] = '"'; OldChar = 0; } else return PUNCT_RETURN; } } String << char(Char); return PUNCT_RETURN; }
long inputfile::ReadNumber(int CallLevel, truth PreserveTerminator) { long Value = 0; static festring Word; truth NumberCorrect = false; for(;;) { ReadWord(Word); char First = Word[0]; if(isdigit(First)) { Value = atoi(Word.CStr()); NumberCorrect = true; continue; } if(Word.GetSize() == 1) { if(First == ';' || First == ',' || First == ':') { if(CallLevel != HIGHEST || PreserveTerminator) ungetc(First, Buffer); return Value; } if(First == ')') { if((CallLevel != HIGHEST && CallLevel != 4) || PreserveTerminator) ungetc(')', Buffer); return Value; } if(First == '~') { Value = ~ReadNumber(4); NumberCorrect = true; continue; } /* Convert this into an inline function! */ #define CHECK_OP(op, cl)\ if(First == #op[0])\ if(cl < CallLevel)\ {\ Value op##= ReadNumber(cl);\ NumberCorrect = true;\ continue;\ }\ else\ {\ ungetc(#op[0], Buffer);\ return Value;\ } CHECK_OP(&, 1); CHECK_OP(|, 1); CHECK_OP(^, 1); CHECK_OP(*, 2); CHECK_OP(/, 2); CHECK_OP(%, 2); CHECK_OP(+, 3); CHECK_OP(-, 3); if(First == '<') { char Next = Get(); if(Next == '<') if(1 < CallLevel) { Value <<= ReadNumber(1); NumberCorrect = true; continue; } else { ungetc('<', Buffer); ungetc('<', Buffer); return Value; } else ungetc(Next, Buffer); } if(First == '>') { char Next = Get(); if(Next == '>') if(1 < CallLevel) { Value >>= ReadNumber(1); NumberCorrect = true; continue; } else { ungetc('>', Buffer); ungetc('>', Buffer); return Value; } else
outputfile::outputfile(const festring& FileName, truth AbortOnErr) : Buffer(fopen(FileName.CStr(), "wb")), FileName(FileName) { if(AbortOnErr && !IsOpen()) ABORT("Can't open %s for output!", FileName.CStr()); }