anchor.diff:        fPredictor.LogStatus(fBalanceText);
       FreeWorkersCnt := 0;
       fBuilder.UpdateState(aTick, FreeWorkersCnt);
  -    fBuilder.ChooseHousesToBuild(Max(0,Ceil(FreeWorkersCnt/WORKER_COEF)));
  +    fBuilder.ChooseHousesToBuild(FreeWorkersCnt, aTick);
  +    //if GA_BUILDER then
  +    //  fBuilder.ChooseHousesToBuildGA(FreeWorkersCnt)
  +    //else
  +    //  fBuilder.ChooseHousesToBuild(Max(0,Ceil(FreeWorkersCnt/WORKER_COEF)));
       if not SKIP_RENDER then // Builder change required houses so builder LogStatus cannot be merged with predictor
  +    begin
         fBuilder.LogStatus(fBalanceText);
  -    LogStatus(fBalanceText);
  +      LogStatus(fBalanceText);
  +    end;
     end;
   
     if (aTick mod LONG_UPDATE = fOwner) then
     begin
       if not GA_PLANNER then
  -      CheckUnitCount();
  -    //CheckMarketplaces();
  -    CheckStoreWares();
  +      CheckUnitCount(aTick);
  +    CheckMarketplaces();
  +    CheckStoreWares(aTick);
  +    CheckAutoRepair();
       OrderWeapons( WeaponsBalance() );
       CheckExhaustedHouses();
     end;
   end;
   
   
  -procedure TKMCityManagement.CheckUnitCount();
  +procedure TKMCityManagement.CheckUnitCount(aTick: Cardinal);
   var
     P: TKMHand;
  -  UnitReq: array [CITIZEN_MIN..CITIZEN_MAX] of Integer;
  -
  -  function TryToTrain(aSchool: TKMHouseSchool; aUnitType: TUnitType; aRequiredCount: Integer): Boolean;
  -  begin
  -    // We summ up requirements for e.g. Recruits required at Towers and Barracks
  -    if P.Stats.GetUnitQty(aUnitType) < (aRequiredCount + UnitReq[aUnitType]) then
  -    begin
  -      Dec(UnitReq[aUnitType]); //So other schools don't order same unit
  -      aSchool.AddUnitToQueue(aUnitType, 1);
  -      Result := True;
  -    end
  -    else
  -      Result := False;
  -  end;
  -
  -  function RecruitsNeeded: Integer;
  -  var AxesLeft: Integer;
  -  begin
  -    if P.Stats.GetHouseQty(ht_Barracks) = 0 then
  -      Result := 0
  -    else
  -      if gGame.IsPeaceTime then
  +  Stats: TKMHandStats;
  +
  +  function RecruitsNeeded(): Integer;
  +  const
  +    RECRUIT_PEACE_DELAY = 17 * 60 * 10;
  +  var
  +    Output: Integer;
  +  begin
  +    Output := Stats.GetHouseQty(ht_WatchTower);
  +
  +    if (aTick - gGame.GameOptions.Peacetime * 600 + RECRUIT_PEACE_DELAY > 0) then
  +    begin
  +      if fSetup.UnlimitedEquip then
         begin
  -        //Keep enough recruits to equip using all weapons once PT ends
  -        //Iron soldiers
  -        Result := Min(P.Stats.GetWareBalance(wt_MetalArmor),
  -                      P.Stats.GetWareBalance(wt_Arbalet) + P.Stats.GetWareBalance(wt_Hallebard)
  -                      + Min(P.Stats.GetWareBalance(wt_Sword), P.Stats.GetWareBalance(wt_MetalShield)));
  -        //Leather soldiers we can make
  -        Inc(Result, Min(P.Stats.GetWareBalance(wt_Armor),
  -                        P.Stats.GetWareBalance(wt_Bow) + P.Stats.GetWareBalance(wt_Pike)
  -                        + Min(P.Stats.GetWareBalance(wt_Axe), P.Stats.GetWareBalance(wt_Shield))));
  -        //Militia with leftover axes
  -        AxesLeft := P.Stats.GetWareBalance(wt_Axe) - Min(P.Stats.GetWareBalance(wt_Armor), P.Stats.GetWareBalance(wt_Shield));
  -        if AxesLeft > 0 then
  -          Inc(Result, AxesLeft);
  +        // Iron soldiers
  +        Output := Min(  Stats.GetWareBalance(wt_MetalArmor), Stats.GetWareBalance(wt_Arbalet) + Stats.GetWareBalance(wt_Hallebard) + Min( Stats.GetWareBalance(wt_Sword), Stats.GetWareBalance(wt_MetalShield) )  );
  +        // Leather soldiers we can make
  +        Inc(  Output, Min( Stats.GetWareBalance(wt_Armor), Stats.GetWareBalance(wt_Bow) + Stats.GetWareBalance(wt_Pike) + Min(Stats.GetWareBalance(wt_Axe), Stats.GetWareBalance(wt_Shield)) )  );
  +        // Militia with leftover axes
  +        Inc(  Output, Max( 0, Stats.GetWareBalance(wt_Axe) - Min(Stats.GetWareBalance(wt_Armor), Stats.GetWareBalance(wt_Shield)) )  );
         end
         else
  -        Result := fSetup.RecruitCount * P.Stats.GetHouseQty(ht_Barracks);
  -  end;
  -
  -  function RequiredServCount: Byte;
  +        Output := Output + 10;
  +    end;
  +    Result := Output;
  +  end;
  +
  +  function RequiredServCount(): Integer;
  +  const
  +    HOUSE_COEF = 0.5;
     var
       I: Integer;
     begin
  -    Result := Max(0, gHands[fOwner].Stats.GetUnitQty(ut_Worker) + Round(gHands[fOwner].Stats.GetHouseTotal(ht_Any) * 0.5) - gHands[fOwner].Stats.GetUnitQty(ut_Serf));
  +    Result := Max(0, gHands[fOwner].Stats.GetUnitQty(ut_Worker) + Round(gHands[fOwner].Stats.GetHouseTotal(ht_Any) * HOUSE_COEF) - gHands[fOwner].Stats.GetUnitQty(ut_Serf));
       //Result := Max(0, gHands[fOwner].Stats.GetUnitQty(ut_Worker) - gHands[fOwner].Stats.GetUnitQty(ut_Serf));
       for I := 0 to P.Units.Count - 1 do
         if not P.Units[I].IsDeadOrDying
  
positive.code:   WT: TWareType;
    GT: TGroupType;
    UT: TUnitType;
    Warfare: TWarfareArr;
  begin
    ArmorCnt := gHands[fOwner].Stats.GetHouseQty(ht_ArmorSmithy) + gHands[fOwner].Stats.GetHouseQty(ht_ArmorWorkshop);
    SmithyCnt := gHands[fOwner].Stats.GetHouseQty(ht_WeaponSmithy);
  
negative.code:   KM_CityPredictor, KM_CityBuilder, KM_CityPlanner, KM_AIArmyEvaluation;
  
  type
    TKMWarfareArr = array[WARFARE_MIN..WARFARE_MAX] of record
      Avaiable, Required: Word;
      Fraction: Single;
    end;
    TKMWarriorsDemands = array[WARRIOR_EQUIPABLE_MIN..WARRIOR_EQUIPABLE_MAX] of Integer;
  
    TKMCityManagement = class
    private
  