anchor.diff:    Result := GetGroupConfig(TERRAIN_GROUPS[ATerrain]);
   end;
   
  -{ TTransitions }
  -
  -constructor TTransitions.Create;
  -begin
  -  inherited Create(TTransition);
  -end;
  -
  -{ TTransition }
  -
  -constructor TTransition.Create(ACollection: TCollection);
  +{ TPatterns }
  +
  +constructor TPatterns.Create;
  +begin
  +  inherited Create(TPattern);
  +end;
  +
  +procedure TPatterns.Loaded;
  +var
  +  i: Integer;
  +begin
  +  for i := 0 to Count - 1 do
  +  begin
  +    TPattern(Items[i]).Loaded;
  +  end;
  +end;
  +
  +{ TPattern }
  +
  +constructor TPattern.Create(ACollection: TCollection);
  +var
  +  i: Integer;
   begin
     inherited Create(ACollection);
  -  FData := TStringList.Create;
  -end;
  -
  -destructor TTransition.Destroy;
  -begin
  -  FData.Free;
  +  FStrData := TStringList.Create;
  +
  +  for i := Low(FData) to High(FData) do
  +  begin
  +    FData[i] := TRules.Create;
  +  end;
  +
  +  FMappings := TMappings.Create;
  +
  +  FlipMode := FLIP_MODE_SAME_IMAGE;
  +end;
  +
  +destructor TPattern.Destroy;
  +var
  +  i: Integer;
  +begin
  +  FMappings.Free;
  +  for i := Low(FData) to High(FData) do
  +  begin
  +    FData[i].Free;
  +  end;
  +  FStrData.Free;
     inherited Destroy;
   end;
   
  -function TTransition.GetData: TStrings;
  -begin
  -  Result := FData;
  -end;
  -
  -procedure TTransition.SetID(AValue: string);
  +function TPattern.GetData: TStrings;
  +begin
  +  Result := FStrData;
  +end;
  +
  +procedure TPattern.Loaded;
  +var
  +  i: Integer;
  +  cell: String;
  +
  +  tmp:TStringList;
  +
  +  rule: TWeightedRule;
  +  m: TMapping;
  +  j: Integer;
  +  p: SizeInt;
  +begin
  +  if not FStrData.Count = 9 then raise Exception.Create('terrain config invalid');
  +
  +  tmp := TStringList.Create;
  +
  +  for I := Low(FData) to High(FData) do
  +  begin
  +    tmp.Clear;
  +
  +    rule.Create();
  +    cell := FStrData[i];
  +    cell := ReplaceStr(cell,#20,'');
  +
  +    SplitRegExpr(',',cell,tmp);
  +
  +    for j := 0 to tmp.Count - 1 do
  +    begin
  +      p := Pos('-',tmp[j]);
  +
  +      if p <> 0 then
  +      begin
  +        rule.name := Copy(tmp[j],1,p-1);
  +
  +        rule.points := StrToInt(Copy(tmp[j],p,MaxInt));
  +      end
  +      else
  +      begin
  +        rule.name := tmp[j];
  +      end;
  +
  +      FData[i].PushBack(rule);
  +    end;
  +
  +    tmp.Clear;
  +
  +    FMapping := ReplaceStr(FMapping,#20,'');
  +    SplitRegExpr(',',FMapping,tmp);
  +
  +    for j := 0 to tmp.Count - 1 do
  +    begin
  +      p := Pos('-',tmp[j]);
  +
  +      if p <> 0 then
  +      begin
  +        m.Lower := StrToInt(Copy(tmp[j],1,p-1));
  +        m.Upper := StrToInt(Copy(tmp[j],p,MaxInt));
  +      end
  +      else
  +      begin
  +        m.Lower := StrToInt(tmp[j]);
  +        m.Upper := StrToInt(tmp[j]);
  +      end;
  +      FMappings.PushBack(m);
  +    end
  +
  +  end;
  +
  +  tmp.Free;
  +end;
  +
  +procedure TPattern.SetFlipMode(AValue: string);
  +begin
  +  if FFlipMode = AValue then Exit;
  +  FFlipMode := AValue;
  +end;
  +
  +procedure TPattern.SetID(AValue: string);
   begin
     if FID = AValue then Exit;
     FID := AValue;
   end;
   
  -procedure TTransition.SetMapping(AValue: string);
  +procedure TPattern.SetMapping(AValue: string);
   begin
     if FMapping = AValue then Exit;
     FMapping := AValue;
   end;
   
  -procedure TTransition.SetMinPoints(AValue: integer);
  +procedure TPattern.SetMinPoints(AValue: integer);
   begin
     if FMinPoints = AValue then Exit;
     FMinPoints := AValue;
  
positive.code:   finally
      stm.Free;
    end;
    //TODO: TTerrainManager.LoadConfig
  end;
  
  procedure TTerrainManager.LoadTerrainGraphics;
  
negative.code:     WATER,
      ROCK);
  
  type
  
    { TWeightedRule }
  
    TWeightedRule = object
      name : string;
      points: Integer;
      constructor Create();
      function IsStandartRule: boolean;
    end;
  
    TRules = specialize TVector<TWeightedRule>;
  
    TMapping = record
      Lower, Upper: Integer;
    end;
  
    TMappings = specialize TVector<TMapping>;
  
    {$push}
    {$m+}
  
    { TPattern }
  
    TPattern = class (TCollectionItem)
    private
      FData: array[0..8] of TRules;
      FMappings: TMappings;
    private
      FFlipMode: string;
      FStrData: TStringList;
      FID: string;
      FMapping: string;
      FMinPoints: integer;
      function GetData: TStrings;
      procedure SetFlipMode(AValue: string);
      procedure SetID(AValue: string);
      procedure SetMapping(AValue: string);
      procedure SetMinPoints(AValue: integer);
    public
      constructor Create(ACollection: TCollection); override;
      destructor Destroy; override;
  
      procedure Loaded;
    published
      property Data: TStrings read GetData;
      property Mapping: string read FMapping write SetMapping;
      property ID:string read FID write SetID;
      property MinPoints: integer read FMinPoints write SetMinPoints;
      property FlipMode:string read FFlipMode write SetFlipMode;
    end;
  
    { TPatterns }
  
    TPatterns = class(TArrayCollection)
    public
      constructor Create;
      procedure Loaded;
    end;
  
    { TTerrainPatternConfig }
  
    TTerrainPatternConfig = class
    private
      FDirt: TPatterns;
      FNormal: TPatterns;
      FRock: TPatterns;
      FSand: TPatterns;
      FWater: TPatterns;
  
    public
      constructor Create;
      destructor Destroy; override;
  
      procedure ConvertConfig;
  
      function GetGroupConfig(AGroup: TTerrainGroup):TPatterns;
  
      function GetTerrainConfig(ATerrain: TTerrainType):TPatterns;
  
      function GetConfigById(AGroup: TTerrainGroup; AId:string): TPattern;
    published
      property Dirt: TPatterns read FDirt;
      property Normal: TPatterns read FNormal;
      property Sand: TPatterns read FSand;
      property Water: TPatterns read FWater;
      property Rock: TPatterns read FRock;
    end;
  
  
  