unit uWorld;

{$mode objfpc}{$H+}
{$codepage UTF8}

interface

uses
  crt, uVar, inifiles, SysUtils, DateUtils;

procedure loadNodesFromFile();
procedure loadAnswersFromFile();

procedure Draw_Dialog_Message();
procedure Draw_Dialog_Variant();

procedure Read_Dialog_Variants();
procedure Read_Dialog_Node();

procedure Process_World(key : string);

procedure Check_Keys(ID : word);

implementation

procedure loadNodesFromFile();
var s: string;
    i, j : integer;
begin
  for i := 1 to high(_nodes) do
    begin
      s := nodesFile.ReadString('NODE ' + IntToStr(i), 'TEXT', '*** ERROR #1');
      if s <> '*** ERROR #1' then
         begin
           _nodes[i].ID   := i;
           _nodes[i].TEXT := s;
           for j := 1 to 3 do
               begin
                 _nodes[i].nodeKeys[j]._keyName  := nodesFile.ReadString('NODE ' + IntToStr(i), 'IFKEY' + IntToStr(j), '**');
                 _nodes[i].nodeKeys[j]._keyValue := nodesFile.ReadString('NODE ' + IntToStr(i), 'KEYVALUE' + IntToStr(j), '***');
               end;
         end else
         _nodes[i].TEXT := ' **** NODE_READING_ERROR. NODE ID = ' + IntToStr(i);
    end;
end;

procedure loadAnswersFromFile();
var s: string;
    i, j : integer;
begin
  for i := 1 to high(_answers) do
    begin

      s := answersFile.ReadString('ANSWER ' + IntToStr(i), 'TEXT', '*** ERROR #1');

      if s <> '*** ERROR #1' then
         begin
           _answers[i].ID       := i;
           _answers[i].TEXT     := s;
           _answers[i].nodeID   := answersFile.ReadInteger('ANSWER ' + IntToStr(i), 'NODE_ID', 1000);
           _answers[i].goToNode := answersFile.ReadInteger('ANSWER ' + IntToStr(i), 'GOTO', 1000);
           for j := 1 to 3 do
               begin
                 _answers[i].nodeIfs[j]._keyName  := answersFile.ReadString('ANSWER ' + IntToStr(i), 'IFKEY' + IntToStr(j), '**');
                 _answers[i].nodeIfs[j]._keyValue := answersFile.ReadString('ANSWER ' + IntToStr(i), 'IFKEYVALUE' + IntToStr(j), '***');
               end;
           for j := 1 to 3 do
               begin
                 _answers[i].nodeSets[j]._keyName  := answersFile.ReadString('ANSWER ' + IntToStr(i), 'SETKEY' + IntToStr(j), '**');
                 _answers[i].nodeSets[j]._keyValue := answersFile.ReadString('ANSWER ' + IntToStr(i), 'SETKEYVALUE' + IntToStr(j), '***');
               end;
         end else
         _answers[i].TEXT := ' **** ANSWER_READING_ERROR. ANSWER ID = ' + IntToStr(i);
    end;
end;

procedure Read_Dialog_Node();
begin
  Node_Text := AnsiToUTF8(_nodes[nodeNumber].TEXT);
end;

procedure Clear_Dialog_Variants();
var i : integer;
begin
  for i := 1 to high(_variants) do
      _variants[i].ID := 0;
end;

procedure Read_Dialog_Variants();
var i, k, v : integer;
    flag : boolean;
begin
  clear_dialog_variants();
  k := 1;
  for i := 1 to high(_answers) do
      if _answers[i].nodeID = NodeNumber then
         begin
           flag := true;

           if _answers[i].nodeIfs[1]._keyName = 'INT' then
              if TryStrToInt(_answers[i].nodeIfs[1]._keyValue, v) then
                 if INT < V then flag := false;

           if _answers[i].nodeIfs[1]._keyName = 'DEX' then
              if TryStrToInt(_answers[i].nodeIfs[1]._keyValue, v) then
                 if DEX < V then flag := false;

           if _answers[i].nodeIfs[1]._keyName = 'STR' then
              if TryStrToInt(_answers[i].nodeIfs[1]._keyValue, v) then
                 if STR < V then flag := false;

           if _answers[i].nodeIfs[1]._keyName = 'CHR' then
              if TryStrToInt(_answers[i].nodeIfs[1]._keyValue, v) then
                 if CHR < V then flag := false;

           if flag then
              begin
                _variants[k].ID := k;
                _variants[k].ansID := i;
                inc(k);
              end;
           if k > high(_variants) then Break;
         end;
end;

procedure Draw_Dialog_Message();
begin
  Textcolor(yellow);
  Read_Dialog_Node();
  Writeln(Node_Text);
end;

procedure Draw_Dialog_Variant();
var i: integer;
begin
  textcolor(green);
  for i := 1 to high(_variants) do
      if _variants[i].ID <> 0 then
         Writeln(_variants[i].ID, ') ', AnsiToUTF8(_answers[_variants[i].ansID].Text));

end;

procedure Process_World(key : string);
var  i      : integer;
    _intKey : integer;
begin
  try
    _intKey := StrToInt(key);

    if (_intKey > 10) or
       (_variants[_intKey].ID = 0) then
          begin
            TextColor(red);
            Writeln('Неверный номер варианта ответа или команда');
            Exit;
          end;

    NodeNumber := _answers[_variants[_intKey].ansID].goToNode;  // Переходим по ноде

    if nodeNumber > high(_nodes) then
       begin
         TextColor(Red);
         Writeln('*** Ошибка сценария. GO TO NODE => ', nodeNumber);
         Writeln('*** Обратитесь к разработчику. Вы будете возвращены в начало сценария.');
         nodeNumber := 1;
       end;

    Check_Keys(_variants[_intKey].ansID);

  except
    if key = 'EXIT' then exit;
    TextColor(Red);
    Writeln('*** Вы можете вводить только номер варианта ответа или команду exit! ***');
  end;
end;

procedure Check_Keys(ID : word);
var i, v, r: integer;
begin
try
  for i := 1 to high(_answers[ID].nodeSets) do
  begin
    //  if _answers[ID].nodeSets[i]._keyName <> '**' then WriteLn(_answers[ID].nodeSets[i]._keyName);

      if _answers[ID].nodeSets[i]._keyName <> '**' then
         case _answers[ID].nodeSets[i]._keyName of
           'TIMER' :
            begin
              TimerStart := DateUtils.SecondOf(Now);
              // TimerIsOn  := true;
            end;
           'START' :
            begin
              STR := 5;
              DEX := 5;
              INT := 5;
              CHR := 5;
              // TimerIsOn  := true;
            end;
           'FAIL' :
            begin
              if TryStrToInt(_answers[ID].nodeSets[i]._keyValue, FailNodeNumber) then
                 Sleep(1)
              else
                 begin
                   FailNodeNumber := 1;
                   TextColor(Red);
                   Writeln('*** ERROR. KEY VALUE => ', _answers[ID].nodeSets[i]._keyValue);
                   Writeln(' Ошибка сценария. Вы будете перемещны в начало.');
                 end;
            end;
           'STR'  : inc(STR);
           'DEX'  : inc(DEX);
           'INT'  : inc(INT);
           'CHR'  : inc(CHR);
           '_STR' : dec(STR);
           '_DEX' : dec(DEX);
           '_INT' : dec(INT);
           '_CHR' : dec(CHR);
           'STR_CHECK_INC':
            begin
              if not TryStrToInt(_answers[ID].nodeSets[i]._keyValue, V) then
                 Sleep(1)
              else
                 begin
                   Writeln(V);
                   R := Random(20) + STR;
                   if R > V then inc(STR);
                 end;
            end;
           'STR_CHECK_CHR':
            begin
              if not TryStrToInt(_answers[ID].nodeSets[i]._keyValue, V) then
                 Sleep(1)
              else
                 begin
                   Writeln(V);
                   R := Random(20) + CHR;
                   if R > V then inc(CHR);
                 end;
            end;
           'COMBAT' :
            begin
              case _answers[ID].nodeSets[i]._keyValue of
                '1' :
                 begin
                   gameStatus := gsCombat;
                   combatRound := 1;
                   enemyIni := 100;
                   heroIni  := 1;
                   enemyDmg := 1;
                   heroDmg  := 1;
                 end;
              else
                 Writeln('*** ERROR. BATTLE ID => ', _answers[ID].nodeSets[i]._keyValue);
                 Writeln(' Ошибка сценария. Вы будете перемещны в начало.');
                 NodeNumber := 1;
              end;
            end;

         else
           if _answers[ID].nodeSets[i]._keyName = '' then exit;
           TextColor(red);
           Writeln('*** Ошибка обработки команды. _keyName => ', _answers[ID].nodeSets[i]._keyName);
         end;
  end;
except
  Writeln(' Some error in Check Keys ' );
end;
end;

end.

