anchor.diff:    FCaching := not FCaching;
     // todo
   end;
  +
  +procedure TPathMap.GrowNodeStorage(var Buffer: TPathMapNodeStorage);
  +var
  +  Allocated: NativeUInt;
  +  Count: NativeUInt;
  +  LastAllocation: Boolean;
  +  Node: PPathMapNode;
  +begin
  +  Allocated := Buffer.Allocated;
  +  if (@Buffer <> @FInfo.NodeStorage) then
  +  if (Buffer.NewNode <> FInfo.NodeStorage.MaximumNode) or
  +     (Allocated <> FInfo.NodeStorage.Allocated) then
  +    CPFException('Incorrect node storage data');
  +
  +  if (Allocated >= High(FInfo.NodeStorage.Buffers)) then
  +    RaiseOutOfMemory(FCallAddress);
  +
  +  Count := NODESTORAGE_INFO[Allocated].Previous + NODESTORAGE_INFO[Allocated].Count;
  +  LastAllocation := (Count >= FCellCount);
  +  if (LastAllocation) then Count := FCellCount;
  +  Dec(Count, NODESTORAGE_INFO[Allocated].Previous);
  +
  +  CPFGetMem(Pointer(FInfo.NodeStorage.Buffers[Allocated]), Count * SizeOf(TPathMapNode));
  +  FInfo.NodeStorage.Allocated := Allocated + 1;
  +  Node := Pointer(FInfo.NodeStorage.Buffers[Allocated]);
  +  FInfo.NodeStorage.NewNode := Node;
  +
  +  {$ifdef LARGEINT}
  +    FInfo.NodeStorage.LargeModifier :=
  +      (NativeInt(Allocated) shl LARGE_NODEPTR_OFFSET) - NativeInt(Node);
  +  {$endif}
  +
  +  Inc(Node, NativeInt(Count) - 1 + Ord(LastAllocation));
  +  FInfo.NodeStorage.MaximumNode := Node;
  +
  +  //  copy to buffer
  +  if (@Buffer <> @FInfo.NodeStorage) then
  +  begin
  +    Buffer.NewNode := FInfo.NodeStorage.NewNode;
  +    Buffer.MaximumNode := FInfo.NodeStorage.MaximumNode;
  +    Buffer.Allocated := Allocated + 1{FInfo.NodeStorage.Allocated};
  +    {$ifdef LARGEINT}
  +      Buffer.LargeModifier := FInfo.NodeStorage.LargeModifier;
  +    {$endif}
  +    Buffer.Buffers[Allocated] := FInfo.NodeStorage.Buffers[Allocated];
  +  end;
  +end;
  +
  +function TPathMap.AllocateNode(const X, Y: NativeInt): PPathMapNode;
  +var
  +  Coordinates: NativeUInt;
  +  Cell: PPathMapCell;
  +  ChildNodePtr: NativeUInt;
  +  NodeInfo: NativeUInt;
  +begin
  +  Coordinates := Y + (X shl 16);
  +  Cell := @FInfo.Cells[X + FInfo.MapWidth * Y];
  +
  +  ChildNodePtr := Cell.NodePtr; // clear bits?
  +  if (ChildNodePtr = 0) then
  +  begin
  +    Result := FInfo.NodeStorage.NewNode;
  +    Cardinal(Result.Coordinates) := Coordinates;
  +    {$ifdef LARGEINT}
  +      Cell.NodePtr := NativeUInt(NativeInt(Result) + FInfo.NodeStorage.LargeModifier);
  +    {$else}
  +      Cell.NodePtr := NativeUInt(Result);
  +    {$endif}
  +
  +    // tile, mask --> (0, mask, 0, tile)
  +    NodeInfo := PWord(Cell)^;
  +    NodeInfo := (NodeInfo + (NodeInfo shl 24)) and Integer($00ff00ff);
  +    Result.NodeInfo := NodeInfo;
  +
  +    // set next allocable node
  +    if (Result = FInfo.NodeStorage.MaximumNode) then
  +    begin
  +      GrowNodeStorage(FInfo.NodeStorage);
  +    end else
  +    begin
  +      Inc(Result);
  +      FInfo.NodeStorage.NewNode := Result;
  +      Dec(Result);
  +    end;
  +  end else
  +  begin
  +    {$ifdef LARGEINT}
  +      Result := Pointer(
  +        (FInfo.NodeStorage.Buffers[ChildNodePtr shr LARGE_NODEPTR_OFFSET]) +
  +        (ChildNodePtr and NODEPTR_MASK) );
  +    {$else}
  +      Result := Pointer(ChildNodePtr and NODEPTR_MASK);
  +    {$endif}
  +  end;
  +end;
  +
  +function TPathMap.CalculateHeuristics(const Start, Finish: TPoint): NativeInt;
  +var
  +  dX, dY, X, Y: NativeInt;
  +  Mask: NativeInt;
  +begin
  +  dY := Start.Y - Finish.Y;
  +  dX := Start.X - Finish.X;
  +
  +  // Y := Abs(dY)
  +  Mask := -(dY shr HIGH_NATIVE_BIT);
  +  Y := (dY xor Mask) - Mask;
  +
  +  // X := Abs(dY)
  +  Mask := -(dX shr HIGH_NATIVE_BIT);
  +  X := (dX xor Mask) - Mask;
  +
  +  if (Self.FKind < mkHexagonal) then
  +  begin
  +    if (X <= Y) then
  +    begin
  +      Result := X * FInfo.HeuristicsDiagonal + (Y - X) * FInfo.HeuristicsLine;
  +    end else
  +    begin
  +      Result := Y * FInfo.HeuristicsDiagonal + (X - Y) * FInfo.HeuristicsLine;
  +    end;
  +  end else
  +  begin
  +    X := X - ((Mask xor Finish.Y) and Y and 1) - (Y shr 1);
  +    Result := Y + (X and ((X shr HIGH_NATIVE_BIT) - 1));
  +    Result := Result * FInfo.HeuristicsLine;
  +  end;
  +end;
  +
  +(*procedure TPathMap.ClearMapCells(Node: PPathMapNode; Count: NativeUInt);
  +var
  +  TopNode: PPathMapNode;
  +  NodeInfo{XY}: NativeUInt;
  +  MapWidth: NativeInt;
  +  Cells: PPathMapCellArray;
  +begin
  +  TopNode := Node;
  +  Inc(TopNode, Count);
  +
  +  Cells := FInfo.Cells;
  +  MapWidth := FInfo.MapWidth;
  +
  +  while (Node <> TopNode) do
  +  begin
  +    NodeInfo{XY} := Cardinal(Node.Coordinates);
  +    Cells[(NativeInt(NodeInfo) shr 16){X} + MapWidth * {Y}Word(NodeInfo)].NodePtr := 0;
  +
  +    Inc(Node);
  +  end;
  +end;
  +
  +procedure TPathMap.ClearMapCells(Node: PPathMapNode{as list});
  +var
  +  NodeInfo{XY}: NativeUInt;
  +  MapWidth: NativeInt;
  +  Cells: PPathMapCellArray;
  +begin
  +  Cells := FInfo.Cells;
  +  MapWidth := FInfo.MapWidth;
  +
  +  while (Node <> nil) do
  +  begin
  +    NodeInfo{XY} := Cardinal(Node.Coordinates);
  +    Cells[(NativeInt(NodeInfo) shr 16){X} + MapWidth * {Y}Word(NodeInfo)].NodePtr := 0;
  +
  +    Node := Node.Next;
  +  end;
  +end; *)
   
   function TPathMap.DoFindPath(StartNode: PPathMapNode): PPathMapNode;
   label
  
positive.code:   {$endif}
  end;
  
  
  {$ifdef CPFLIB}
  var
  
negative.code: {$ifdef CPFLIB}procedure{$else}constructor{$endif}
    TPathMap.Create(const AWidth, AHeight: Word; const AKind: TPathMapKind;
      const AHighTile: TPathMapTile);
  var
    i: NativeInt;
    Size: NativeUInt;
  begin
    {$ifNdef CPFLIB}
      FCallAddress := ReturnAddress;
      inherited Create;
    {$endif}
  
    // arguments test
    begin
      FCellCount := NativeUInt(AWidth) * NativeUInt(AHeight);
  
      if (FCellCount = 0) then
        CPFExceptionFmt('Incorrect map size: %dx%d', [AWidth, AHeight]);
  
      if (FCellCount > CELLCOUNT_LIMIT) then
        CPFExceptionFmt('Too large map size %dx%d, cell count limit is %d', [AWidth, AHeight, CELLCOUNT_LIMIT]);
  
      if (Ord(AKind) > Ord(High(TPathMapKind))) then
        CPFExceptionFmt('Incorrect map kind: %d, high value mkHexagonal is %d', [Ord(AKind), Ord(High(TPathMapKind))]);
  
      if (AHighTile = $FF) then
        CPFException('High tile can''t be equal 255(0xFF), it means barrier');
    end;
  
    // fill parameters
    FWidth := AWidth;
    FHeight := AHeight;
    FKind := AKind;
    FHighTile := AHighTile;
    FInfo.MapWidth := AWidth;
  
    // offsets
    for i := 0 to 7 do
    FInfo.CellOffsets[i] := SizeOf(TPathMapCell) *
      (POINT_OFFSETS[i].y * FInfo.MapWidth + POINT_OFFSETS[i].x);
  
    // allocate and fill cells
    Size := FCellCount * SizeOf(TPathMapCell);
    CPFGetMem(Pointer(FInfo.Cells), Size);
    ZeroMemory(FInfo.Cells, Size);
    Clear;
  
    // allocate first
    GrowNodeStorage(FInfo.NodeStorage);
  end;
  
  {$ifdef CPFLIB}procedure{$else}destructor{$endif}
    TPathMap.Destroy;
  var
    i: NativeInt;
  begin
    {$ifNdef CPFLIB}
      FCallAddress := ReturnAddress;
    {$endif}
  
    // node storage
    for i := FInfo.NodeStorage.Allocated - 1 downto 0 do
      CPFFreeMem(Pointer(FInfo.NodeStorage.Buffers[i]));
  
    // cells
    CPFFreeMem(Pointer(FInfo.Cells));
  
    // sectors
    CPFFreeMem(Pointer(FSectors));
  
    {$ifNdef CPFLIB}
      inherited;
  