diff --git a/BearURQ.dproj b/BearURQ.dproj
index 2a5f8d4..8337238 100644
--- a/BearURQ.dproj
+++ b/BearURQ.dproj
@@ -96,6 +96,9 @@
-d quests\test.qst
+ 1033
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)
+ (None)
@@ -132,6 +135,10 @@
BearURQ.dpr
+
+ Microsoft Office 2000 Sample Automation Server Wrapper Components
+ Microsoft Office XP Sample Automation Server Wrapper Components
+
False
diff --git a/quests/inc.qst b/quests/inc.qst
deleted file mode 100644
index 43b6396..0000000
--- a/quests/inc.qst
+++ /dev/null
@@ -1,4 +0,0 @@
-:loc3
- pln Test 3
- btn loc1, 1
-end
\ No newline at end of file
diff --git a/quests/inc1.qst b/quests/inc1.qst
new file mode 100644
index 0000000..0ff3115
--- /dev/null
+++ b/quests/inc1.qst
@@ -0,0 +1,8 @@
+;
+
+:loc3
+ pln Test 3
+ btn loc1, Назад
+end
+
+include inc2.qst
\ No newline at end of file
diff --git a/quests/test.qst b/quests/test.qst
index 2983d0b..1433f87 100644
--- a/quests/test.qst
+++ b/quests/test.qst
@@ -1,17 +1,25 @@
-
-
-:loc1
+;
+gametitle = "serg"
+;
+ :loc1
+ a =(2+2)*2+1
+ p 123
+ p 456
+ p 789
+ pln hhhh
pln Test 1
- btn loc2, 2
- btn loc3, 3
-end
+ pln Значение переменной А: #a$
+ btn loc2, Локация 2
+ btn loc3, Локация 3
+ btn loc4, Локация 4
+ end
-:loc2
+ :loc2
pln Test 2
- btn loc1,
-end
+ btn loc1, Назад
+ end
-include inc.qst
+include inc1.qst
diff --git a/sources/BearURQ.Engine.pas b/sources/BearURQ.Engine.pas
index a6ad8d2..ef86520 100644
--- a/sources/BearURQ.Engine.pas
+++ b/sources/BearURQ.Engine.pas
@@ -12,6 +12,10 @@ interface
type
TEngine = class(TObject)
+ private type
+ IfResult = record
+ If1, If2, If3, If4: string;
+ end;
private
FLocCount: Integer;
FTerminal: TTerminal;
@@ -19,7 +23,15 @@ TEngine = class(TObject)
FButtons: TButtons;
FVars: TVars;
FQuest: TQuest;
+ function LoadFromFile(const AFileName: string; DefCode: string)
+ : string; overload;
+ procedure ReplaceVars(var Code: string);
+ function GetCode(Code: string): string;
+ function GetLeksemsFromString(Text: String): TStringList;
+ function GetIf(S: string): IfResult;
+ procedure GetVars(A, B: string; Id: Integer = 0);
public
+ FIsClick: Boolean; // Щелчек, выбор локации
FIsGoTo: Boolean; // Для перехода по GoTo
FirstText: Boolean; // Новый текст
FLocBtnCnt: Byte; // Счетчик кнопок на локации
@@ -35,10 +47,8 @@ TEngine = class(TObject)
property Quest: TQuest read FQuest write FQuest;
procedure Clear;
procedure LoadFromFile(const AFileName: string); overload;
- function LoadFromFile(const AFileName: string; DefCode: string)
- : string; overload;
procedure GoToLocation(const ALocName: string);
- procedure Run(const ACode: string);
+ procedure RunCode(const ACode: string);
end;
implementation
@@ -46,7 +56,8 @@ implementation
uses
SysUtils,
Vcl.Dialogs,
- BearURQ.Utils;
+ BearURQ.Utils,
+ BearURQ.Math;
{ TEngine }
@@ -82,40 +93,239 @@ destructor TEngine.Destroy;
end;
// Переход на метку локации
+function TEngine.GetCode(Code: string): string;
+var
+ I, J, V1, U: Integer;
+ SS, LX, LT, LR, LL: String;
+ HF: TSplitResult;
+ LS: TStringList;
+ B: Boolean;
+begin
+ // Выполнить инструкции URQL и вернуть результат
+ B := False;
+ // Строковые переменные
+ if (Code[1] = '%') then
+ begin
+ // Это точно строка
+ Delete(Code, 1, 1);
+ // Конкатенация строк
+ // Загружаем список лексем
+ LS := GetLeksemsFromString(Code);
+ Code := '';
+ // Перебираем лексемы и склеиваем строки
+ SS := '';
+ for I := 0 to LS.Count - 1 do
+ if not Math.IsDelimiter(LS[I]) then
+ if Vars.IsVar(LS[I]) then
+ SS := SS + Vars.GetVarValue(LS[I], '')
+ else
+ SS := SS + LS[I];
+ if (SS = '0') then
+ SS := '';
+ ReplaceVars(SS);
+ Result := SS;
+ Exit;
+ end;
+
+ // Использовать текстовые переменные в кавычках без instr
+ if (Code[1] = '"') then
+ begin
+ SS := '';
+ HF := Explode('+', Code);
+ for I := 0 to High(HF) do
+ begin
+ LL := Trim(HF[I]);
+ Delete(LL, 1, 1);
+ J := Length(LL);
+ Delete(LL, J, J);
+ SS := SS + LL;
+ end;
+ ReplaceVars(SS);
+ Result := SS;
+ Exit;
+ end;
+
+ // Приводим код к удобному выражению
+ LS := TStringList.Create;
+ // Загружаем список лексем
+ LS := GetLeksemsFromString(Code);
+ Code := '';
+ for I := 0 to LS.Count - 1 do
+ // Если лексема не число ...
+ if not Math.IsNumber(LS[I])
+ // ... и не символ ...
+ and not Math.IsDelimiter(LS[I])
+ // ... и не функция ...
+ and not Math.IsFunction(LS[I]) then
+ begin
+ // Возможно это функция URQL RAND?
+ LS[I] := AdvLowerCase(LS[I]);
+ if (Copy(LS[I], 1, 3) = 'rnd') then
+ begin
+ LS[I] := Trim(Copy(LS[I], 4, Length(LS[I])));
+ U := StrToIntDef(LS[I], 0);
+ Randomize;
+ LS[I] := IntToStr(Random(U) + 1)
+ end
+ else // Это переменная
+ // Отмечаем, что это строковая переменная
+ if not Math.IsNumber(Vars.GetVarValue(LS[I], '')) then
+ B := True;
+ // Конкатенация строк
+ if not Vars.IsVar(LS[I]) then
+ if (Trim(LS[I]) <> '') then
+ Continue;
+ // Заменяем переменные их значениями
+ LS[I] := Vars.GetVarValue(LS[I], '');
+ end;
+
+ // Заполняем измененную строку для интерпретации выражения
+ for I := 0 to LS.Count - 1 do
+ Code := Code + LS[I];
+ LS.Free;
+ Result := Code;
+ // Результат для строк
+ if B then
+ begin
+ Result := StrReplace(Code, '+', '');
+ Result := StrReplace(Result, '"', '');
+ ReplaceVars(Result);
+ // Exit;
+ end;
+end;
+
+function TEngine.GetIf(S: string): IfResult;
+var
+ Z: array [0 .. 5] of string;
+ E: TSplitResult;
+ I: Byte;
+ K: String;
+ C: Integer;
+begin
+ Result.If1 := '';
+ Result.If2 := '';
+ Result.If3 := '';
+ Result.If4 := '';
+ if (Pos('not ', S) > 0) then
+ Result.If4 := 'NOT';
+ S := StrReplace(S, 'not ', '');
+ Z[0] := '<>';
+ Z[1] := '>=';
+ Z[2] := '<=';
+ Z[3] := '=';
+ Z[4] := '>';
+ Z[5] := '<';
+ // Условия
+ for I := 0 to High(Z) do
+ if (Pos(Z[I], S) > 0) then
+ begin
+ E := Explode(Z[I], S);
+ Result.If1 := Trim(E[0]);
+ Result.If2 := Z[I];
+ Result.If3 := Trim(E[1]);
+ Exit;
+ end;
+ // Условия для предметов
+ E := Explode(',', S);
+ K := Trim(E[0]);
+ if High(E) > 0 then
+ C := StrToIntDef(E[1], 1)
+ else
+ C := 1;
+ Result.If1 := K;
+ Result.If2 := '#';
+ Result.If3 := IntToStr(C);
+end;
+
+function TEngine.GetLeksemsFromString(Text: String): TStringList;
+var
+ I, P: Integer;
+ S: string;
+
+ procedure AddLexem(F: string);
+ begin
+ if (F <> '') then
+ begin
+ Result.Append(F);
+ S := '';
+ end;
+ end;
+
+begin
+ S := '';
+ P := 0;
+ Result := TStringList.Create;
+ for I := 1 to Length(Text) do
+ begin
+ if (Text[I] in [' ', '&', '=', '+', '-', '*', '/', '^', '(', ')', '<', '>',
+ '#', '%', '$', '{', '}', '"']) then
+ begin
+ AddLexem(S);
+ AddLexem(Text[I]);
+ Continue;
+ end;
+ S := S + Text[I];
+ end;
+ AddLexem(S);
+end;
+
+procedure TEngine.GetVars(A, B: string; Id: Integer);
+var
+ E: TSplitResult;
+ I, X: Integer;
+ H: string;
+begin
+ E := Explode(',', A);
+ for I := 0 to High(E) do
+ begin
+ H := Trim(E[I]);
+ Vars.SetVarValue(H, B);
+ end;
+end;
+
procedure TEngine.GoToLocation(const ALocName: string);
var
CurrLocName: string;
- I, A, C, CurLocCount: Integer;
- B: Boolean;
+ I, CurrLocIndex: Integer; // Нач. индекс тек. локации
+ CommLocIndex: Integer; // Нач. индекс локации COMMON
+ CurrLocCount: Integer; // Счетчик заходов на тек. локацию
SL: TStringList;
begin
CurrLocName := AdvLowerCase(Trim(ALocName));
if (CurrLocName = '') then
- A := 0
+ CurrLocIndex := 0
else
- A := FQuestList.IndexOf(':' + CurrLocName);
- if (A < 0) then
+ CurrLocIndex := FQuestList.IndexOf(':' + CurrLocName);
+ if (CurrLocIndex < 0) then
Exit;
// Счетчик заходов на локацию
- CurLocCount := Vars.GetVarValue('count_' + CurrLocName, 0);
- Vars.SetVarValue('count_' + CurrLocName, CurLocCount + 1);
+ CurrLocCount := Vars.GetVarValue('count_' + CurrLocName, 0);
+ Vars.SetVarValue('count_' + CurrLocName, CurrLocCount + 1);
//
SL := TStringList.Create;
try
// Грузим локацию COMMON
-
+ if FIsClick then
+ begin
+ FIsClick := False;
+ CommLocIndex := FQuestList.IndexOf(':common');
+ if (CommLocIndex >= 0) then
+ for I := CommLocIndex to FQuestList.Count - 1 do
+ begin
+ if CompText(FQuestList[I], 'end') then
+ Break;
+ SL.Append(FQuestList[I]);
+ end;
+ RunCode(SL.Text);
+ FIsGoTo := False;
+ end;
// Грузим текущую локацию
SL.Clear;
- for I := A to FQuestList.Count - 1 do
+ for I := CurrLocIndex to FQuestList.Count - 1 do
begin
- try
- // if ((FQuestList[I][1] = 'e') or (FQuestList[I][1] = 'E')) and
- // ((FQuestList[I][2] = 'n') or (FQuestList[I][2] = 'N')) and
- // ((FQuestList[I][3] = 'd') or (FQuestList[I][3] = 'D')) then
- // Break;
- SL.Append(FQuestList[I]);
- except
- end;
+ if CompText(FQuestList[I], 'end') then
+ Break;
+ SL.Append(FQuestList[I]);
end;
// Удаляем все метки внутри локации
for I := SL.Count - 1 downto 0 do
@@ -124,7 +334,7 @@ procedure TEngine.GoToLocation(const ALocName: string);
// Сохраняем имя текущей локации в переменной
Vars.SetVarValue('location', CurrLocName);
// Выполняем комманды
- Run(SL.Text);
+ RunCode(SL.Text);
FIsGoTo := False;
finally
SL.Free;
@@ -134,7 +344,7 @@ procedure TEngine.GoToLocation(const ALocName: string);
// Загрузить квест из файла
procedure TEngine.LoadFromFile(const AFileName: string);
var
- I, J, A, B, C: Integer;
+ I, J, B, C: Integer;
SL: array [1 .. 3] of TStringList;
F: string;
label BR;
@@ -142,10 +352,11 @@ procedure TEngine.LoadFromFile(const AFileName: string);
// Текущий квест
FQuestFileName := Trim(AFileName);
// Путь к папке квеста
- Vars.SetVarValue('quest_path', ExtractFilePath(FQuestFileName));
+ Vars.SetVarValue('quest_path', ExtractFilePath(ParamStr(0)) + FQuestFileName);
Vars.SetVarValue('previous_loc', '');
FLocCount := 0;
FIsGoTo := False;
+ FIsClick := False;
FQuestList.Clear;
FQuestList.Text := LoadFromFile(FQuestFileName, '');
// Вставки Include
@@ -155,17 +366,19 @@ procedure TEngine.LoadFromFile(const AFileName: string);
BR: // Начало проверки на наличие вставок Include
for I := 0 to FQuestList.Count - 1 do
begin
- if Copy(FQuestList[I], 1, 7) = 'include' then
+ if CompText(FQuestList[I], 'include') then
begin
for J := 1 to 3 do
SL[J].Clear;
-
for B := 0 to I - 1 do
SL[1].Append(FQuestList[B]);
F := Trim(Copy(FQuestList[I], 8, Length(FQuestList[I])));
- SL[2].Text := LoadFromFile(ExtractFilePath(FQuestFileName) + F, '');
+ SL[2].Text := LoadFromFile(ExtractFilePath(ParamStr(0)) +
+ ExtractFilePath(FQuestFileName) + F, '');
for C := I + 1 to FQuestList.Count - 1 do
SL[3].Append(FQuestList[C]);
+ // Добавляем код инклюда в код квеста и проверяем снова код
+ // на наличие инклюдов
FQuestList.Text := SL[1].Text + SL[2].Text + SL[3].Text;
GoTo BR;
Break;
@@ -198,7 +411,7 @@ function TEngine.LoadFromFile(const AFileName: string; DefCode: string): string;
try
if FileExists(AFileName) then
begin
- SL.LoadFromFile(AFileName);
+ SL.LoadFromFile(AFileName, TEncoding.UTF8);
// Многострочный комментарий /* */
T := SL.Text;
L := Length(T);
@@ -243,9 +456,328 @@ function TEngine.LoadFromFile(const AFileName: string; DefCode: string): string;
end;
// Разбор кода
-procedure TEngine.Run(const ACode: string);
+procedure TEngine.ReplaceVars(var Code: string);
+var
+ I, L, P1, P2: Integer;
+ S, F: string;
+ AddTextFlag: Boolean;
begin
- ShowMessage(ACode);
+ // Подстановки
+ // Пробел
+ Code := StrReplace(Code, '#$', ' ');
+ // Выполняем комманды в подстановках
+ AddTextFlag := False;
+ S := '';
+ F := Code;
+ L := Length(F);
+ Code := '';
+ if (L > 0) then
+ for I := 1 to L do
+ begin
+ if AddTextFlag then
+ begin
+ if F[I] = '$' then
+ begin
+ Code := Code + GetCode(S);
+ AddTextFlag := False;
+ S := '';
+ Continue;
+ end;
+ S := S + F[I];
+ end
+ else if (F[I] <> '#') or (F[I + 1] = '/') then
+ Code := Code + F[I]
+ else
+ AddTextFlag := True;
+ end;
+end;
+
+procedure TEngine.RunCode(const ACode: string);
+var
+ I, P, J, D, C, L, N, U, SR, AP: Integer;
+ A, G, S, CS, K, V, R, LX, LT, LR, E1, E2, F1, TU, SS, LL: string;
+ E, H, W, B, M, T, HF: TSplitResult;
+ DoOrCnt, DoCnt: Byte;
+ F: IfResult;
+ V1, V2, V3: Integer;
+ Z: TStringList;
+begin
+ if (ACode = '') then
+ Exit;
+ Z := TStringList.Create;
+ try
+ try
+ Z.Text := ACode;
+ for I := 0 to Z.Count - 1 do
+ begin
+ // Если это был GOTO, то пропускаются все комманды после него
+ if FIsGoTo then
+ Continue;
+ S := Trim(Z[I]);
+ if (Copy(S, 1, 3) <> 'if ') then
+ if (Pos('&', S) > 0) then
+ begin
+ H := Explode('&', S);
+ for U := 0 to High(H) do
+ if not FExitFlag then
+ RunCode(Trim(H[U]));
+ Continue;
+ end;
+ // Выход из вложенности операторами quit и end
+ if FExitFlag then
+ Exit;
+ {
+ if (Copy(S, 1, 3) = 'inv') then
+ begin
+ U := 1;
+ while (U < Length(V)) do
+ begin
+ if (S[U] = '+') or (S[U] = '-') then begin Inc(U, 2); Continue; end;
+ if (S[U] = ' ') then Delete(S, U, 1) else Inc(U);
+ end;
+ end;
+ }
+ P := Pos(' ', S);
+ if (P <= 0) then
+ P := Length(S);
+ K := AdvLowerCase(Trim(Copy(S, 1, P)));
+ V := Copy(S, P + 1, Length(S));
+ begin
+ { // TextAlign
+ case Vars.GIVar('textalign') of
+ 3:
+ TextAlign := 1;
+ else
+ TextAlign := 0;
+ end; }
+ // Sellect
+ if (K = 'quit') or (K = 'end') then
+ begin
+ FExitFlag := True;
+ Exit;
+ end
+ else if (K = 'perkill') then
+ Vars.Clear
+ else if (K = 'invkill') then
+ // Inv.Clear
+ else if (K = 'cls') then
+ begin
+ // Очистить экран
+ Location.Clear;
+ Buttons.Clear;
+ FirstText := True;
+ end
+ else
+ // PROC и GOTO не выполняют COMMON!
+ if (K = 'proc') then
+ begin
+ GoToLocation(Trim(V));
+ FIsGoTo := False;
+ end
+ else if (K = 'goto') then
+ begin
+ GoToLocation(Trim(V));
+ FIsGoTo := True;
+ end
+ else if (K = 'p') or (K = 'print') then
+ begin
+ ReplaceVars(V);
+ E := Explode('#/$', V);
+ if (High(E) >= 0) then
+ for U := 0 to High(E) do
+ Location.Append(E[U]);
+ end
+ else if (K = 'pln') or (K = 'println') then
+ begin
+ ReplaceVars(V);
+ E := Explode('#/$', V);
+ if (High(E) >= 0) then
+ for U := 0 to High(E) do
+ begin
+ Location.Append(E[U]);
+ Location.Append(#13#10);
+ end;
+ end
+ else
+ // Кнопки
+ if (K = 'btn') then
+ begin
+ ReplaceVars(V);
+ E := Explode(',', V);
+ R := E[1];
+ if (High(E) > 1) then
+ for U := 2 to High(E) do
+ R := R + ',' + E[U];
+ // Добавляем кнопку в список
+ Buttons.Append(Trim(E[0]), Trim(R));
+ end
+ else
+ // Записываем текст в переменные
+ if (K = 'instr') then
+ begin
+ ReplaceVars(V);
+ E := Explode('=', V);
+ GetVars(E[0], E[1]);
+ end
+ else
+ // Конструкция IF
+ if (K = 'if') then
+ begin
+ // if Pos(' then ', V) <= 0 then
+ // ShowMessage('После IF oтсутствует оператор THEN!');
+ A := Trim(GetINIKey(V, 'then'));
+ G := Trim(GetINIValue(V, 'then'));
+ E1 := Trim(GetINIKey(G, 'else'));
+ E2 := Trim(GetINIValue(G, 'else'));
+ DoOrCnt := 0;
+ V := Trim(A);
+ T := Explode(' or ', V);
+ for N := 0 to High(T) do
+ begin
+ DoCnt := 0;
+ B := Explode(' and ', T[N]);
+ for J := 0 to High(B) do
+ begin
+ F := GetIf(Trim(B[J]));
+ // Разбор условий
+ if Vars.IsVar(F.If3) then
+ F.If3 := Vars.GetVarValue(F.If3, '');
+ if (F.If4 = '') then
+ begin
+ if (F.If2 = '<>') then
+ if (Vars.GetVarValue(F.If1, 0) <>
+ StrToIntDef(F.If3, 0)) then
+ Inc(DoCnt);
+ if (F.If2 = '>=') then
+ if (Vars.GetVarValue(F.If1, 0) >=
+ StrToIntDef(F.If3, 0)) then
+ Inc(DoCnt);
+ if (F.If2 = '<=') then
+ if (Vars.GetVarValue(F.If1, 0) <=
+ StrToIntDef(F.If3, 0)) then
+ Inc(DoCnt);
+ if (F.If2 = '=') then
+ if (Vars.GetVarValue(F.If1, 0)
+ = StrToIntDef(F.If3, 0)) then
+ Inc(DoCnt);
+ if (F.If2 = '>') then
+ if (Vars.GetVarValue(F.If1, 0) >
+ StrToIntDef(F.If3, 0)) then
+ Inc(DoCnt);
+ if (F.If2 = '<') then
+ if (Vars.GetVarValue(F.If1, 0) <
+ StrToIntDef(F.If3, 0)) then
+ Inc(DoCnt);
+ end
+ else
+ begin
+ // NOT!
+ if (F.If2 = '<>') then
+ if not(Vars.GetVarValue(F.If1, 0) <>
+ StrToIntDef(F.If3, 0)) then
+ Inc(DoCnt);
+ if (F.If2 = '>=') then
+ if not(Vars.GetVarValue(F.If1, 0) >=
+ StrToIntDef(F.If3, 0)) then
+ Inc(DoCnt);
+ if (F.If2 = '<=') then
+ if not(Vars.GetVarValue(F.If1, 0) <=
+ StrToIntDef(F.If3, 0)) then
+ Inc(DoCnt);
+ if (F.If2 = '=') then
+ if not(Vars.GetVarValue(F.If1, 0)
+ = StrToIntDef(F.If3, 0)) then
+ Inc(DoCnt);
+ if (F.If2 = '>') then
+ if not(Vars.GetVarValue(F.If1, 0) >
+ StrToIntDef(F.If3, 0)) then
+ Inc(DoCnt);
+ if (F.If2 = '<') then
+ if not(Vars.GetVarValue(F.If1, 0) <
+ StrToIntDef(F.If3, 0)) then
+ Inc(DoCnt);
+ end;
+ // Предметы в условиях
+ if (F.If2 = '#') then
+ begin
+ // Снача приводим к обычному виду форму типа "30 семян"
+ F1 := F.If1;
+ if Math.IsNumber(F1[1]) then
+ begin
+ SR := Pos(' ', F1);
+ F.If3 := Trim(Copy(F1, 1, SR));
+ F.If1 := Trim(Copy(F1, SR + 1, Length(F1)));
+ end;
+ //
+ { if ((F.If4 = '') and
+ (Inv.IsItem(F.If1, StrToInt(F.If3)))) or
+ ((F.If4 = 'NOT') and
+ (not Inv.IsItem(F.If1, StrToInt(F.If3)))) then
+ Inc(DoCnt); }
+ end;
+ end;
+ // DO IF .. THEN .. ELSE ..
+ if (DoCnt - 1 = High(B)) then
+ begin
+ if (E1 <> '') then
+ RunCode(E1);
+ end
+ else
+ begin
+ if (E2 <> '') then
+ RunCode(E2);
+ end;
+ end;
+ end
+ else
+ // Inventory
+ if ((K = 'inv+') or (K = 'inv-')) then
+ begin
+ ReplaceVars(V);
+ if Pos(',', V) <= 0 then
+ begin
+ R := V;
+ C := 1;
+ end
+ else
+ begin
+ R := Trim(GetINIValue(V, ',', ''));
+ C := StrToIntDef(GetINIKey(V, ','), 1);
+ end;
+ if (C < 1) then
+ C := 1;
+ if (K = 'inv+') and (R <> '') then
+ // Inv.Add(R, C)
+ else if (K = 'inv-') and (R <> '') then
+ // Inv.Del(R, C);
+ end
+ else
+ // Записываем данные в переменные
+ //if (Pos('=', S) > 0) then
+ begin
+ //E := Explode('=', S);
+ //R := Trim(E[1]);
+ //ShowMessage(E[0]);
+ //GetVars(Trim(E[0]), GetCode(R));
+ { // Считываем значения переменных инвентаря и перезаписываем их новое значение
+ for U := 0 to Vars.Count - 1 do
+ if (Copy(Trim(Vars.FID[U]), 1, 4) = 'inv_') then
+ begin
+ R := Trim(Copy(Trim(Vars.FID[U]), 5,
+ Length(Vars.FID[U])));
+ Inv.Let(R, StrToIntDef(Vars.FValue[U], 0));
+ end; }
+ end;
+ end; // IF
+ end;
+ finally
+ Z.Free;
+ end;
+ // Сохраняем в переменную количество слотов в инвентаре
+ // Vars.SetVarValue('urq_inv', Inv.Count);
+ // Vars.SaveToFile('vars.txt'); // Тест
+ except
+ end;
end;
end.
diff --git a/sources/BearURQ.Location.pas b/sources/BearURQ.Location.pas
index f2b4726..95e16bd 100644
--- a/sources/BearURQ.Location.pas
+++ b/sources/BearURQ.Location.pas
@@ -5,12 +5,10 @@ interface
type
TLocation = class(TObject)
private
- FTitle: string;
FContent: string;
public
constructor Create;
destructor Destroy; override;
- property Title: string read FTitle write FTitle;
property Content: string read FContent write FContent;
procedure Append(const S: string);
procedure Clear;
@@ -27,7 +25,6 @@ procedure TLocation.Append(const S: string);
procedure TLocation.Clear;
begin
- FTitle := '';
FContent := '';
end;
diff --git a/sources/BearURQ.Math.pas b/sources/BearURQ.Math.pas
index 75beee5..908175d 100644
--- a/sources/BearURQ.Math.pas
+++ b/sources/BearURQ.Math.pas
@@ -6,6 +6,7 @@ interface
Math = class
class function IsDelimiter(const S: string): Boolean;
class function IsNumber(const S: string): Boolean;
+ class function IsFunction(const S: string): Boolean;
end;
implementation
@@ -23,6 +24,11 @@ class function Math.IsDelimiter(const S: string): Boolean;
end;
// Строка число или нет?
+class function Math.IsFunction(const S: string): Boolean;
+begin
+ Result := False;
+end;
+
class function Math.IsNumber(const S: string): Boolean;
var
I: Integer;
diff --git a/sources/BearURQ.Player.pas b/sources/BearURQ.Player.pas
index 0ad6809..fe85df9 100644
--- a/sources/BearURQ.Player.pas
+++ b/sources/BearURQ.Player.pas
@@ -36,6 +36,7 @@ implementation
uses
Math,
SysUtils,
+ Vcl.Dialogs,
BearLibTerminal;
var
@@ -58,7 +59,6 @@ constructor TPlayer.Create;
begin
N := 2;
FIsDebug := True;
- // Box('-d');
end;
if ParamCount > 0 then
begin
diff --git a/sources/BearURQ.Scenes.pas b/sources/BearURQ.Scenes.pas
index 3c584f2..7040dc9 100644
--- a/sources/BearURQ.Scenes.pas
+++ b/sources/BearURQ.Scenes.pas
@@ -197,23 +197,15 @@ procedure TSceneGame.Jump(const Index: Integer);
Engine.Vars.SetVarValue('previous_loc',
Engine.Vars.GetVarValue('current_loc', ''));
Engine.Vars.SetVarValue('current_loc', CurrLoc);
- Engine.Location.Title := CurrButText;
Self.Render;
end;
procedure TSceneGame.Render;
var
- I, T: Integer;
+ I: Integer;
begin
- T := 0;
- // Текст последней нажатой кнопки
- if (Engine.Location.Title <> '') then
- begin
- T := 2;
- Print(0, Engine.Location.Title);
- end;
// Показываем содержимое окна локации
- Print(0, T, Engine.Location.Content);
+ Print(0, 0, Engine.Location.Content);
// Показываем инвентарь
// Показываем все кнопки на локации
diff --git a/sources/BearURQ.Utils.pas b/sources/BearURQ.Utils.pas
index 741c63c..de08c3c 100644
--- a/sources/BearURQ.Utils.pas
+++ b/sources/BearURQ.Utils.pas
@@ -5,47 +5,51 @@ interface
type
TSplitResult = array of string;
-function AdvLowerCase(const s: string): string;
-function StrReplace(const s, Srch, Replace: string): string;
+function AdvLowerCase(const S: string): string;
+function StrReplace(const S, Srch, Replace: string): string;
function Explode(const cSeparator, vString: string): TSplitResult;
function Implode(const cSeparator: string; const cArray: TSplitResult): string;
-function StrLeft(s: string; I: Integer): string;
-function StrRight(s: string; I: Integer): string;
-function GetINIKey(s, Key: string): string;
-function GetINIValue(s, Key: string; Default: string = ''): string;
+function StrLeft(S: string; I: Integer): string;
+function StrRight(S: string; I: Integer): string;
+function GetINIKey(S, Key: string): string;
+function GetINIValue(S, Key: string; Default: string = ''): string;
+function CompText(const AText, KeyWord: string): Boolean;
implementation
+uses
+ SysUtils;
+
// В нижний регистр
-function AdvLowerCase(const s: string): string;
+function AdvLowerCase(const S: string): string;
var
I: Integer;
begin
- result := s;
- for I := 1 to length(result) do
- if (result[I] in ['A' .. 'Z', 'А' .. 'Я']) then
- result[I] := chr(ord(result[I]) + 32)
- else if (result[I] in ['І']) then
- result[I] := 'і';
+ Result := S;
+ for I := 1 to Length(Result) do
+ if (Result[I] in ['A' .. 'Z', 'А' .. 'Я']) then
+ Result[I] := chr(ord(Result[I]) + 32)
+ else if (Result[I] in ['І']) then
+ Result[I] := 'і';
end;
// Замена в строке
-function StrReplace(const s, Srch, Replace: string): string;
+function StrReplace(const S, Srch, Replace: string): string;
var
I: Integer;
Source: string;
begin
- Source := s;
- result := '';
+ Source := S;
+ Result := '';
repeat
I := Pos(AdvLowerCase(Srch), AdvLowerCase(Source));
if I > 0 then
begin
- result := result + Copy(Source, 1, I - 1) + Replace;
- Source := Copy(Source, I + length(Srch), MaxInt);
+ Result := Result + Copy(Source, 1, I - 1) + Replace;
+ Source := Copy(Source, I + Length(Srch), MaxInt);
end
else
- result := result + Source;
+ Result := Result + Source;
until I <= 0;
end;
@@ -53,20 +57,20 @@ function StrReplace(const s, Srch, Replace: string): string;
function Explode(const cSeparator, vString: string): TSplitResult;
var
I: Integer;
- s: String;
+ S: String;
begin
- s := vString;
- SetLength(result, 0);
+ S := vString;
+ SetLength(Result, 0);
I := 0;
- while Pos(cSeparator, s) > 0 do
+ while Pos(cSeparator, S) > 0 do
begin
- SetLength(result, length(result) + 1);
- result[I] := Copy(s, 1, Pos(cSeparator, s) - 1);
+ SetLength(Result, Length(Result) + 1);
+ Result[I] := Copy(S, 1, Pos(cSeparator, S) - 1);
Inc(I);
- s := Copy(s, Pos(cSeparator, s) + length(cSeparator), length(s));
+ S := Copy(S, Pos(cSeparator, S) + Length(cSeparator), Length(S));
end;
- SetLength(result, length(result) + 1);
- result[I] := Copy(s, 1, length(s));
+ SetLength(Result, Length(Result) + 1);
+ Result[I] := Copy(S, 1, Length(S));
end;
// Соединить массив TSplitResult в одну строку, аналог Join
@@ -74,57 +78,65 @@ function Implode(const cSeparator: string; const cArray: TSplitResult): string;
var
I: Integer;
begin
- result := '';
- for I := 0 to length(cArray) - 1 do
+ Result := '';
+ for I := 0 to Length(cArray) - 1 do
begin
- result := result + cSeparator + cArray[I];
+ Result := Result + cSeparator + cArray[I];
end;
- System.Delete(result, 1, length(cSeparator));
+ System.Delete(Result, 1, Length(cSeparator));
end;
// Копия строки слева
-function StrLeft(s: string; I: Integer): string;
+function StrLeft(S: string; I: Integer): string;
begin
- result := Copy(s, 1, I);
+ Result := Copy(S, 1, I);
end;
// Копия строки справа
-function StrRight(s: string; I: Integer): string;
+function StrRight(S: string; I: Integer): string;
var
L: Integer;
begin
- L := length(s);
- result := Copy(s, L - I + 1, L);
+ L := Length(S);
+ Result := Copy(S, L - I + 1, L);
end;
// Ключ
-function GetINIKey(s, Key: string): string;
+function GetINIKey(S, Key: string): string;
var
P: Integer;
begin
- P := Pos(Key, s);
+ P := Pos(Key, S);
if (P <= 0) then
begin
- result := s;
+ Result := S;
Exit;
end;
- result := StrLeft(s, P - 1);
+ Result := StrLeft(S, P - 1);
end;
// Значение ключа
-function GetINIValue(s, Key: string; Default: string = ''): string;
+function GetINIValue(S, Key: string; Default: string = ''): string;
var
L, P, K: Integer;
begin
- P := Pos(Key, s);
+ P := Pos(Key, S);
if (P <= 0) then
begin
- result := Default;
+ Result := Default;
Exit;
end;
- L := length(s);
- K := length(Key);
- result := StrRight(s, L - P - K + 1);
+ L := Length(S);
+ K := Length(Key);
+ Result := StrRight(S, L - P - K + 1);
+end;
+
+function CompText(const AText, KeyWord: string): Boolean;
+var
+ S: string;
+begin
+ S := Copy(AText, 1, Length(KeyWord));
+ Result := CompareText(S, KeyWord) = 0;
end;
end.