anchor.diff:  
   procedure TKMScriptingIdCache.UpdateState;
   var
  -  I: Integer;
  +  I: ShortInt;
   begin
     //Clear out dead IDs every now and again
     //Leave them in the cache as nils, because we still might need to lookup that ID
     if fGame.GameTickCount mod 11 = 0 then
     begin
  -    for I := 0 to fUnitCount - 1 do
  +    for I := Low(fUnitCache) to High(fUnitCache) do
         if (fUnitCache[I].U <> nil) and fUnitCache[I].U.IsDead then
           fPlayers.CleanUpUnitPointer(fUnitCache[I].U);
   
  -    for I := 0 to fHouseCount - 1 do
  +    for I := Low(fHouseCache) to High(fHouseCache) do
         if (fHouseCache[I].H <> nil) and fHouseCache[I].H.IsDestroyed then
           fPlayers.CleanUpHousePointer(fHouseCache[I].H);
   
  -    for I := 0 to fGroupCount - 1 do
  +    for I := Low(fGroupCache) to High(fGroupCache) do
         if (fGroupCache[I].G <> nil) and fGroupCache[I].G.IsDead then
           fPlayers.CleanUpGroupPointer(fGroupCache[I].G);
     end;
  
positive.code: 
  { TKMScriptingIdCache }
  procedure TKMScriptingIdCache.CacheUnit(aUnit: TKMUnit; aID: Integer);
  var I, NewItem: Shortint;
  begin
    for I := 0 to fUnitCount - 1 do
      if fUnitCache[i].ID = aID then
        Exit; //Already in cache
  
    if fUnitCount < CACHE_SIZE then
    begin
      NewItem := fUnitCount;
      Inc(fUnitCount);
    end
    else
    begin
      //Cache full, overwrite the oldest item
      NewItem := fUnitLastAdded;
      Inc(fUnitLastAdded);
      if fUnitLastAdded = CACHE_SIZE then fUnitLastAdded := 0;
    end;
  
    fUnitCache[NewItem].ID := aID;
    if aUnit <> nil then
      fUnitCache[NewItem].U := aUnit.GetUnitPointer
    else
      fUnitCache[NewItem].U := nil;
  end;
  
  
  procedure TKMScriptingIdCache.CacheHouse(aHouse: TKMHouse; aID: Integer);
  var I, NewItem: Shortint;
  begin
    for I := 0 to fHouseCount - 1 do
      if fHouseCache[i].ID = aID then
        Exit; //Already in cache
  
    if fHouseCount < CACHE_SIZE then
    begin
      NewItem := fHouseCount;
      Inc(fHouseCount);
    end
    else
    begin
      //Cache full, overwrite the oldest item
      NewItem := fHouseLastAdded;
      Inc(fHouseLastAdded);
      if fHouseLastAdded = CACHE_SIZE then fHouseLastAdded := 0;
    end;
  
    fHouseCache[NewItem].ID := aID;
    if aHouse <> nil then
      fHouseCache[NewItem].H := aHouse.GetHousePointer
    else
      fHouseCache[NewItem].H := nil;
  end;
  
  
  procedure TKMScriptingIdCache.CacheGroup(aGroup: TKMUnitGroup; aID: Integer);
  var I, NewItem: Shortint;
  begin
    for I := 0 to fGroupCount - 1 do
      if fGroupCache[i].ID = aID then
        Exit; //Already in cache
  
    if fGroupCount < CACHE_SIZE then
    begin
      NewItem := fGroupCount;
      Inc(fGroupCount);
    end
    else
    begin
      //Cache full, overwrite the oldest item
      NewItem := fGroupLastAdded;
      Inc(fGroupLastAdded);
      if fGroupLastAdded = CACHE_SIZE then fGroupLastAdded := 0;
    end;
  
    fGroupCache[NewItem].ID := aID;
    if aGroup <> nil then
      fGroupCache[NewItem].G := aGroup.GetGroupPointer
    else
      fGroupCache[NewItem].G := nil;
  end;
  
  
  function TKMScriptingIdCache.GetUnit(aID:Integer): TKMUnit;
  var I: Shortint;
  begin
    for I := 0 to fUnitCount - 1 do
      if fUnitCache[i].ID = aID then
      begin
        Result := fUnitCache[i].U;
        Exit;
      end;
  
    //Not found so do lookup and add it to the cache
    Result := fPlayers.GetUnitByID(aID);
  
negative.code: 
  
  function TKMScriptingIdCache.GetGroup(aID:Integer): TKMUnitGroup;
  var I: ShortInt;
  begin
    for I := Low(fGroupCache) to High(fGroupCache) do
    if fGroupCache[I].ID = aID then
    begin
      Result := fGroupCache[I].G;
      Exit;
    end;
  
    //Not found so do lookup and add it to the cache
    Result := fPlayers.GetGroupByID(aID);
  