unit battle;
interface

uses
  loadz, LevGen, GroupGen, svet, aData, sysUtils, RogueLabGen;

procedure GenerateRandomLocation(x, y: byte; IsSpecial: boolean);

implementation

uses
  MyCRT, NewUnit1;

var
  ForHouse: array[1..RESOLUTION_X, 1..RESOLUTION_Y] of boolean;

procedure ZapAll(aType: string);
var
  x, y: byte;
begin
  for y := 1 to RESOLUTION_Y do
    for x := 1 to RESOLUTION_X do
      SetElement(x, y, aType);
end;

procedure Ramka(aType: string);
var
  i: byte;
begin
  for i := 2 to RESOLUTION_X - 1 do
  begin
    SetElement(i, 2, aType);
    SetElement(i, RESOLUTION_Y - 1, aType);
  end;
  for i := 2 to RESOLUTION_Y - 1 do
  begin
    SetElement(2, i, aType);
    SetElement(RESOLUTION_X - 1, i, aType);
  end;
end;

procedure SaveLevel;
var
  f: file of level_rec;
begin
  AssignFile(f, MAPFOLDER + data.location + LEV_EXTENSION);
  rewrite(f);
  System.write(f, cur_lev);
  CloseFile(f);
end;

function around(x, y: byte; aType: string): integer;
begin
  Result := 0;
  if (x > 1) then
    if (IsType(x - 1, y, aType)) then
      inc(Result);
  if (x < RESOLUTION_X) then
    if (IsType(x + 1, y, aType)) then
      inc(Result);
  if (y < 1) then
    if (IsType(x, y - 1, aType)) then
      inc(Result);
  if (y < RESOLUTION_Y) then
    if (IsType(x, y + 1, aType)) then
      inc(Result);
end;

function VokrugType(x, y: byte; TypeName: string): integer;
begin
  Result := 0;
  if IsType(x - 1, y - 1, TypeName) then
    inc(Result);
  if IsType(x, y - 1, TypeName) then
    inc(Result);
  if IsType(x + 1, y - 1, TypeName) then
    inc(Result);
  if IsType(x - 1, y, TypeName) then
    inc(Result);
  if IsType(x + 1, y, TypeName) then
    inc(Result);
  if IsType(x - 1, y + 1, TypeName) then
    inc(Result);
  if IsType(x, y + 1, TypeName) then
    inc(Result);
  if IsType(x + 1, y + 1, TypeName) then
    inc(Result);
end;

procedure MakeBrod;
var
  x, y: byte;
begin
  for y := 1 to RESOLUTION_Y do
    for x := 1 to RESOLUTION_X do
      if (VokrugType(x, y, 'Water') > 0) and ((IsType(x, y, 'Grass')) or (IsType(x, y, 'Ground')) or (IsType(x, y, 'Sand'))) then
        SetElement(x, y, 'Floor_water');
end;

function RandomPoint: APoint;
var
  x, y: byte;
begin
  x := Random(RESOLUTION_X) + 1;
  y := Random(RESOLUTION_Y) + 1;
  while (IsBold(x, y)) do
  begin
    x := Random(RESOLUTION_X) + 1;
    y := Random(RESOLUTION_Y) + 1;
  end;
  Result.x := x;
  Result.y := y;
end;

procedure PlaceMonster(num: word; x, y: integer; item, count: word);
var
  enemy: TEnemy;
begin
  mon_info(num, enemy);
  cur_lev.map[x, y].Monster.health := Random(enemy.health div 3) + ((enemy.health div 3) * 2);
  cur_lev.map[x, y].Monster.montype := num;
  cur_lev.map[x, y].Monster.monchar := enemy.character;
  if (item <> 0) then
  begin
    cur_lev.map[x, y].Monster.item := item;
    cur_lev.map[x, y].Monster.count := count;
  end
  else
  begin
    cur_lev.map[x, y].Monster.item := enemy.Item;
    cur_lev.map[x, y].Monster.count := Random(enemy.Count) + 1;
  end;
  cur_lev.map[x, y].Monster.point := 0;
  cur_lev.map[x, y].Monster.shod := false;
  if (enemy.Attrz and 1024) > 0 then
    cur_lev.map[x, y].Monster.gold := random(num * 3) + 1
  else
    cur_lev.map[x, y].Monster.gold := 0;
  cur_lev.map[x, y].Monster.Zak.ZakType := 0;
  cur_lev.map[x, y].Monster.Zak.ZakLong := 0;
end;

procedure GenerateMonster(num: integer; item: word = 0; count: word = 0);
var
  point: APoint;
begin
  repeat
    point := RandomPoint;
  until not IsThisAMonster(point.x, point.y) and (not IsType(point.x, point.y, 'PrisonUp')) and (not IsType(point.x, point.y, 'PrisonDown'));
  PlaceMonster(num, point.x, point.y, item, count);
end;

procedure GenerateMonsters(minnum, maxnum, mincount, maxcount: integer);
var
  i, j: integer;
  enemy: TEnemy;
  item, count: integer;
  anItem: TItem;
begin
  i := Random(maxcount - mincount + 1) + mincount;
  for i := i downto 1 do
  begin
    j := Random(maxnum - minnum + 1) + minnum;
    mon_info(j, enemy);
    if (enemy.Intellect <> AITurret) then
    begin
      item := 0;
      count := 0;
      if (enemy.w1Min <> 0) or (enemy.w2Min <> 0) then
      begin
        if ((Random(10) + 1) mod 2 = 0) and (enemy.w1Min <> 0) then
          item := Random(enemy.w1Max - enemy.w1Min + 1) + enemy.w1Min
        else
          item := Random(enemy.w2Max - enemy.w2Min + 1) + enemy.w2Min;
        iteminfo(item, anItem);
        if anItem.IsShooting then
          count := Random(anItem.InOboyma + 1)
        else
          count := 1;
      end
      else if (enemy.Item <> 0) then
      begin
        item := enemy.Item;
        count := enemy.Count;
      end;
      GenerateMonster(j, item, count);
    end;
  end;
end;

function Check(x, y, w, h: integer): boolean;
var
  cx, cy: integer;
begin
  Result := false;
  for cx := x to (x + w) do
    for cy := y to (y + h) do
      if not (x in [4..RESOLUTION_X - 4]) or not (y in [4..RESOLUTION_Y - 4]) or (IsBold(cx, cy)) or (IsType(cx, cy, 'Road')) then
        exit;
  Result := true;
end;

procedure GenerateHouse;
var
  f: TextFile;
  count: integer;
  s: string;
  w, h: integer;
  x, y: integer;
  i, j: integer;
  arr: array of record
                  x, y: byte;
                end;
  arrlen: integer;
  t: integer;
  ammo: integer;
  item: TItem;
  points: array of APoint;
  pLen: integer;
begin
  arrlen := 0;
  SetLength(arr, 0);
  pLen := 0;
  SetLength(points, 0);
  w := Random(10) + 10;
  h := Random(10) + 10;
  x := Random(RESOLUTION_X - w - 3) + 3;
  y := Random(RESOLUTION_Y - h - 3) + 3;
  if not Check(x, y, w, h) then
    exit;
  GenerateSpaceShuttle(x, x + w, y, y + h, 3, 3, 10);
  for i := 1 to w + 2 do
  begin
    SetElement(x + i - 2, y - 1, 'Wall');
    SetElement(x + i - 2, y + h, 'Wall');
  end;
  for i := 1 to h + 2 do
  begin
    SetElement(x - 1, y + i - 2, 'Wall');
    SetElement(x + w, y + i - 2, 'Wall');
  end;
  for i := 1 to w + 2 do
  begin
    if (vokrug(x + i - 2, y - 1, 'Wall') = 2) and ((IsType(x + i - 1, y - 1, 'Wall') and IsType(x + i - 3, y - 1, 'Wall')) or (IsType(x + i - 2, y - 2, 'Wall') and IsType(x + i - 2, y, 'Wall'))) and (vokrug(x + i - 2, y - 1, 'Door') = 0) then
    begin
      SetLength(points, pLen + 1);
      points[pLen].x := x + i - 2;
      points[pLen].y := y - 1;
      inc(pLen);
    end;
    if (vokrug(x + i - 2, y + h, 'Wall') = 2) and ((IsType(x + i - 1, y + h, 'Wall') and IsType(x + i - 3, y + h, 'Wall')) or (IsType(x + i - 2, y + h - 1, 'Wall') and IsType(x + i - 2, y + h + 1, 'Wall'))) and (vokrug(x + i - 2, y - 1, 'Door') = 0) then
    begin
      SetLength(points, pLen + 1);
      points[pLen].x := x + i - 2;
      points[pLen].y := y + h;
      inc(pLen);
    end;
  end;
  for i := 1 to h + 2 do
  begin
    if (vokrug(x - 1, y + i - 2, 'Wall') = 2) and (((IsType(x - 2, y + i - 2, 'Wall')) and (IsType(x, y + i - 2, 'Wall'))) or (IsType(x - 1, y + i - 3, 'Wall') and IsType(x - 1, y + i - 1, 'Wall'))) and (vokrug(x - 1, y + i - 2, 'Door') = 0) then
    begin
      SetLength(points, pLen + 1);
      points[pLen].x := x - 1;
      points[pLen].y := y + i - 2;
      inc(pLen);
    end;
    if (vokrug(x + w, y + i - 2, 'Wall') = 2) and (((IsType(x + w - 1, y + i - 2, 'Wall')) and (IsType(x + w + 1, y + i - 2, 'Wall'))) or (IsType(x - 1, y + i - 3, 'Wall') and IsType(x - 1, y + i - 1, 'Wall'))) and (vokrug(x - 1, y + i - 2, 'Door') = 0) then
    begin
      SetLength(points, pLen + 1);
      points[pLen].x := x + w;
      points[pLen].y := y + i - 2;
      inc(pLen);
    end;
  end;
  j := Random(pLen);
  SetElement(points[j].x, points[j].y, 'Door');
  for j := j to pLen - 2 do
    points[j] := points[j + 1];
  dec(pLen);
  SetLength(points, pLen);
  for i := 1 to Random(4) do
  begin
    j := Random(pLen);
    SetElement(points[j].x, points[j].y, 'Window');
    for j := j to pLen - 2 do
      points[j] := points[j + 1];
    dec(pLen);
    SetLength(points, pLen);
  end;
  for j := 1 to h + 2 do
  begin
    for i := 1 to w + 2 do
    begin
      cur_lev.map[x + i - 2, y + j - 2].attrz := cur_lev.map[x + i - 2, y + j - 2].attrz or 2;
      if (not IsBold(x + i - 2, y + j - 2)) and (not IsType(x + i - 2, y + j - 2, 'Door')) then
      begin
        SetLength(arr, arrlen + 1);
        arr[arrlen].x := x + i - 2;
        arr[arrlen].y := y + j - 2;
        inc(arrlen);
        SetElement(x + i - 2, y + j - 2, 'Floor');
      end;
    end;
  end;
  if ((Random(2) + 1) mod 2 = 0) and (arrlen > 0) then
  begin
    t := Random(arrlen);
    case (Random(2) + 1) mod 2 of
      0: SetObject(arr[t].x, arr[t].y, 'Corpse');
      1: SetObject(arr[t].x, arr[t].y, 'Corpse_examined');
      2: SetObject(arr[t].x, arr[t].y, 'Skeleton');
      3: SetObject(arr[t].x, arr[t].y, 'Skeleton');
    end;
    cur_lev.map[arr[t].x, arr[t].y].attrz := cur_lev.map[arr[t].x, arr[t].y].attrz or 2;
    for t := t to arrlen - 2 do
      arr[t] := arr[t + 1];
    SetLength(arr, arrlen - 1);
    dec(arrlen);
  end;
  j := Random(arrlen) div 10;
  for i := 1 to j do
  begin
    t := Random(arrlen);
    ammo := 1;
    case (Random(15) + 1) of
      1, 2, 4: count := Random(LITTER_MAX - LITTER_MIN + 1) + LITTER_MIN;
      5, 6, 7, 8: count := Random(LITTER_PRISON_MAX - LITTER_PRISON_MIN + 1) + LITTER_PRISON_MIN;
      9, 10, 11: count := Random(EAT_MAX - EAT_MIN + 1) + EAT_MIN;
      12, 15: count := Random(MEDIC_MAX - MEDIC_MIN + 1) + MEDIC_MIN;
      14: count := Random(WEAPON_PRIMITIVE_MAX - WEAPON_PRIMITIVE_MIN + 1) + WEAPON_PRIMITIVE_MIN;
      13:
      begin
        count := Random(WEAPON_SHOOT_MIN + 4 - WEAPON_BOWS_MIN) + WEAPON_BOWS_MIN;
        iteminfo(count, item);
        ammo := Random(item.InOboyma + 1);
      end;
      3:
      begin
        count := MONEY_MIN + 2;
        ammo := Random(101 + data.level * 10);
      end;
    end;
    cur_lev.map[arr[t].x, arr[t].y].item := count;
    cur_lev.map[arr[t].x, arr[t].y].ItemCount := ammo;
  end;
  for j := j downto 1 do
  begin
    if (Random(2) = 1) then
      x := x + w + Random(w)
    else
      x := x - Random(w);
    if (Random(2) = 1) then
      y := y + h + Random(h)
    else
      y := y - Random(h);
    if (x in [1..RESOLUTION_X]) and (y in [1..RESOLUTION_Y]) and (not IsBold(x, y)) and (cur_lev.map[x, y].item = 0) then
    begin
      ammo := 1;
      case (Random(15) + 1) of
        1, 2, 4: count := Random(LITTER_MAX - LITTER_MIN + 1) + LITTER_MIN;
        5, 6, 7, 8: count := Random(LITTER_PRISON_MAX - LITTER_PRISON_MIN + 1) + LITTER_PRISON_MIN;
        9, 10, 11: count := Random(EAT_MAX - EAT_MIN + 1) + EAT_MIN;
        12, 15: count := Random(MEDIC_MAX - MEDIC_MIN + 1) + MEDIC_MIN;
        14: count := Random(WEAPON_PRIMITIVE_MAX - WEAPON_PRIMITIVE_MIN + 1) + WEAPON_PRIMITIVE_MIN;
        13:
        begin
          count := Random(WEAPON_SHOOT_MIN + 4 - WEAPON_BOWS_MIN) + WEAPON_BOWS_MIN;
          iteminfo(count, item);
          ammo := Random(item.InOboyma + 1);
        end;
        3:
        begin
          count := MONEY_MIN + 2;
          ammo := Random(101 + data.level * 10);
        end;
      end;
      cur_lev.map[x, y].item := count;
      cur_lev.map[x, y].ItemCount := ammo;
    end;
  end;
end;

procedure SetCorner(sx, x, sy, y: integer; dx, dy: integer; aType: string; SetInhouse: boolean);
var
  i, j: integer;
  start, s: integer;
begin
  if (dy = 0) then
  begin
    start := sx;
    for i := 1 to RESOLUTION_Y do
    begin
      j := Random(3) - 1;
      if ((x + j > 0) and (x + j < RESOLUTION_X)) then
        inc(x, j);
      s := sx;
      while (s <> x) do
      begin
        SetElement(s, i, aType);
        SetObject(s, i, '[Empty]');
        if (SetInHouse) then
          cur_lev.map[s, i].attrz := cur_lev.map[s, i].attrz or 2
        else if ((s <> sx) and (aType = 'Mountain')) then
        begin
          ForHouse[s, i] := true;
          osvkletka(s, i);
        end;
        inc(s, dx);
      end;
    end;
  end
  else
  begin
    for i := 1 to RESOLUTION_X do
    begin
      j := Random(3) - 1;
      if ((y + j > 0) and (y + j < RESOLUTION_Y)) then
        inc(y, j);
      s := sy;
      while (s <> y) do
      begin
        SetElement(i, s, aType);
        SetObject(i, s, '[Empty]');
        if (SetInHouse) then
          cur_lev.map[i, s].attrz := cur_lev.map[i, s].attrz or 2
        else if ((s <> sy) and (aType = 'Mountain')) then
        begin
          ForHouse[i, s] := true;
          osvkletka(i, s);
        end;
        inc(s, dy);
      end;
    end;
  end;
end;

procedure GenerateCornerType(corner, dlina: byte; hollow: boolean; aType: string);
var
  x, y, sx, sy: byte;
  i, j: integer;
  dx, dy: shortint;
  startx: byte;
  cx, cy: byte;
  IsGenerate: boolean;
  dlina2: integer;
begin
  startx := 10 - (data.luck div 3);
  if (startx < 1) then
    startx := 1;
  IsGenerate := ((Random(20) + 1) mod startx = 0);
  x := 0;
  dx := 0;
  dy := 0;
  startx := 0;
  dlina2 := dlina + 13;
  if ((dx <> 0) and (dlina2 >= RESOLUTION_X - 2)) then
    dlina2 := RESOLUTION_X - 3
  else if ((dy <> 0) and (dlina2 >= RESOLUTION_Y - 2)) then
    dlina2 := RESOLUTION_Y - 3;
  if (aType = 'Water') then
    case corner of
      1: SetCorner(1, dlina2, 0, 0, 1, 0, 'Sand', true);
      2: SetCorner(RESOLUTION_X, RESOLUTION_X - dlina2, 0, 0, -1, 0, 'Sand', false);
      3: SetCorner(0, 0, 1, dlina2, 0, 1, 'Sand', true);
      4: SetCorner(0, 0, RESOLUTION_Y, RESOLUTION_Y - dlina2, 0, -1, 'Sand', false);
    end;
  case corner of
    1: SetCorner(1, dlina, 0, 0, 1, 0, aType, true);
    2: SetCorner(RESOLUTION_X, RESOLUTION_X - dlina, 0, 0, -1, 0, aType, false);
    3: SetCorner(0, 0, 1, dlina, 0, 1, aType, true);
    4: SetCorner(0, 0, RESOLUTION_Y, RESOLUTION_Y - dlina, 0, -1, aType, false);
  end;
  for y := 1 to RESOLUTION_Y do
    for x := 1 to RESOLUTION_X do
    begin
      if (IsType(x, y, 'Mountain')) and (vokrug(x, y, 'Mountain') + vokrug(x, y, 'Rock') = 8) then
        SetElement(x, y, 'Rock');
      if (((x = 1) or (x = RESOLUTION_X) or (y = 1) or (y = RESOLUTION_Y))
        and (IsType(x, y, 'Mountain')) and (vokrug(x, y, 'Mountain') + vokrug(x, y, 'Rock') = 5)) then
          SetElement(x, y, 'Rock');
    end;
  if (hollow) and (aType = 'Mountain') then
  begin
    case corner of
      1:
      begin
        x := 1 + (dlina div 2) + Random(dlina div 4) - Random(dlina div 2);
        y := Random(RESOLUTION_Y - 2) + 2;
        dx := 1;
        dy := 0;
      end;
      2:
      begin
        x := RESOLUTION_X - (dlina div 2) - 1 - Random(dlina div 4) + Random(dlina div 2);
        y := Random(RESOLUTION_Y - 2) + 2;
        dx := -1;
        dy := 0;
      end;
      3:
      begin
        y := 1 + (dlina div 2) + Random(dlina div 4) - Random(dlina div 2);
        x := Random(RESOLUTION_X - 2) + 2;
        dy := 1;
        dx := 0;
      end;
      4:
      begin
        y := RESOLUTION_Y - (dlina div 2) - 1 - Random(dlina div 4) + Random(dlina div 2);
        x := Random(RESOLUTION_X - 2) + 2;
        dy := -1;
        dx := 0;
      end;
    end;
    cx := x;
    cy := y;
    while (x in [1..RESOLUTION_X]) and (y in [1..RESOLUTION_Y]) and ((IsType(x, y, 'Mountain')) or (IsType(x, y, 'Rock'))) do
    begin
      SetElement(x, y, 'Floor_ground');
      i := Random(3) - 1;
      if (dy = 0) then
      begin
        if ((y + i) in [2..RESOLUTION_Y - 1]) then
        begin
          if IsType(x, y + i, 'Floor_ground') then
            i := 0;
          y := y + i;
          if i <> 0 then
            x := x - dx;
        end;
        x := x + dx;
      end
      else
      begin
        if ((x + i) in [2..RESOLUTION_X - 1]) then
        begin
          if IsType(x + i, y, 'Floor_ground') then
            i := 0;
          x := x + i;
          if i <> 0 then
            y := y - dy;
        end;
        y := y + dy;
      end;
    end;
    GenerateGroup(cx, cy, 300, 'Floor_ground', 4, IsGenerate);
  end;
end;

procedure OsvLevel;
var
  x, y: integer;
begin
  for x := 1 to RESOLUTION_X do
    for y := 1 to RESOLUTION_Y do
    begin
      if not IsInHouse(x, y) then
        osvkletka(x, y)
      else if IsInHouse(x, y) and ((IsType(x, y, 'Mountain')) or (IsType(x, y, 'Floor_ground')) or (IsType(x, y, 'Rock'))) then
        cur_lev.map[x, y].vid := '^'
      else if IsInHouse(x, y) and ((IsType(x, y, 'Wall')) or (IsType(x, y, 'Door')) or (IsType(x, y, 'Window')) or (IsType(x, y, 'Floor'))) then
        cur_lev.map[x, y].vid := '#';
    end;
end;

procedure MakeRoad(sx, sy, ex, ey: integer; IsSpecial: boolean);
var
  i, j: integer;
  x, y, t: integer;
  count, ammo: integer;
  item: TItem;
  d: integer;
  turn: integer;
begin
  d := 10;
  turn := 0;
  for i := sx to ex do
    for j := sy to ey do
      SetElement(i, j, 'Road');
  if (not isSpecial) then
  begin
    j := Random(7);
    for i := 1 to j do
    begin
      t := Random(15) + 1;
      ammo := 1;
      case t of
        1, 2, 4, 9: count := Random(LITTER_MAX - LITTER_MIN + 1) + LITTER_MIN;
        5, 6, 14, 15: count := Random(LITTER_PRISON_MAX - LITTER_PRISON_MIN + 1) + LITTER_PRISON_MIN;
        7: count := Random(MEDIC_MAX - MEDIC_MIN + 1) + MEDIC_MIN;
        8: count := Random(WEAPON_PRIMITIVE_MAX - WEAPON_PRIMITIVE_MIN + 1) + WEAPON_PRIMITIVE_MIN;
        10:
        begin
          count := Random(WEAPON_SHOOT_MIN + 4 - WEAPON_BOWS_MIN) + WEAPON_BOWS_MIN;
          iteminfo(count, item);
          ammo := Random(item.InOboyma + 1);
        end;
        11:
        begin
          count := MONEY_MIN;
          ammo := Random(10) + 1;
        end;
      end;
      turn := 0;
      repeat
        x := Random(ex - sx + d * 2) + sx - d;
        y := Random(ey - sy + d * 2) + sy - d;
        inc(turn);
      until ((not IsBold(x, y)) and (cur_lev.map[x, y].item = 0)) or (turn > 1000);
      if (turn > 1000) then
        continue;
      if (x < 3) then
        x := 3
      else if (x > RESOLUTION_X - 2) then
        x := RESOLUTION_X - 2;
      if (y < 3) then
        y := 3
      else if (y > RESOLUTION_Y - 2) then
        y := RESOLUTION_Y - 2;
      if ((t <> 12) and (t <> 13)) then
      begin
        cur_lev.map[x, y].item := count;
        cur_lev.map[x, y].ItemCount := ammo;
      end
      else if (t = 12) then
      begin
        if (Random(2) = 1) then
          SetObject(x, y, 'Corpse')
        else
          SetObject(x, y, 'Corpse_examined');
        d := 0;
        if (x > 7) then
          sx := x - 5
        else
          sx := 3;
        if (x < RESOLUTION_X - 7) then
          ex := x + 5
        else
          ex := RESOLUTION_X - 2;
        if (y > 7) then
          sy := y - 5
        else
          sy := 3;
        if (y < RESOLUTION_Y - 7) then
          ey := y + 5
        else
          ey := RESOLUTION_Y - 2;
      end
      else if (t = 13) then
      begin
        if (Random(2) = 1) then
          SetObject(x, y, 'Skeleton')
        else
          SetObject(x, y, 'Skeleton_examined');
      end;
    end;
  end;
end;

procedure GenerateRandomLocation(x, y: byte; IsSpecial: boolean);
var
  anType: string;
  i, j, sx, sy, ex, ey, w, h: integer;
  arr: array[1..10] of byte;
  {
    1 - Трава
    2 - Земля (Ground)
    3 - Болота
    4 - Вода
    5 - Лес
  }
  Mount, Water, Road: array [1..4] of boolean;
  GenFactor: integer;
  luck: integer;
begin
  if not FileExists(MAPFOLDER + 'random.lev') then
  begin
    if (IsSpecial) then
      Info(STR_OSM_VOKRUG)
    else
      Info(STR_POBL_OSM);
    for i := 1 to 4 do
    begin
      Mount[i] := false;
      Water[i] := false;
      Road[i] := false;
    end;
    if (x > 1) then
    begin
      if (IsType(x - 1, y, 'Mountain')) then
        Mount[1] := true
      else if (IsType(x - 1, y, 'Water')) then
        Water[1] := true;
    end;
    if (x < RESOLUTION_X) then
    begin
      if IsType(x + 1, y, 'Mountain') then
        Mount[2] := true
      else if IsType(x + 1, y, 'Water') then
        Water[2] := true;
    end;
    if (y > 1) then
    begin
      if IsType(x, y - 1, 'Mountain') then
        Mount[3] := true
      else if IsType(x, y - 1, 'Water') then
        Water[3] := true;
    end;
    if (y < RESOLUTION_Y) then
    begin
      if IsType(x, y + 1, 'Mountain') then
        Mount[4] := true
      else if IsType(x, y + 1, 'Water') then
        Water[4] := true;
    end;
    luck := 10 - data.luck;
    if (luck <= 1) then
     luck := 1;
    GenFactor := 5;   // 5 - оптимальный вариант
    anType := 'Grass';
    arr[2] := Random(8);
    arr[1] := 0;
    if (IsType(x, y, 'Road')) then
    begin
      if (x > 1) and (IsType(x - 1, y, 'Road') or IsType(x - 1, y, 'Entrace')) then
      begin
        Road[2] := true;
        Water[1] := false;
        Mount[1] := false;
        Water[3] := false;
        Mount[3] := false;
        Water[4] := false;
        Mount[4] := false;
      end;
      if (x < RESOLUTION_X) and (IsType(x + 1, y, 'Road') or IsType(x + 1, y, 'Entrace')) then
      begin
        Road[3] := true;
        Water[4] := false;
        Mount[4] := false;
        Water[2] := false;
        Mount[2] := false;
        Water[3] := false;
        Mount[3] := false;
      end;
      if (y > 1) and (IsType(x, y - 1, 'Road') or IsType(x, y - 1, 'Entrace')) then
      begin
        Road[1] := true;
        Water[4] := false;
        Mount[4] := false;
        Water[3] := false;
        Mount[3] := false;
      end;
      if (y < RESOLUTION_Y) and (IsType(x, y + 1, 'Road') or IsType(x, y + 1, 'Entrace')) then
      begin
        Road[4] := true;
        Water[4] := false;
        Mount[4] := false;
        Water[3] := false;
        Mount[3] := false;
      end;
    end;
    arr[3] := around(x, y, 'Boloto') * Random(2);
    if (arr[3] = 0) then
      arr[4] := around(x, y, 'Water') * Random(4) + Random(3)
    else
     arr[4] := 0;
    if IsType(x, y, 'Boloto') then
      arr[3] := arr[3] + Random(5);
    if IsType(x, y, 'Water') then
      arr[4] := arr[4] + Random(5);
    arr[5] := around(x, y, 'Boloto') + (around(x, y, 'Water') * 2) + (around(x, y, 'Forest') * 3) + Random(3);
    if IsType(x, y, 'Forest') then
      arr[5] := arr[5] + Random(5);
    saveizm;
    for y := 1 to RESOLUTION_Y do
      for x := 1 to RESOLUTION_X do
      begin
        cur_lev.map[x, y] := EmptyKletka;
        ForHouse[x, y] := false;
      end;

    cur_lev.street := false;
    cur_lev.sleep := true;
    cur_lev.dark := false;
    cur_lev.feeling := '';  // Возможно, в будущем можно будет вставить случайные впечатления
    cur_lev.groza := false;
    cur_lev.LastVisit := 0;
    data.global_x := data.posx;
    data.global_y := data.posy;

    data.location := 'random';
    ZapAll(anType);
    Ramka('Global_exit');
    for i := 1 to 4 do
      if ((Random(10) + 1) mod 3 = 0) then
      begin
        if Mount[i] then
          GenerateCornerType(i, Random((RESOLUTION_X div 2) - (RESOLUTION_X div 8)), ((Random(10) + 1) mod 2 = 0), 'Mountain')
        else if Water[i] then
          GenerateCornerType(i, Random((RESOLUTION_X div 2) - (RESOLUTION_X div 8)), ((Random(10) + 1) mod 2 = 0), 'Water');
      end;
    i := Random(GenFactor);
    GenerateAGroup(1, 1, arr[1] * 50, i, arr[1] + i, 'Grass', true, 4);
    i := Random(GenFactor);
    GenerateAGroup(1, 1, arr[2] * 50, i, arr[2] + i, 'Ground', true, 4);
    i := Random(GenFactor);
    GenerateAGroup(1, 1, arr[3] * 30, 0, arr[3], 'Boloto', true, 5);
    i := Random(GenFactor - 1);
    GenerateAGroup(1, 1, arr[4] * 40, i, arr[4] + i, 'Water', true, 5);
    i := Random(GenFactor);
    GenerateAGroup(1, 1, arr[5] * 50, i, arr[5] + i, 'Tree', true, 5);
    w := Random(5) + 2;
    h := Random(5) + 2;
    if Road[1] then
    begin
      sx := (RESOLUTION_X div 2) - w;
      ex := (RESOLUTION_X div 2) + w;
      sy := 1;
      ey := (RESOLUTION_Y div 2) + h;
      MakeRoad(sx, sy, ex, ey, IsSpecial);
    end;
    if Road[2] then
    begin
      sy := (RESOLUTION_Y div 2) - h;
      ey := (RESOLUTION_Y div 2) + h;
      sx := 1;
      ex := (RESOLUTION_X div 2) + w;
      MakeRoad(sx, sy, ex, ey, IsSpecial);
    end;
    if Road[3] then
    begin
      sy := (RESOLUTION_Y div 2) - h;
      ey := (RESOLUTION_Y div 2) + h;
      sx := (RESOLUTION_X div 2) - w;
      ex := RESOLUTION_X;
      MakeRoad(sx, sy, ex, ey, IsSpecial);
    end;
    if Road[4] then
    begin
      sx := (RESOLUTION_X div 2) - w;
      ex := (RESOLUTION_X div 2) + w;
      sy := (RESOLUTION_Y div 2) - h;
      ey := RESOLUTION_Y;
      MakeRoad(sx, sy, ex, ey, IsSpecial);
    end;
    MakeBrod;
    if (((Random(10) + 1) mod luck = 0) and not IsSpecial) then
      GenerateHouse;
    if not IsSpecial then
      GenerateMonsters(data.level, (((data.level - 1) * LEVELUP_MNOZH) div 3) + MONSTERS_PACK, data.PrisonLevel + Random(data.PrisonLevel), (data.PrisonLevel * 2) + Random(data.PrisonLevel) + Random(10));
    repeat
      cur_lev.gamer_x := Random(RESOLUTION_X - 6) + 3;
      cur_lev.gamer_y := Random(RESOLUTION_Y - 6) + 3;
      data.posx := cur_lev.gamer_x;
      data.posy := cur_lev.gamer_y;
    until (IsType(data.posx, data.posy, 'Ground')) or (IsType(data.posx, data.posy, 'Grass'));
    for i := 1 to RESOLUTION_X do
      for j := 1 to RESOLUTION_Y do
        if (ForHouse[i, j]) then
          cur_lev.map[i, j].attrz := cur_lev.map[i, j].attrz or 2;
    if (daytime <> DT_NIGHT) then
      OsvLevel;
    SaveLevel;
  end
  else
  begin
    data.location := 'random';
    loadlevel12;
    data.posx := cur_lev.gamer_x;
    data.posy := cur_lev.gamer_y;
  end;
  clean_all;
  gotoxy(data.posx, data.posy);
  osv;
end;

end.
