DEADSOFTWARE

save/load fixes
authorKetmar Dark <ketmar@ketmar.no-ip.org>
Fri, 8 Sep 2017 20:29:10 +0000 (23:29 +0300)
committerKetmar Dark <ketmar@ketmar.no-ip.org>
Fri, 8 Sep 2017 20:29:49 +0000 (23:29 +0300)
  plus one very experimental feature, do not touch!

src/game/Doom2DF.dpr
src/game/g_map.pas
src/game/g_panel.pas
src/game/g_triggers.pas
src/mapdef/mapdef.txt
src/shared/BinEditor.pas
src/shared/exoma.pas [new file with mode: 0644]
src/shared/hashtable.pas
src/shared/mapdef.inc
src/shared/xparser.pas
src/tools/mapgen.dpr

index a47b72d1db22465bab5092fbcc08ba1400e3a82b..806032dce301e929dcaf969d2d07692292aef34a 100644 (file)
@@ -101,6 +101,7 @@ uses
   idpool in '../shared/idpool.pas',
   xparser in '../shared/xparser.pas',
   xdynrec in '../shared/xdynrec.pas',
+  exoma in '../shared/exoma.pas',
   BinEditor in '../shared/BinEditor.pas',
   envvars in '../shared/envvars.pas',
   g_panel in 'g_panel.pas',
index e2612f454e3c624895f54eb0c6ae7dce431622ec..c395dab92374f94db5ffefe36903406bf1646bfd 100644 (file)
@@ -1338,22 +1338,9 @@ begin
     trigPanelGUID := atrigpanid;
     //trigShotPanelId := ashotpanid;
     //Data.Default := Trigger.DATA;
-    if (Trigger.trigRec = nil) then
-    begin
-      trigDataRec := nil;
-      //HACK!
-      if (TriggerType <> TRIGGER_SECRET) then
-      begin
-        e_LogWritefln('trigger of type %s has no triggerdata; wtf?!', [TriggerType], MSG_WARNING);
-      end;
-    end
-    else
-    begin
-      trigDataRec := Trigger.trigRec.clone(nil);
-    end;
   end;
 
-  result := Integer(g_Triggers_Create(_trigger));
+  result := Integer(g_Triggers_Create(_trigger, Trigger));
 end;
 
 procedure CreateMonster(monster: TDynRecord);
@@ -3083,14 +3070,12 @@ var
   var
     PAMem: TBinMemoryWriter;
     pan: TPanel;
-    count: Integer;
   begin
     // Ñîçäàåì íîâûé ñïèñîê ñîõðàíÿåìûõ ïàíåëåé
     PAMem := TBinMemoryWriter.Create((Length(panByGUID)+1) * 40);
 
     // Ñîõðàíÿåì ïàíåëè
-    count := Length(panByGUID);
-    Mem.WriteInt(count);
+    //Mem.WriteInt(Length(panByGUID));
     for pan in panByGUID do pan.SaveState(PAMem);
 
     // Ñîõðàíÿåì ýòîò ñïèñîê ïàíåëåé
@@ -3174,15 +3159,16 @@ var
   var
     PAMem: TBinMemoryReader;
     pan: TPanel;
-    count: LongInt;
+    //count: LongInt;
   begin
     // Çàãðóæàåì òåêóùèé ñïèñîê ïàíåëåé
     PAMem := TBinMemoryReader.Create();
     PAMem.LoadFromMemory(Mem);
 
     // Çàãðóæàåì ïàíåëè
-    PAMem.ReadInt(count);
-    if (count <> Length(panByGUID)) then raise EBinSizeError.Create('g_Map_LoadState: LoadPanelArray: invalid number of panels');
+    //PAMem.ReadInt(count);
+    //if (count <> Length(panByGUID)) then raise EBinSizeError.Create('g_Map_LoadState: LoadPanelArray: invalid number of panels');
+    //if (count <> Length(panByGUID)) then raise EBinSizeError.Create(Format('g_Map_LoadState: LoadPanelArray: invalid number of panels (%d : %d)', [count, Length(panByGUID)]));
     for pan in panByGUID do
     begin
       pan.LoadState(PAMem);
index 563beffbbeac9cb783a2adee4d1ec9f417c0ceea..07fe2d6103e5dd4f2fc57ec38e1b67330060203b 100644 (file)
@@ -1009,10 +1009,11 @@ begin
        Result := Result + 100;
 end;
 
+
 const
   PAN_SAVE_VERSION = 1;
 
-procedure TPanel.SaveState(Var Mem: TBinMemoryWriter);
+procedure TPanel.SaveState (var Mem: TBinMemoryWriter);
 var
   sig: DWORD;
   anim: Boolean;
@@ -1020,35 +1021,35 @@ var
 begin
   if (Mem = nil) then exit;
 
-// Ñèãíàòóðà ïàíåëè:
+  // Ñèãíàòóðà ïàíåëè
   sig := PANEL_SIGNATURE; // 'PANL'
   Mem.WriteDWORD(sig);
   ver := PAN_SAVE_VERSION;
   Mem.WriteByte(ver);
-// Îòêðûòà/çàêðûòà, åñëè äâåðü:
+  // Îòêðûòà/çàêðûòà, åñëè äâåðü
   Mem.WriteBoolean(FEnabled);
-// Íàïðàâëåíèå ëèôòà, åñëè ëèôò:
+  // Íàïðàâëåíèå ëèôòà, åñëè ëèôò
   Mem.WriteByte(FLiftType);
-// Íîìåð òåêóùåé òåêñòóðû:
+  // Íîìåð òåêóùåé òåêñòóðû
   Mem.WriteInt(FCurTexture);
-// Êîîðäû
+  // Êîîðäû
   Mem.WriteInt(FX);
   Mem.WriteInt(FY);
   Mem.WriteWord(FWidth);
   Mem.WriteWord(FHeight);
-// Àíèìèðîâàííàÿ ëè òåêóùàÿ òåêñòóðà:
+  // Àíèìèðîâàííàÿ ëè òåêóùàÿ òåêñòóðà
   if (FCurTexture >= 0) and (FTextureIDs[FCurTexture].Anim) then
-    begin
-      Assert(FTextureIDs[FCurTexture].AnTex <> nil,
-             'TPanel.SaveState: No animation object');
-      anim := True;
-    end
+  begin
+    assert(FTextureIDs[FCurTexture].AnTex <> nil, 'TPanel.SaveState: No animation object');
+    anim := True;
+  end
   else
+  begin
     anim := False;
+  end;
   Mem.WriteBoolean(anim);
-// Åñëè äà - ñîõðàíÿåì àíèìàöèþ:
-  if anim then
-    FTextureIDs[FCurTexture].AnTex.SaveState(Mem);
+  // Åñëè äà - ñîõðàíÿåì àíèìàöèþ
+  if anim then FTextureIDs[FCurTexture].AnTex.SaveState(Mem);
 
   // moving platform state
   Mem.WriteInt(mMovingSpeed.X);
@@ -1062,6 +1063,7 @@ begin
   Mem.WriteInt(mSizeSpeed.h);
   Mem.WriteInt(mSizeEnd.w);
   Mem.WriteInt(mSizeEnd.h);
+
   Mem.WriteBoolean(mMovingActive);
   Mem.WriteBoolean(mMoveOnce);
 
@@ -1069,37 +1071,35 @@ begin
   Mem.WriteInt(mEndSizeTrig);
 end;
 
-procedure TPanel.LoadState(var Mem: TBinMemoryReader);
+
+procedure TPanel.LoadState (var Mem: TBinMemoryReader);
 var
   sig: DWORD;
   anim: Boolean;
   ver: Byte;
-  //ox, oy: Integer;
 begin
   if (Mem = nil) then exit;
 
-// Ñèãíàòóðà ïàíåëè:
+  // Ñèãíàòóðà ïàíåëè
   Mem.ReadDWORD(sig);
   if (sig <> PANEL_SIGNATURE) then raise EBinSizeError.Create('TPanel.LoadState: wrong panel signature'); // 'PANL'
   Mem.ReadByte(ver);
   if (ver <> PAN_SAVE_VERSION) then raise EBinSizeError.Create('TPanel.LoadState: invalid panel version');
-// Îòêðûòà/çàêðûòà, åñëè äâåðü:
+  // Îòêðûòà/çàêðûòà, åñëè äâåðü
   Mem.ReadBoolean(FEnabled);
-// Íàïðàâëåíèå ëèôòà, åñëè ëèôò:
+  // Íàïðàâëåíèå ëèôòà, åñëè ëèôò
   Mem.ReadByte(FLiftType);
-// Íîìåð òåêóùåé òåêñòóðû:
+  // Íîìåð òåêóùåé òåêñòóðû
   Mem.ReadInt(FCurTexture);
-// Êîîðäû
-  //ox := FX;
-  //oy := FY;
+  // Êîîðäû
   Mem.ReadInt(FX);
   Mem.ReadInt(FY);
   Mem.ReadWord(FWidth);
   Mem.ReadWord(FHeight);
   //e_LogWritefln('panel %s(%s): old=(%s,%s); new=(%s,%s); delta=(%s,%s)', [arrIdx, proxyId, ox, oy, FX, FY, FX-ox, FY-oy]);
-// Àíèìèðîâàííàÿ ëè òåêóùàÿ òåêñòóðà:
+  // Àíèìèðîâàííàÿ ëè òåêóùàÿ òåêñòóðà
   Mem.ReadBoolean(anim);
-// Åñëè äà - çàãðóæàåì àíèìàöèþ:
+  // Åñëè äà - çàãðóæàåì àíèìàöèþ
   if anim then
   begin
     Assert((FCurTexture >= 0) and
@@ -1116,10 +1116,12 @@ begin
   Mem.ReadInt(mMovingStart.Y);
   Mem.ReadInt(mMovingEnd.X);
   Mem.ReadInt(mMovingEnd.Y);
+
   Mem.ReadInt(mSizeSpeed.w);
   Mem.ReadInt(mSizeSpeed.h);
   Mem.ReadInt(mSizeEnd.w);
   Mem.ReadInt(mSizeEnd.h);
+
   Mem.ReadBoolean(mMovingActive);
   Mem.ReadBoolean(mMoveOnce);
 
index fab30ec3324c2627cc4140c93b72a5cabad3b180..e49a4ef493e49baed5ab454213ceae3125545729 100644 (file)
@@ -19,14 +19,18 @@ unit g_triggers;
 interface
 
 uses
+  Variants,
   MAPDEF, e_graphics, g_basic, g_sound,
-  BinEditor, xdynrec;
+  BinEditor, xdynrec, hashtable, exoma;
 
 type
+  THashStrVariant = specialize THashBase<AnsiString, Variant>;
+
   TActivator = record
     UID:     Word;
     TimeOut: Word;
   end;
+
   PTrigger = ^TTrigger;
   TTrigger = record
   public
@@ -67,6 +71,9 @@ type
     trigPanelGUID: Integer;
 
     trigDataRec: TDynRecord; // triggerdata; owned by trigger (cloned)
+    exoInit, exoThink, exoCheck, exoAction: TExprBase;
+
+    userVars: THashStrVariant;
 
     {$INCLUDE ../shared/mapdef_tgc_def.inc}
 
@@ -74,7 +81,7 @@ type
     function trigCenter (): TDFPoint; inline;
   end;
 
-function g_Triggers_Create(Trigger: TTrigger; forceInternalIndex: Integer=-1): DWORD;
+function g_Triggers_Create(Trigger: TTrigger; trec: TDynRecord; forceInternalIndex: Integer=-1): DWORD;
 procedure g_Triggers_Update();
 procedure g_Triggers_Press(ID: DWORD; ActivateType: Byte; ActivateUID: Word = 0);
 function g_Triggers_PressR(X, Y: Integer; Width, Height: Word; UID: Word;
@@ -110,6 +117,101 @@ const
 
 {$INCLUDE ../shared/mapdef_tgc_impl.inc}
 
+
+// ////////////////////////////////////////////////////////////////////////// //
+type
+  TTrigScope = class(TExprScope)
+  private
+    plrprops: TPropHash;
+    monsprops: TPropHash;
+    platprops: TPropHash;
+
+  public
+    me: PTrigger;
+
+  public
+    constructor Create ();
+    destructor Destroy (); override;
+
+    function getObj (const aname: AnsiString): TObject; override;
+    function getField (obj: TObject; const afldname: AnsiString): Variant; override;
+    procedure setField (obj: TObject; const afldname: AnsiString; var aval: Variant); override;
+  end;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
+constructor TTrigScope.Create ();
+begin
+  plrprops := TPropHash.Create(TPlayer);
+  monsprops := TPropHash.Create(TMonster);
+  platprops := TPropHash.Create(TPanel);
+  me := nil;
+end;
+
+
+destructor TTrigScope.Destroy ();
+begin
+  platprops.Free();
+  monsprops.Free();
+  plrprops.Free();
+  inherited;
+end;
+
+
+function TTrigScope.getObj (const aname: AnsiString): TObject;
+begin
+       if (aname = 'player') then result := gPlayers[0] //FIXME
+  else if (aname = 'self') or (aname = 'this') then result := TObject(Pointer(PtrUInt(1)))
+  else result := inherited getObj(aname);
+end;
+
+
+function TTrigScope.getField (obj: TObject; const afldname: AnsiString): Variant;
+begin
+  if (obj = gPlayers[0]) then
+  begin
+    if plrprops.get(obj, afldname, result) then exit;
+  end
+  else if (obj = TObject(Pointer(PtrUInt(1)))) then
+  begin
+    if (me <> nil) and (me.userVars <> nil) then
+    begin
+      if me.userVars.get(afldname, result) then exit;
+    end;
+  end;
+  result := inherited getField(obj, afldname);
+end;
+
+
+procedure TTrigScope.setField (obj: TObject; const afldname: AnsiString; var aval: Variant);
+begin
+  if (obj = gPlayers[0]) then
+  begin
+    if plrprops.put(obj, afldname, aval) then exit;
+  end
+  else if (obj = TObject(Pointer(PtrUInt(1)))) then
+  begin
+    if (me <> nil) then
+    begin
+      if (Length(afldname) > 4) and (afldname[1] = 'u') and (afldname[2] = 's') and
+         (afldname[3] = 'e') and (afldname[4] = 'r') then
+      begin
+        if (me.userVars = nil) then me.userVars := THashStrVariant.Create(hsihash, hsiequ);
+        me.userVars.put(afldname, aval);
+        exit;
+      end;
+    end;
+  end;
+  inherited setField(obj, afldname, aval);
+end;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
+var
+  tgscope: TTrigScope = nil;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
 function TTrigger.trigCenter (): TDFPoint; inline;
 begin
   result := TDFPoint.Create(x+width div 2, y+height div 2);
@@ -118,23 +220,27 @@ end;
 
 function FindTrigger (): DWORD;
 var
-  i: Integer;
+  i, olen: Integer;
 begin
-  for i := 0 to High(gTriggers) do
+  olen := Length(gTriggers);
+
+  for i := 0 to olen-1 do
   begin
     if gTriggers[i].TriggerType = TRIGGER_NONE then begin result := i; exit; end;
   end;
 
-  if (gTriggers = nil) then
-  begin
-    SetLength(gTriggers, 8);
-    result := 0;
-  end
-  else
+  SetLength(gTriggers, olen+8);
+  result := olen;
+
+  for i := result to High(gTriggers) do
   begin
-    result := Length(gTriggers);
-    SetLength(gTriggers, result+8);
-    for i := result to High(gTriggers) do gTriggers[i].TriggerType := TRIGGER_NONE;
+    gTriggers[i].TriggerType := TRIGGER_NONE;
+    gTriggers[i].trigDataRec := nil;
+    gTriggers[i].exoInit := nil;
+    gTriggers[i].exoThink := nil;
+    gTriggers[i].exoCheck := nil;
+    gTriggers[i].exoAction := nil;
+    gTriggers[i].userVars := nil;
   end;
 end;
 
@@ -1065,18 +1171,49 @@ var
     end;
   end;
 
+var
+  tvval: Variant;
 begin
   result := false;
   if g_Game_IsClient then exit;
 
   if not Trigger.Enabled then exit;
   if (Trigger.TimeOut <> 0) and (actType <> ACTIVATE_CUSTOM) then exit;
-  if gLMSRespawn = LMS_RESPAWN_WARMUP then exit;
+  if (gLMSRespawn = LMS_RESPAWN_WARMUP) then exit;
+
+  if (Trigger.exoCheck <> nil) then
+  begin
+    //conwritefln('exocheck: [%s]', [Trigger.exoCheck.toString()]);
+    try
+      tgscope.me := @Trigger;
+      tvval := Trigger.exoCheck.value(tgscope);
+      tgscope.me := nil;
+      if not Boolean(tvval) then exit;
+    except
+      tgscope.me := nil;
+      conwritefln('trigger exocheck error: %s', [Trigger.exoCheck.toString()]);
+      exit;
+    end;
+  end;
 
   animonce := False;
 
   coolDown := (actType <> 0);
 
+  if (Trigger.exoAction <> nil) then
+  begin
+    //conwritefln('exoactivate: [%s]', [Trigger.exoAction.toString()]);
+    try
+      tgscope.me := @Trigger;
+      Trigger.exoAction.value(tgscope);
+      tgscope.me := nil;
+    except
+      tgscope.me := nil;
+      conwritefln('trigger exoactivate error: %s', [Trigger.exoAction.toString()]);
+      exit;
+    end;
+  end;
+
   with Trigger do
   begin
     case TriggerType of
@@ -2139,10 +2276,11 @@ begin
   triggers := gCurrentMap['trigger'];
   if (triggers = nil) then raise Exception.Create('LOAD: map has no triggers');
   if (mapidx < 0) or (mapidx >= triggers.count) then raise Exception.Create('LOAD: invalid map trigger index');
-  Trigger.trigDataRec := triggers.itemAt[mapidx];
-  if (Trigger.trigDataRec = nil) then raise Exception.Create('LOAD: internal error in trigger loader');
-  Trigger.mapId := Trigger.trigDataRec.id;
+  //Trigger.trigDataRec := triggers.itemAt[mapidx];
+  //if (Trigger.trigDataRec = nil) then raise Exception.Create('LOAD: internal error in trigger loader');
+  //Trigger.mapId := Trigger.trigDataRec.id;
   Trigger.mapIndex := mapidx;
+  {
   if (Trigger.trigDataRec.trigRec <> nil) then
   begin
     Trigger.trigDataRec := Trigger.trigDataRec.trigRec.clone(nil);
@@ -2151,16 +2289,19 @@ begin
   begin
     Trigger.trigDataRec := nil;
   end;
-  result := g_Triggers_Create(Trigger, arridx);
+  }
+  result := g_Triggers_Create(Trigger, triggers.itemAt[mapidx], arridx);
 end;
 
 
-function g_Triggers_Create(Trigger: TTrigger; forceInternalIndex: Integer=-1): DWORD;
+function g_Triggers_Create(Trigger: TTrigger; trec: TDynRecord; forceInternalIndex: Integer=-1): DWORD;
 var
   find_id: DWORD;
   fn, mapw: AnsiString;
   f, olen: Integer;
 begin
+  if (tgscope = nil) then tgscope := TTrigScope.Create();
+
   // Íå ñîçäàâàòü âûõîä, åñëè èãðà áåç âûõîäà
   if (Trigger.TriggerType = TRIGGER_EXIT) and
      (not LongBool(gGameSettings.Options and GAME_OPTION_ALLOWEXIT)) then
@@ -2185,12 +2326,50 @@ begin
     if (forceInternalIndex >= olen) then
     begin
       SetLength(gTriggers, forceInternalIndex+1);
-      for f := olen to High(gTriggers) do gTriggers[f].TriggerType := TRIGGER_NONE;
+      for f := olen to High(gTriggers) do
+      begin
+        gTriggers[f].TriggerType := TRIGGER_NONE;
+        gTriggers[f].trigDataRec := nil;
+        gTriggers[f].exoInit := nil;
+        gTriggers[f].exoThink := nil;
+        gTriggers[f].exoCheck := nil;
+        gTriggers[f].exoAction := nil;
+        gTriggers[f].userVars := nil;
+      end;
     end;
+    f := forceInternalIndex;
+    gTriggers[f].trigDataRec.Free();
+    gTriggers[f].exoInit.Free();
+    gTriggers[f].exoThink.Free();
+    gTriggers[f].exoCheck.Free();
+    gTriggers[f].exoAction.Free();
+    gTriggers[f].userVars.Free();
+    gTriggers[f].trigDataRec := nil;
+    gTriggers[f].exoInit := nil;
+    gTriggers[f].exoThink := nil;
+    gTriggers[f].exoCheck := nil;
+    gTriggers[f].exoAction := nil;
+    gTriggers[f].userVars := nil;
     find_id := DWORD(forceInternalIndex);
   end;
   gTriggers[find_id] := Trigger;
 
+  Trigger.mapId := trec.id;
+  // clone trigger data
+  if (trec.trigRec = nil) then
+  begin
+    gTriggers[find_id].trigDataRec := nil;
+    //HACK!
+    if (gTriggers[find_id].TriggerType <> TRIGGER_SECRET) then
+    begin
+      e_LogWritefln('trigger of type %s has no triggerdata; wtf?!', [gTriggers[find_id].TriggerType], MSG_WARNING);
+    end;
+  end
+  else
+  begin
+    gTriggers[find_id].trigDataRec := trec.trigRec.clone(nil);
+  end;
+
   with gTriggers[find_id] do
   begin
     ID := find_id;
@@ -2221,6 +2400,47 @@ begin
   // update cached trigger variables
   trigUpdateCacheData(gTriggers[find_id], gTriggers[find_id].trigDataRec);
 
+  gTriggers[find_id].userVars := nil; //THashStrVariant.Create(hsihash, hsiequ);
+
+  try
+    gTriggers[find_id].exoThink := TExprBase.parseStatList(VarToStr(trec.user['exoma_think']));
+  except
+    conwritefln('*** ERROR parsing exoma_think: [%s]', [VarToStr(trec.user['exoma_think'])]);
+    gTriggers[find_id].exoThink := nil;
+  end;
+  try
+    gTriggers[find_id].exoCheck := TExprBase.parse(VarToStr(trec.user['exoma_check']));
+  except
+    conwritefln('*** ERROR parsing exoma_check: [%s]', [VarToStr(trec.user['exoma_check'])]);
+    gTriggers[find_id].exoCheck := nil;
+  end;
+  try
+    gTriggers[find_id].exoAction := TExprBase.parseStatList(VarToStr(trec.user['exoma_action']));
+  except
+    conwritefln('*** ERROR parsing exoma_action: [%s]', [VarToStr(trec.user['exoma_action'])]);
+    gTriggers[find_id].exoAction := nil;
+  end;
+  try
+    gTriggers[find_id].exoInit := TExprBase.parseStatList(VarToStr(trec.user['exoma_init']));
+  except
+    conwritefln('*** ERROR parsing exoma_init: [%s]', [VarToStr(trec.user['exoma_init'])]);
+    gTriggers[find_id].exoInit := nil;
+  end;
+
+  if (forceInternalIndex < 0) and (gTriggers[find_id].exoInit <> nil) then
+  begin
+    //conwritefln('executing trigger init: [%s]', [gTriggers[find_id].exoInit.toString()]);
+    try
+      tgscope.me := @gTriggers[find_id];
+      gTriggers[find_id].exoInit.value(tgscope);
+      tgscope.me := nil;
+    except
+      tgscope.me := nil;
+      conwritefln('*** trigger exoactivate error: %s', [gTriggers[find_id].exoInit.toString()]);
+      exit;
+    end;
+  end;
+
   // Çàãðóæàåì çâóê, åñëè ýòî òðèããåð "Çâóê"
   if (Trigger.TriggerType = TRIGGER_SOUND) and (Trigger.tgcSoundName <> '') then
   begin
@@ -2809,6 +3029,11 @@ begin
       SetLength(gTriggers[a].Activators, 0);
     end;
     gTriggers[a].trigDataRec.Free();
+
+    gTriggers[a].exoThink.Free();
+    gTriggers[a].exoCheck.Free();
+    gTriggers[a].exoAction.Free();
+    gTriggers[a].userVars.Free();
   end;
 
   gTriggers := nil;
@@ -2823,6 +3048,10 @@ var
   dw: DWORD;
   sg: Single;
   b: Boolean;
+  kv: THashStrVariant.PEntry;
+  //it: THashStrVariant.TKeyValEnumerator;
+  //uname: AnsiString;
+  t: LongInt;
 begin
   // Ñ÷èòàåì êîëè÷åñòâî ñóùåñòâóþùèõ òðèããåðîâ
   count := Length(gTriggers);
@@ -2906,6 +3135,35 @@ begin
       sg := gTriggers[i].Sound.GetPan();
       Mem.WriteSingle(sg);
     end;
+    // uservars
+    if (gTriggers[i].userVars = nil) then
+    begin
+      Mem.WriteInt(0);
+    end
+    else
+    begin
+      Mem.WriteInt(gTriggers[i].userVars.count);
+      for kv in gTriggers[i].userVars.byKeyValue do
+      begin
+        //writeln('<', kv.key, '>:<', VarToStr(kv.value), '>');
+        Mem.WriteString(kv.key);
+        t := LongInt(varType(kv.value));
+        Mem.WriteInt(t);
+        case t of
+          varString: Mem.WriteString(AnsiString(kv.value));
+          varBoolean: Mem.WriteBoolean(Boolean(kv.value));
+          varShortInt: Mem.WriteInt(Integer(kv.value));
+          varSmallint: Mem.WriteInt(Integer(kv.value));
+          varInteger: Mem.WriteInt(Integer(kv.value));
+          //varInt64: Mem.WriteInt(Integer(kv.value));
+          varByte: Mem.WriteInt(Integer(kv.value));
+          varWord: Mem.WriteInt(Integer(kv.value));
+          varLongWord: Mem.WriteInt(Integer(kv.value));
+          //varQWord:
+          else raise Exception.CreateFmt('cannot save uservar ''%s''', [kv.key]);
+        end;
+      end;
+    end;
   end;
 end;
 
@@ -2918,6 +3176,13 @@ var
   b: Boolean;
   Trig: TTrigger;
   mapIndex: Integer;
+  uvcount: Integer;
+  vt: LongInt;
+  vv: Variant;
+  uvname: AnsiString;
+  ustr: AnsiString;
+  uint: LongInt;
+  ubool: Boolean;
 begin
   if (Mem = nil) then exit;
 
@@ -2938,18 +3203,6 @@ begin
     if (Trig.TriggerType = TRIGGER_NONE) then continue; // empty one
     Mem.ReadInt(mapIndex);
     i := g_Triggers_CreateWithMapIndex(Trig, a, mapIndex);
-    {
-    if (gTriggers[i].trigData <> nil) then
-    begin
-      tw := TStrTextWriter.Create();
-      try
-        gTriggers[i].trigData.writeTo(tw);
-        e_LogWritefln('=== trigger #%s loaded ==='#10'%s'#10'---', [mapIndex, tw.str]);
-      finally
-        tw.Free();
-      end;
-    end;
-    }
   // Êîîðäèíàòû ëåâîãî âåðõíåãî óãëà:
     Mem.ReadInt(gTriggers[i].X);
     Mem.ReadInt(gTriggers[i].Y);
@@ -3019,7 +3272,36 @@ begin
         gTriggers[i].Sound.SetPosition(dw);
       end
     end;
+    // uservars
+    gTriggers[i].userVars.Free();
+    gTriggers[i].userVars := nil;
+    Mem.ReadInt(uvcount);
+    if (uvcount > 0) then
+    begin
+      gTriggers[i].userVars := THashStrVariant.Create(hsihash, hsiequ);
+      vv := Unassigned;
+      while (uvcount > 0) do
+      begin
+        Dec(uvcount);
+        uvname := '';
+        Mem.ReadString(uvname);
+        Mem.ReadInt(vt);
+        case vt of
+          varString: begin ustr := ''; Mem.ReadString(ustr); vv := ustr; end;
+          varBoolean: begin Mem.ReadBoolean(ubool); vv := ubool; end;
+          varShortInt: begin Mem.ReadInt(uint); vv := ShortInt(uint); end;
+          varSmallint: begin Mem.ReadInt(uint); vv := SmallInt(uint); end;
+          varInteger: begin Mem.ReadInt(uint); vv := LongInt(uint); end;
+          varByte: begin Mem.ReadInt(uint); vv := Byte(uint); end;
+          varWord: begin Mem.ReadInt(uint); vv := Word(uint); end;
+          varLongWord: begin Mem.ReadInt(uint); vv := LongWord(uint); end;
+          else raise Exception.CreateFmt('cannot load uservar ''%s''', [uvname]);
+        end;
+        gTriggers[i].userVars.put(uvname, vv);
+      end;
+    end;
   end;
 end;
 
+
 end.
index 889feeefde60632f2a317c1a5f5c9d9734a0a8de..afa87222a21dd5c5312a1f45f26f2be0cc0c435b 100644 (file)
   "keys" type ubyte offset 19 bitset Key default KEY_NONE;
   //WARNING: "trigdata" MUST be defined before "type", and "type" MUST be named "type" (for now, can be changed later)
   "triggerdata" type trigdata[128] offset 20; // the only special nested structure
+  //DO NOT USE! experimental feature! will be removed!
+  "exoma_init" type string default "" tip "will be called on trigger creation";
+  "exoma_think" type string default "" tip "will be called on each think step";
+  "exoma_check" type string default "" tip "will be called before activation";
+  "exoma_action" type string default "" tip "will be called on activation";
 }
 
 
index 25526e14c0374b5ac3de55ff639872625d34d5a4..e1e90229576fdcf6eef72af0257f189f15d36ed7 100644 (file)
@@ -30,25 +30,26 @@ Type
     FData: Pointer;
     FPosition: Cardinal;
 
-    Procedure   WriteVar(Var x; varSize: Cardinal);
+    Procedure   WriteVar (var x; varSize: Cardinal);
     Procedure   ExtendMemory(addLen: Cardinal);
 
   Public
-    Constructor Create(aSize: Cardinal);
-    Destructor  Destroy(); Override;
-    Procedure   WriteByte(Var x: Byte);
-    Procedure   WriteWord(Var x: Word);
-    Procedure   WriteDWORD(Var x: DWORD);
-    Procedure   WriteShortInt(Var x: ShortInt);
-    Procedure   WriteSmallInt(Var x: SmallInt);
-    Procedure   WriteInt(Var x: Integer);
-    Procedure   WriteSingle(Var x: Single);
-    Procedure   WriteBoolean(Var x: Boolean);
-    Procedure   WriteString(const x: AnsiString; aMaxLen: Word=65535);
-    Procedure   WriteMemory(Var x: Pointer; memSize: Cardinal);
-    Procedure   Fill(aLen: Cardinal; aFillSym: Byte);
-    Procedure   SaveToFile(Var aFile: File);
-    Procedure   SaveToMemory(Var aMem: TBinMemoryWriter);
+    Constructor Create (aSize: Cardinal);
+    Destructor  Destroy (); Override;
+
+    Procedure   WriteByte (x: Byte);
+    Procedure   WriteWord (x: Word);
+    Procedure   WriteDWORD (x: DWORD);
+    Procedure   WriteShortInt (x: ShortInt);
+    Procedure   WriteSmallInt (x: SmallInt);
+    Procedure   WriteInt (x: Integer);
+    Procedure   WriteSingle (x: Single);
+    Procedure   WriteBoolean (x: Boolean);
+    Procedure   WriteString (const x: AnsiString; aMaxLen: Word=65535);
+    Procedure   WriteMemory (x: Pointer; memSize: Cardinal);
+    Procedure   Fill (aLen: Cardinal; aFillSym: Byte);
+    Procedure   SaveToFile (Var aFile: File);
+    Procedure   SaveToMemory (Var aMem: TBinMemoryWriter);
   End;
 
   TBinMemoryReader = Class (TObject)
@@ -161,14 +162,11 @@ begin
   Inherited;
 end;
 
-Procedure TBinMemoryWriter.WriteVar(Var x; varSize: Cardinal);
+Procedure TBinMemoryWriter.WriteVar (var x; varSize: Cardinal);
 begin
-  if (FPosition + varSize) > FSize then
-    ExtendMemory(varSize);
-
-  CopyMemory(Pointer(NativeUInt(FData) + FPosition),
-             @x, varSize);
-  FPosition := FPosition + varSize;
+  if (FPosition+varSize > FSize) then ExtendMemory(varSize);
+  CopyMemory(Pointer(PtrUInt(FData)+FPosition), @x, varSize);
+  FPosition := FPosition+varSize;
 end;
 
 Procedure TBinMemoryWriter.ExtendMemory(addLen: Cardinal);
@@ -197,51 +195,46 @@ begin
   e_WriteLog('Save Memory Extended: '+IntToStr(FSize), MSG_NOTIFY);
 end;
 
-Procedure TBinMemoryWriter.WriteByte(Var x: Byte);
+Procedure TBinMemoryWriter.WriteByte (x: Byte);
 begin
   WriteVar(x, SizeOf(Byte));
 end;
 
-Procedure TBinMemoryWriter.WriteWord(Var x: Word);
+Procedure TBinMemoryWriter.WriteWord (x: Word);
 begin
   WriteVar(x, SizeOf(Word));
 end;
 
-Procedure TBinMemoryWriter.WriteDWORD(Var x: DWORD);
+Procedure TBinMemoryWriter.WriteDWORD (x: DWORD);
 begin
   WriteVar(x, SizeOf(DWORD));
 end;
 
-Procedure TBinMemoryWriter.WriteShortInt(Var x: ShortInt);
+Procedure TBinMemoryWriter.WriteShortInt (x: ShortInt);
 begin
   WriteVar(x, SizeOf(ShortInt));
 end;
 
-Procedure TBinMemoryWriter.WriteSmallInt(Var x: SmallInt);
+Procedure TBinMemoryWriter.WriteSmallInt (x: SmallInt);
 begin
   WriteVar(x, SizeOf(SmallInt));
 end;
 
-Procedure TBinMemoryWriter.WriteInt(Var x: Integer);
+Procedure TBinMemoryWriter.WriteInt (x: Integer);
 begin
   WriteVar(x, SizeOf(Integer));
 end;
 
-Procedure TBinMemoryWriter.WriteSingle(Var x: Single);
+Procedure TBinMemoryWriter.WriteSingle (x: Single);
 begin
   WriteVar(x, SizeOf(Single));
 end;
 
-Procedure TBinMemoryWriter.WriteBoolean(Var x: Boolean);
+Procedure TBinMemoryWriter.WriteBoolean (x: Boolean);
 var
   y: Byte;
-
 begin
-  if x then
-    y := 1
-  else
-    y := 0;
-
+  if x then y := 1 else y := 0;
   WriteVar(y, SizeOf(Byte));
 end;
 
@@ -264,34 +257,27 @@ begin
   end;
 end;
 
-Procedure TBinMemoryWriter.WriteMemory(Var x: Pointer; memSize: Cardinal);
+Procedure TBinMemoryWriter.WriteMemory (x: Pointer; memSize: Cardinal);
 begin
-  if (FPosition + SizeOf(Cardinal) + memSize) > FSize then
-    ExtendMemory(SizeOf(Cardinal) + memSize);
-
-// Äëèíà áëîêà ïàìÿòè:
-  CopyMemory(Pointer(NativeUInt(FData) + FPosition),
-             @memSize, SizeOf(Cardinal));
-  FPosition := FPosition + SizeOf(Cardinal);
-// Áëîê ïàìÿòè:
-  if memSize > 0 then
+  if (FPosition+SizeOf(Cardinal)+memSize) > FSize then ExtendMemory(SizeOf(Cardinal)+memSize);
+  // Äëèíà áëîêà ïàìÿòè
+  CopyMemory(Pointer(PtrUInt(FData)+FPosition), @memSize, SizeOf(Cardinal));
+  FPosition := FPosition+SizeOf(Cardinal);
+  // Áëîê ïàìÿòè
+  if (memSize > 0) then
   begin
-    CopyMemory(Pointer(NativeUInt(FData) + FPosition),
-               x, memSize);
-    FPosition := FPosition + memSize;
+    CopyMemory(Pointer(PtrUInt(FData)+FPosition), x, memSize);
+    FPosition := FPosition+memSize;
   end;
 end;
 
-Procedure TBinMemoryWriter.Fill(aLen: Cardinal; aFillSym: Byte);
+Procedure TBinMemoryWriter.Fill (aLen: Cardinal; aFillSym: Byte);
 begin
-  if (FPosition + aLen) > FSize then
-    ExtendMemory(aLen);
-
-  if aLen > 0 then
+  if (FPosition+aLen > FSize) then ExtendMemory(aLen);
+  if (aLen > 0) then
   begin
-    FillMemory(Pointer(NativeUInt(FData) + FPosition),
-               aLen, aFillSym);
-    FPosition := FPosition + aLen;
+    FillMemory(Pointer(PtrUInt(FData) + FPosition), aLen, aFillSym);
+    FPosition := FPosition+aLen;
   end;
 end;
 
diff --git a/src/shared/exoma.pas b/src/shared/exoma.pas
new file mode 100644 (file)
index 0000000..9d628e5
--- /dev/null
@@ -0,0 +1,1007 @@
+(* Copyright (C)  DooM 2D:Forever Developers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *)
+{$INCLUDE a_modes.inc}
+unit exoma;
+
+interface
+
+uses
+  typinfo, Variants, hashtable, xparser;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
+type
+  TPropHash = class
+  private
+    mClass: TClass;
+    mNames: THashStrInt;
+    pl: PPropList;
+    pc: Integer;
+
+  public
+    constructor Create (aklass: TClass);
+    destructor Destroy (); override;
+
+    function get (obj: TObject; const fldname: AnsiString; out v: Variant): Boolean;
+    function put (obj: TObject; const fldname: AnsiString; var v: Variant): Boolean;
+  end;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
+type
+  TExprScope = class
+  public
+    function getObj (const aname: AnsiString): TObject; virtual;
+    function getField (obj: TObject; const afldname: AnsiString): Variant; virtual;
+    procedure setField (obj: TObject; const afldname: AnsiString; var aval: Variant); virtual;
+  end;
+
+  TExprBase = class
+  public
+    class function coerce2bool (var v0: Variant): Boolean;
+    class function toInt (var v: Variant): LongInt;
+  public
+    class procedure error ();
+    class function parse (pr: TTextParser; allowAssign: Boolean=false): TExprBase;
+    class function parse (const str: AnsiString; allowAssign: Boolean=false): TExprBase;
+    class function parseStatList (const str: AnsiString): TExprBase;
+  public
+    function value (scope: TExprScope): Variant; virtual; abstract;
+    procedure assign (scope: TExprScope; var v: Variant); virtual;
+    function clone (): TExprBase; virtual; abstract;
+  end;
+
+  TExprStatList = class(TExprBase)
+  private
+    mList: array of TExprBase;
+  public
+    constructor Create ();
+    destructor Destroy (); override;
+    function value (scope: TExprScope): Variant; override;
+    function toString (): AnsiString; override;
+    function clone (): TExprBase; override;
+  end;
+
+  TObjExpr = class(TExprBase)
+  private
+    mName: AnsiString;
+  public
+    constructor Create (const aval: AnsiString);
+
+    function value (scope: TExprScope): Variant; override;
+    function toString (): AnsiString; override;
+    function clone (): TExprBase; override;
+  end;
+
+  TLitExpr = class(TExprBase)
+  private
+    mValue: Variant;
+  public
+    constructor Create (aval: Boolean);
+    constructor Create (aval: LongInt);
+    constructor Create (const aval: AnsiString);
+
+    function value (scope: TExprScope): Variant; override;
+    function toString (): AnsiString; override;
+    function clone (): TExprBase; override;
+  end;
+
+  TUnExpr = class(TExprBase)
+  private
+    mOp0: TExprBase;
+  public
+    constructor Create (aop0: TExprBase);
+    destructor Destroy (); override;
+    function clone (): TExprBase; override;
+  end;
+
+  TUnExprNeg = class(TUnExpr) public function value (scope: TExprScope): Variant; override; function toString (): AnsiString; override; end;
+  TUnExprNot = class(TUnExpr) public function value (scope: TExprScope): Variant; override; function toString (): AnsiString; override; end;
+
+  TDotExpr = class(TExprBase)
+  private
+    mOp0: TExprBase;
+    mField: AnsiString;
+  public
+    constructor Create (aop0: TExprBase; const afield: AnsiString);
+    function value (scope: TExprScope): Variant; override;
+    procedure assign (scope: TExprScope; var v: Variant); override;
+    function toString (): AnsiString; override;
+    function clone (): TExprBase; override;
+  end;
+
+  TBinExpr = class(TExprBase)
+  private
+    mOp0, mOp1: TExprBase;
+  private
+    class procedure coerce (var v0, v1: Variant); // modifies both variants
+  public
+    constructor Create (aop0, aop1: TExprBase);
+    destructor Destroy (); override;
+    function clone (): TExprBase; override;
+  end;
+
+  TBinExprAdd = class(TBinExpr) public function value (scope: TExprScope): Variant; override; function toString (): AnsiString; override; end;
+  TBinExprSub = class(TBinExpr) public function value (scope: TExprScope): Variant; override; function toString (): AnsiString; override; end;
+  TBinExprMul = class(TBinExpr) public function value (scope: TExprScope): Variant; override; function toString (): AnsiString; override; end;
+  TBinExprDiv = class(TBinExpr) public function value (scope: TExprScope): Variant; override; function toString (): AnsiString; override; end;
+  TBinExprMod = class(TBinExpr) public function value (scope: TExprScope): Variant; override; function toString (): AnsiString; override; end;
+
+  TBinExprLogAnd = class(TBinExpr) public function value (scope: TExprScope): Variant; override; function toString (): AnsiString; override; end;
+  TBinExprLogOr = class(TBinExpr) public function value (scope: TExprScope): Variant; override; function toString (): AnsiString; override; end;
+
+  TBinExprCmpLess = class(TBinExpr) public function value (scope: TExprScope): Variant; override; function toString (): AnsiString; override; end;
+  TBinExprCmpGreat = class(TBinExpr) public function value (scope: TExprScope): Variant; override; function toString (): AnsiString; override; end;
+  TBinExprCmpLessEqu = class(TBinExpr) public function value (scope: TExprScope): Variant; override; function toString (): AnsiString; override; end;
+  TBinExprCmpGreatEqu = class(TBinExpr) public function value (scope: TExprScope): Variant; override; function toString (): AnsiString; override; end;
+  TBinExprCmpEqu = class(TBinExpr) public function value (scope: TExprScope): Variant; override; function toString (): AnsiString; override; end;
+  TBinExprCmpNotEqu = class(TBinExpr) public function value (scope: TExprScope): Variant; override; function toString (): AnsiString; override; end;
+
+  TBinAssign = class(TBinExpr) public function value (scope: TExprScope): Variant; override; function toString (): AnsiString; override; end;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
+function typeKind2Str (t: TTypeKind): AnsiString;
+
+
+implementation
+
+uses
+  SysUtils, utils;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
+function typeKind2Str (t: TTypeKind): AnsiString;
+begin
+  case t of
+    tkUnknown: result := 'Unknown';
+    tkInteger: result := 'Integer';
+    tkChar: result := 'AnsiChar';
+    tkEnumeration: result := 'Enumeration';
+    tkFloat: result := 'Float';
+    tkSet: result := 'Set';
+    tkMethod: result := 'Method';
+    tkSString: result := 'ShortString';
+    tkLString: result := 'LString';
+    tkAString: result := 'AnsiString';
+    tkWString: result := 'WideString';
+    tkVariant: result := 'Variant';
+    tkArray: result := 'Array';
+    tkRecord: result := 'Record';
+    tkInterface: result := 'Interface';
+    tkClass: result := 'Class';
+    tkObject: result := 'Object';
+    tkWChar: result := 'WideChar';
+    tkBool: result := 'Boolean';
+    tkInt64: result := 'Int64';
+    tkQWord: result := 'UInt64';
+    tkDynArray: result := 'DynArray';
+    tkInterfaceRaw: result := 'InterfaceRaw';
+    tkProcVar: result := 'ProcVar';
+    tkUString: result := 'UString';
+    tkUChar: result := 'UChar';
+    tkHelper: result := 'Helper';
+    tkFile: result := 'File';
+    tkClassRef: result := 'ClassRef';
+    tkPointer: result := 'Pointer';
+    else result := '<unknown>';
+  end;
+end;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
+(*
+procedure dumpPublishedProperties (obj: TObject);
+var
+  pt: PTypeData;
+  pi: PTypeInfo;
+  i, j: Integer;
+  pp: PPropList;
+begin
+  if (obj = nil) then exit;
+  //e_LogWritefln('Object of type ''%s'':', [obj.ClassName]);
+  pi := obj.ClassInfo;
+  pt := GetTypeData(pi);
+  //e_LogWritefln('property count: %s', [pt.PropCount]);
+  GetMem(pp, pt^.PropCount*sizeof(Pointer));
+  try
+    j := GetPropList(pi, [tkInteger, tkBool, tkSString, tkLString, tkAString, tkSet, tkEnumeration], pp);
+    //e_LogWritefln('ordinal property count: %s', [j]);
+    for i := 0 to j-1 do
+    begin
+      {
+      if (typinfo.PropType(obj, pp^[i].name) in [tkSString, tkLString, tkAString]) then
+      begin
+        e_LogWritefln('  #%s: <%s>; type: %s; value: <%s>', [i+1, pp^[i].name, typeKind2Str(typinfo.PropType(obj, pp^[i].name)), GetStrProp(obj, pp^[i])]);
+      end
+      else if (typinfo.PropType(obj, pp^[i].name) = tkSet) then
+      begin
+        e_LogWritefln('  #%s: <%s>; type: %s; value: %s', [i+1, pp^[i].name, typeKind2Str(typinfo.PropType(obj, pp^[i].name)), GetSetProp(obj, pp^[i], true)]);
+      end
+      else if (typinfo.PropType(obj, pp^[i].name) = tkEnumeration) then
+      begin
+        e_LogWritefln('  #%s: <%s>; type: %s; value: <%s>', [i+1, pp^[i].name, typeKind2Str(typinfo.PropType(obj, pp^[i].name)), GetEnumProp(obj, pp^[i])]);
+      end
+      else
+      begin
+        e_LogWritefln('  #%s: <%s>; type: %s; value: %s', [i+1, pp^[i].name, typeKind2Str(typinfo.PropType(obj, pp^[i].name)), GetOrdProp(obj, pp^[i])]);
+      end;
+      }
+    end;
+  finally
+    FreeMem(pp);
+  end;
+end;
+*)
+
+
+// ////////////////////////////////////////////////////////////////////////// //
+constructor TPropHash.Create (aklass: TClass);
+var
+  pi: PTypeInfo;
+  pt: PTypeData;
+  idx: Integer;
+begin
+  mClass := aklass;
+  mNames := hashNewStrInt();
+  pi := aklass.ClassInfo;
+  pt := GetTypeData(pi);
+  GetMem(pl, pt^.PropCount*sizeof(Pointer));
+  pc := GetPropList(pi, [tkInteger, tkBool, tkSString, tkLString, tkAString, {tkSet,} tkEnumeration], pl);
+  for idx := 0 to pc-1 do mNames.put(pl^[idx].name, idx);
+end;
+
+destructor TPropHash.Destroy ();
+begin
+  mNames.Free();
+  mNames := nil;
+  if (pl <> nil) then FreeMem(pl);
+  pl := nil;
+  pc := 0;
+  mClass := nil;
+end;
+
+function TPropHash.get (obj: TObject; const fldname: AnsiString; out v: Variant): Boolean;
+var
+  idx: Integer;
+begin
+  result := false;
+  if mNames.get(fldname, idx) then
+  begin
+    result := true;
+    case pl^[idx].PropType.Kind of
+      tkSString, tkLString, tkAString: v := GetStrProp(obj, pl^[idx]);
+      tkEnumeration: v := GetEnumProp(obj, pl^[idx]);
+      tkBool: if (GetOrdProp(obj, pl^[idx]) = 0) then v := false else v := true;
+      tkInteger, tkChar: v := LongInt(GetOrdProp(obj, pl^[idx]));
+      //tkFloat: result := 'Float';
+      //tkClass: result := 'Class';
+      //tkInt64: result := 'Int64';
+      //tkClassRef: result := 'ClassRef';
+      else result := false;
+    end;
+    if result then exit;
+  end;
+  v := Unassigned;
+end;
+
+function TPropHash.put (obj: TObject; const fldname: AnsiString; var v: Variant): Boolean;
+var
+  idx: Integer;
+begin
+  result := false;
+  if mNames.get(fldname, idx) then
+  begin
+    result := true;
+    case pl^[idx].PropType.Kind of
+      tkSString, tkLString, tkAString: SetStrProp(obj, pl^[idx], VarToStr(v));
+      tkEnumeration: SetEnumProp(obj, pl^[idx], VarToStr(v));
+      tkBool: if TExprBase.coerce2bool(v) then SetOrdProp(obj, pl^[idx], 1) else SetOrdProp(obj, pl^[idx], 0);
+      tkInteger, tkChar: SetOrdProp(obj, pl^[idx], TExprBase.toInt(v));
+      //tkFloat: result := 'Float';
+      //tkClass: result := 'Class';
+      //tkInt64: result := 'Int64';
+      //tkClassRef: result := 'ClassRef';
+      else result := false;
+    end;
+    if result then exit;
+  end;
+end;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
+function TExprScope.getObj (const aname: AnsiString): TObject; begin result := nil; TExprBase.error(); end;
+function TExprScope.getField (obj: TObject; const afldname: AnsiString): Variant; begin result := Unassigned; TExprBase.error(); end;
+procedure TExprScope.setField (obj: TObject; const afldname: AnsiString; var aval: Variant); begin TExprBase.error(); end;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
+class procedure TExprBase.error (); begin raise Exception.Create('math error'); end;
+
+class function TExprBase.coerce2bool (var v0: Variant): Boolean;
+begin
+  case varType(v0) of
+    varEmpty: result := false;
+    varNull: result := false;
+    varSingle: result := (Single(v0) <> 0.0);
+    varDouble: result := (Double(v0) <> 0.0);
+    varString: result := (Length(AnsiString(v0)) <> 0);
+    varBoolean: result := Boolean(v0);
+    varShortInt, varSmallint, varInteger, varByte, varWord, varLongWord: result := (LongInt(v0) <> 0);
+    varInt64: result := (Int64(v0) <> 0);
+    varQWord: result := (UInt64(v0) <> 0);
+    else begin result := false; error(); end;
+  end;
+end;
+
+class function TExprBase.toInt (var v: Variant): LongInt;
+begin
+  case varType(v) of
+    varSingle: result := trunc(Single(v));
+    varDouble: result := trunc(Double(v));
+    varBoolean: if Boolean(v) then result := 1 else result := 0;
+    varShortInt, varSmallint, varInteger, varByte, varWord, varLongWord: result := LongInt(v);
+    varInt64: result := LongInt(Int64(v));
+    else begin result := 0; TExprBase.error(); end;
+  end;
+end;
+
+procedure TExprBase.assign (scope: TExprScope; var v: Variant); begin error(); end;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
+constructor TExprStatList.Create (); begin mList := nil; end;
+destructor TExprStatList.Destroy (); var f: Integer; begin for f := 0 to High(mList) do mList[f].Free(); mList := nil; end;
+
+function TExprStatList.value (scope: TExprScope): Variant;
+var
+  f: Integer;
+begin
+  result := false;
+  for f := 0 to High(mList) do result := mList[f].value(scope);
+end;
+function TExprStatList.toString (): AnsiString;
+var
+  f: Integer;
+begin
+  result := '';
+  for f := 0 to High(mList) do result += mList[f].toString()+';';
+end;
+function TExprStatList.clone (): TExprBase;
+var
+  r: TExprStatList;
+  f: Integer;
+begin
+  r := TExprStatList.Create();
+  SetLength(r.mList, Length(mList));
+  for f := 0 to High(mList) do r.mList[f] := nil;
+  try
+    for f := 0 to High(mList) do r.mList[f] := mList[f].clone();
+  except
+    r.Free();
+  end;
+  result := r;
+end;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
+constructor TObjExpr.Create (const aval: AnsiString); begin mName := aval; end;
+function TObjExpr.value (scope: TExprScope): Variant; begin result := UInt64(PtrUInt(Pointer(scope.getObj(mName)))); end;
+function TObjExpr.toString (): AnsiString; begin result := mName; end;
+function TObjExpr.clone (): TExprBase; begin result := TObjExpr.Create(mName); end;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
+constructor TLitExpr.Create (aval: Boolean); begin mValue := aval; end;
+constructor TLitExpr.Create (aval: LongInt); begin mValue := aval; end;
+constructor TLitExpr.Create (const aval: AnsiString); begin mValue := aval; end;
+function TLitExpr.value (scope: TExprScope): Variant; begin result := mValue; end;
+function TLitExpr.toString (): AnsiString; begin result := VarToStr(mValue); end;
+function TLitExpr.clone (): TExprBase; begin result := TLitExpr.Create(0); (result as TLitExpr).mValue := mValue; end;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
+constructor TUnExpr.Create (aop0: TExprBase); begin mOp0 := aop0; end;
+destructor TUnExpr.Destroy (); begin mOp0.Free(); inherited; end;
+function TUnExpr.clone (): TExprBase; begin result := (self.ClassType.Create() as TUnExpr); (result as TUnExpr).mOp0 := mOp0.clone(); end;
+
+function TUnExprNeg.value (scope: TExprScope): Variant;
+begin
+  result := mOp0.value(scope);
+  case varType(result) of
+    varSingle: result := -Single(result);
+    varDouble: result := -Double(result);
+    varShortInt, varSmallInt, varInteger, varByte, varWord: result := -LongInt(result);
+    varInt64: result := -Int64(result);
+    varLongWord: result := -LongInt(result);
+    else error();
+  end;
+end;
+
+function TUnExprNeg.toString (): AnsiString; begin result := '-('+mOp0.toString()+')'; end;
+
+function TUnExprNot.value (scope: TExprScope): Variant;
+begin
+  result := mOp0.value(scope);
+  result := not coerce2bool(result);
+end;
+
+function TUnExprNot.toString (): AnsiString; begin result := '!('+mOp0.toString()+')'; end;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
+constructor TDotExpr.Create (aop0: TExprBase; const afield: AnsiString);
+begin
+  mOp0 := aop0;
+  mField := afield;
+end;
+
+function TDotExpr.value (scope: TExprScope): Variant;
+begin
+  result := mOp0.value(scope);
+  if (varType(result) <> varQWord) then error();
+  result := scope.getField(TObject(PtrUInt(UInt64(result))), mField);
+end;
+
+procedure TDotExpr.assign (scope: TExprScope; var v: Variant);
+var
+  o: Variant;
+begin
+  o := mOp0.value(scope);
+  if (varType(o) <> varQWord) then error();
+  scope.setField(TObject(PtrUInt(UInt64(o))), mField, v);
+end;
+
+function TDotExpr.clone (): TExprBase; begin result := TDotExpr.Create(mOp0, mField); end;
+
+function TDotExpr.toString (): AnsiString; begin result := mOp0.toString()+'.'+mField; end;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
+constructor TBinExpr.Create (aop0, aop1: TExprBase); begin mOp0 := aop0; mOp1 := aop1; end;
+destructor TBinExpr.Destroy (); begin mOp1.Free(); mOp0.Free(); inherited; end;
+function TBinExpr.clone (): TExprBase; begin result := (self.ClassType.Create() as TBinExpr); (result as TBinExpr).mOp0 := mOp0.clone(); (result as TBinExpr).mOp1 := mOp1.clone(); end;
+
+class procedure TBinExpr.coerce (var v0, v1: Variant);
+  function isFloat (var v: Variant): Boolean; inline;
+  begin
+    case varType(v) of
+      varSingle, varDouble: result := true;
+      else result := false;
+    end;
+  end;
+
+  function isInt (var v: Variant): Boolean; inline;
+  begin
+    case varType(v) of
+      varShortInt, varSmallint, varInteger, varByte, varWord, varLongWord: result := true;
+      else result := false;
+    end;
+  end;
+
+  function isBool (var v: Variant): Boolean; inline;
+  begin
+    result := (varType(v) = varBoolean);
+  end;
+
+  function isStr (var v: Variant): Boolean; inline;
+  begin
+    result := (varType(v) = varString);
+  end;
+
+begin
+  if (varType(v0) <> varType(v1)) then
+  begin
+    if isStr(v0) or isStr(v1) then
+    begin
+           if isFloat(v0) then v0 := formatstrf('%s', [Double(v0)])
+      else if isInt(v0) then v0 := formatstrf('%s', [LongInt(v0)])
+      else if isBool(v0) then v0 := formatstrf('%s', [Boolean(v0)])
+      else if isStr(v0) then begin end
+      else error();
+           if isFloat(v1) then v1 := formatstrf('%s', [Double(v1)])
+      else if isInt(v1) then v1 := formatstrf('%s', [LongInt(v1)])
+      else if isBool(v1) then v1 := formatstrf('%s', [Boolean(v1)])
+      else if isStr(v0) then begin end
+      else error();
+    end
+    else if isFloat(v0) or isFloat(v1) then
+    begin
+           if isFloat(v0) or isInt(v0) then v0 := Double(v0)
+      else if isBool(v0) then begin if Boolean(v0) then v0 := Double(1.0) else v0 := Double(0.0); end
+      else error();
+           if isFloat(v1) or isInt(v1) then v1 := Double(v1)
+      else if isBool(v1) then begin if Boolean(v1) then v1 := Double(1.0) else v1 := Double(0.0); end
+      else error();
+    end
+    else if isInt(v0) or isInt(v1) then
+    begin
+           if isBool(v0) then begin if Boolean(v0) then v0 := LongInt(1) else v0 := LongInt(0); end
+      else if isFloat(v0) then v0 := LongInt(trunc(Double(v0)))
+      else if isInt(v0) then begin end
+      else error();
+           if isBool(v1) then begin if Boolean(v1) then v1 := LongInt(1) else v1 := LongInt(0); end
+      else if isFloat(v1) then v1 := LongInt(trunc(Double(v1)))
+      else if isInt(v1) then begin end
+      else error();
+    end
+    else
+    begin
+      error();
+    end;
+  end;
+end;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
+function TBinExprAdd.value (scope: TExprScope): Variant;
+var
+  r1: Variant;
+begin
+  result := mOp0.value(scope);
+  r1 := mOp1.value(scope);
+  coerce(result, r1);
+  case varType(result) of
+    varSingle, varDouble: result := Double(result)+Double(r1);
+    varString: result := AnsiString(result)+AnsiString(r1);
+    varShortInt, varSmallint, varInteger, varByte, varWord, varLongWord: result := LongInt(result)+LongInt(r1);
+    varInt64: result := Int64(result)+Int64(r1);
+    else error();
+  end;
+end;
+function TBinExprAdd.toString (): AnsiString; begin result := '('+mOp0.toString()+'+'+mOp1.toString+')'; end;
+
+function TBinExprSub.value (scope: TExprScope): Variant;
+var
+  r1: Variant;
+begin
+  result := mOp0.value(scope);
+  r1 := mOp1.value(scope);
+  coerce(result, r1);
+  case varType(result) of
+    varSingle, varDouble: result := Double(result)-Double(r1);
+    varShortInt, varSmallint, varInteger, varByte, varWord, varLongWord: result := LongInt(result)-LongInt(r1);
+    varInt64: result := Int64(result)-Int64(r1);
+    else error();
+  end;
+end;
+function TBinExprSub.toString (): AnsiString; begin result := '('+mOp0.toString()+'-'+mOp1.toString+')'; end;
+
+function TBinExprMul.value (scope: TExprScope): Variant;
+var
+  r1: Variant;
+begin
+  result := mOp0.value(scope);
+  r1 := mOp1.value(scope);
+  coerce(result, r1);
+  case varType(result) of
+    varSingle, varDouble: result := Double(result)*Double(r1);
+    varShortInt, varSmallint, varInteger, varByte, varWord, varLongWord: result := LongInt(result)*LongInt(r1);
+    varInt64: result := Int64(result)*Int64(r1);
+    else error();
+  end;
+end;
+function TBinExprMul.toString (): AnsiString; begin result := '('+mOp0.toString()+'*'+mOp1.toString+')'; end;
+
+function TBinExprDiv.value (scope: TExprScope): Variant;
+var
+  r1: Variant;
+begin
+  result := mOp0.value(scope);
+  r1 := mOp1.value(scope);
+  coerce(result, r1);
+  case varType(result) of
+    varSingle, varDouble: result := Double(result)/Double(r1);
+    varShortInt, varSmallint, varInteger, varByte, varWord, varLongWord: result := LongInt(result) div LongInt(r1);
+    varInt64: result := Int64(result) div Int64(r1);
+    else error();
+  end;
+end;
+function TBinExprDiv.toString (): AnsiString; begin result := '('+mOp0.toString()+'/'+mOp1.toString+')'; end;
+
+function TBinExprMod.value (scope: TExprScope): Variant;
+var
+  r1: Variant;
+begin
+  result := mOp0.value(scope);
+  r1 := mOp1.value(scope);
+  coerce(result, r1);
+  case varType(result) of
+    varShortInt, varSmallint, varInteger, varByte, varWord, varLongWord: result := LongInt(result) mod LongInt(r1);
+    varInt64: result := Int64(result) mod Int64(r1);
+    else error();
+  end;
+end;
+function TBinExprMod.toString (): AnsiString; begin result := '('+mOp0.toString()+'%'+mOp1.toString+')'; end;
+
+function TBinExprLogAnd.value (scope: TExprScope): Variant;
+begin
+  result := mOp0.value(scope);
+  if not coerce2bool(result) then begin result := false; exit; end;
+  result := mOp1.value(scope);
+  result := coerce2bool(result);
+end;
+function TBinExprLogAnd.toString (): AnsiString; begin result := '('+mOp0.toString()+'&&'+mOp1.toString+')'; end;
+
+function TBinExprLogOr.value (scope: TExprScope): Variant;
+begin
+  result := mOp0.value(scope);
+  if coerce2bool(result) then begin result := true; exit; end;
+  result := mOp1.value(scope);
+  result := coerce2bool(result);
+end;
+function TBinExprLogOr.toString (): AnsiString; begin result := '('+mOp0.toString()+'||'+mOp1.toString+')'; end;
+
+function TBinExprCmpLess.value (scope: TExprScope): Variant;
+var
+  r1: Variant;
+begin
+  result := mOp0.value(scope);
+  r1 := mOp1.value(scope);
+  coerce(result, r1);
+  case varType(result) of
+    varSingle, varDouble: result := Boolean(Double(result) < Double(r1));
+    varShortInt, varSmallint, varInteger, varByte, varWord, varLongWord: result := Boolean(LongInt(result) < LongInt(r1));
+    varInt64: result := Boolean(Int64(result) < Int64(r1));
+    varString: result := Boolean(AnsiString(result) < AnsiString(r1));
+    else error();
+  end;
+end;
+function TBinExprCmpLess.toString (): AnsiString; begin result := '('+mOp0.toString()+'<'+mOp1.toString+')'; end;
+
+function TBinExprCmpGreat.value (scope: TExprScope): Variant;
+var
+  r1: Variant;
+begin
+  result := mOp0.value(scope);
+  r1 := mOp1.value(scope);
+  coerce(result, r1);
+  case varType(result) of
+    varSingle, varDouble: result := Boolean(Double(result) > Double(r1));
+    varShortInt, varSmallint, varInteger, varByte, varWord, varLongWord: result := Boolean(LongInt(result) > LongInt(r1));
+    varInt64: result := Boolean(Int64(result) > Int64(r1));
+    varString: result := Boolean(AnsiString(result) > AnsiString(r1));
+    else error();
+  end;
+end;
+function TBinExprCmpGreat.toString (): AnsiString; begin result := '('+mOp0.toString()+'>'+mOp1.toString+')'; end;
+
+function TBinExprCmpLessEqu.value (scope: TExprScope): Variant;
+var
+  r1: Variant;
+begin
+  result := mOp0.value(scope);
+  r1 := mOp1.value(scope);
+  coerce(result, r1);
+  case varType(result) of
+    varSingle, varDouble: result := Boolean(Double(result) <= Double(r1));
+    varShortInt, varSmallint, varInteger, varByte, varWord, varLongWord: result := Boolean(LongInt(result) <= LongInt(r1));
+    varInt64: result := Boolean(Int64(result) <= Int64(r1));
+    varString: result := Boolean(AnsiString(result) <= AnsiString(r1));
+    else error();
+  end;
+end;
+function TBinExprCmpLessEqu.toString (): AnsiString; begin result := '('+mOp0.toString()+'<='+mOp1.toString+')'; end;
+
+function TBinExprCmpGreatEqu.value (scope: TExprScope): Variant;
+var
+  r1: Variant;
+begin
+  result := mOp0.value(scope);
+  r1 := mOp1.value(scope);
+  coerce(result, r1);
+  case varType(result) of
+    varSingle, varDouble: result := Boolean(Double(result) >= Double(r1));
+    varShortInt, varSmallint, varInteger, varByte, varWord, varLongWord: result := Boolean(LongInt(result) >= LongInt(r1));
+    varInt64: result := Boolean(Int64(result) >= Int64(r1));
+    varString: result := Boolean(AnsiString(result) >= AnsiString(r1));
+    else error();
+  end;
+end;
+function TBinExprCmpGreatEqu.toString (): AnsiString; begin result := '('+mOp0.toString()+'>='+mOp1.toString+')'; end;
+
+function TBinExprCmpEqu.value (scope: TExprScope): Variant;
+var
+  r1: Variant;
+begin
+  result := mOp0.value(scope);
+  r1 := mOp1.value(scope);
+  coerce(result, r1);
+  case varType(result) of
+    varSingle, varDouble: result := Boolean(Double(result) = Double(r1));
+    varShortInt, varSmallint, varInteger, varByte, varWord, varLongWord: result := Boolean(LongInt(result) = LongInt(r1));
+    varInt64: result := Boolean(Int64(result) = Int64(r1));
+    varString: result := Boolean(AnsiString(result) = AnsiString(r1));
+    varBoolean: result := (Boolean(result) = Boolean(r1));
+    varQWord: result := (UInt64(result) = UInt64(r1));
+    else error();
+  end;
+end;
+function TBinExprCmpEqu.toString (): AnsiString; begin result := '('+mOp0.toString()+'=='+mOp1.toString+')'; end;
+
+function TBinExprCmpNotEqu.value (scope: TExprScope): Variant;
+var
+  r1: Variant;
+begin
+  result := mOp0.value(scope);
+  r1 := mOp1.value(scope);
+  coerce(result, r1);
+  case varType(result) of
+    varSingle, varDouble: result := Boolean(Double(result) <> Double(r1));
+    varShortInt, varSmallint, varInteger, varByte, varWord, varLongWord: result := Boolean(LongInt(result) <> LongInt(r1));
+    varInt64: result := Boolean(Int64(result) <> Int64(r1));
+    varString: result := Boolean(AnsiString(result) <> AnsiString(r1));
+    varBoolean: result := (Boolean(result) <> Boolean(r1));
+    varQWord: result := (UInt64(result) <> UInt64(r1));
+    else error();
+  end;
+end;
+function TBinExprCmpNotEqu.toString (): AnsiString; begin result := '('+mOp0.toString()+'<>'+mOp1.toString+')'; end;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
+function TBinAssign.value (scope: TExprScope): Variant;
+begin
+  result := mOp1.value(scope);
+  mOp0.assign(scope, result);
+end;
+
+function TBinAssign.toString (): AnsiString; begin result := mOp0.toString()+'='+mOp1.toString(); end;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
+class function TExprBase.parse (const str: AnsiString; allowAssign: Boolean=false): TExprBase;
+var
+  pr: TTextParser;
+begin
+  pr := TStrTextParser.Create(str);
+  try
+    result := parse(pr, allowAssign);
+    if (pr.tokType <> pr.TTEOF) then begin result.Free(); error(); end;
+  finally
+    pr.Free();
+  end;
+end;
+
+class function TExprBase.parseStatList (const str: AnsiString): TExprBase;
+var
+  pr: TTextParser;
+  r: TExprStatList;
+  e: TExprBase;
+begin
+  pr := TStrTextParser.Create(str);
+  if (pr.tokType = pr.TTEOF) then begin pr.Free(); result := nil; exit; end;
+  r := TExprStatList.Create();
+  result := nil;
+  try
+    while true do
+    begin
+      while pr.eatTT(pr.TTSemi) do begin end;
+      if (pr.tokType = pr.TTEOF) then break;
+      e := parse(pr, true);
+      if (e = nil) then break;
+      SetLength(r.mList, Length(r.mList)+1);
+      r.mList[High(r.mList)] := e;
+      if (pr.tokType = pr.TTEOF) then break;
+      pr.expectTT(pr.TTSemi);
+    end;
+    result := r;
+    r := nil;
+  finally
+    r.Free();
+    pr.Free();
+  end;
+end;
+
+
+class function TExprBase.parse (pr: TTextParser; allowAssign: Boolean=false): TExprBase;
+
+  function expr (): TExprBase; forward;
+
+  function doTerm (): TExprBase;
+  begin
+    result := nil;
+    try
+      if pr.eatDelim('(') then begin result := expr(); pr.expectDelim(')'); exit; end;
+      if pr.eatDelim('!') then begin result := expr(); result := TUnExprNot.Create(result); exit; end;
+      if pr.eatDelim('-') then begin result := expr(); result := TUnExprNeg.Create(result); exit; end;
+      if pr.eatDelim('+') then begin result := expr(); exit; end;
+      if (pr.tokType = pr.TTInt) then begin result := TLitExpr.Create(pr.expectInt()); exit; end;
+      if (pr.tokType = pr.TTStr) then begin result := TLitExpr.Create(pr.expectStr(true)); exit; end;
+      if (pr.tokType = pr.TTId) then
+      begin
+        if (pr.tokStr = 'true') then begin result := TLitExpr.Create(true); pr.skipToken(); exit; end;
+        if (pr.tokStr = 'false') then begin result := TLitExpr.Create(false); pr.skipToken(); exit; end;
+        if (CompareText(pr.tokStr, 'true') = 0) or (CompareText(pr.tokStr, 'false') = 0) then error();
+        result := TObjExpr.Create(pr.expectId());
+        while (pr.tokType = pr.TTDelim) and (pr.tokChar = '.') do
+        begin
+          pr.skipToken();
+          result := TDotExpr.Create(result, pr.expectId());
+        end;
+        exit;
+      end;
+    except
+      result.Free();
+      raise;
+    end;
+    error();
+  end;
+
+  function doMulDiv (): TExprBase;
+  begin
+    result := doTerm();
+    try
+      while true do
+      begin
+             if pr.eatDelim('*') then result := TBinExprMul.Create(result, doTerm())
+        else if pr.eatDelim('/') then result := TBinExprDiv.Create(result, doTerm())
+        else if pr.eatDelim('%') then result := TBinExprMod.Create(result, doTerm())
+        else break;
+      end;
+    except
+      result.Free();
+      raise;
+    end;
+  end;
+
+  function doPlusMinus (): TExprBase;
+  begin
+    result := doMulDiv();
+    try
+      while true do
+      begin
+             if pr.eatDelim('+') then result := TBinExprAdd.Create(result, doMulDiv())
+        else if pr.eatDelim('-') then result := TBinExprSub.Create(result, doMulDiv())
+        else break;
+      end;
+    except
+      result.Free();
+      raise;
+    end;
+  end;
+
+  function doCmp (): TExprBase;
+  begin
+    result := doPlusMinus();
+    try
+      while true do
+      begin
+             if pr.eatDelim('<') then result := TBinExprCmpLess.Create(result, doPlusMinus())
+        else if pr.eatDelim('>') then result := TBinExprCmpGreat.Create(result, doPlusMinus())
+        else if pr.eatTT(pr.TTLessEqu) then result := TBinExprCmpLessEqu.Create(result, doPlusMinus())
+        else if pr.eatTT(pr.TTGreatEqu) then result := TBinExprCmpGreatEqu.Create(result, doPlusMinus())
+        else break;
+      end;
+    except
+      result.Free();
+      raise;
+    end;
+  end;
+
+  function doCmpEqu (): TExprBase;
+  begin
+    result := doCmp();
+    try
+      while true do
+      begin
+             if pr.eatTT(pr.TTEqu) then result := TBinExprCmpEqu.Create(result, doCmp())
+        else if pr.eatTT(pr.TTNotEqu) then result := TBinExprCmpNotEqu.Create(result, doCmp())
+        else break;
+      end;
+    except
+      result.Free();
+      raise;
+    end;
+  end;
+
+  function doLogAnd (): TExprBase;
+  begin
+    result := doCmpEqu();
+    try
+      while true do
+      begin
+        if pr.eatTT(pr.TTLogAnd) then result := TBinExprLogAnd.Create(result, doCmpEqu()) else break;
+      end;
+    except
+      result.Free();
+      raise;
+    end;
+  end;
+
+  function doLogOr (): TExprBase;
+  begin
+    result := doLogAnd();
+    try
+      while true do
+      begin
+        if pr.eatTT(pr.TTLogOr) then result := TBinExprLogOr.Create(result, doLogAnd()) else break;
+      end;
+    except
+      result.Free();
+      raise;
+    end;
+  end;
+
+  // funcall, [], dot
+  // !, ~
+  // *, /, %
+  // +, -
+  // <<, >>
+  // <, <=, >, >=
+  // ==, !=
+  // &
+  // ^
+  // |
+  // &&
+  // ||
+
+  function expr (): TExprBase;
+  var
+    neg: Boolean = false;
+  begin
+         if pr.eatDelim('-') then neg := true
+    else if pr.eatDelim('+') then neg := false;
+    result := doLogOr();
+    if neg then result := TUnExprNeg.Create(result);
+  end;
+
+var
+  oas: Boolean;
+begin
+  if (pr = nil) or (pr.tokType = pr.TTEOF) then begin result := nil; exit; end;
+  oas := pr.allowSignedNumbers;
+  pr.allowSignedNumbers := false;
+  try
+    result := expr();
+    if allowAssign and pr.eatDelim('=') then
+    try
+      result := TBinAssign.Create(result, expr());
+    except
+      result.Free();
+    end;
+  finally
+    pr.allowSignedNumbers := oas;
+  end;
+end;
+
+
+{
+    varEmpty:
+    varNull:
+    varSingle:
+    varDouble:
+    varDecimal:
+    varCurrency:
+    varDate:
+    varOleStr:
+    varStrArg:
+    varString:
+    varDispatch:
+    varBoolean:
+    varVariant:
+    varUnknown:
+    varShortInt:
+    varSmallint:
+    varInteger:
+    varInt64:
+    varByte:
+    varWord:
+    varLongWord:
+    varQWord:
+    varError:
+}
+end.
index 8aaa522a45bae64530243a8fa031f42b4b035b4f..fa6ec85f4c7d6d9e14a58298c3e0450275c72463 100644 (file)
@@ -54,6 +54,8 @@ type
     type
       TEntryArray = array of TEntry;
 
+  public
+    type
       TValEnumerator = record
       private
         mEntries: TEntryArray;
@@ -62,6 +64,7 @@ type
         constructor Create (const aents: TEntryArray; afirst, alast: Integer);
         function MoveNext (): Boolean; inline;
         function getCurrent (): ValueT; inline;
+        function GetEnumerator (): TValEnumerator; inline;
         property Current: ValueT read getCurrent;
       end;
 
@@ -73,6 +76,7 @@ type
         constructor Create (const aents: TEntryArray; afirst, alast: Integer);
         function MoveNext (): Boolean; inline;
         function getCurrent (): KeyT; inline;
+        function GetEnumerator (): TKeyEnumerator; inline;
         property Current: KeyT read getCurrent;
       end;
 
@@ -84,6 +88,7 @@ type
         constructor Create (const aents: TEntryArray; afirst, alast: Integer);
         function MoveNext (): Boolean; inline;
         function getCurrent (): PEntry; inline;
+        function GetEnumerator (): TKeyValEnumerator; inline;
         property Current: PEntry read getCurrent;
       end;
 
@@ -959,6 +964,11 @@ begin
 end;
 
 
+function THashBase.TValEnumerator.GetEnumerator (): TValEnumerator; inline; begin result.mEntries := self.mEntries; result.mFirstEntry := self.mFirstEntry; result.mLastEntry := self.mLastEntry; result.cur := self.cur; end;
+function THashBase.TKeyEnumerator.GetEnumerator (): TKeyEnumerator; inline; begin result.mEntries := self.mEntries; result.mFirstEntry := self.mFirstEntry; result.mLastEntry := self.mLastEntry; result.cur := self.cur; end;
+function THashBase.TKeyValEnumerator.GetEnumerator (): TKeyValEnumerator; inline; begin result.mEntries := self.mEntries; result.mFirstEntry := self.mFirstEntry; result.mLastEntry := self.mLastEntry; result.cur := self.cur; end;
+
+
 // ////////////////////////////////////////////////////////////////////////// //
 constructor THashBase.TValEnumerator.Create (const aents: TEntryArray; afirst, alast: Integer);
 begin
index 2e457b6c1da2b7e49cd59c8cafba82e1059a6f39..1fe1c0363f03904daafb1d02382ec3bc5a79f2e8 100644 (file)
@@ -483,566 +483,584 @@ const defaultMapDef: AnsiString = ''+
   #116#114#105#103#103#101#114#100#97#116#97#34#32#116#121#112#101#32#116#114+
   #105#103#100#97#116#97#91#49#50#56#93#32#111#102#102#115#101#116#32#50#48#59+
   #32#47#47#32#116#104#101#32#111#110#108#121#32#115#112#101#99#105#97#108#32+
-  #110#101#115#116#101#100#32#115#116#114#117#99#116#117#114#101#10#125#10#10+
-  #10#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47+
+  #110#101#115#116#101#100#32#115#116#114#117#99#116#117#114#101#10#32#32#47+
+  #47#68#79#32#78#79#84#32#85#83#69#33#32#101#120#112#101#114#105#109#101#110+
+  #116#97#108#32#102#101#97#116#117#114#101#33#32#119#105#108#108#32#98#101#32+
+  #114#101#109#111#118#101#100#33#10#32#32#34#101#120#111#109#97#95#105#110+
+  #105#116#34#32#116#121#112#101#32#115#116#114#105#110#103#32#100#101#102#97+
+  #117#108#116#32#34#34#32#116#105#112#32#34#119#105#108#108#32#98#101#32#99+
+  #97#108#108#101#100#32#111#110#32#116#114#105#103#103#101#114#32#99#114#101+
+  #97#116#105#111#110#34#59#10#32#32#34#101#120#111#109#97#95#116#104#105#110+
+  #107#34#32#116#121#112#101#32#115#116#114#105#110#103#32#100#101#102#97#117+
+  #108#116#32#34#34#32#116#105#112#32#34#119#105#108#108#32#98#101#32#99#97+
+  #108#108#101#100#32#111#110#32#101#97#99#104#32#116#104#105#110#107#32#115+
+  #116#101#112#34#59#10#32#32#34#101#120#111#109#97#95#99#104#101#99#107#34#32+
+  #116#121#112#101#32#115#116#114#105#110#103#32#100#101#102#97#117#108#116#32+
+  #34#34#32#116#105#112#32#34#119#105#108#108#32#98#101#32#99#97#108#108#101+
+  #100#32#98#101#102#111#114#101#32#97#99#116#105#118#97#116#105#111#110#34#59+
+  #10#32#32#34#101#120#111#109#97#95#97#99#116#105#111#110#34#32#116#121#112+
+  #101#32#115#116#114#105#110#103#32#100#101#102#97#117#108#116#32#34#34#32+
+  #116#105#112#32#34#119#105#108#108#32#98#101#32#99#97#108#108#101#100#32#111+
+  #110#32#97#99#116#105#118#97#116#105#111#110#34#59#10#125#10#10#10#47#47#47+
   #47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47+
   #47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47+
-  #47#47#47#47#47#47#10#47#47#32#115#112#101#99#105#97#108#32#116#101#120#116+
-  #117#114#101#32#105#100#101#110#116#105#102#105#101#114#115#44#32#117#115+
-  #101#100#32#116#111#32#103#101#110#101#114#97#116#101#32#112#97#115#99#97+
-  #108#32#115#111#117#114#99#101#115#10#101#110#117#109#32#84#101#120#116#117+
-  #114#101#83#112#101#99#105#97#108#32#123#10#32#32#84#69#88#84#85#82#69#95#83+
-  #80#69#67#73#65#76#95#87#65#84#69#82#32#61#32#45#49#44#10#32#32#84#69#88#84+
-  #85#82#69#95#83#80#69#67#73#65#76#95#65#67#73#68#49#32#61#32#45#50#44#10#32+
-  #32#84#69#88#84#85#82#69#95#83#80#69#67#73#65#76#95#65#67#73#68#50#32#61#32+
-  #45#51#44#10#32#32#84#69#88#84#85#82#69#95#78#79#78#69#32#61#32#45#52#44#10+
-  #125#10#10#47#47#32#100#105#114#101#99#116#105#111#110#115#10#101#110#117+
-  #109#32#68#105#114#84#121#112#101#32#123#10#32#32#68#73#82#95#76#69#70#84#44+
-  #32#47#47#32#48#10#32#32#68#73#82#95#82#73#71#72#84#44#32#47#47#32#49#10#32+
-  #32#68#73#82#95#83#79#77#69#84#72#73#78#71#50#44#32#47#47#32#50#10#125#10#10+
-  #47#47#32#116#114#105#103#103#101#114#115#10#101#110#117#109#32#84#114#105+
-  #103#103#101#114#84#121#112#101#32#123#10#32#32#84#82#73#71#71#69#82#95#78+
-  #79#78#69#44#32#47#47#32#48#10#32#32#84#82#73#71#71#69#82#95#69#88#73#84#44+
-  #32#47#47#32#49#10#32#32#84#82#73#71#71#69#82#95#84#69#76#69#80#79#82#84#44+
-  #32#47#47#32#50#10#32#32#84#82#73#71#71#69#82#95#79#80#69#78#68#79#79#82#44+
-  #32#47#47#32#51#10#32#32#84#82#73#71#71#69#82#95#67#76#79#83#69#68#79#79#82+
-  #44#32#47#47#32#52#10#32#32#84#82#73#71#71#69#82#95#68#79#79#82#44#32#47#47+
-  #32#53#10#32#32#84#82#73#71#71#69#82#95#68#79#79#82#53#44#32#47#47#32#54#10+
-  #32#32#84#82#73#71#71#69#82#95#67#76#79#83#69#84#82#65#80#44#32#47#47#32#55+
-  #10#32#32#84#82#73#71#71#69#82#95#84#82#65#80#44#32#47#47#32#56#10#32#32#84+
-  #82#73#71#71#69#82#95#80#82#69#83#83#44#32#47#47#32#57#10#32#32#84#82#73#71+
-  #71#69#82#95#83#69#67#82#69#84#44#32#47#47#32#49#48#10#32#32#84#82#73#71#71+
-  #69#82#95#76#73#70#84#85#80#44#32#47#47#32#49#49#10#32#32#84#82#73#71#71#69+
-  #82#95#76#73#70#84#68#79#87#78#44#32#47#47#32#49#50#10#32#32#84#82#73#71#71+
-  #69#82#95#76#73#70#84#44#32#47#47#32#49#51#10#32#32#84#82#73#71#71#69#82#95+
-  #84#69#88#84#85#82#69#44#32#47#47#32#49#52#10#32#32#84#82#73#71#71#69#82#95+
-  #79#78#44#32#47#47#32#49#53#10#32#32#84#82#73#71#71#69#82#95#79#70#70#44#32+
-  #47#47#32#49#54#10#32#32#84#82#73#71#71#69#82#95#79#78#79#70#70#44#32#47#47+
-  #32#49#55#10#32#32#84#82#73#71#71#69#82#95#83#79#85#78#68#44#32#47#47#32#49+
-  #56#10#32#32#84#82#73#71#71#69#82#95#83#80#65#87#78#77#79#78#83#84#69#82#44+
-  #32#47#47#32#49#57#10#32#32#84#82#73#71#71#69#82#95#83#80#65#87#78#73#84#69+
-  #77#44#32#47#47#32#50#48#10#32#32#84#82#73#71#71#69#82#95#77#85#83#73#67#44+
-  #32#47#47#32#50#49#10#32#32#84#82#73#71#71#69#82#95#80#85#83#72#44#32#47#47+
-  #32#50#50#10#32#32#84#82#73#71#71#69#82#95#83#67#79#82#69#44#32#47#47#32#50+
-  #51#10#32#32#84#82#73#71#71#69#82#95#77#69#83#83#65#71#69#44#32#47#47#32#50+
-  #52#10#32#32#84#82#73#71#71#69#82#95#68#65#77#65#71#69#44#32#47#47#32#50#53+
-  #10#32#32#84#82#73#71#71#69#82#95#72#69#65#76#84#72#44#32#47#47#32#50#54#10+
-  #32#32#84#82#73#71#71#69#82#95#83#72#79#84#44#32#47#47#32#50#55#10#32#32#84+
-  #82#73#71#71#69#82#95#69#70#70#69#67#84#44#32#47#47#32#50#56#10#32#32#84#82+
-  #73#71#71#69#82#95#83#67#82#73#80#84#44#32#47#47#32#50#57#10#32#32#47#47#10+
-  #32#32#84#82#73#71#71#69#82#95#77#65#88#32#61#32#77#65#88#44#10#125#10#10#47+
-  #47#32#34#97#115#32#88#88#88#34#32#109#101#97#110#115#32#34#103#101#110#101+
-  #114#97#116#101#32#116#104#105#115#32#105#100#101#110#116#105#102#105#101+
-  #114#32#102#111#114#32#112#97#115#99#97#108#32#115#111#117#114#99#101#115#10+
-  #98#105#116#115#101#116#32#80#97#110#101#108#84#121#112#101#32#123#10#32#32+
-  #80#65#78#69#76#95#78#79#78#69#32#61#32#48#44#32#47#47#32#48#10#32#32#80#65+
-  #78#69#76#95#87#65#76#76#44#32#47#47#32#49#10#32#32#80#65#78#69#76#95#66#65+
-  #67#75#44#32#47#47#32#50#10#32#32#80#65#78#69#76#95#70#79#82#69#44#32#47#47+
-  #32#52#10#32#32#80#65#78#69#76#95#87#65#84#69#82#44#32#47#47#32#56#10#32#32+
-  #80#65#78#69#76#95#65#67#73#68#49#44#32#47#47#32#49#54#10#32#32#80#65#78#69+
-  #76#95#65#67#73#68#50#44#32#47#47#32#51#50#10#32#32#80#65#78#69#76#95#83#84+
-  #69#80#44#32#47#47#32#54#52#10#32#32#80#65#78#69#76#95#76#73#70#84#85#80#44+
-  #32#47#47#32#49#50#56#10#32#32#80#65#78#69#76#95#76#73#70#84#68#79#87#78#44+
-  #32#47#47#32#50#53#54#10#32#32#80#65#78#69#76#95#79#80#69#78#68#79#79#82#44+
-  #32#47#47#32#53#49#50#10#32#32#80#65#78#69#76#95#67#76#79#83#69#68#79#79#82+
-  #44#32#47#47#32#49#48#50#52#10#32#32#80#65#78#69#76#95#66#76#79#67#75#77#79+
-  #78#44#32#47#47#32#50#48#52#56#10#32#32#80#65#78#69#76#95#76#73#70#84#76#69+
-  #70#84#44#32#47#47#32#52#48#57#54#10#32#32#80#65#78#69#76#95#76#73#70#84#82+
-  #73#71#72#84#44#32#47#47#32#56#49#57#50#10#125#10#10#98#105#116#115#101#116+
-  #32#80#97#110#101#108#70#108#97#103#32#123#10#32#32#80#65#78#69#76#95#70#76+
-  #65#71#95#78#79#78#69#32#61#32#48#44#32#47#47#32#48#10#32#32#80#65#78#69#76+
-  #95#70#76#65#71#95#66#76#69#78#68#73#78#71#44#32#47#47#32#49#10#32#32#80#65+
-  #78#69#76#95#70#76#65#71#95#72#73#68#69#44#32#47#47#32#50#10#32#32#80#65#78+
-  #69#76#95#70#76#65#71#95#87#65#84#69#82#84#69#88#84#85#82#69#83#44#32#47#47+
-  #32#52#10#125#10#10#101#110#117#109#32#69#102#102#101#99#116#65#99#116#105+
-  #111#110#32#123#10#32#32#69#70#70#69#67#84#95#78#79#78#69#44#32#47#47#32#48+
-  #10#32#32#69#70#70#69#67#84#95#84#69#76#69#80#79#82#84#44#32#47#47#32#49#10+
-  #32#32#69#70#70#69#67#84#95#82#69#83#80#65#87#78#44#32#47#47#32#50#10#32#32+
-  #69#70#70#69#67#84#95#70#73#82#69#44#32#47#47#32#51#10#125#10#10#101#110#117+
-  #109#32#73#116#101#109#32#123#10#32#32#73#84#69#77#95#78#79#78#69#44#32#47+
-  #47#32#48#10#32#32#73#84#69#77#95#77#69#68#75#73#84#95#83#77#65#76#76#44#32+
-  #47#47#32#49#10#32#32#73#84#69#77#95#77#69#68#75#73#84#95#76#65#82#71#69#44+
-  #32#47#47#32#50#10#32#32#73#84#69#77#95#77#69#68#75#73#84#95#66#76#65#67#75+
-  #44#32#47#47#32#51#10#32#32#73#84#69#77#95#65#82#77#79#82#95#71#82#69#69#78+
-  #44#32#47#47#32#52#10#32#32#73#84#69#77#95#65#82#77#79#82#95#66#76#85#69#44+
-  #32#47#47#32#53#10#32#32#73#84#69#77#95#83#80#72#69#82#69#95#66#76#85#69#44+
-  #32#47#47#32#54#10#32#32#73#84#69#77#95#83#80#72#69#82#69#95#87#72#73#84#69+
-  #44#32#47#47#32#55#10#32#32#73#84#69#77#95#83#85#73#84#44#32#47#47#32#56#10+
-  #32#32#73#84#69#77#95#79#88#89#71#69#78#44#32#47#47#32#57#10#32#32#73#84#69+
-  #77#95#73#78#86#85#76#44#32#47#47#32#49#48#10#32#32#73#84#69#77#95#87#69#65+
-  #80#79#78#95#83#65#87#44#32#47#47#32#49#49#10#32#32#73#84#69#77#95#87#69#65+
-  #80#79#78#95#83#72#79#84#71#85#78#49#44#32#47#47#32#49#50#10#32#32#73#84#69+
-  #77#95#87#69#65#80#79#78#95#83#72#79#84#71#85#78#50#44#32#47#47#32#49#51#10+
-  #32#32#73#84#69#77#95#87#69#65#80#79#78#95#67#72#65#73#78#71#85#78#44#32#47+
-  #47#32#49#52#10#32#32#73#84#69#77#95#87#69#65#80#79#78#95#82#79#67#75#69#84+
-  #76#65#85#78#67#72#69#82#44#32#47#47#32#49#53#10#32#32#73#84#69#77#95#87#69+
-  #65#80#79#78#95#80#76#65#83#77#65#44#32#47#47#32#49#54#10#32#32#73#84#69#77+
-  #95#87#69#65#80#79#78#95#66#70#71#44#32#47#47#32#49#55#10#32#32#73#84#69#77+
-  #95#87#69#65#80#79#78#95#83#85#80#69#82#80#85#76#69#77#69#84#44#32#47#47#32+
-  #49#56#10#32#32#73#84#69#77#95#65#77#77#79#95#66#85#76#76#69#84#83#44#32#47+
-  #47#32#49#57#10#32#32#73#84#69#77#95#65#77#77#79#95#66#85#76#76#69#84#83#95+
-  #66#79#88#44#32#47#47#32#50#48#10#32#32#73#84#69#77#95#65#77#77#79#95#83#72+
-  #69#76#76#83#44#32#47#47#32#50#49#10#32#32#73#84#69#77#95#65#77#77#79#95#83+
-  #72#69#76#76#83#95#66#79#88#44#32#47#47#32#50#50#10#32#32#73#84#69#77#95#65+
-  #77#77#79#95#82#79#67#75#69#84#44#32#47#47#32#50#51#10#32#32#73#84#69#77#95+
-  #65#77#77#79#95#82#79#67#75#69#84#95#66#79#88#44#32#47#47#32#50#52#10#32#32+
-  #73#84#69#77#95#65#77#77#79#95#67#69#76#76#44#32#47#47#32#50#53#10#32#32#73+
-  #84#69#77#95#65#77#77#79#95#67#69#76#76#95#66#73#71#44#32#47#47#32#50#54#10+
-  #32#32#73#84#69#77#95#65#77#77#79#95#66#65#67#75#80#65#67#75#44#32#47#47#32+
-  #50#55#10#32#32#73#84#69#77#95#75#69#89#95#82#69#68#44#32#47#47#32#50#56#10+
-  #32#32#73#84#69#77#95#75#69#89#95#71#82#69#69#78#44#32#47#47#32#50#57#10#32+
-  #32#73#84#69#77#95#75#69#89#95#66#76#85#69#44#32#47#47#32#51#48#10#32#32#73+
-  #84#69#77#95#87#69#65#80#79#78#95#75#65#83#84#69#84#44#32#47#47#32#51#49#10+
-  #32#32#73#84#69#77#95#87#69#65#80#79#78#95#80#73#83#84#79#76#44#32#47#47#32+
-  #51#50#10#32#32#73#84#69#77#95#66#79#84#84#76#69#44#32#47#47#32#51#51#10#32+
-  #32#73#84#69#77#95#72#69#76#77#69#84#44#32#47#47#32#51#52#10#32#32#73#84#69+
-  #77#95#74#69#84#80#65#67#75#44#32#47#47#32#51#53#10#32#32#73#84#69#77#95#73+
-  #78#86#73#83#44#32#47#47#32#51#54#10#32#32#73#84#69#77#95#87#69#65#80#79#78+
-  #95#70#76#65#77#69#84#72#82#79#87#69#82#44#32#47#47#32#51#55#10#32#32#73#84+
-  #69#77#95#65#77#77#79#95#70#85#69#76#67#65#78#44#32#47#47#32#51#56#10#32#32+
-  #47#47#10#32#32#73#84#69#77#95#77#65#88#32#61#32#77#65#88#44#32#47#47#32#115+
-  #116#111#114#101#32#116#104#101#32#108#97#115#116#32#105#116#101#109#39#115+
-  #32#105#100#32#105#110#32#104#101#114#101#32#117#115#101#32#116#104#105#115+
-  #32#105#110#32#102#111#114#32#108#111#111#112#115#10#125#10#10#98#105#116+
-  #115#101#116#32#73#116#101#109#79#112#116#105#111#110#32#123#10#32#32#73#84+
-  #69#77#95#79#80#84#73#79#78#95#78#79#78#69#32#61#32#48#44#32#47#47#32#48#10+
-  #32#32#73#84#69#77#95#79#80#84#73#79#78#95#79#78#76#89#68#77#44#32#47#47#32+
-  #49#10#32#32#73#84#69#77#95#79#80#84#73#79#78#95#70#65#76#76#44#32#47#47#32+
-  #50#10#125#10#10#101#110#117#109#32#65#114#101#97#84#121#112#101#32#123#10+
-  #32#32#65#82#69#65#95#78#79#78#69#44#32#47#47#32#48#10#32#32#65#82#69#65#95+
-  #80#76#65#89#69#82#80#79#73#78#84#49#44#32#47#47#32#49#10#32#32#65#82#69#65+
-  #95#80#76#65#89#69#82#80#79#73#78#84#50#44#32#47#47#32#50#10#32#32#65#82#69+
-  #65#95#68#77#80#79#73#78#84#44#32#47#47#32#51#10#32#32#65#82#69#65#95#82#69+
-  #68#70#76#65#71#44#32#47#47#32#52#10#32#32#65#82#69#65#95#66#76#85#69#70#76+
-  #65#71#44#32#47#47#32#53#10#32#32#65#82#69#65#95#68#79#77#70#76#65#71#44#32+
-  #47#47#32#54#10#32#32#65#82#69#65#95#82#69#68#84#69#65#77#80#79#73#78#84#44+
-  #32#47#47#32#55#10#32#32#65#82#69#65#95#66#76#85#69#84#69#65#77#80#79#73#78+
-  #84#44#32#47#47#32#56#10#125#10#10#101#110#117#109#32#77#111#110#115#116#101+
-  #114#32#123#10#32#32#77#79#78#83#84#69#82#95#78#79#78#69#44#32#47#47#32#48+
-  #10#32#32#77#79#78#83#84#69#82#95#68#69#77#79#78#44#32#47#47#32#49#10#32#32+
-  #77#79#78#83#84#69#82#95#73#77#80#44#32#47#47#32#50#10#32#32#77#79#78#83#84+
-  #69#82#95#90#79#77#66#89#44#32#47#47#32#51#10#32#32#77#79#78#83#84#69#82#95+
-  #83#69#82#71#44#32#47#47#32#52#10#32#32#77#79#78#83#84#69#82#95#67#89#66#69+
-  #82#44#32#47#47#32#53#10#32#32#77#79#78#83#84#69#82#95#67#71#85#78#44#32#47+
-  #47#32#54#10#32#32#77#79#78#83#84#69#82#95#66#65#82#79#78#44#32#47#47#32#55+
-  #10#32#32#77#79#78#83#84#69#82#95#75#78#73#71#72#84#44#32#47#47#32#56#10#32+
-  #32#77#79#78#83#84#69#82#95#67#65#67#79#44#32#47#47#32#57#10#32#32#77#79#78+
-  #83#84#69#82#95#83#79#85#76#44#32#47#47#32#49#48#10#32#32#77#79#78#83#84#69+
-  #82#95#80#65#73#78#44#32#47#47#32#49#49#10#32#32#77#79#78#83#84#69#82#95#83+
-  #80#73#68#69#82#44#32#47#47#32#49#50#10#32#32#77#79#78#83#84#69#82#95#66#83+
-  #80#44#32#47#47#32#49#51#10#32#32#77#79#78#83#84#69#82#95#77#65#78#67#85#66+
-  #44#32#47#47#32#49#52#10#32#32#77#79#78#83#84#69#82#95#83#75#69#76#44#32#47+
-  #47#32#49#53#10#32#32#77#79#78#83#84#69#82#95#86#73#76#69#44#32#47#47#32#49+
-  #54#10#32#32#77#79#78#83#84#69#82#95#70#73#83#72#44#32#47#47#32#49#55#10#32+
-  #32#77#79#78#83#84#69#82#95#66#65#82#82#69#76#44#32#47#47#32#49#56#10#32#32+
-  #77#79#78#83#84#69#82#95#82#79#66#79#44#32#47#47#32#49#57#10#32#32#77#79#78+
-  #83#84#69#82#95#77#65#78#44#32#47#47#32#50#48#10#32#32#47#47#32#97#108#105+
-  #97#115#101#115#32#40#102#105#120#109#101#58#32#105#116#32#115#104#111#117+
-  #108#100#32#98#101#32#96#77#79#78#83#84#69#82#95#90#79#77#66#73#69#32#61#32+
-  #77#79#78#83#84#69#82#95#90#79#77#66#89#96#33#41#10#32#32#77#79#78#83#84#69+
-  #82#95#90#79#77#66#73#69#32#61#32#51#44#10#125#10#10#101#110#117#109#32#77+
-  #111#110#115#116#101#114#66#101#104#97#118#105#111#117#114#32#123#10#32#32+
-  #66#72#95#78#79#82#77#65#76#44#32#47#47#32#48#10#32#32#66#72#95#75#73#76#76+
-  #69#82#44#32#47#47#32#49#10#32#32#66#72#95#77#65#78#73#65#67#44#32#47#47#32+
-  #50#10#32#32#66#72#95#73#78#83#65#78#69#44#32#47#47#32#51#10#32#32#66#72#95+
-  #67#65#78#78#73#66#65#76#44#32#47#47#32#52#10#32#32#66#72#95#71#79#79#68#44+
-  #32#47#47#32#53#10#125#10#10#101#110#117#109#32#84#114#105#103#103#101#114+
-  #83#104#111#116#32#123#10#32#32#84#82#73#71#71#69#82#95#83#72#79#84#95#80#73+
-  #83#84#79#76#44#32#47#47#32#48#10#32#32#84#82#73#71#71#69#82#95#83#72#79#84+
-  #95#66#85#76#76#69#84#44#32#47#47#32#49#10#32#32#84#82#73#71#71#69#82#95#83+
-  #72#79#84#95#83#72#79#84#71#85#78#44#32#47#47#32#50#10#32#32#84#82#73#71#71+
-  #69#82#95#83#72#79#84#95#83#83#71#44#32#47#47#32#51#10#32#32#84#82#73#71#71+
-  #69#82#95#83#72#79#84#95#73#77#80#44#32#47#47#32#52#10#32#32#84#82#73#71#71+
-  #69#82#95#83#72#79#84#95#80#76#65#83#77#65#44#32#47#47#32#53#10#32#32#84#82+
-  #73#71#71#69#82#95#83#72#79#84#95#83#80#73#68#69#82#44#32#47#47#32#54#10#32+
-  #32#84#82#73#71#71#69#82#95#83#72#79#84#95#67#65#67#79#44#32#47#47#32#55#10+
-  #32#32#84#82#73#71#71#69#82#95#83#72#79#84#95#66#65#82#79#78#44#32#47#47#32+
-  #56#10#32#32#84#82#73#71#71#69#82#95#83#72#79#84#95#77#65#78#67#85#66#44#32+
-  #47#47#32#57#10#32#32#84#82#73#71#71#69#82#95#83#72#79#84#95#82#69#86#44#32+
-  #47#47#32#49#48#10#32#32#84#82#73#71#71#69#82#95#83#72#79#84#95#82#79#67#75+
-  #69#84#44#32#47#47#32#49#49#10#32#32#84#82#73#71#71#69#82#95#83#72#79#84#95+
-  #66#70#71#44#32#47#47#32#49#50#10#32#32#84#82#73#71#71#69#82#95#83#72#79#84+
-  #95#69#88#80#76#44#32#47#47#32#49#51#10#32#32#84#82#73#71#71#69#82#95#83#72+
-  #79#84#95#66#70#71#69#88#80#76#44#32#47#47#32#49#52#10#32#32#47#47#10#32#32+
-  #84#82#73#71#71#69#82#95#83#72#79#84#95#77#65#88#32#61#32#77#65#88#44#10#125+
-  #10#10#101#110#117#109#32#84#114#105#103#103#101#114#83#104#111#116#84#97+
-  #114#103#101#116#32#123#10#32#32#84#82#73#71#71#69#82#95#83#72#79#84#95#84+
-  #65#82#71#69#84#95#78#79#78#69#44#32#47#47#32#48#10#32#32#84#82#73#71#71#69+
-  #82#95#83#72#79#84#95#84#65#82#71#69#84#95#77#79#78#44#32#47#47#32#49#10#32+
-  #32#84#82#73#71#71#69#82#95#83#72#79#84#95#84#65#82#71#69#84#95#80#76#82#44+
-  #32#47#47#32#50#10#32#32#84#82#73#71#71#69#82#95#83#72#79#84#95#84#65#82#71+
-  #69#84#95#82#69#68#44#32#47#47#32#51#10#32#32#84#82#73#71#71#69#82#95#83#72+
-  #79#84#95#84#65#82#71#69#84#95#66#76#85#69#44#32#47#47#32#52#10#32#32#84#82+
-  #73#71#71#69#82#95#83#72#79#84#95#84#65#82#71#69#84#95#77#79#78#80#76#82#44+
-  #32#47#47#32#53#10#32#32#84#82#73#71#71#69#82#95#83#72#79#84#95#84#65#82#71+
-  #69#84#95#80#76#82#77#79#78#44#32#47#47#32#54#10#125#10#10#101#110#117#109+
-  #32#84#114#105#103#103#101#114#83#104#111#116#65#105#109#32#123#10#32#32#84+
-  #82#73#71#71#69#82#95#83#72#79#84#95#65#73#77#95#68#69#70#65#85#76#84#44#32+
-  #47#47#32#48#10#32#32#84#82#73#71#71#69#82#95#83#72#79#84#95#65#73#77#95#65+
-  #76#76#77#65#80#44#32#47#47#32#49#10#32#32#84#82#73#71#71#69#82#95#83#72#79+
-  #84#95#65#73#77#95#84#82#65#67#69#44#32#47#47#32#50#10#32#32#84#82#73#71#71+
-  #69#82#95#83#72#79#84#95#65#73#77#95#84#82#65#67#69#65#76#76#44#32#47#47#32+
-  #51#10#125#10#10#101#110#117#109#32#84#114#105#103#103#101#114#69#102#102+
-  #101#99#116#32#123#10#32#32#84#82#73#71#71#69#82#95#69#70#70#69#67#84#95#80+
-  #65#82#84#73#67#76#69#44#32#47#47#32#48#10#32#32#84#82#73#71#71#69#82#95#69+
-  #70#70#69#67#84#95#65#78#73#77#65#84#73#79#78#44#32#47#47#32#49#10#125#10#10+
-  #101#110#117#109#32#84#114#105#103#103#101#114#69#102#102#101#99#116#84#121+
-  #112#101#32#123#10#32#32#84#82#73#71#71#69#82#95#69#70#70#69#67#84#95#83#76+
-  #73#81#85#73#68#44#32#47#47#32#48#10#32#32#84#82#73#71#71#69#82#95#69#70#70+
-  #69#67#84#95#76#76#73#81#85#73#68#44#32#47#47#32#49#10#32#32#84#82#73#71#71+
-  #69#82#95#69#70#70#69#67#84#95#68#76#73#81#85#73#68#44#32#47#47#32#50#10#32+
-  #32#84#82#73#71#71#69#82#95#69#70#70#69#67#84#95#66#76#79#79#68#44#32#47#47+
-  #32#51#10#32#32#84#82#73#71#71#69#82#95#69#70#70#69#67#84#95#83#80#65#82#75+
-  #44#32#47#47#32#52#10#32#32#84#82#73#71#71#69#82#95#69#70#70#69#67#84#95#66+
-  #85#66#66#76#69#44#32#47#47#32#53#10#32#32#84#82#73#71#71#69#82#95#69#70#70+
-  #69#67#84#95#77#65#88#32#61#32#77#65#88#44#10#125#10#10#101#110#117#109#32+
-  #84#114#105#103#103#101#114#69#102#102#101#99#116#80#111#115#32#123#10#32#32+
-  #84#82#73#71#71#69#82#95#69#70#70#69#67#84#95#80#79#83#95#67#69#78#84#69#82+
-  #44#32#47#47#32#48#10#32#32#84#82#73#71#71#69#82#95#69#70#70#69#67#84#95#80+
-  #79#83#95#65#82#69#65#44#32#47#47#32#49#10#125#10#10#101#110#117#109#32#84+
-  #114#105#103#103#101#114#77#117#115#105#99#65#99#116#105#111#110#32#123#10+
-  #32#32#84#82#73#71#71#69#82#95#77#85#83#73#67#95#65#67#84#73#79#78#95#83#84+
-  #79#80#44#32#47#47#32#48#10#32#32#84#82#73#71#71#69#82#95#77#85#83#73#67#95+
-  #65#67#84#73#79#78#95#80#76#65#89#44#32#47#47#32#49#59#32#117#110#112#97#117+
-  #115#101#32#111#114#32#114#101#115#116#97#114#116#10#125#10#10#101#110#117+
-  #109#32#84#114#105#103#103#101#114#83#99#111#114#101#65#99#116#105#111#110+
-  #32#123#10#32#32#84#82#73#71#71#69#82#95#83#67#79#82#69#95#65#67#84#73#79#78+
-  #95#65#68#68#44#32#47#47#32#48#10#32#32#84#82#73#71#71#69#82#95#83#67#79#82+
-  #69#95#65#67#84#73#79#78#95#83#85#66#44#32#47#47#32#49#10#32#32#84#82#73#71+
-  #71#69#82#95#83#67#79#82#69#95#65#67#84#73#79#78#95#87#73#78#44#32#47#47#32+
-  #50#10#32#32#84#82#73#71#71#69#82#95#83#67#79#82#69#95#65#67#84#73#79#78#95+
-  #76#79#79#83#69#44#32#47#47#32#51#10#125#10#10#101#110#117#109#32#84#114#105+
-  #103#103#101#114#77#101#115#115#97#103#101#68#101#115#116#32#123#10#32#32#84+
-  #82#73#71#71#69#82#95#77#69#83#83#65#71#69#95#68#69#83#84#95#77#69#44#32#47+
-  #47#32#48#10#32#32#84#82#73#71#71#69#82#95#77#69#83#83#65#71#69#95#68#69#83+
-  #84#95#77#89#95#84#69#65#77#44#32#47#47#32#49#10#32#32#84#82#73#71#71#69#82+
-  #95#77#69#83#83#65#71#69#95#68#69#83#84#95#69#78#69#77#89#95#84#69#65#77#44+
-  #32#47#47#32#50#10#32#32#84#82#73#71#71#69#82#95#77#69#83#83#65#71#69#95#68+
-  #69#83#84#95#82#69#68#95#84#69#65#77#44#32#47#47#32#51#10#32#32#84#82#73#71+
-  #71#69#82#95#77#69#83#83#65#71#69#95#68#69#83#84#95#66#76#85#69#95#84#69#65+
-  #77#44#32#47#47#32#52#10#32#32#84#82#73#71#71#69#82#95#77#69#83#83#65#71#69+
-  #95#68#69#83#84#95#69#86#69#82#89#79#78#69#44#32#47#47#32#53#10#125#10#10+
-  #101#110#117#109#32#84#114#105#103#103#101#114#77#101#115#115#97#103#101#75+
-  #105#110#100#32#123#10#32#32#84#82#73#71#71#69#82#95#77#69#83#83#65#71#69#95+
-  #75#73#78#68#95#67#72#65#84#44#32#47#47#32#48#10#32#32#84#82#73#71#71#69#82+
-  #95#77#69#83#83#65#71#69#95#75#73#78#68#95#71#65#77#69#44#32#47#47#32#49#10+
-  #125#10#10#98#105#116#115#101#116#32#65#99#116#105#118#97#116#101#84#121#112+
-  #101#32#123#10#32#32#65#67#84#73#86#65#84#69#95#78#79#78#69#32#61#32#48#44+
-  #32#47#47#32#48#10#32#32#65#67#84#73#86#65#84#69#95#80#76#65#89#69#82#67#79+
-  #76#76#73#68#69#44#32#47#47#32#49#10#32#32#65#67#84#73#86#65#84#69#95#77#79+
-  #78#83#84#69#82#67#79#76#76#73#68#69#44#32#47#47#32#50#10#32#32#65#67#84#73+
-  #86#65#84#69#95#80#76#65#89#69#82#80#82#69#83#83#44#32#47#47#32#52#10#32#32+
-  #65#67#84#73#86#65#84#69#95#77#79#78#83#84#69#82#80#82#69#83#83#44#32#47#47+
-  #32#56#10#32#32#65#67#84#73#86#65#84#69#95#83#72#79#84#44#32#47#47#32#49#54+
-  #10#32#32#65#67#84#73#86#65#84#69#95#78#79#77#79#78#83#84#69#82#44#32#47#47+
-  #32#51#50#10#32#32#65#67#84#73#86#65#84#69#95#67#85#83#84#79#77#32#61#32#50+
-  #53#53#44#32#47#47#32#110#111#116#101#32#116#104#97#116#32#34#100#105#114+
-  #101#99#116#32#97#115#115#105#103#110#34#32#102#105#101#108#100#32#100#111+
-  #101#115#110#39#116#32#97#102#102#101#99#116#32#98#105#116#32#99#111#117#110+
-  #116#101#114#10#125#10#10#98#105#116#115#101#116#32#75#101#121#32#123#10#32+
-  #32#75#69#89#95#78#79#78#69#32#61#32#48#44#32#47#47#32#48#10#32#32#75#69#89+
-  #95#82#69#68#44#32#47#47#32#49#10#32#32#75#69#89#95#71#82#69#69#78#44#32#47+
-  #47#32#50#10#32#32#75#69#89#95#66#76#85#69#44#32#47#47#32#52#10#32#32#75#69+
-  #89#95#82#69#68#84#69#65#77#44#32#47#47#32#56#10#32#32#75#69#89#95#66#76#85+
-  #69#84#69#65#77#44#32#47#47#32#49#54#10#125#10#10#10#47#47#47#47#47#47#47#47+
   #47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47+
+  #47#47#10#47#47#32#115#112#101#99#105#97#108#32#116#101#120#116#117#114#101+
+  #32#105#100#101#110#116#105#102#105#101#114#115#44#32#117#115#101#100#32#116+
+  #111#32#103#101#110#101#114#97#116#101#32#112#97#115#99#97#108#32#115#111+
+  #117#114#99#101#115#10#101#110#117#109#32#84#101#120#116#117#114#101#83#112+
+  #101#99#105#97#108#32#123#10#32#32#84#69#88#84#85#82#69#95#83#80#69#67#73#65+
+  #76#95#87#65#84#69#82#32#61#32#45#49#44#10#32#32#84#69#88#84#85#82#69#95#83+
+  #80#69#67#73#65#76#95#65#67#73#68#49#32#61#32#45#50#44#10#32#32#84#69#88#84+
+  #85#82#69#95#83#80#69#67#73#65#76#95#65#67#73#68#50#32#61#32#45#51#44#10#32+
+  #32#84#69#88#84#85#82#69#95#78#79#78#69#32#61#32#45#52#44#10#125#10#10#47#47+
+  #32#100#105#114#101#99#116#105#111#110#115#10#101#110#117#109#32#68#105#114+
+  #84#121#112#101#32#123#10#32#32#68#73#82#95#76#69#70#84#44#32#47#47#32#48#10+
+  #32#32#68#73#82#95#82#73#71#72#84#44#32#47#47#32#49#10#32#32#68#73#82#95#83+
+  #79#77#69#84#72#73#78#71#50#44#32#47#47#32#50#10#125#10#10#47#47#32#116#114+
+  #105#103#103#101#114#115#10#101#110#117#109#32#84#114#105#103#103#101#114#84+
+  #121#112#101#32#123#10#32#32#84#82#73#71#71#69#82#95#78#79#78#69#44#32#47#47+
+  #32#48#10#32#32#84#82#73#71#71#69#82#95#69#88#73#84#44#32#47#47#32#49#10#32+
+  #32#84#82#73#71#71#69#82#95#84#69#76#69#80#79#82#84#44#32#47#47#32#50#10#32+
+  #32#84#82#73#71#71#69#82#95#79#80#69#78#68#79#79#82#44#32#47#47#32#51#10#32+
+  #32#84#82#73#71#71#69#82#95#67#76#79#83#69#68#79#79#82#44#32#47#47#32#52#10+
+  #32#32#84#82#73#71#71#69#82#95#68#79#79#82#44#32#47#47#32#53#10#32#32#84#82+
+  #73#71#71#69#82#95#68#79#79#82#53#44#32#47#47#32#54#10#32#32#84#82#73#71#71+
+  #69#82#95#67#76#79#83#69#84#82#65#80#44#32#47#47#32#55#10#32#32#84#82#73#71+
+  #71#69#82#95#84#82#65#80#44#32#47#47#32#56#10#32#32#84#82#73#71#71#69#82#95+
+  #80#82#69#83#83#44#32#47#47#32#57#10#32#32#84#82#73#71#71#69#82#95#83#69#67+
+  #82#69#84#44#32#47#47#32#49#48#10#32#32#84#82#73#71#71#69#82#95#76#73#70#84+
+  #85#80#44#32#47#47#32#49#49#10#32#32#84#82#73#71#71#69#82#95#76#73#70#84#68+
+  #79#87#78#44#32#47#47#32#49#50#10#32#32#84#82#73#71#71#69#82#95#76#73#70#84+
+  #44#32#47#47#32#49#51#10#32#32#84#82#73#71#71#69#82#95#84#69#88#84#85#82#69+
+  #44#32#47#47#32#49#52#10#32#32#84#82#73#71#71#69#82#95#79#78#44#32#47#47#32+
+  #49#53#10#32#32#84#82#73#71#71#69#82#95#79#70#70#44#32#47#47#32#49#54#10#32+
+  #32#84#82#73#71#71#69#82#95#79#78#79#70#70#44#32#47#47#32#49#55#10#32#32#84+
+  #82#73#71#71#69#82#95#83#79#85#78#68#44#32#47#47#32#49#56#10#32#32#84#82#73+
+  #71#71#69#82#95#83#80#65#87#78#77#79#78#83#84#69#82#44#32#47#47#32#49#57#10+
+  #32#32#84#82#73#71#71#69#82#95#83#80#65#87#78#73#84#69#77#44#32#47#47#32#50+
+  #48#10#32#32#84#82#73#71#71#69#82#95#77#85#83#73#67#44#32#47#47#32#50#49#10+
+  #32#32#84#82#73#71#71#69#82#95#80#85#83#72#44#32#47#47#32#50#50#10#32#32#84+
+  #82#73#71#71#69#82#95#83#67#79#82#69#44#32#47#47#32#50#51#10#32#32#84#82#73+
+  #71#71#69#82#95#77#69#83#83#65#71#69#44#32#47#47#32#50#52#10#32#32#84#82#73+
+  #71#71#69#82#95#68#65#77#65#71#69#44#32#47#47#32#50#53#10#32#32#84#82#73#71+
+  #71#69#82#95#72#69#65#76#84#72#44#32#47#47#32#50#54#10#32#32#84#82#73#71#71+
+  #69#82#95#83#72#79#84#44#32#47#47#32#50#55#10#32#32#84#82#73#71#71#69#82#95+
+  #69#70#70#69#67#84#44#32#47#47#32#50#56#10#32#32#84#82#73#71#71#69#82#95#83+
+  #67#82#73#80#84#44#32#47#47#32#50#57#10#32#32#47#47#10#32#32#84#82#73#71#71+
+  #69#82#95#77#65#88#32#61#32#77#65#88#44#10#125#10#10#47#47#32#34#97#115#32+
+  #88#88#88#34#32#109#101#97#110#115#32#34#103#101#110#101#114#97#116#101#32+
+  #116#104#105#115#32#105#100#101#110#116#105#102#105#101#114#32#102#111#114+
+  #32#112#97#115#99#97#108#32#115#111#117#114#99#101#115#10#98#105#116#115#101+
+  #116#32#80#97#110#101#108#84#121#112#101#32#123#10#32#32#80#65#78#69#76#95+
+  #78#79#78#69#32#61#32#48#44#32#47#47#32#48#10#32#32#80#65#78#69#76#95#87#65+
+  #76#76#44#32#47#47#32#49#10#32#32#80#65#78#69#76#95#66#65#67#75#44#32#47#47+
+  #32#50#10#32#32#80#65#78#69#76#95#70#79#82#69#44#32#47#47#32#52#10#32#32#80+
+  #65#78#69#76#95#87#65#84#69#82#44#32#47#47#32#56#10#32#32#80#65#78#69#76#95+
+  #65#67#73#68#49#44#32#47#47#32#49#54#10#32#32#80#65#78#69#76#95#65#67#73#68+
+  #50#44#32#47#47#32#51#50#10#32#32#80#65#78#69#76#95#83#84#69#80#44#32#47#47+
+  #32#54#52#10#32#32#80#65#78#69#76#95#76#73#70#84#85#80#44#32#47#47#32#49#50+
+  #56#10#32#32#80#65#78#69#76#95#76#73#70#84#68#79#87#78#44#32#47#47#32#50#53+
+  #54#10#32#32#80#65#78#69#76#95#79#80#69#78#68#79#79#82#44#32#47#47#32#53#49+
+  #50#10#32#32#80#65#78#69#76#95#67#76#79#83#69#68#79#79#82#44#32#47#47#32#49+
+  #48#50#52#10#32#32#80#65#78#69#76#95#66#76#79#67#75#77#79#78#44#32#47#47#32+
+  #50#48#52#56#10#32#32#80#65#78#69#76#95#76#73#70#84#76#69#70#84#44#32#47#47+
+  #32#52#48#57#54#10#32#32#80#65#78#69#76#95#76#73#70#84#82#73#71#72#84#44#32+
+  #47#47#32#56#49#57#50#10#125#10#10#98#105#116#115#101#116#32#80#97#110#101+
+  #108#70#108#97#103#32#123#10#32#32#80#65#78#69#76#95#70#76#65#71#95#78#79#78+
+  #69#32#61#32#48#44#32#47#47#32#48#10#32#32#80#65#78#69#76#95#70#76#65#71#95+
+  #66#76#69#78#68#73#78#71#44#32#47#47#32#49#10#32#32#80#65#78#69#76#95#70#76+
+  #65#71#95#72#73#68#69#44#32#47#47#32#50#10#32#32#80#65#78#69#76#95#70#76#65+
+  #71#95#87#65#84#69#82#84#69#88#84#85#82#69#83#44#32#47#47#32#52#10#125#10#10+
+  #101#110#117#109#32#69#102#102#101#99#116#65#99#116#105#111#110#32#123#10#32+
+  #32#69#70#70#69#67#84#95#78#79#78#69#44#32#47#47#32#48#10#32#32#69#70#70#69+
+  #67#84#95#84#69#76#69#80#79#82#84#44#32#47#47#32#49#10#32#32#69#70#70#69#67+
+  #84#95#82#69#83#80#65#87#78#44#32#47#47#32#50#10#32#32#69#70#70#69#67#84#95+
+  #70#73#82#69#44#32#47#47#32#51#10#125#10#10#101#110#117#109#32#73#116#101+
+  #109#32#123#10#32#32#73#84#69#77#95#78#79#78#69#44#32#47#47#32#48#10#32#32+
+  #73#84#69#77#95#77#69#68#75#73#84#95#83#77#65#76#76#44#32#47#47#32#49#10#32+
+  #32#73#84#69#77#95#77#69#68#75#73#84#95#76#65#82#71#69#44#32#47#47#32#50#10+
+  #32#32#73#84#69#77#95#77#69#68#75#73#84#95#66#76#65#67#75#44#32#47#47#32#51+
+  #10#32#32#73#84#69#77#95#65#82#77#79#82#95#71#82#69#69#78#44#32#47#47#32#52+
+  #10#32#32#73#84#69#77#95#65#82#77#79#82#95#66#76#85#69#44#32#47#47#32#53#10+
+  #32#32#73#84#69#77#95#83#80#72#69#82#69#95#66#76#85#69#44#32#47#47#32#54#10+
+  #32#32#73#84#69#77#95#83#80#72#69#82#69#95#87#72#73#84#69#44#32#47#47#32#55+
+  #10#32#32#73#84#69#77#95#83#85#73#84#44#32#47#47#32#56#10#32#32#73#84#69#77+
+  #95#79#88#89#71#69#78#44#32#47#47#32#57#10#32#32#73#84#69#77#95#73#78#86#85+
+  #76#44#32#47#47#32#49#48#10#32#32#73#84#69#77#95#87#69#65#80#79#78#95#83#65+
+  #87#44#32#47#47#32#49#49#10#32#32#73#84#69#77#95#87#69#65#80#79#78#95#83#72+
+  #79#84#71#85#78#49#44#32#47#47#32#49#50#10#32#32#73#84#69#77#95#87#69#65#80+
+  #79#78#95#83#72#79#84#71#85#78#50#44#32#47#47#32#49#51#10#32#32#73#84#69#77+
+  #95#87#69#65#80#79#78#95#67#72#65#73#78#71#85#78#44#32#47#47#32#49#52#10#32+
+  #32#73#84#69#77#95#87#69#65#80#79#78#95#82#79#67#75#69#84#76#65#85#78#67#72+
+  #69#82#44#32#47#47#32#49#53#10#32#32#73#84#69#77#95#87#69#65#80#79#78#95#80+
+  #76#65#83#77#65#44#32#47#47#32#49#54#10#32#32#73#84#69#77#95#87#69#65#80#79+
+  #78#95#66#70#71#44#32#47#47#32#49#55#10#32#32#73#84#69#77#95#87#69#65#80#79+
+  #78#95#83#85#80#69#82#80#85#76#69#77#69#84#44#32#47#47#32#49#56#10#32#32#73+
+  #84#69#77#95#65#77#77#79#95#66#85#76#76#69#84#83#44#32#47#47#32#49#57#10#32+
+  #32#73#84#69#77#95#65#77#77#79#95#66#85#76#76#69#84#83#95#66#79#88#44#32#47+
+  #47#32#50#48#10#32#32#73#84#69#77#95#65#77#77#79#95#83#72#69#76#76#83#44#32+
+  #47#47#32#50#49#10#32#32#73#84#69#77#95#65#77#77#79#95#83#72#69#76#76#83#95+
+  #66#79#88#44#32#47#47#32#50#50#10#32#32#73#84#69#77#95#65#77#77#79#95#82#79+
+  #67#75#69#84#44#32#47#47#32#50#51#10#32#32#73#84#69#77#95#65#77#77#79#95#82+
+  #79#67#75#69#84#95#66#79#88#44#32#47#47#32#50#52#10#32#32#73#84#69#77#95#65+
+  #77#77#79#95#67#69#76#76#44#32#47#47#32#50#53#10#32#32#73#84#69#77#95#65#77+
+  #77#79#95#67#69#76#76#95#66#73#71#44#32#47#47#32#50#54#10#32#32#73#84#69#77+
+  #95#65#77#77#79#95#66#65#67#75#80#65#67#75#44#32#47#47#32#50#55#10#32#32#73+
+  #84#69#77#95#75#69#89#95#82#69#68#44#32#47#47#32#50#56#10#32#32#73#84#69#77+
+  #95#75#69#89#95#71#82#69#69#78#44#32#47#47#32#50#57#10#32#32#73#84#69#77#95+
+  #75#69#89#95#66#76#85#69#44#32#47#47#32#51#48#10#32#32#73#84#69#77#95#87#69+
+  #65#80#79#78#95#75#65#83#84#69#84#44#32#47#47#32#51#49#10#32#32#73#84#69#77+
+  #95#87#69#65#80#79#78#95#80#73#83#84#79#76#44#32#47#47#32#51#50#10#32#32#73+
+  #84#69#77#95#66#79#84#84#76#69#44#32#47#47#32#51#51#10#32#32#73#84#69#77#95+
+  #72#69#76#77#69#84#44#32#47#47#32#51#52#10#32#32#73#84#69#77#95#74#69#84#80+
+  #65#67#75#44#32#47#47#32#51#53#10#32#32#73#84#69#77#95#73#78#86#73#83#44#32+
+  #47#47#32#51#54#10#32#32#73#84#69#77#95#87#69#65#80#79#78#95#70#76#65#77#69+
+  #84#72#82#79#87#69#82#44#32#47#47#32#51#55#10#32#32#73#84#69#77#95#65#77#77+
+  #79#95#70#85#69#76#67#65#78#44#32#47#47#32#51#56#10#32#32#47#47#10#32#32#73+
+  #84#69#77#95#77#65#88#32#61#32#77#65#88#44#32#47#47#32#115#116#111#114#101+
+  #32#116#104#101#32#108#97#115#116#32#105#116#101#109#39#115#32#105#100#32+
+  #105#110#32#104#101#114#101#32#117#115#101#32#116#104#105#115#32#105#110#32+
+  #102#111#114#32#108#111#111#112#115#10#125#10#10#98#105#116#115#101#116#32+
+  #73#116#101#109#79#112#116#105#111#110#32#123#10#32#32#73#84#69#77#95#79#80+
+  #84#73#79#78#95#78#79#78#69#32#61#32#48#44#32#47#47#32#48#10#32#32#73#84#69+
+  #77#95#79#80#84#73#79#78#95#79#78#76#89#68#77#44#32#47#47#32#49#10#32#32#73+
+  #84#69#77#95#79#80#84#73#79#78#95#70#65#76#76#44#32#47#47#32#50#10#125#10#10+
+  #101#110#117#109#32#65#114#101#97#84#121#112#101#32#123#10#32#32#65#82#69#65+
+  #95#78#79#78#69#44#32#47#47#32#48#10#32#32#65#82#69#65#95#80#76#65#89#69#82+
+  #80#79#73#78#84#49#44#32#47#47#32#49#10#32#32#65#82#69#65#95#80#76#65#89#69+
+  #82#80#79#73#78#84#50#44#32#47#47#32#50#10#32#32#65#82#69#65#95#68#77#80#79+
+  #73#78#84#44#32#47#47#32#51#10#32#32#65#82#69#65#95#82#69#68#70#76#65#71#44+
+  #32#47#47#32#52#10#32#32#65#82#69#65#95#66#76#85#69#70#76#65#71#44#32#47#47+
+  #32#53#10#32#32#65#82#69#65#95#68#79#77#70#76#65#71#44#32#47#47#32#54#10#32+
+  #32#65#82#69#65#95#82#69#68#84#69#65#77#80#79#73#78#84#44#32#47#47#32#55#10+
+  #32#32#65#82#69#65#95#66#76#85#69#84#69#65#77#80#79#73#78#84#44#32#47#47#32+
+  #56#10#125#10#10#101#110#117#109#32#77#111#110#115#116#101#114#32#123#10#32+
+  #32#77#79#78#83#84#69#82#95#78#79#78#69#44#32#47#47#32#48#10#32#32#77#79#78+
+  #83#84#69#82#95#68#69#77#79#78#44#32#47#47#32#49#10#32#32#77#79#78#83#84#69+
+  #82#95#73#77#80#44#32#47#47#32#50#10#32#32#77#79#78#83#84#69#82#95#90#79#77+
+  #66#89#44#32#47#47#32#51#10#32#32#77#79#78#83#84#69#82#95#83#69#82#71#44#32+
+  #47#47#32#52#10#32#32#77#79#78#83#84#69#82#95#67#89#66#69#82#44#32#47#47#32+
+  #53#10#32#32#77#79#78#83#84#69#82#95#67#71#85#78#44#32#47#47#32#54#10#32#32+
+  #77#79#78#83#84#69#82#95#66#65#82#79#78#44#32#47#47#32#55#10#32#32#77#79#78+
+  #83#84#69#82#95#75#78#73#71#72#84#44#32#47#47#32#56#10#32#32#77#79#78#83#84+
+  #69#82#95#67#65#67#79#44#32#47#47#32#57#10#32#32#77#79#78#83#84#69#82#95#83+
+  #79#85#76#44#32#47#47#32#49#48#10#32#32#77#79#78#83#84#69#82#95#80#65#73#78+
+  #44#32#47#47#32#49#49#10#32#32#77#79#78#83#84#69#82#95#83#80#73#68#69#82#44+
+  #32#47#47#32#49#50#10#32#32#77#79#78#83#84#69#82#95#66#83#80#44#32#47#47#32+
+  #49#51#10#32#32#77#79#78#83#84#69#82#95#77#65#78#67#85#66#44#32#47#47#32#49+
+  #52#10#32#32#77#79#78#83#84#69#82#95#83#75#69#76#44#32#47#47#32#49#53#10#32+
+  #32#77#79#78#83#84#69#82#95#86#73#76#69#44#32#47#47#32#49#54#10#32#32#77#79+
+  #78#83#84#69#82#95#70#73#83#72#44#32#47#47#32#49#55#10#32#32#77#79#78#83#84+
+  #69#82#95#66#65#82#82#69#76#44#32#47#47#32#49#56#10#32#32#77#79#78#83#84#69+
+  #82#95#82#79#66#79#44#32#47#47#32#49#57#10#32#32#77#79#78#83#84#69#82#95#77+
+  #65#78#44#32#47#47#32#50#48#10#32#32#47#47#32#97#108#105#97#115#101#115#32+
+  #40#102#105#120#109#101#58#32#105#116#32#115#104#111#117#108#100#32#98#101+
+  #32#96#77#79#78#83#84#69#82#95#90#79#77#66#73#69#32#61#32#77#79#78#83#84#69+
+  #82#95#90#79#77#66#89#96#33#41#10#32#32#77#79#78#83#84#69#82#95#90#79#77#66+
+  #73#69#32#61#32#51#44#10#125#10#10#101#110#117#109#32#77#111#110#115#116#101+
+  #114#66#101#104#97#118#105#111#117#114#32#123#10#32#32#66#72#95#78#79#82#77+
+  #65#76#44#32#47#47#32#48#10#32#32#66#72#95#75#73#76#76#69#82#44#32#47#47#32+
+  #49#10#32#32#66#72#95#77#65#78#73#65#67#44#32#47#47#32#50#10#32#32#66#72#95+
+  #73#78#83#65#78#69#44#32#47#47#32#51#10#32#32#66#72#95#67#65#78#78#73#66#65+
+  #76#44#32#47#47#32#52#10#32#32#66#72#95#71#79#79#68#44#32#47#47#32#53#10#125+
+  #10#10#101#110#117#109#32#84#114#105#103#103#101#114#83#104#111#116#32#123+
+  #10#32#32#84#82#73#71#71#69#82#95#83#72#79#84#95#80#73#83#84#79#76#44#32#47+
+  #47#32#48#10#32#32#84#82#73#71#71#69#82#95#83#72#79#84#95#66#85#76#76#69#84+
+  #44#32#47#47#32#49#10#32#32#84#82#73#71#71#69#82#95#83#72#79#84#95#83#72#79+
+  #84#71#85#78#44#32#47#47#32#50#10#32#32#84#82#73#71#71#69#82#95#83#72#79#84+
+  #95#83#83#71#44#32#47#47#32#51#10#32#32#84#82#73#71#71#69#82#95#83#72#79#84+
+  #95#73#77#80#44#32#47#47#32#52#10#32#32#84#82#73#71#71#69#82#95#83#72#79#84+
+  #95#80#76#65#83#77#65#44#32#47#47#32#53#10#32#32#84#82#73#71#71#69#82#95#83+
+  #72#79#84#95#83#80#73#68#69#82#44#32#47#47#32#54#10#32#32#84#82#73#71#71#69+
+  #82#95#83#72#79#84#95#67#65#67#79#44#32#47#47#32#55#10#32#32#84#82#73#71#71+
+  #69#82#95#83#72#79#84#95#66#65#82#79#78#44#32#47#47#32#56#10#32#32#84#82#73+
+  #71#71#69#82#95#83#72#79#84#95#77#65#78#67#85#66#44#32#47#47#32#57#10#32#32+
+  #84#82#73#71#71#69#82#95#83#72#79#84#95#82#69#86#44#32#47#47#32#49#48#10#32+
+  #32#84#82#73#71#71#69#82#95#83#72#79#84#95#82#79#67#75#69#84#44#32#47#47#32+
+  #49#49#10#32#32#84#82#73#71#71#69#82#95#83#72#79#84#95#66#70#71#44#32#47#47+
+  #32#49#50#10#32#32#84#82#73#71#71#69#82#95#83#72#79#84#95#69#88#80#76#44#32+
+  #47#47#32#49#51#10#32#32#84#82#73#71#71#69#82#95#83#72#79#84#95#66#70#71#69+
+  #88#80#76#44#32#47#47#32#49#52#10#32#32#47#47#10#32#32#84#82#73#71#71#69#82+
+  #95#83#72#79#84#95#77#65#88#32#61#32#77#65#88#44#10#125#10#10#101#110#117+
+  #109#32#84#114#105#103#103#101#114#83#104#111#116#84#97#114#103#101#116#32+
+  #123#10#32#32#84#82#73#71#71#69#82#95#83#72#79#84#95#84#65#82#71#69#84#95#78+
+  #79#78#69#44#32#47#47#32#48#10#32#32#84#82#73#71#71#69#82#95#83#72#79#84#95+
+  #84#65#82#71#69#84#95#77#79#78#44#32#47#47#32#49#10#32#32#84#82#73#71#71#69+
+  #82#95#83#72#79#84#95#84#65#82#71#69#84#95#80#76#82#44#32#47#47#32#50#10#32+
+  #32#84#82#73#71#71#69#82#95#83#72#79#84#95#84#65#82#71#69#84#95#82#69#68#44+
+  #32#47#47#32#51#10#32#32#84#82#73#71#71#69#82#95#83#72#79#84#95#84#65#82#71+
+  #69#84#95#66#76#85#69#44#32#47#47#32#52#10#32#32#84#82#73#71#71#69#82#95#83+
+  #72#79#84#95#84#65#82#71#69#84#95#77#79#78#80#76#82#44#32#47#47#32#53#10#32+
+  #32#84#82#73#71#71#69#82#95#83#72#79#84#95#84#65#82#71#69#84#95#80#76#82#77+
+  #79#78#44#32#47#47#32#54#10#125#10#10#101#110#117#109#32#84#114#105#103#103+
+  #101#114#83#104#111#116#65#105#109#32#123#10#32#32#84#82#73#71#71#69#82#95+
+  #83#72#79#84#95#65#73#77#95#68#69#70#65#85#76#84#44#32#47#47#32#48#10#32#32+
+  #84#82#73#71#71#69#82#95#83#72#79#84#95#65#73#77#95#65#76#76#77#65#80#44#32+
+  #47#47#32#49#10#32#32#84#82#73#71#71#69#82#95#83#72#79#84#95#65#73#77#95#84+
+  #82#65#67#69#44#32#47#47#32#50#10#32#32#84#82#73#71#71#69#82#95#83#72#79#84+
+  #95#65#73#77#95#84#82#65#67#69#65#76#76#44#32#47#47#32#51#10#125#10#10#101+
+  #110#117#109#32#84#114#105#103#103#101#114#69#102#102#101#99#116#32#123#10+
+  #32#32#84#82#73#71#71#69#82#95#69#70#70#69#67#84#95#80#65#82#84#73#67#76#69+
+  #44#32#47#47#32#48#10#32#32#84#82#73#71#71#69#82#95#69#70#70#69#67#84#95#65+
+  #78#73#77#65#84#73#79#78#44#32#47#47#32#49#10#125#10#10#101#110#117#109#32+
+  #84#114#105#103#103#101#114#69#102#102#101#99#116#84#121#112#101#32#123#10+
+  #32#32#84#82#73#71#71#69#82#95#69#70#70#69#67#84#95#83#76#73#81#85#73#68#44+
+  #32#47#47#32#48#10#32#32#84#82#73#71#71#69#82#95#69#70#70#69#67#84#95#76#76+
+  #73#81#85#73#68#44#32#47#47#32#49#10#32#32#84#82#73#71#71#69#82#95#69#70#70+
+  #69#67#84#95#68#76#73#81#85#73#68#44#32#47#47#32#50#10#32#32#84#82#73#71#71+
+  #69#82#95#69#70#70#69#67#84#95#66#76#79#79#68#44#32#47#47#32#51#10#32#32#84+
+  #82#73#71#71#69#82#95#69#70#70#69#67#84#95#83#80#65#82#75#44#32#47#47#32#52+
+  #10#32#32#84#82#73#71#71#69#82#95#69#70#70#69#67#84#95#66#85#66#66#76#69#44+
+  #32#47#47#32#53#10#32#32#84#82#73#71#71#69#82#95#69#70#70#69#67#84#95#77#65+
+  #88#32#61#32#77#65#88#44#10#125#10#10#101#110#117#109#32#84#114#105#103#103+
+  #101#114#69#102#102#101#99#116#80#111#115#32#123#10#32#32#84#82#73#71#71#69+
+  #82#95#69#70#70#69#67#84#95#80#79#83#95#67#69#78#84#69#82#44#32#47#47#32#48+
+  #10#32#32#84#82#73#71#71#69#82#95#69#70#70#69#67#84#95#80#79#83#95#65#82#69+
+  #65#44#32#47#47#32#49#10#125#10#10#101#110#117#109#32#84#114#105#103#103#101+
+  #114#77#117#115#105#99#65#99#116#105#111#110#32#123#10#32#32#84#82#73#71#71+
+  #69#82#95#77#85#83#73#67#95#65#67#84#73#79#78#95#83#84#79#80#44#32#47#47#32+
+  #48#10#32#32#84#82#73#71#71#69#82#95#77#85#83#73#67#95#65#67#84#73#79#78#95+
+  #80#76#65#89#44#32#47#47#32#49#59#32#117#110#112#97#117#115#101#32#111#114+
+  #32#114#101#115#116#97#114#116#10#125#10#10#101#110#117#109#32#84#114#105+
+  #103#103#101#114#83#99#111#114#101#65#99#116#105#111#110#32#123#10#32#32#84+
+  #82#73#71#71#69#82#95#83#67#79#82#69#95#65#67#84#73#79#78#95#65#68#68#44#32+
+  #47#47#32#48#10#32#32#84#82#73#71#71#69#82#95#83#67#79#82#69#95#65#67#84#73+
+  #79#78#95#83#85#66#44#32#47#47#32#49#10#32#32#84#82#73#71#71#69#82#95#83#67+
+  #79#82#69#95#65#67#84#73#79#78#95#87#73#78#44#32#47#47#32#50#10#32#32#84#82+
+  #73#71#71#69#82#95#83#67#79#82#69#95#65#67#84#73#79#78#95#76#79#79#83#69#44+
+  #32#47#47#32#51#10#125#10#10#101#110#117#109#32#84#114#105#103#103#101#114+
+  #77#101#115#115#97#103#101#68#101#115#116#32#123#10#32#32#84#82#73#71#71#69+
+  #82#95#77#69#83#83#65#71#69#95#68#69#83#84#95#77#69#44#32#47#47#32#48#10#32+
+  #32#84#82#73#71#71#69#82#95#77#69#83#83#65#71#69#95#68#69#83#84#95#77#89#95+
+  #84#69#65#77#44#32#47#47#32#49#10#32#32#84#82#73#71#71#69#82#95#77#69#83#83+
+  #65#71#69#95#68#69#83#84#95#69#78#69#77#89#95#84#69#65#77#44#32#47#47#32#50+
+  #10#32#32#84#82#73#71#71#69#82#95#77#69#83#83#65#71#69#95#68#69#83#84#95#82+
+  #69#68#95#84#69#65#77#44#32#47#47#32#51#10#32#32#84#82#73#71#71#69#82#95#77+
+  #69#83#83#65#71#69#95#68#69#83#84#95#66#76#85#69#95#84#69#65#77#44#32#47#47+
+  #32#52#10#32#32#84#82#73#71#71#69#82#95#77#69#83#83#65#71#69#95#68#69#83#84+
+  #95#69#86#69#82#89#79#78#69#44#32#47#47#32#53#10#125#10#10#101#110#117#109+
+  #32#84#114#105#103#103#101#114#77#101#115#115#97#103#101#75#105#110#100#32+
+  #123#10#32#32#84#82#73#71#71#69#82#95#77#69#83#83#65#71#69#95#75#73#78#68#95+
+  #67#72#65#84#44#32#47#47#32#48#10#32#32#84#82#73#71#71#69#82#95#77#69#83#83+
+  #65#71#69#95#75#73#78#68#95#71#65#77#69#44#32#47#47#32#49#10#125#10#10#98+
+  #105#116#115#101#116#32#65#99#116#105#118#97#116#101#84#121#112#101#32#123+
+  #10#32#32#65#67#84#73#86#65#84#69#95#78#79#78#69#32#61#32#48#44#32#47#47#32+
+  #48#10#32#32#65#67#84#73#86#65#84#69#95#80#76#65#89#69#82#67#79#76#76#73#68+
+  #69#44#32#47#47#32#49#10#32#32#65#67#84#73#86#65#84#69#95#77#79#78#83#84#69+
+  #82#67#79#76#76#73#68#69#44#32#47#47#32#50#10#32#32#65#67#84#73#86#65#84#69+
+  #95#80#76#65#89#69#82#80#82#69#83#83#44#32#47#47#32#52#10#32#32#65#67#84#73+
+  #86#65#84#69#95#77#79#78#83#84#69#82#80#82#69#83#83#44#32#47#47#32#56#10#32+
+  #32#65#67#84#73#86#65#84#69#95#83#72#79#84#44#32#47#47#32#49#54#10#32#32#65+
+  #67#84#73#86#65#84#69#95#78#79#77#79#78#83#84#69#82#44#32#47#47#32#51#50#10+
+  #32#32#65#67#84#73#86#65#84#69#95#67#85#83#84#79#77#32#61#32#50#53#53#44#32+
+  #47#47#32#110#111#116#101#32#116#104#97#116#32#34#100#105#114#101#99#116#32+
+  #97#115#115#105#103#110#34#32#102#105#101#108#100#32#100#111#101#115#110#39+
+  #116#32#97#102#102#101#99#116#32#98#105#116#32#99#111#117#110#116#101#114#10+
+  #125#10#10#98#105#116#115#101#116#32#75#101#121#32#123#10#32#32#75#69#89#95+
+  #78#79#78#69#32#61#32#48#44#32#47#47#32#48#10#32#32#75#69#89#95#82#69#68#44+
+  #32#47#47#32#49#10#32#32#75#69#89#95#71#82#69#69#78#44#32#47#47#32#50#10#32+
+  #32#75#69#89#95#66#76#85#69#44#32#47#47#32#52#10#32#32#75#69#89#95#82#69#68+
+  #84#69#65#77#44#32#47#47#32#56#10#32#32#75#69#89#95#66#76#85#69#84#69#65#77+
+  #44#32#47#47#32#49#54#10#125#10#10#10#47#47#47#47#47#47#47#47#47#47#47#47#47+
   #47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47+
-  #47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#10#47#47+
-  #32#118#97#114#105#111#117#115#32#116#114#105#103#103#101#114#115#10#84#114+
-  #105#103#103#101#114#68#97#116#97#32#102#111#114#32#84#82#73#71#71#69#82#95+
-  #69#88#73#84#32#123#10#32#32#34#109#97#112#34#32#116#121#112#101#32#99#104+
-  #97#114#91#49#54#93#32#111#102#102#115#101#116#32#48#32#119#114#105#116#101+
-  #100#101#102#97#117#108#116#59#10#125#10#10#84#114#105#103#103#101#114#68#97+
-  #116#97#32#102#111#114#32#84#82#73#71#71#69#82#95#84#69#76#69#80#79#82#84#32+
-  #123#10#32#32#34#116#97#114#103#101#116#34#32#116#121#112#101#32#112#111#105+
-  #110#116#32#111#102#102#115#101#116#32#48#32#119#114#105#116#101#100#101#102+
-  #97#117#108#116#59#10#32#32#34#100#50#100#34#32#116#121#112#101#32#98#111+
-  #111#108#32#111#102#102#115#101#116#32#56#32#100#101#102#97#117#108#116#32+
-  #102#97#108#115#101#59#10#32#32#34#115#105#108#101#110#116#34#32#116#121#112+
-  #101#32#98#111#111#108#32#111#102#102#115#101#116#32#57#32#100#101#102#97+
-  #117#108#116#32#102#97#108#115#101#59#10#32#32#34#100#105#114#101#99#116#105+
-  #111#110#34#32#116#121#112#101#32#117#98#121#116#101#32#111#102#102#115#101+
-  #116#32#49#48#32#101#110#117#109#32#68#105#114#84#121#112#101#32#100#101#102+
-  #97#117#108#116#32#68#73#82#95#76#69#70#84#59#10#125#10#10#84#114#105#103+
-  #103#101#114#68#97#116#97#32#102#111#114#32#40#84#82#73#71#71#69#82#95#79#80+
-  #69#78#68#79#79#82#44#32#84#82#73#71#71#69#82#95#67#76#79#83#69#68#79#79#82+
-  #44#32#84#82#73#71#71#69#82#95#68#79#79#82#44#32#84#82#73#71#71#69#82#95#68+
-  #79#79#82#53#44#32#84#82#73#71#71#69#82#95#67#76#79#83#69#84#82#65#80#44#32+
-  #84#82#73#71#71#69#82#95#84#82#65#80#44#32#84#82#73#71#71#69#82#95#76#73#70+
-  #84#85#80#44#32#84#82#73#71#71#69#82#95#76#73#70#84#68#79#87#78#44#32#84#82+
-  #73#71#71#69#82#95#76#73#70#84#41#32#123#10#32#32#34#112#97#110#101#108#105+
-  #100#34#32#116#121#112#101#32#105#110#116#32#111#102#102#115#101#116#32#48+
-  #32#112#97#110#101#108#32#119#114#105#116#101#100#101#102#97#117#108#116#59+
-  #10#32#32#34#115#105#108#101#110#116#34#32#116#121#112#101#32#98#111#111#108+
-  #32#111#102#102#115#101#116#32#52#32#100#101#102#97#117#108#116#32#102#97+
-  #108#115#101#59#10#32#32#34#100#50#100#34#32#116#121#112#101#32#98#111#111+
-  #108#32#111#102#102#115#101#116#32#53#32#100#101#102#97#117#108#116#32#102+
-  #97#108#115#101#59#10#125#10#10#84#114#105#103#103#101#114#68#97#116#97#32+
-  #102#111#114#32#40#84#82#73#71#71#69#82#95#80#82#69#83#83#44#32#84#82#73#71+
-  #71#69#82#95#79#78#44#32#84#82#73#71#71#69#82#95#79#70#70#44#32#84#82#73#71+
-  #71#69#82#95#79#78#79#70#70#41#32#123#10#32#32#34#112#111#115#105#116#105+
-  #111#110#34#32#116#121#112#101#32#112#111#105#110#116#32#111#102#102#115#101+
-  #116#32#48#32#97#115#32#116#120#121#32#100#101#102#97#117#108#116#32#40#48+
-  #32#48#41#32#119#114#105#116#101#100#101#102#97#117#108#116#59#10#32#32#34+
-  #115#105#122#101#34#32#116#121#112#101#32#115#105#122#101#32#111#102#102#115+
-  #101#116#32#56#32#97#115#32#116#119#104#32#100#101#102#97#117#108#116#32#40+
-  #48#32#48#41#59#10#32#32#34#119#97#105#116#34#32#116#121#112#101#32#117#115+
-  #104#111#114#116#32#111#102#102#115#101#116#32#49#50#32#100#101#102#97#117+
-  #108#116#32#48#59#10#32#32#34#99#111#117#110#116#34#32#97#108#105#97#115#32+
-  #112#114#101#115#115#67#111#117#110#116#32#116#121#112#101#32#117#115#104+
-  #111#114#116#32#111#102#102#115#101#116#32#49#52#32#100#101#102#97#117#108+
-  #116#32#48#59#10#32#32#34#109#111#110#115#116#101#114#105#100#34#32#116#121+
-  #112#101#32#105#110#116#32#111#102#102#115#101#116#32#49#54#32#109#111#110+
-  #115#116#101#114#32#97#115#32#109#111#110#115#116#101#114#105#100#32#100#101+
-  #102#97#117#108#116#32#110#117#108#108#59#10#32#32#34#101#120#116#95#114#97+
-  #110#100#111#109#34#32#116#121#112#101#32#98#111#111#108#32#111#102#102#115+
-  #101#116#32#50#48#32#100#101#102#97#117#108#116#32#102#97#108#115#101#59#10+
-  #32#32#47#47#32#116#104#105#115#32#111#110#101#32#105#115#32#102#111#114#32+
-  #109#111#118#105#110#103#32#112#108#97#116#102#111#114#109#115#10#32#32#34+
-  #112#97#110#101#108#105#100#34#32#112#97#110#101#108#32#100#101#102#97#117+
-  #108#116#32#110#117#108#108#59#10#32#32#34#115#105#108#101#110#116#34#32#116+
-  #121#112#101#32#98#111#111#108#32#100#101#102#97#117#108#116#32#116#114#117+
-  #101#59#10#32#32#34#115#111#117#110#100#34#32#116#121#112#101#32#115#116#114+
-  #105#110#103#32#100#101#102#97#117#108#116#32#34#34#59#10#125#10#10#101#110+
-  #117#109#32#84#114#105#103#103#101#114#83#99#111#114#101#84#101#97#109#32+
-  #123#10#32#32#84#82#73#71#71#69#82#95#83#67#79#82#69#95#84#69#65#77#95#77#73+
-  #78#69#95#82#69#68#44#32#47#47#32#48#10#32#32#84#82#73#71#71#69#82#95#83#67+
-  #79#82#69#95#84#69#65#77#95#77#73#78#69#95#66#76#85#69#44#32#47#47#32#49#10+
-  #32#32#84#82#73#71#71#69#82#95#83#67#79#82#69#95#84#69#65#77#95#70#79#82#67+
-  #69#95#82#69#68#44#32#47#47#32#50#10#32#32#84#82#73#71#71#69#82#95#83#67#79+
-  #82#69#95#84#69#65#77#95#70#79#82#67#69#95#66#76#85#69#44#32#47#47#32#51#10+
-  #125#10#10#84#114#105#103#103#101#114#68#97#116#97#32#102#111#114#32#84#82+
-  #73#71#71#69#82#95#83#69#67#82#69#84#32#123#10#125#10#10#84#114#105#103#103+
-  #101#114#68#97#116#97#32#102#111#114#32#84#82#73#71#71#69#82#95#84#69#88#84+
-  #85#82#69#32#123#10#32#32#34#97#99#116#105#118#97#116#101#95#111#110#99#101+
-  #34#32#116#121#112#101#32#98#111#111#108#32#111#102#102#115#101#116#32#48#32+
-  #100#101#102#97#117#108#116#32#102#97#108#115#101#32#119#114#105#116#101#100+
-  #101#102#97#117#108#116#59#10#32#32#34#97#110#105#109#97#116#101#95#111#110+
-  #99#101#34#32#116#121#112#101#32#98#111#111#108#32#111#102#102#115#101#116+
-  #32#49#32#100#101#102#97#117#108#116#32#102#97#108#115#101#32#119#114#105+
-  #116#101#100#101#102#97#117#108#116#59#10#125#10#10#84#114#105#103#103#101+
-  #114#68#97#116#97#32#102#111#114#32#84#82#73#71#71#69#82#95#83#79#85#78#68+
-  #32#123#10#32#32#34#115#111#117#110#100#95#110#97#109#101#34#32#116#121#112+
-  #101#32#99#104#97#114#91#54#52#93#32#111#102#102#115#101#116#32#48#32#119+
-  #114#105#116#101#100#101#102#97#117#108#116#59#10#32#32#34#118#111#108#117+
-  #109#101#34#32#116#121#112#101#32#117#98#121#116#101#32#111#102#102#115#101+
-  #116#32#54#52#32#100#101#102#97#117#108#116#32#48#32#119#114#105#116#101#100+
-  #101#102#97#117#108#116#59#32#47#47#63#63#63#32#100#101#102#97#117#108#116+
-  #32#63#63#63#10#32#32#34#112#97#110#34#32#116#121#112#101#32#117#98#121#116+
-  #101#32#111#102#102#115#101#116#32#54#53#32#100#101#102#97#117#108#116#32#48+
-  #59#10#32#32#34#108#111#99#97#108#34#32#116#121#112#101#32#98#111#111#108#32+
-  #111#102#102#115#101#116#32#54#54#32#100#101#102#97#117#108#116#32#116#114+
-  #117#101#59#32#47#47#63#63#63#32#100#101#102#97#117#108#116#32#63#63#63#10+
-  #32#32#34#112#108#97#121#95#99#111#117#110#116#34#32#116#121#112#101#32#117+
-  #98#121#116#101#32#111#102#102#115#101#116#32#54#55#32#100#101#102#97#117+
-  #108#116#32#49#59#10#32#32#34#115#111#117#110#100#95#115#119#105#116#99#104+
-  #34#32#116#121#112#101#32#98#111#111#108#32#111#102#102#115#101#116#32#54#56+
-  #32#100#101#102#97#117#108#116#32#102#97#108#115#101#59#32#47#47#63#63#63#32+
-  #100#101#102#97#117#108#116#32#63#63#63#10#125#10#10#84#114#105#103#103#101+
-  #114#68#97#116#97#32#102#111#114#32#84#82#73#71#71#69#82#95#83#80#65#87#78+
-  #77#79#78#83#84#69#82#32#123#10#32#32#34#112#111#115#105#116#105#111#110#34+
-  #32#116#121#112#101#32#112#111#105#110#116#32#111#102#102#115#101#116#32#48+
-  #32#97#115#32#116#120#121#32#119#114#105#116#101#100#101#102#97#117#108#116+
-  #59#10#32#32#34#116#121#112#101#34#32#97#108#105#97#115#32#115#112#97#119+
-  #110#77#111#110#115#84#121#112#101#32#116#121#112#101#32#117#98#121#116#101+
-  #32#111#102#102#115#101#116#32#56#32#101#110#117#109#32#77#111#110#115#116+
-  #101#114#32#100#101#102#97#117#108#116#32#77#79#78#83#84#69#82#95#73#77#80+
-  #32#119#114#105#116#101#100#101#102#97#117#108#116#59#10#32#32#34#104#101#97+
-  #108#116#104#34#32#116#121#112#101#32#105#110#116#32#111#102#102#115#101#116+
-  #32#49#50#32#119#114#105#116#101#100#101#102#97#117#108#116#59#10#32#32#34+
-  #100#105#114#101#99#116#105#111#110#34#32#116#121#112#101#32#117#98#121#116+
-  #101#32#111#102#102#115#101#116#32#49#54#32#101#110#117#109#32#68#105#114#84+
-  #121#112#101#32#100#101#102#97#117#108#116#32#68#73#82#95#76#69#70#84#32#119+
-  #114#105#116#101#100#101#102#97#117#108#116#59#10#32#32#34#97#99#116#105#118+
-  #101#34#32#116#121#112#101#32#98#111#111#108#32#111#102#102#115#101#116#32+
-  #49#55#32#100#101#102#97#117#108#116#32#116#114#117#101#59#10#32#32#34#99+
-  #111#117#110#116#34#32#97#108#105#97#115#32#109#111#110#115#67#111#117#110+
-  #116#32#116#121#112#101#32#105#110#116#32#111#102#102#115#101#116#32#50#48+
-  #32#100#101#102#97#117#108#116#32#49#32#119#114#105#116#101#100#101#102#97+
-  #117#108#116#59#10#32#32#34#101#102#102#101#99#116#34#32#116#121#112#101#32+
-  #117#98#121#116#101#32#111#102#102#115#101#116#32#50#52#32#101#110#117#109+
-  #32#69#102#102#101#99#116#65#99#116#105#111#110#32#100#101#102#97#117#108+
-  #116#32#69#70#70#69#67#84#95#78#79#78#69#32#119#114#105#116#101#100#101#102+
-  #97#117#108#116#59#10#32#32#34#109#97#120#34#32#116#121#112#101#32#117#115+
-  #104#111#114#116#32#111#102#102#115#101#116#32#50#54#32#100#101#102#97#117+
-  #108#116#32#49#32#119#114#105#116#101#100#101#102#97#117#108#116#59#10#32#32+
-  #34#100#101#108#97#121#34#32#116#121#112#101#32#117#115#104#111#114#116#32+
-  #111#102#102#115#101#116#32#50#56#32#100#101#102#97#117#108#116#32#49#48#48+
-  #48#32#119#114#105#116#101#100#101#102#97#117#108#116#59#10#32#32#34#98#101+
-  #104#97#118#105#111#117#114#34#32#116#121#112#101#32#117#98#121#116#101#32+
-  #111#102#102#115#101#116#32#51#48#32#101#110#117#109#32#77#111#110#115#116+
-  #101#114#66#101#104#97#118#105#111#117#114#32#100#101#102#97#117#108#116#32+
-  #66#72#95#78#79#82#77#65#76#59#10#125#10#10#84#114#105#103#103#101#114#68#97+
-  #116#97#32#102#111#114#32#84#82#73#71#71#69#82#95#83#80#65#87#78#73#84#69#77+
-  #32#123#10#32#32#34#112#111#115#105#116#105#111#110#34#32#116#121#112#101#32+
-  #112#111#105#110#116#32#111#102#102#115#101#116#32#48#32#97#115#32#116#120+
-  #121#32#119#114#105#116#101#100#101#102#97#117#108#116#59#10#32#32#34#116+
-  #121#112#101#34#32#97#108#105#97#115#32#115#112#97#119#110#73#116#101#109#84+
-  #121#112#101#32#116#121#112#101#32#117#98#121#116#101#32#111#102#102#115#101+
-  #116#32#56#32#101#110#117#109#32#73#116#101#109#32#100#101#102#97#117#108+
-  #116#32#73#84#69#77#95#78#79#78#69#32#119#114#105#116#101#100#101#102#97#117+
-  #108#116#59#10#32#32#34#103#114#97#118#105#116#121#34#32#116#121#112#101#32+
+  #47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47+
+  #47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#47#10#47#47#32#118#97#114+
+  #105#111#117#115#32#116#114#105#103#103#101#114#115#10#84#114#105#103#103+
+  #101#114#68#97#116#97#32#102#111#114#32#84#82#73#71#71#69#82#95#69#88#73#84+
+  #32#123#10#32#32#34#109#97#112#34#32#116#121#112#101#32#99#104#97#114#91#49+
+  #54#93#32#111#102#102#115#101#116#32#48#32#119#114#105#116#101#100#101#102+
+  #97#117#108#116#59#10#125#10#10#84#114#105#103#103#101#114#68#97#116#97#32+
+  #102#111#114#32#84#82#73#71#71#69#82#95#84#69#76#69#80#79#82#84#32#123#10#32+
+  #32#34#116#97#114#103#101#116#34#32#116#121#112#101#32#112#111#105#110#116+
+  #32#111#102#102#115#101#116#32#48#32#119#114#105#116#101#100#101#102#97#117+
+  #108#116#59#10#32#32#34#100#50#100#34#32#116#121#112#101#32#98#111#111#108+
+  #32#111#102#102#115#101#116#32#56#32#100#101#102#97#117#108#116#32#102#97+
+  #108#115#101#59#10#32#32#34#115#105#108#101#110#116#34#32#116#121#112#101#32+
   #98#111#111#108#32#111#102#102#115#101#116#32#57#32#100#101#102#97#117#108+
-  #116#32#116#114#117#101#59#10#32#32#34#100#109#111#110#108#121#34#32#116#121+
-  #112#101#32#98#111#111#108#32#111#102#102#115#101#116#32#49#48#32#100#101+
-  #102#97#117#108#116#32#102#97#108#115#101#59#10#32#32#34#99#111#117#110#116+
-  #34#32#97#108#105#97#115#32#105#116#101#109#67#111#117#110#116#32#116#121+
-  #112#101#32#105#110#116#32#111#102#102#115#101#116#32#49#50#32#100#101#102+
-  #97#117#108#116#32#49#59#10#32#32#34#101#102#102#101#99#116#34#32#116#121+
-  #112#101#32#117#98#121#116#101#32#111#102#102#115#101#116#32#49#54#32#101+
-  #110#117#109#32#69#102#102#101#99#116#65#99#116#105#111#110#32#100#101#102+
-  #97#117#108#116#32#69#70#70#69#67#84#95#78#79#78#69#32#119#114#105#116#101+
-  #100#101#102#97#117#108#116#59#10#32#32#34#109#97#120#34#32#116#121#112#101+
-  #32#117#115#104#111#114#116#32#111#102#102#115#101#116#32#49#56#32#100#101+
-  #102#97#117#108#116#32#49#59#10#32#32#34#100#101#108#97#121#34#32#116#121+
-  #112#101#32#117#115#104#111#114#116#32#111#102#102#115#101#116#32#50#48#32+
-  #100#101#102#97#117#108#116#32#49#48#48#48#32#119#114#105#116#101#100#101+
-  #102#97#117#108#116#59#10#125#10#10#84#114#105#103#103#101#114#68#97#116#97+
-  #32#102#111#114#32#84#82#73#71#71#69#82#95#77#85#83#73#67#32#123#10#32#32#34+
-  #110#97#109#101#34#32#97#108#105#97#115#32#109#117#115#105#99#78#97#109#101+
-  #32#116#121#112#101#32#99#104#97#114#91#54#52#93#32#111#102#102#115#101#116+
-  #32#48#32#119#114#105#116#101#100#101#102#97#117#108#116#59#10#32#32#34#97+
-  #99#116#105#111#110#34#32#97#108#105#97#115#32#109#117#115#105#99#65#99#116+
-  #105#111#110#32#116#121#112#101#32#117#98#121#116#101#32#111#102#102#115#101+
-  #116#32#54#52#32#101#110#117#109#32#84#114#105#103#103#101#114#77#117#115+
-  #105#99#65#99#116#105#111#110#32#119#114#105#116#101#100#101#102#97#117#108+
-  #116#59#10#125#10#10#84#114#105#103#103#101#114#68#97#116#97#32#102#111#114+
-  #32#84#82#73#71#71#69#82#95#80#85#83#72#32#123#10#32#32#34#97#110#103#108+
-  #101#34#32#116#121#112#101#32#117#115#104#111#114#116#32#111#102#102#115#101+
-  #116#32#48#32#119#114#105#116#101#100#101#102#97#117#108#116#59#10#32#32#34+
-  #102#111#114#99#101#34#32#116#121#112#101#32#117#98#121#116#101#32#111#102+
-  #102#115#101#116#32#50#32#119#114#105#116#101#100#101#102#97#117#108#116#59+
-  #10#32#32#34#114#101#115#101#116#95#118#101#108#111#99#105#116#121#34#32#116+
-  #121#112#101#32#98#111#111#108#32#111#102#102#115#101#116#32#51#32#100#101+
+  #116#32#102#97#108#115#101#59#10#32#32#34#100#105#114#101#99#116#105#111#110+
+  #34#32#116#121#112#101#32#117#98#121#116#101#32#111#102#102#115#101#116#32+
+  #49#48#32#101#110#117#109#32#68#105#114#84#121#112#101#32#100#101#102#97#117+
+  #108#116#32#68#73#82#95#76#69#70#84#59#10#125#10#10#84#114#105#103#103#101+
+  #114#68#97#116#97#32#102#111#114#32#40#84#82#73#71#71#69#82#95#79#80#69#78+
+  #68#79#79#82#44#32#84#82#73#71#71#69#82#95#67#76#79#83#69#68#79#79#82#44#32+
+  #84#82#73#71#71#69#82#95#68#79#79#82#44#32#84#82#73#71#71#69#82#95#68#79#79+
+  #82#53#44#32#84#82#73#71#71#69#82#95#67#76#79#83#69#84#82#65#80#44#32#84#82+
+  #73#71#71#69#82#95#84#82#65#80#44#32#84#82#73#71#71#69#82#95#76#73#70#84#85+
+  #80#44#32#84#82#73#71#71#69#82#95#76#73#70#84#68#79#87#78#44#32#84#82#73#71+
+  #71#69#82#95#76#73#70#84#41#32#123#10#32#32#34#112#97#110#101#108#105#100#34+
+  #32#116#121#112#101#32#105#110#116#32#111#102#102#115#101#116#32#48#32#112+
+  #97#110#101#108#32#119#114#105#116#101#100#101#102#97#117#108#116#59#10#32+
+  #32#34#115#105#108#101#110#116#34#32#116#121#112#101#32#98#111#111#108#32+
+  #111#102#102#115#101#116#32#52#32#100#101#102#97#117#108#116#32#102#97#108+
+  #115#101#59#10#32#32#34#100#50#100#34#32#116#121#112#101#32#98#111#111#108+
+  #32#111#102#102#115#101#116#32#53#32#100#101#102#97#117#108#116#32#102#97+
+  #108#115#101#59#10#125#10#10#84#114#105#103#103#101#114#68#97#116#97#32#102+
+  #111#114#32#40#84#82#73#71#71#69#82#95#80#82#69#83#83#44#32#84#82#73#71#71+
+  #69#82#95#79#78#44#32#84#82#73#71#71#69#82#95#79#70#70#44#32#84#82#73#71#71+
+  #69#82#95#79#78#79#70#70#41#32#123#10#32#32#34#112#111#115#105#116#105#111+
+  #110#34#32#116#121#112#101#32#112#111#105#110#116#32#111#102#102#115#101#116+
+  #32#48#32#97#115#32#116#120#121#32#100#101#102#97#117#108#116#32#40#48#32#48+
+  #41#32#119#114#105#116#101#100#101#102#97#117#108#116#59#10#32#32#34#115#105+
+  #122#101#34#32#116#121#112#101#32#115#105#122#101#32#111#102#102#115#101#116+
+  #32#56#32#97#115#32#116#119#104#32#100#101#102#97#117#108#116#32#40#48#32#48+
+  #41#59#10#32#32#34#119#97#105#116#34#32#116#121#112#101#32#117#115#104#111+
+  #114#116#32#111#102#102#115#101#116#32#49#50#32#100#101#102#97#117#108#116+
+  #32#48#59#10#32#32#34#99#111#117#110#116#34#32#97#108#105#97#115#32#112#114+
+  #101#115#115#67#111#117#110#116#32#116#121#112#101#32#117#115#104#111#114+
+  #116#32#111#102#102#115#101#116#32#49#52#32#100#101#102#97#117#108#116#32#48+
+  #59#10#32#32#34#109#111#110#115#116#101#114#105#100#34#32#116#121#112#101#32+
+  #105#110#116#32#111#102#102#115#101#116#32#49#54#32#109#111#110#115#116#101+
+  #114#32#97#115#32#109#111#110#115#116#101#114#105#100#32#100#101#102#97#117+
+  #108#116#32#110#117#108#108#59#10#32#32#34#101#120#116#95#114#97#110#100#111+
+  #109#34#32#116#121#112#101#32#98#111#111#108#32#111#102#102#115#101#116#32+
+  #50#48#32#100#101#102#97#117#108#116#32#102#97#108#115#101#59#10#32#32#47#47+
+  #32#116#104#105#115#32#111#110#101#32#105#115#32#102#111#114#32#109#111#118+
+  #105#110#103#32#112#108#97#116#102#111#114#109#115#10#32#32#34#112#97#110+
+  #101#108#105#100#34#32#112#97#110#101#108#32#100#101#102#97#117#108#116#32+
+  #110#117#108#108#59#10#32#32#34#115#105#108#101#110#116#34#32#116#121#112+
+  #101#32#98#111#111#108#32#100#101#102#97#117#108#116#32#116#114#117#101#59+
+  #10#32#32#34#115#111#117#110#100#34#32#116#121#112#101#32#115#116#114#105+
+  #110#103#32#100#101#102#97#117#108#116#32#34#34#59#10#125#10#10#101#110#117+
+  #109#32#84#114#105#103#103#101#114#83#99#111#114#101#84#101#97#109#32#123#10+
+  #32#32#84#82#73#71#71#69#82#95#83#67#79#82#69#95#84#69#65#77#95#77#73#78#69+
+  #95#82#69#68#44#32#47#47#32#48#10#32#32#84#82#73#71#71#69#82#95#83#67#79#82+
+  #69#95#84#69#65#77#95#77#73#78#69#95#66#76#85#69#44#32#47#47#32#49#10#32#32+
+  #84#82#73#71#71#69#82#95#83#67#79#82#69#95#84#69#65#77#95#70#79#82#67#69#95+
+  #82#69#68#44#32#47#47#32#50#10#32#32#84#82#73#71#71#69#82#95#83#67#79#82#69+
+  #95#84#69#65#77#95#70#79#82#67#69#95#66#76#85#69#44#32#47#47#32#51#10#125#10+
+  #10#84#114#105#103#103#101#114#68#97#116#97#32#102#111#114#32#84#82#73#71#71+
+  #69#82#95#83#69#67#82#69#84#32#123#10#125#10#10#84#114#105#103#103#101#114+
+  #68#97#116#97#32#102#111#114#32#84#82#73#71#71#69#82#95#84#69#88#84#85#82#69+
+  #32#123#10#32#32#34#97#99#116#105#118#97#116#101#95#111#110#99#101#34#32#116+
+  #121#112#101#32#98#111#111#108#32#111#102#102#115#101#116#32#48#32#100#101+
   #102#97#117#108#116#32#102#97#108#115#101#32#119#114#105#116#101#100#101#102+
-  #97#117#108#116#59#10#125#10#10#84#114#105#103#103#101#114#68#97#116#97#32+
-  #102#111#114#32#84#82#73#71#71#69#82#95#83#67#79#82#69#32#123#10#32#32#34#97+
-  #99#116#105#111#110#34#32#97#108#105#97#115#32#115#99#111#114#101#65#99#116+
-  #105#111#110#32#116#121#112#101#32#117#98#121#116#101#32#111#102#102#115#101+
-  #116#32#48#32#101#110#117#109#32#84#114#105#103#103#101#114#83#99#111#114+
-  #101#65#99#116#105#111#110#32#100#101#102#97#117#108#116#32#84#82#73#71#71+
-  #69#82#95#83#67#79#82#69#95#65#67#84#73#79#78#95#65#68#68#32#119#114#105#116+
-  #101#100#101#102#97#117#108#116#59#10#32#32#34#99#111#117#110#116#34#32#97+
-  #108#105#97#115#32#115#99#111#114#101#67#111#117#110#116#32#116#121#112#101+
-  #32#117#98#121#116#101#32#111#102#102#115#101#116#32#49#32#100#101#102#97+
-  #117#108#116#32#49#32#119#114#105#116#101#100#101#102#97#117#108#116#59#10+
-  #32#32#34#116#101#97#109#34#32#97#108#105#97#115#32#115#99#111#114#101#84+
-  #101#97#109#32#116#121#112#101#32#117#98#121#116#101#32#111#102#102#115#101+
-  #116#32#50#32#101#110#117#109#32#84#114#105#103#103#101#114#83#99#111#114+
-  #101#84#101#97#109#32#119#114#105#116#101#100#101#102#97#117#108#116#59#10+
-  #32#32#34#99#111#110#115#111#108#101#34#32#97#108#105#97#115#32#115#99#111+
-  #114#101#67#111#110#32#116#121#112#101#32#98#111#111#108#32#111#102#102#115+
-  #101#116#32#51#32#100#101#102#97#117#108#116#32#102#97#108#115#101#32#119+
-  #114#105#116#101#100#101#102#97#117#108#116#59#10#32#32#34#109#101#115#115+
-  #97#103#101#34#32#97#108#105#97#115#32#115#99#111#114#101#77#115#103#32#116+
-  #121#112#101#32#98#111#111#108#32#111#102#102#115#101#116#32#52#32#100#101+
-  #102#97#117#108#116#32#116#114#117#101#32#119#114#105#116#101#100#101#102#97+
-  #117#108#116#59#10#125#10#10#84#114#105#103#103#101#114#68#97#116#97#32#102+
-  #111#114#32#84#82#73#71#71#69#82#95#77#69#83#83#65#71#69#32#123#10#32#32#34+
-  #107#105#110#100#34#32#116#121#112#101#32#117#98#121#116#101#32#111#102#102+
-  #115#101#116#32#48#32#101#110#117#109#32#84#114#105#103#103#101#114#77#101+
-  #115#115#97#103#101#75#105#110#100#32#100#101#102#97#117#108#116#32#84#82#73+
-  #71#71#69#82#95#77#69#83#83#65#71#69#95#75#73#78#68#95#71#65#77#69#32#119+
-  #114#105#116#101#100#101#102#97#117#108#116#59#10#32#32#34#100#101#115#116+
-  #34#32#97#108#105#97#115#32#109#115#103#68#101#115#116#32#116#121#112#101#32+
-  #117#98#121#116#101#32#101#110#117#109#32#84#114#105#103#103#101#114#77#101+
-  #115#115#97#103#101#68#101#115#116#32#111#102#102#115#101#116#32#49#59#10#32+
-  #32#34#116#101#120#116#34#32#116#121#112#101#32#99#104#97#114#91#49#48#48#93+
-  #32#111#102#102#115#101#116#32#50#32#119#114#105#116#101#100#101#102#97#117+
-  #108#116#59#10#32#32#34#116#105#109#101#34#32#97#108#105#97#115#32#109#115+
-  #103#84#105#109#101#32#116#121#112#101#32#117#115#104#111#114#116#32#111#102+
-  #102#115#101#116#32#49#48#50#32#119#114#105#116#101#100#101#102#97#117#108+
-  #116#59#10#125#10#10#84#114#105#103#103#101#114#68#97#116#97#32#102#111#114+
-  #32#84#82#73#71#71#69#82#95#68#65#77#65#71#69#32#123#10#32#32#34#97#109#111+
-  #117#110#116#34#32#116#121#112#101#32#117#115#104#111#114#116#32#111#102#102+
-  #115#101#116#32#48#32#119#114#105#116#101#100#101#102#97#117#108#116#59#10+
-  #32#32#34#105#110#116#101#114#118#97#108#34#32#116#121#112#101#32#117#115+
-  #104#111#114#116#32#111#102#102#115#101#116#32#50#32#119#114#105#116#101#100+
-  #101#102#97#117#108#116#59#10#125#10#10#84#114#105#103#103#101#114#68#97#116+
-  #97#32#102#111#114#32#84#82#73#71#71#69#82#95#72#69#65#76#84#72#32#123#10#32+
-  #32#34#97#109#111#117#110#116#34#32#116#121#112#101#32#117#115#104#111#114+
-  #116#32#111#102#102#115#101#116#32#48#32#119#114#105#116#101#100#101#102#97+
-  #117#108#116#59#10#32#32#34#105#110#116#101#114#118#97#108#34#32#116#121#112+
-  #101#32#117#115#104#111#114#116#32#111#102#102#115#101#116#32#50#32#119#114+
-  #105#116#101#100#101#102#97#117#108#116#59#10#32#32#34#109#97#120#34#32#97+
-  #108#105#97#115#32#104#101#97#108#77#97#120#32#116#121#112#101#32#98#111#111+
-  #108#32#111#102#102#115#101#116#32#52#32#119#114#105#116#101#100#101#102#97+
-  #117#108#116#59#10#32#32#34#115#105#108#101#110#116#34#32#116#121#112#101#32+
-  #98#111#111#108#32#111#102#102#115#101#116#32#53#32#119#114#105#116#101#100+
+  #97#117#108#116#59#10#32#32#34#97#110#105#109#97#116#101#95#111#110#99#101+
+  #34#32#116#121#112#101#32#98#111#111#108#32#111#102#102#115#101#116#32#49#32+
+  #100#101#102#97#117#108#116#32#102#97#108#115#101#32#119#114#105#116#101#100+
   #101#102#97#117#108#116#59#10#125#10#10#84#114#105#103#103#101#114#68#97#116+
-  #97#32#102#111#114#32#84#82#73#71#71#69#82#95#83#72#79#84#32#123#10#32#32#34+
-  #112#111#115#105#116#105#111#110#34#32#116#121#112#101#32#112#111#105#110+
-  #116#32#111#102#102#115#101#116#32#48#32#97#115#32#116#120#121#32#119#114+
-  #105#116#101#100#101#102#97#117#108#116#59#10#32#32#34#116#121#112#101#34#32+
-  #97#108#105#97#115#32#115#104#111#116#84#121#112#101#32#116#121#112#101#32+
-  #117#98#121#116#101#32#111#102#102#115#101#116#32#56#32#101#110#117#109#32+
-  #84#114#105#103#103#101#114#83#104#111#116#32#119#114#105#116#101#100#101+
-  #102#97#117#108#116#59#10#32#32#34#116#97#114#103#101#116#34#32#97#108#105+
-  #97#115#32#115#104#111#116#84#97#114#103#101#116#32#116#121#112#101#32#117+
-  #98#121#116#101#32#111#102#102#115#101#116#32#57#32#101#110#117#109#32#84+
-  #114#105#103#103#101#114#83#104#111#116#84#97#114#103#101#116#32#119#114#105+
-  #116#101#100#101#102#97#117#108#116#59#10#32#32#34#113#117#105#101#116#34#32+
-  #116#121#112#101#32#110#101#103#98#111#111#108#32#111#102#102#115#101#116#32+
-  #49#48#59#32#47#47#32#110#101#103#98#111#111#108#33#10#32#32#34#97#105#109+
-  #34#32#116#121#112#101#32#98#121#116#101#32#111#102#102#115#101#116#32#49#49+
-  #32#101#110#117#109#32#84#114#105#103#103#101#114#83#104#111#116#65#105#109+
-  #32#100#101#102#97#117#108#116#32#84#82#73#71#71#69#82#95#83#72#79#84#95#65+
-  #73#77#95#68#69#70#65#85#76#84#59#10#32#32#34#112#97#110#101#108#105#100#34+
+  #97#32#102#111#114#32#84#82#73#71#71#69#82#95#83#79#85#78#68#32#123#10#32#32+
+  #34#115#111#117#110#100#95#110#97#109#101#34#32#116#121#112#101#32#99#104#97+
+  #114#91#54#52#93#32#111#102#102#115#101#116#32#48#32#119#114#105#116#101#100+
+  #101#102#97#117#108#116#59#10#32#32#34#118#111#108#117#109#101#34#32#116#121+
+  #112#101#32#117#98#121#116#101#32#111#102#102#115#101#116#32#54#52#32#100+
+  #101#102#97#117#108#116#32#48#32#119#114#105#116#101#100#101#102#97#117#108+
+  #116#59#32#47#47#63#63#63#32#100#101#102#97#117#108#116#32#63#63#63#10#32#32+
+  #34#112#97#110#34#32#116#121#112#101#32#117#98#121#116#101#32#111#102#102+
+  #115#101#116#32#54#53#32#100#101#102#97#117#108#116#32#48#59#10#32#32#34#108+
+  #111#99#97#108#34#32#116#121#112#101#32#98#111#111#108#32#111#102#102#115+
+  #101#116#32#54#54#32#100#101#102#97#117#108#116#32#116#114#117#101#59#32#47+
+  #47#63#63#63#32#100#101#102#97#117#108#116#32#63#63#63#10#32#32#34#112#108+
+  #97#121#95#99#111#117#110#116#34#32#116#121#112#101#32#117#98#121#116#101#32+
+  #111#102#102#115#101#116#32#54#55#32#100#101#102#97#117#108#116#32#49#59#10+
+  #32#32#34#115#111#117#110#100#95#115#119#105#116#99#104#34#32#116#121#112+
+  #101#32#98#111#111#108#32#111#102#102#115#101#116#32#54#56#32#100#101#102#97+
+  #117#108#116#32#102#97#108#115#101#59#32#47#47#63#63#63#32#100#101#102#97+
+  #117#108#116#32#63#63#63#10#125#10#10#84#114#105#103#103#101#114#68#97#116+
+  #97#32#102#111#114#32#84#82#73#71#71#69#82#95#83#80#65#87#78#77#79#78#83#84+
+  #69#82#32#123#10#32#32#34#112#111#115#105#116#105#111#110#34#32#116#121#112+
+  #101#32#112#111#105#110#116#32#111#102#102#115#101#116#32#48#32#97#115#32+
+  #116#120#121#32#119#114#105#116#101#100#101#102#97#117#108#116#59#10#32#32+
+  #34#116#121#112#101#34#32#97#108#105#97#115#32#115#112#97#119#110#77#111#110+
+  #115#84#121#112#101#32#116#121#112#101#32#117#98#121#116#101#32#111#102#102+
+  #115#101#116#32#56#32#101#110#117#109#32#77#111#110#115#116#101#114#32#100+
+  #101#102#97#117#108#116#32#77#79#78#83#84#69#82#95#73#77#80#32#119#114#105+
+  #116#101#100#101#102#97#117#108#116#59#10#32#32#34#104#101#97#108#116#104#34+
   #32#116#121#112#101#32#105#110#116#32#111#102#102#115#101#116#32#49#50#32+
-  #112#97#110#101#108#32#100#101#102#97#117#108#116#32#110#117#108#108#32#119+
-  #114#105#116#101#100#101#102#97#117#108#116#59#10#32#32#34#115#105#103#104+
+  #119#114#105#116#101#100#101#102#97#117#108#116#59#10#32#32#34#100#105#114+
+  #101#99#116#105#111#110#34#32#116#121#112#101#32#117#98#121#116#101#32#111+
+  #102#102#115#101#116#32#49#54#32#101#110#117#109#32#68#105#114#84#121#112+
+  #101#32#100#101#102#97#117#108#116#32#68#73#82#95#76#69#70#84#32#119#114#105+
+  #116#101#100#101#102#97#117#108#116#59#10#32#32#34#97#99#116#105#118#101#34+
+  #32#116#121#112#101#32#98#111#111#108#32#111#102#102#115#101#116#32#49#55#32+
+  #100#101#102#97#117#108#116#32#116#114#117#101#59#10#32#32#34#99#111#117#110+
+  #116#34#32#97#108#105#97#115#32#109#111#110#115#67#111#117#110#116#32#116+
+  #121#112#101#32#105#110#116#32#111#102#102#115#101#116#32#50#48#32#100#101+
+  #102#97#117#108#116#32#49#32#119#114#105#116#101#100#101#102#97#117#108#116+
+  #59#10#32#32#34#101#102#102#101#99#116#34#32#116#121#112#101#32#117#98#121+
+  #116#101#32#111#102#102#115#101#116#32#50#52#32#101#110#117#109#32#69#102+
+  #102#101#99#116#65#99#116#105#111#110#32#100#101#102#97#117#108#116#32#69#70+
+  #70#69#67#84#95#78#79#78#69#32#119#114#105#116#101#100#101#102#97#117#108+
+  #116#59#10#32#32#34#109#97#120#34#32#116#121#112#101#32#117#115#104#111#114+
+  #116#32#111#102#102#115#101#116#32#50#54#32#100#101#102#97#117#108#116#32#49+
+  #32#119#114#105#116#101#100#101#102#97#117#108#116#59#10#32#32#34#100#101+
+  #108#97#121#34#32#116#121#112#101#32#117#115#104#111#114#116#32#111#102#102+
+  #115#101#116#32#50#56#32#100#101#102#97#117#108#116#32#49#48#48#48#32#119+
+  #114#105#116#101#100#101#102#97#117#108#116#59#10#32#32#34#98#101#104#97#118+
+  #105#111#117#114#34#32#116#121#112#101#32#117#98#121#116#101#32#111#102#102+
+  #115#101#116#32#51#48#32#101#110#117#109#32#77#111#110#115#116#101#114#66+
+  #101#104#97#118#105#111#117#114#32#100#101#102#97#117#108#116#32#66#72#95#78+
+  #79#82#77#65#76#59#10#125#10#10#84#114#105#103#103#101#114#68#97#116#97#32+
+  #102#111#114#32#84#82#73#71#71#69#82#95#83#80#65#87#78#73#84#69#77#32#123#10+
+  #32#32#34#112#111#115#105#116#105#111#110#34#32#116#121#112#101#32#112#111+
+  #105#110#116#32#111#102#102#115#101#116#32#48#32#97#115#32#116#120#121#32+
+  #119#114#105#116#101#100#101#102#97#117#108#116#59#10#32#32#34#116#121#112+
+  #101#34#32#97#108#105#97#115#32#115#112#97#119#110#73#116#101#109#84#121#112+
+  #101#32#116#121#112#101#32#117#98#121#116#101#32#111#102#102#115#101#116#32+
+  #56#32#101#110#117#109#32#73#116#101#109#32#100#101#102#97#117#108#116#32#73+
+  #84#69#77#95#78#79#78#69#32#119#114#105#116#101#100#101#102#97#117#108#116+
+  #59#10#32#32#34#103#114#97#118#105#116#121#34#32#116#121#112#101#32#98#111+
+  #111#108#32#111#102#102#115#101#116#32#57#32#100#101#102#97#117#108#116#32+
+  #116#114#117#101#59#10#32#32#34#100#109#111#110#108#121#34#32#116#121#112+
+  #101#32#98#111#111#108#32#111#102#102#115#101#116#32#49#48#32#100#101#102#97+
+  #117#108#116#32#102#97#108#115#101#59#10#32#32#34#99#111#117#110#116#34#32+
+  #97#108#105#97#115#32#105#116#101#109#67#111#117#110#116#32#116#121#112#101+
+  #32#105#110#116#32#111#102#102#115#101#116#32#49#50#32#100#101#102#97#117+
+  #108#116#32#49#59#10#32#32#34#101#102#102#101#99#116#34#32#116#121#112#101+
+  #32#117#98#121#116#101#32#111#102#102#115#101#116#32#49#54#32#101#110#117+
+  #109#32#69#102#102#101#99#116#65#99#116#105#111#110#32#100#101#102#97#117+
+  #108#116#32#69#70#70#69#67#84#95#78#79#78#69#32#119#114#105#116#101#100#101+
+  #102#97#117#108#116#59#10#32#32#34#109#97#120#34#32#116#121#112#101#32#117+
+  #115#104#111#114#116#32#111#102#102#115#101#116#32#49#56#32#100#101#102#97+
+  #117#108#116#32#49#59#10#32#32#34#100#101#108#97#121#34#32#116#121#112#101+
+  #32#117#115#104#111#114#116#32#111#102#102#115#101#116#32#50#48#32#100#101+
+  #102#97#117#108#116#32#49#48#48#48#32#119#114#105#116#101#100#101#102#97#117+
+  #108#116#59#10#125#10#10#84#114#105#103#103#101#114#68#97#116#97#32#102#111+
+  #114#32#84#82#73#71#71#69#82#95#77#85#83#73#67#32#123#10#32#32#34#110#97#109+
+  #101#34#32#97#108#105#97#115#32#109#117#115#105#99#78#97#109#101#32#116#121+
+  #112#101#32#99#104#97#114#91#54#52#93#32#111#102#102#115#101#116#32#48#32+
+  #119#114#105#116#101#100#101#102#97#117#108#116#59#10#32#32#34#97#99#116#105+
+  #111#110#34#32#97#108#105#97#115#32#109#117#115#105#99#65#99#116#105#111#110+
+  #32#116#121#112#101#32#117#98#121#116#101#32#111#102#102#115#101#116#32#54+
+  #52#32#101#110#117#109#32#84#114#105#103#103#101#114#77#117#115#105#99#65#99+
+  #116#105#111#110#32#119#114#105#116#101#100#101#102#97#117#108#116#59#10#125+
+  #10#10#84#114#105#103#103#101#114#68#97#116#97#32#102#111#114#32#84#82#73#71+
+  #71#69#82#95#80#85#83#72#32#123#10#32#32#34#97#110#103#108#101#34#32#116#121+
+  #112#101#32#117#115#104#111#114#116#32#111#102#102#115#101#116#32#48#32#119+
+  #114#105#116#101#100#101#102#97#117#108#116#59#10#32#32#34#102#111#114#99+
+  #101#34#32#116#121#112#101#32#117#98#121#116#101#32#111#102#102#115#101#116+
+  #32#50#32#119#114#105#116#101#100#101#102#97#117#108#116#59#10#32#32#34#114+
+  #101#115#101#116#95#118#101#108#111#99#105#116#121#34#32#116#121#112#101#32+
+  #98#111#111#108#32#111#102#102#115#101#116#32#51#32#100#101#102#97#117#108+
+  #116#32#102#97#108#115#101#32#119#114#105#116#101#100#101#102#97#117#108#116+
+  #59#10#125#10#10#84#114#105#103#103#101#114#68#97#116#97#32#102#111#114#32+
+  #84#82#73#71#71#69#82#95#83#67#79#82#69#32#123#10#32#32#34#97#99#116#105#111+
+  #110#34#32#97#108#105#97#115#32#115#99#111#114#101#65#99#116#105#111#110#32+
+  #116#121#112#101#32#117#98#121#116#101#32#111#102#102#115#101#116#32#48#32+
+  #101#110#117#109#32#84#114#105#103#103#101#114#83#99#111#114#101#65#99#116+
+  #105#111#110#32#100#101#102#97#117#108#116#32#84#82#73#71#71#69#82#95#83#67+
+  #79#82#69#95#65#67#84#73#79#78#95#65#68#68#32#119#114#105#116#101#100#101+
+  #102#97#117#108#116#59#10#32#32#34#99#111#117#110#116#34#32#97#108#105#97+
+  #115#32#115#99#111#114#101#67#111#117#110#116#32#116#121#112#101#32#117#98+
+  #121#116#101#32#111#102#102#115#101#116#32#49#32#100#101#102#97#117#108#116+
+  #32#49#32#119#114#105#116#101#100#101#102#97#117#108#116#59#10#32#32#34#116+
+  #101#97#109#34#32#97#108#105#97#115#32#115#99#111#114#101#84#101#97#109#32+
+  #116#121#112#101#32#117#98#121#116#101#32#111#102#102#115#101#116#32#50#32+
+  #101#110#117#109#32#84#114#105#103#103#101#114#83#99#111#114#101#84#101#97+
+  #109#32#119#114#105#116#101#100#101#102#97#117#108#116#59#10#32#32#34#99#111+
+  #110#115#111#108#101#34#32#97#108#105#97#115#32#115#99#111#114#101#67#111+
+  #110#32#116#121#112#101#32#98#111#111#108#32#111#102#102#115#101#116#32#51+
+  #32#100#101#102#97#117#108#116#32#102#97#108#115#101#32#119#114#105#116#101+
+  #100#101#102#97#117#108#116#59#10#32#32#34#109#101#115#115#97#103#101#34#32+
+  #97#108#105#97#115#32#115#99#111#114#101#77#115#103#32#116#121#112#101#32#98+
+  #111#111#108#32#111#102#102#115#101#116#32#52#32#100#101#102#97#117#108#116+
+  #32#116#114#117#101#32#119#114#105#116#101#100#101#102#97#117#108#116#59#10+
+  #125#10#10#84#114#105#103#103#101#114#68#97#116#97#32#102#111#114#32#84#82+
+  #73#71#71#69#82#95#77#69#83#83#65#71#69#32#123#10#32#32#34#107#105#110#100+
+  #34#32#116#121#112#101#32#117#98#121#116#101#32#111#102#102#115#101#116#32+
+  #48#32#101#110#117#109#32#84#114#105#103#103#101#114#77#101#115#115#97#103+
+  #101#75#105#110#100#32#100#101#102#97#117#108#116#32#84#82#73#71#71#69#82#95+
+  #77#69#83#83#65#71#69#95#75#73#78#68#95#71#65#77#69#32#119#114#105#116#101+
+  #100#101#102#97#117#108#116#59#10#32#32#34#100#101#115#116#34#32#97#108#105+
+  #97#115#32#109#115#103#68#101#115#116#32#116#121#112#101#32#117#98#121#116+
+  #101#32#101#110#117#109#32#84#114#105#103#103#101#114#77#101#115#115#97#103+
+  #101#68#101#115#116#32#111#102#102#115#101#116#32#49#59#10#32#32#34#116#101+
+  #120#116#34#32#116#121#112#101#32#99#104#97#114#91#49#48#48#93#32#111#102+
+  #102#115#101#116#32#50#32#119#114#105#116#101#100#101#102#97#117#108#116#59+
+  #10#32#32#34#116#105#109#101#34#32#97#108#105#97#115#32#109#115#103#84#105+
+  #109#101#32#116#121#112#101#32#117#115#104#111#114#116#32#111#102#102#115+
+  #101#116#32#49#48#50#32#119#114#105#116#101#100#101#102#97#117#108#116#59#10+
+  #125#10#10#84#114#105#103#103#101#114#68#97#116#97#32#102#111#114#32#84#82+
+  #73#71#71#69#82#95#68#65#77#65#71#69#32#123#10#32#32#34#97#109#111#117#110+
   #116#34#32#116#121#112#101#32#117#115#104#111#114#116#32#111#102#102#115#101+
-  #116#32#49#54#59#10#32#32#34#97#110#103#108#101#34#32#116#121#112#101#32#117+
-  #115#104#111#114#116#32#111#102#102#115#101#116#32#49#56#59#10#32#32#34#119+
-  #97#105#116#34#32#116#121#112#101#32#117#115#104#111#114#116#32#111#102#102+
-  #115#101#116#32#50#48#59#10#32#32#34#97#99#99#117#114#97#99#121#34#32#116+
-  #121#112#101#32#117#115#104#111#114#116#32#111#102#102#115#101#116#32#50#50+
-  #59#10#32#32#34#97#109#109#111#34#32#116#121#112#101#32#117#115#104#111#114+
-  #116#32#111#102#102#115#101#116#32#50#52#59#10#32#32#34#114#101#108#111#97+
-  #100#34#32#116#121#112#101#32#117#115#104#111#114#116#32#111#102#102#115#101+
-  #116#32#50#54#59#10#125#10#10#84#114#105#103#103#101#114#68#97#116#97#32#102+
-  #111#114#32#84#82#73#71#71#69#82#95#69#70#70#69#67#84#32#123#10#32#32#34#99+
-  #111#117#110#116#34#32#97#108#105#97#115#32#70#88#67#111#117#110#116#32#116+
-  #121#112#101#32#117#98#121#116#101#32#111#102#102#115#101#116#32#48#32#119+
-  #114#105#116#101#100#101#102#97#117#108#116#59#10#32#32#34#116#121#112#101+
-  #34#32#97#108#105#97#115#32#70#88#84#121#112#101#32#116#121#112#101#32#117+
-  #98#121#116#101#32#111#102#102#115#101#116#32#49#32#101#110#117#109#32#84+
-  #114#105#103#103#101#114#69#102#102#101#99#116#32#100#101#102#97#117#108#116+
-  #32#84#82#73#71#71#69#82#95#69#70#70#69#67#84#95#80#65#82#84#73#67#76#69#32+
-  #119#114#105#116#101#100#101#102#97#117#108#116#59#10#32#32#34#115#117#98+
-  #116#121#112#101#34#32#97#108#105#97#115#32#70#88#83#117#98#84#121#112#101+
-  #32#116#121#112#101#32#117#98#121#116#101#32#111#102#102#115#101#116#32#50+
-  #32#101#110#117#109#32#84#114#105#103#103#101#114#69#102#102#101#99#116#84+
-  #121#112#101#32#100#101#102#97#117#108#116#32#84#82#73#71#71#69#82#95#69#70+
-  #70#69#67#84#95#83#80#65#82#75#32#119#114#105#116#101#100#101#102#97#117#108+
-  #116#59#10#32#32#34#114#101#100#34#32#97#108#105#97#115#32#70#88#82#101#100+
-  #32#116#121#112#101#32#117#98#121#116#101#32#111#102#102#115#101#116#32#51+
-  #32#119#114#105#116#101#100#101#102#97#117#108#116#59#10#32#32#34#103#114+
-  #101#101#110#34#32#97#108#105#97#115#32#70#88#71#114#101#101#110#32#116#121+
-  #112#101#32#117#98#121#116#101#32#111#102#102#115#101#116#32#52#32#119#114+
-  #105#116#101#100#101#102#97#117#108#116#59#10#32#32#34#98#108#117#101#34#32+
-  #97#108#105#97#115#32#70#88#66#108#117#101#32#116#121#112#101#32#117#98#121+
-  #116#101#32#111#102#102#115#101#116#32#53#32#119#114#105#116#101#100#101#102+
-  #97#117#108#116#59#10#32#32#34#112#111#115#34#32#97#108#105#97#115#32#70#88+
-  #80#111#115#32#116#121#112#101#32#117#98#121#116#101#32#111#102#102#115#101+
-  #116#32#54#32#101#110#117#109#32#84#114#105#103#103#101#114#69#102#102#101+
-  #99#116#80#111#115#32#100#101#102#97#117#108#116#32#84#82#73#71#71#69#82#95+
-  #69#70#70#69#67#84#95#80#79#83#95#67#69#78#84#69#82#32#119#114#105#116#101+
-  #100#101#102#97#117#108#116#59#10#32#32#34#119#97#105#116#34#32#116#121#112+
-  #101#32#117#115#104#111#114#116#32#111#102#102#115#101#116#32#56#32#119#114+
-  #105#116#101#100#101#102#97#117#108#116#59#10#32#32#34#118#101#108#95#120#34+
-  #32#116#121#112#101#32#98#121#116#101#32#111#102#102#115#101#116#32#49#48#32+
-  #119#114#105#116#101#100#101#102#97#117#108#116#59#10#32#32#34#118#101#108+
-  #95#121#34#32#116#121#112#101#32#98#121#116#101#32#111#102#102#115#101#116+
-  #32#49#49#32#119#114#105#116#101#100#101#102#97#117#108#116#59#10#32#32#34+
-  #115#112#114#101#97#100#95#108#34#32#116#121#112#101#32#117#98#121#116#101+
-  #32#111#102#102#115#101#116#32#49#50#32#119#114#105#116#101#100#101#102#97+
-  #117#108#116#59#10#32#32#34#115#112#114#101#97#100#95#114#34#32#116#121#112+
-  #101#32#117#98#121#116#101#32#111#102#102#115#101#116#32#49#51#32#119#114+
-  #105#116#101#100#101#102#97#117#108#116#59#10#32#32#34#115#112#114#101#97+
-  #100#95#117#34#32#116#121#112#101#32#117#98#121#116#101#32#111#102#102#115+
-  #101#116#32#49#52#32#119#114#105#116#101#100#101#102#97#117#108#116#59#10#32+
-  #32#34#115#112#114#101#97#100#95#100#34#32#116#121#112#101#32#117#98#121#116+
-  #101#32#111#102#102#115#101#116#32#49#53#32#119#114#105#116#101#100#101#102+
-  #97#117#108#116#59#10#125#10
+  #116#32#48#32#119#114#105#116#101#100#101#102#97#117#108#116#59#10#32#32#34+
+  #105#110#116#101#114#118#97#108#34#32#116#121#112#101#32#117#115#104#111#114+
+  #116#32#111#102#102#115#101#116#32#50#32#119#114#105#116#101#100#101#102#97+
+  #117#108#116#59#10#125#10#10#84#114#105#103#103#101#114#68#97#116#97#32#102+
+  #111#114#32#84#82#73#71#71#69#82#95#72#69#65#76#84#72#32#123#10#32#32#34#97+
+  #109#111#117#110#116#34#32#116#121#112#101#32#117#115#104#111#114#116#32#111+
+  #102#102#115#101#116#32#48#32#119#114#105#116#101#100#101#102#97#117#108#116+
+  #59#10#32#32#34#105#110#116#101#114#118#97#108#34#32#116#121#112#101#32#117+
+  #115#104#111#114#116#32#111#102#102#115#101#116#32#50#32#119#114#105#116#101+
+  #100#101#102#97#117#108#116#59#10#32#32#34#109#97#120#34#32#97#108#105#97+
+  #115#32#104#101#97#108#77#97#120#32#116#121#112#101#32#98#111#111#108#32#111+
+  #102#102#115#101#116#32#52#32#119#114#105#116#101#100#101#102#97#117#108#116+
+  #59#10#32#32#34#115#105#108#101#110#116#34#32#116#121#112#101#32#98#111#111+
+  #108#32#111#102#102#115#101#116#32#53#32#119#114#105#116#101#100#101#102#97+
+  #117#108#116#59#10#125#10#10#84#114#105#103#103#101#114#68#97#116#97#32#102+
+  #111#114#32#84#82#73#71#71#69#82#95#83#72#79#84#32#123#10#32#32#34#112#111+
+  #115#105#116#105#111#110#34#32#116#121#112#101#32#112#111#105#110#116#32#111+
+  #102#102#115#101#116#32#48#32#97#115#32#116#120#121#32#119#114#105#116#101+
+  #100#101#102#97#117#108#116#59#10#32#32#34#116#121#112#101#34#32#97#108#105+
+  #97#115#32#115#104#111#116#84#121#112#101#32#116#121#112#101#32#117#98#121+
+  #116#101#32#111#102#102#115#101#116#32#56#32#101#110#117#109#32#84#114#105+
+  #103#103#101#114#83#104#111#116#32#119#114#105#116#101#100#101#102#97#117+
+  #108#116#59#10#32#32#34#116#97#114#103#101#116#34#32#97#108#105#97#115#32+
+  #115#104#111#116#84#97#114#103#101#116#32#116#121#112#101#32#117#98#121#116+
+  #101#32#111#102#102#115#101#116#32#57#32#101#110#117#109#32#84#114#105#103+
+  #103#101#114#83#104#111#116#84#97#114#103#101#116#32#119#114#105#116#101#100+
+  #101#102#97#117#108#116#59#10#32#32#34#113#117#105#101#116#34#32#116#121#112+
+  #101#32#110#101#103#98#111#111#108#32#111#102#102#115#101#116#32#49#48#59#32+
+  #47#47#32#110#101#103#98#111#111#108#33#10#32#32#34#97#105#109#34#32#116#121+
+  #112#101#32#98#121#116#101#32#111#102#102#115#101#116#32#49#49#32#101#110+
+  #117#109#32#84#114#105#103#103#101#114#83#104#111#116#65#105#109#32#100#101+
+  #102#97#117#108#116#32#84#82#73#71#71#69#82#95#83#72#79#84#95#65#73#77#95#68+
+  #69#70#65#85#76#84#59#10#32#32#34#112#97#110#101#108#105#100#34#32#116#121+
+  #112#101#32#105#110#116#32#111#102#102#115#101#116#32#49#50#32#112#97#110+
+  #101#108#32#100#101#102#97#117#108#116#32#110#117#108#108#32#119#114#105#116+
+  #101#100#101#102#97#117#108#116#59#10#32#32#34#115#105#103#104#116#34#32#116+
+  #121#112#101#32#117#115#104#111#114#116#32#111#102#102#115#101#116#32#49#54+
+  #59#10#32#32#34#97#110#103#108#101#34#32#116#121#112#101#32#117#115#104#111+
+  #114#116#32#111#102#102#115#101#116#32#49#56#59#10#32#32#34#119#97#105#116+
+  #34#32#116#121#112#101#32#117#115#104#111#114#116#32#111#102#102#115#101#116+
+  #32#50#48#59#10#32#32#34#97#99#99#117#114#97#99#121#34#32#116#121#112#101#32+
+  #117#115#104#111#114#116#32#111#102#102#115#101#116#32#50#50#59#10#32#32#34+
+  #97#109#109#111#34#32#116#121#112#101#32#117#115#104#111#114#116#32#111#102+
+  #102#115#101#116#32#50#52#59#10#32#32#34#114#101#108#111#97#100#34#32#116+
+  #121#112#101#32#117#115#104#111#114#116#32#111#102#102#115#101#116#32#50#54+
+  #59#10#125#10#10#84#114#105#103#103#101#114#68#97#116#97#32#102#111#114#32+
+  #84#82#73#71#71#69#82#95#69#70#70#69#67#84#32#123#10#32#32#34#99#111#117#110+
+  #116#34#32#97#108#105#97#115#32#70#88#67#111#117#110#116#32#116#121#112#101+
+  #32#117#98#121#116#101#32#111#102#102#115#101#116#32#48#32#119#114#105#116+
+  #101#100#101#102#97#117#108#116#59#10#32#32#34#116#121#112#101#34#32#97#108+
+  #105#97#115#32#70#88#84#121#112#101#32#116#121#112#101#32#117#98#121#116#101+
+  #32#111#102#102#115#101#116#32#49#32#101#110#117#109#32#84#114#105#103#103+
+  #101#114#69#102#102#101#99#116#32#100#101#102#97#117#108#116#32#84#82#73#71+
+  #71#69#82#95#69#70#70#69#67#84#95#80#65#82#84#73#67#76#69#32#119#114#105#116+
+  #101#100#101#102#97#117#108#116#59#10#32#32#34#115#117#98#116#121#112#101#34+
+  #32#97#108#105#97#115#32#70#88#83#117#98#84#121#112#101#32#116#121#112#101+
+  #32#117#98#121#116#101#32#111#102#102#115#101#116#32#50#32#101#110#117#109+
+  #32#84#114#105#103#103#101#114#69#102#102#101#99#116#84#121#112#101#32#100+
+  #101#102#97#117#108#116#32#84#82#73#71#71#69#82#95#69#70#70#69#67#84#95#83+
+  #80#65#82#75#32#119#114#105#116#101#100#101#102#97#117#108#116#59#10#32#32+
+  #34#114#101#100#34#32#97#108#105#97#115#32#70#88#82#101#100#32#116#121#112+
+  #101#32#117#98#121#116#101#32#111#102#102#115#101#116#32#51#32#119#114#105+
+  #116#101#100#101#102#97#117#108#116#59#10#32#32#34#103#114#101#101#110#34#32+
+  #97#108#105#97#115#32#70#88#71#114#101#101#110#32#116#121#112#101#32#117#98+
+  #121#116#101#32#111#102#102#115#101#116#32#52#32#119#114#105#116#101#100#101+
+  #102#97#117#108#116#59#10#32#32#34#98#108#117#101#34#32#97#108#105#97#115#32+
+  #70#88#66#108#117#101#32#116#121#112#101#32#117#98#121#116#101#32#111#102+
+  #102#115#101#116#32#53#32#119#114#105#116#101#100#101#102#97#117#108#116#59+
+  #10#32#32#34#112#111#115#34#32#97#108#105#97#115#32#70#88#80#111#115#32#116+
+  #121#112#101#32#117#98#121#116#101#32#111#102#102#115#101#116#32#54#32#101+
+  #110#117#109#32#84#114#105#103#103#101#114#69#102#102#101#99#116#80#111#115+
+  #32#100#101#102#97#117#108#116#32#84#82#73#71#71#69#82#95#69#70#70#69#67#84+
+  #95#80#79#83#95#67#69#78#84#69#82#32#119#114#105#116#101#100#101#102#97#117+
+  #108#116#59#10#32#32#34#119#97#105#116#34#32#116#121#112#101#32#117#115#104+
+  #111#114#116#32#111#102#102#115#101#116#32#56#32#119#114#105#116#101#100#101+
+  #102#97#117#108#116#59#10#32#32#34#118#101#108#95#120#34#32#116#121#112#101+
+  #32#98#121#116#101#32#111#102#102#115#101#116#32#49#48#32#119#114#105#116+
+  #101#100#101#102#97#117#108#116#59#10#32#32#34#118#101#108#95#121#34#32#116+
+  #121#112#101#32#98#121#116#101#32#111#102#102#115#101#116#32#49#49#32#119+
+  #114#105#116#101#100#101#102#97#117#108#116#59#10#32#32#34#115#112#114#101+
+  #97#100#95#108#34#32#116#121#112#101#32#117#98#121#116#101#32#111#102#102+
+  #115#101#116#32#49#50#32#119#114#105#116#101#100#101#102#97#117#108#116#59+
+  #10#32#32#34#115#112#114#101#97#100#95#114#34#32#116#121#112#101#32#117#98+
+  #121#116#101#32#111#102#102#115#101#116#32#49#51#32#119#114#105#116#101#100+
+  #101#102#97#117#108#116#59#10#32#32#34#115#112#114#101#97#100#95#117#34#32+
+  #116#121#112#101#32#117#98#121#116#101#32#111#102#102#115#101#116#32#49#52+
+  #32#119#114#105#116#101#100#101#102#97#117#108#116#59#10#32#32#34#115#112+
+  #114#101#97#100#95#100#34#32#116#121#112#101#32#117#98#121#116#101#32#111+
+  #102#102#115#101#116#32#49#53#32#119#114#105#116#101#100#101#102#97#117#108+
+  #116#59#10#125#10
 ;
\ No newline at end of file
index f539536ce0ffe98da543820f560365b6de8a8279..bac4e4a8153feb04faf29362eb0fbfc1295766c1 100644 (file)
@@ -39,6 +39,13 @@ type
       TTBegin = 8; // left curly
       TTEnd = 9; // right curly
       TTDelim = 10; // other delimiters
+      //
+      TTLogAnd = 11; // &&
+      TTLogOr = 12; // ||
+      TTLessEqu = 13; // <=
+      TTGreatEqu = 14; // >=
+      TTNotEqu = 15; // !=
+      TTEqu = 16; // ==
 
   private
     mLine, mCol: Integer;
@@ -67,6 +74,7 @@ type
     function skipBlanks (): Boolean; // ...and comments; returns `false` on eof
 
     function skipToken (): Boolean; // returns `false` on eof
+    //function skipToken1 (): Boolean;
 
     function expectId (): AnsiString;
     procedure expectId (const aid: AnsiString);
@@ -83,6 +91,9 @@ type
     function expectDelim (const ch: AnsiChar): AnsiChar;
     function eatDelim (const ch: AnsiChar): Boolean;
 
+  public
+    property allowSignedNumbers: Boolean read mAllowSignedNumbers write mAllowSignedNumbers;
+
   public
     property col: Integer read mCol;
     property line: Integer read mLine;
@@ -336,6 +347,16 @@ begin
 end;
 
 
+{
+function TTextParser.skipToken (): Boolean;
+begin
+  writeln('getting token...');
+  result := skipToken1();
+  writeln('  got token: ', mTokType, ' <', mTokStr, '> : <', mTokChar, '>');
+end;
+}
+
+
 function TTextParser.skipToken (): Boolean;
 
   procedure parseInt ();
@@ -503,16 +524,27 @@ begin
   if (curChar = '_') or ((curChar >= 'A') and (curChar <= 'Z')) or ((curChar >= 'a') and (curChar <= 'z')) or (curChar >= #128) then begin parseId(); exit; end;
 
   // known delimiters?
-  case curChar of
+  mTokChar := curChar;
+  mTokType := TTDelim;
+  skipChar();
+  if (curChar = '=') then
+  begin
+    case mTokChar of
+      '<': begin mTokType := TTLessEqu; mTokStr := '<='; skipChar(); exit; end;
+      '>': begin mTokType := TTGreatEqu; mTokStr := '>='; skipChar(); exit; end;
+      '!': begin mTokType := TTNotEqu; mTokStr := '!='; skipChar(); exit; end;
+      '=': begin mTokType := TTEqu; mTokStr := '=='; skipChar(); exit; end;
+    end;
+  end;
+  case mTokChar of
     ',': mTokType := TTComma;
     ':': mTokType := TTColon;
     ';': mTokType := TTSemi;
     '{': mTokType := TTBegin;
     '}': mTokType := TTEnd;
-    else mTokType := TTDelim;
+    '&': if (curChar = '&') then begin mTokType := TTLogAnd; mTokStr := '&&'; skipChar(); exit; end;
+    '|': if (curChar = '|') then begin mTokType := TTLogOr; mTokStr := '||'; skipChar(); exit; end;
   end;
-  mTokChar := curChar;
-  skipChar();
 end;
 
 
index 1a4850593b81dcf21d215761a613be7e971bc713..28b035c12981d590ae9593fbbb253d92797c34a5 100644 (file)
@@ -265,14 +265,21 @@ begin
     writeln('FATAL: mapdef not found!');
   end;
 
+  writeln('parsing "mapdef.txt"...');
   pr := TFileTextParser.Create(st, false); // don't own
   try
     dfmapdef := TDynMapDef.Create(pr);
-  except on e: Exception do
-    begin
-      writeln('ERROR at (', pr.tokLine, ',', pr.tokCol, '): ', e.message);
-      Halt(1);
-    end;
+  except
+    on e: TDynParseException do
+      begin
+        writeln('ERROR at (', e.tokLine, ',', e.tokCol, '): ', e.message);
+        Halt(1);
+      end;
+    on e: Exception do
+      begin
+        writeln('ERROR: ', e.message);
+        Halt(1);
+      end;
   end;
   pr.Free();