unit LevGen;

interface

uses
  windows, messages, sysutils, Arc, RogueLabGen;

procedure GenerateAPrison(aName: string; StrangeRooms: boolean; IsOsv: Boolean = True);
procedure GeneratePrison(aName: string; StrangeRooms: boolean);
procedure GenerateVault(aName: string; StrangeRooms: boolean);
procedure SavePrison;
procedure DrawLevel;
procedure GenerateAGroup(x, y, intens, mincount, maxcount: integer; aType: string; randomly: boolean; chance: integer);

implementation

uses
  GroupGen, maze_my, loadz, svet, aData, MyCRT;

const
  MAXROOMSIZE = 10;

type
  TRoom = record
    x, y, width, height: integer;
  end;

type
  aRoomType = (RTVerticalCoridor, RTHorizontalCoridor, RTRoom);

var
  arr: array of string;
  strrooms: boolean = false;
  rooms: array of TRoom;
  walls1, walls2: array of integer;
  predType: aRoomType;
  RoomInDoors: boolean = true;
  globx, globy: integer;
  keys: array[1..5] of boolean = (false, false, false, false, false);
  groups: array[1..RESOLUTION_X, 1..RESOLUTION_Y] of boolean;

procedure DrawLevel;
var
  i, j: integer;
begin
  textcolor(white);
  for j := 1 to RESOLUTION_Y do
    for i := 1 to RESOLUTION_X do
      osvkletka(i, j);
end;

procedure GenerateAGroup(x, y, intens, mincount, maxcount: integer; aType: string; randomly: boolean; chance: integer);
var
  a, b, z, i: integer;
begin
  z := Random(maxcount - mincount) + mincount;
  for z := z downto 1 do
  begin
    if (randomly) then
    begin
      repeat
        a := Random(RESOLUTION_X) + 1;
        b := Random(RESOLUTION_Y) + 1;
      until ((IsType(a, b, 'Grass')) or (IsType(a, b, 'Ground')) or (IsType(a, b, 'Floor_water')) or (IsType(a, b, 'Floor_blood')));
      i := Random(intens) + 1;
      GenerateGroup(a, b, i, aType, chance);
    end
    else
      GenerateGroup(x, y, intens, aType, chance);
  end;
end;

function RandomPoint: APoint;
var
  n: integer;
begin
  if (Length(rooms) <= 0) then
  begin
    Result.x := 0;
    Result.y := 0;
    exit;
  end;
  n := Random(Length(rooms));
  Result.x := rooms[n].x + Random(rooms[n].width);
  Result.y := rooms[n].y + Random(rooms[n].height);
end;

var
  ar: array of APoint;
  arLen: integer;

procedure GetKletArr(x, y: integer);
begin
  if (groups[x, y]) then
    exit;
  if ((x > 0) and (x <= RESOLUTION_X) and (y > 0) and (y <= RESOLUTION_Y) and (IsType(x, y, 'Floor'))
    and (cur_lev.map[x, y].item = 0)) then
  begin
    SetLength(ar, arLen + 1);
    ar[arLen].x := x;
    ar[arLen].y := y;
    inc(arLen);
  end;
  groups[x, y] := true;  
  if ((not IsBold(x, y)) or IsType(x, y, 'Door')) then
  begin
    GetKletArr(x - 1, y - 1);
    GetKletArr(x - 1, y);
    GetKletArr(x - 1, y + 1);
    GetKletArr(x, y - 1);
    GetKletArr(x, y + 1);
    GetKletArr(x + 1, y - 1);
    GetKletArr(x + 1, y);
    GetKletArr(x + 1, y + 1);
  end;
end;

procedure MakeKeyDoor(sX, sY: integer; IsaKey: boolean);
var
  i, j, k: integer;
  doorsArr: array of APoint;
  dLen: integer;
  colors: array of integer;
  cCount: integer;
begin
  keys[1] := false;
  keys[2] := false;
  keys[3] := false;
  keys[4] := false;
  keys[5] := false;
  arLen := 0;
  dLen := 0;
  cCount := 0;
  for i := 1 to RESOLUTION_X do
    for j := 1 to RESOLUTION_Y do
    begin
      groups[i, j] := false;
      if ((IsType(i, j, 'Door')) and (cur_lev.map[i, j].DoorCode = 0) and (cur_lev.map[i, j].levAttrz = 0)) then
      begin
        SetLength(doorsArr, dLen + 1);
        doorsArr[dLen].x := i;
        doorsArr[dLen].y := j;
        inc(dLen);
      end;
    end;
  k := Random(dLen);
  for i := 1 to 5 do
    if (not keys[i]) then
    begin
      SetLength(colors, cCount + 1);
      colors[cCount] := 428 + i;
      inc(cCount);
    end;
  i := colors[Random(cCount)];
  if (IsAKey) then
    cur_lev.map[doorsArr[k].x, doorsArr[k].y].levAttrz := i
  else
    cur_lev.map[doorsArr[k].x, doorsArr[k].y].levAttrz := maxint;
  arLen := 0;
  GetKletArr(sX, sY);
  j := Random(arLen);
  if (IsAKey) then
  begin
    cur_lev.map[ar[j].x, ar[j].y].item := i;
    cur_lev.map[ar[j].x, ar[j].y].ItemCount := 1;
  end
  else
  begin
    SetObject(ar[j].x, ar[j].y, 'Richag');
    cur_lev.map[ar[j].x, ar[j].y].ObjAttrz := doorsArr[k].x * 256 + doorsArr[k].y;
  end;
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;
  cur_lev.map[x, y].Monster.Zak.ZakType := 0;
  cur_lev.map[x, y].Monster.Zak.ZakLong := 0;
end;

function GenerateRandomPoint: 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 GenerateItemsInLabyrinth(minnum, maxnum, mincount, maxcount: integer; count: word = 1);
var
  i: integer;
  point: APoint;
begin
  i := Random(maxcount - mincount + 1) + mincount;
  for i := i downto 1 do
  begin
    repeat
      point := GenerateRandomPoint;
    until (not IsThisAMonster(point.x, point.y)) and (cur_lev.map[point.x, point.y].item = 0) and (not IsType(point.x, point.y, 'PrisonUp')) and ((not IsType(point.x, point.y, 'PrisonDown')));
    cur_lev.map[point.x, point.y].item := Random(maxnum - minnum + 1) + minnum;
    cur_lev.map[point.x, point.y].ItemCount := Random(count) + 1;
  end;
end;

procedure GenerateItems(minnum, maxnum, mincount, maxcount: integer; count: word = 1);
var
  i: integer;
  point: APoint;
begin
  i := Random(maxcount - mincount + 1) + mincount;
  for i := i downto 1 do
  begin
    point := RandomPoint;
    if (cur_lev.map[point.x, point.y].item = 0) and (cur_lev.map[point.x, point.y].AnObject = #0) and (not IsType(point.x, point.y, 'PrisonUp')) and (not IsType(point.x, point.y, 'PrisonDown')) then
    begin
      cur_lev.map[point.x, point.y].item := Random(maxnum - minnum + 1) + minnum;
      cur_lev.map[point.x, point.y].ItemCount := Random(count) + 1;
    end;
  end;
end;

procedure PlaceItemInLabyrinth(num, count: word);
var
  point: APoint;
begin
  repeat
    point := GenerateRandomPoint;
  until (not IsThisAMonster(point.x, point.y)) and (cur_lev.map[point.x, point.y].item = 0) and (not IsType(point.x, point.y, 'PrisonUp')) and (not IsType(point.x, point.y, 'PrisonDown'));
  cur_lev.map[point.x, point.y].item := num;
  cur_lev.map[point.x, point.y].ItemCount := count;
end;

procedure PlaceUniqueItemInLabyrinth(num, count: word; Montype: word = 0);
var
  point: APoint;
  enemy: TEnemy;
  x, y: byte;
begin
  repeat
    point := GenerateRandomPoint;
  until (not IsThisAMonster(point.x, point.y)) and (cur_lev.map[point.x, point.y].item = 0) and (not IsType(point.x, point.y, 'PrisonUp')) and (not IsType(point.x, point.y, 'PrisonDown'));
  if Montype = 0 then
  begin
    cur_lev.map[point.x, point.y].item := num;
    cur_lev.map[point.x, point.y].ItemCount := count;
  end
  else
  begin
    mon_info(Montype, enemy);
    x := point.x;
    y := point.y;
    cur_lev.map[x, y].Monster.montype := Montype;
    cur_lev.map[x, y].Monster.health := enemy.health;
    cur_lev.map[x, y].Monster.monchar := enemy.character;
    cur_lev.map[x, y].Monster.point := 0;
    cur_lev.map[x, y].Monster.shod := false;
    cur_lev.map[x, y].Monster.Zak := EmptyZakl;
    cur_lev.map[x, y].Monster.item := num;
    cur_lev.map[x, y].Monster.count := 1;
  end;
end;

procedure MakeInLabyrinth(ElementName: string);
var
  point: APoint;
begin
  point := GenerateRandomPoint;
  SetElement(point.x, point.y, ElementName);
end;

procedure MakeEntraceInLabyrinth;
var
  point: APoint;
begin
  repeat
    point := GenerateRandomPoint;
  until (not IsThisAMonster(point.x, point.y)) and (cur_lev.map[point.x, point.y].item = 0);
  SetElement(point.x, point.y, 'PrisonUp');
  cur_lev.map[point.x, point.y].levAttrz := data.posx * 256 + data.posy;
  data.posx := point.x;
  data.posy := point.y;
  globx := point.x;
  globy := point.y;
  if data.PrisonLevel = 1 then
    data.LastLocation := data.location;
  data.location := 'prison' + Inttostr(data.PrisonLevel);
end;

procedure GenerateMonsterInLabyrinth(num: integer; item: word = 0; count: word = 0);
var
  point: APoint;
begin
  repeat
    point := GenerateRandomPoint;
  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 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
  if (data.PrisonLevel = 1) then
  begin
    minnum := minnum + 3;
    maxnum := maxnum + 3;
  end;
  i := Random(maxcount - mincount + 1) + mincount;
  for i := i downto 1 do
  begin
    j := Random(maxnum - minnum + 1) + minnum;
    mon_info(j, enemy);
    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;

procedure GenerateMonstersInLabyrinth(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);
    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;
    GenerateMonsterInLabyrinth(j, item, count);
  end;
end;

procedure GeneratePrimitive(var minitem, maxitem: integer);
begin
  minitem := WEAPON_PRIMITIVE_MIN;
  if ((data.PrisonLevel div 2) + 2 < (WEAPON_PRIMITIVE_MAX - WEAPON_PRIMITIVE_MIN)) then
    maxitem := Random(data.PrisonLevel div 2) + WEAPON_PRIMITIVE_MIN + 2
  else
    maxitem := Random(WEAPON_PRIMITIVE_MAX - WEAPON_PRIMITIVE_MIN + 1) + WEAPON_PRIMITIVE_MIN;
end;

procedure GenerateWeapon(var minitem, maxitem: integer);
begin
  minitem := WEAPON_SHOOT_MIN;
  if ((data.PrisonLevel div 2) < (WEAPON_SHOOT_MAX - WEAPON_SHOOT_MIN) + 2) then
    maxitem := Random((data.PrisonLevel div 2) + 2) + WEAPON_SHOOT_MIN
  else
    maxitem := Random(WEAPON_SHOOT_MAX - WEAPON_SHOOT_MIN + 1) + WEAPON_SHOOT_MIN;
end;

procedure GenerateArmor(var minitem, maxitem: integer);
begin
  minitem := ARMOR_MIN;
  if ((data.PrisonLevel div 2) < (ARMOR_MAX - ARMOR_MIN) + 2) then
    maxitem := Random((data.PrisonLevel div 2) + 2) + ARMOR_MIN
  else
    maxitem := Random(ARMOR_MAX - ARMOR_MIN + 1) + ARMOR_MIN;
end;

procedure GenerateLitter(var minitem, maxitem: integer);
begin
  minitem := LITTER_MIN;
  maxitem := LITTER_MAX;
end;

procedure GenerateZNF(var minitem, maxitem: integer);
var
  i: integer;
begin
  if (data.PrisonLevel < 10) then
  begin
    if (Random(100) mod (15 - data.PrisonLevel) = 0) then
      minitem := TECHNO_MIN
    else if Random(2) >= 1 then
      minitem := DRINK_MIN
    else
      minitem := FLOPPY_MIN;
  end
  else
  begin
    i := Random(10) + 1;
    case (i mod 3) of
      0: minitem := TECHNO_MIN;
      1: minitem := FLOPPY_MIN;
      2: minitem := DRINK_MIN;
    end;
  end;
  if (minitem = DRINK_MIN) then
  begin
    if ((data.PrisonLevel div 2) < (DRINK_MAX - DRINK_MIN) + 1) then
      maxitem := Random((data.PrisonLevel div 2) + 1) + DRINK_MIN
    else
      maxitem := Random(DRINK_MAX - DRINK_MIN + 1) + DRINK_MIN;
  end
  else if (minitem = FLOPPY_MIN) then
  begin
    if ((data.PrisonLevel div 2) < (FLOPPY_MAX - FLOPPY_MIN) + 2) then
      maxitem := Random((data.PrisonLevel div 2) + 2) + FLOPPY_MIN
    else
      maxitem := Random(FLOPPY_MAX - FLOPPY_MIN + 1) + FLOPPY_MIN;
  end
  else if (minitem = TECHNO_MIN) then
  begin
    if (Random(10) + 1) mod 3 = 0 then
    begin
      minitem := 653;
      maxitem := 653;
    end
    else
    begin
      if ((data.PrisonLevel div 2) < (TECHNO_MAX - TECHNO_MIN) + 2) then
        maxitem := Random((data.PrisonLevel div 2) + 2) + TECHNO_MIN
      else
        maxitem := Random(TECHNO_MAX - TECHNO_MIN + 1) + TECHNO_MIN;
    end;
  end;
end;

procedure GenerateDragStones(var minitem, maxitem: integer);
begin
  minitem := DRAGSTONE_MIN;
  maxitem := data.PrisonLevel + DRAGSTONE_MIN - 1 + Round(data.luck / 15);
end;

procedure GenerateEat(var minitem, maxitem: integer);
begin
  minitem := EAT_MIN;
  maxitem := EAT_MAX;
end;

procedure GenerateMedic(var minitem, maxitem: integer);
begin
  minitem := MEDIC_MIN;
  maxitem := MEDIC_MAX - 1;
  if data.PrisonLevel > 7 then
    inc(maxitem);
end;

function GetMaxCount: integer;
begin
  if data.PrisonLevel < 5 then
    GetMaxCount := Random(data.PrisonLevel * 2) + MINITEMWEAPONINLEVEL
  else
    GetMaxCount := Random(data.PrisonLevel) + MINITEMWEAPONINLEVEL;
end;

procedure GenerateLabyrinth(aName: string);
var
  x, y: byte;
  minitem, maxitem: integer;
  Point: APoint;
  i, j: integer;
begin
  for y := 1 to RESOLUTION_Y do
    for x := 1 to RESOLUTION_X do
      cur_lev.map[x, y] := EmptyKletka;
  cur_lev.street := false;
  cur_lev.sleep := true;
  cur_lev.dark := false;
  cur_lev.feeling := '';  // Возможно, в будущем можно будет вставить случайные впечатления
  cur_lev.groza := false;
  cur_lev.LastVisit := 0;
  cur_lev.name := aName;
  Generate;
  for y := 1 to RESOLUTION_X do
  begin
    SetElement(y, RESOLUTION_Y - 1, 'Wall');
    SetElement(y, RESOLUTION_Y, 'Wall');
  end;
  for y := 1 to RESOLUTION_Y do
  begin
    SetElement(RESOLUTION_X - 1, y, 'Wall');
    SetElement(RESOLUTION_X, y, 'Wall');
  end;
  if (data.PrisonLevel < data.MaxLevel) then
    MakeInLabyrinth('PrisonDown');
  MakeEntraceInLabyrinth;
  while ((Random(100) + 1) mod 25 = 0) do
  begin
    repeat
      Point := GenerateRandomPoint;
    until (not IsType(point.x, point.y, 'PrisonUp')) and (not IsType(point.x, point.y, 'PrisonDown'));
    GenerateGroupInPrison(Point.X, Point.Y, 10, 'Floor_water', 2);
  end;
  while ((Random(30) + 1) mod 25 = 0) do
  begin
    repeat
      Point := GenerateRandomPoint;
    until (not IsType(point.x, point.y, 'PrisonUp')) and (not IsType(point.x, point.y, 'PrisonDown'));
    GenerateGroupInPrison(Point.X, Point.Y, 10, 'Floor_blood', 2);
    if (Random(10) mod 3 = 0) then
      SetObject(Point.x, Point.y, 'Corpse_examined');
  end;
  GenerateMonstersInLabyrinth(data.PrisonLevel, (((data.level - 1) * LEVELUP_MNOZH) div 3) + data.PrisonLevel + MONSTERS_PACK, data.PrisonLevel + Random(data.PrisonLevel), (data.PrisonLevel * 2) + Random(data.PrisonLevel) + Random(10));
  i := GetMaxCount;
  for i := i downto 1 do
  begin
    j := Random(10) mod 4;
    if (j = 0) then
      GeneratePrimitive(minitem, maxitem)
    else if (j = 1) then
      GenerateWeapon(minitem, maxitem)
    else
      GenerateArmor(minitem, maxitem);
    GenerateItemsInLabyrinth(minitem, maxitem, 1, 1)
  end;
  i := GetMaxCount * 3;
  for i := i downto 1 do
  begin
    j := Random(10);
    if (j in [0, 1]) then
      GenerateMedic(minitem, maxitem)
    else if (j in [2]) then
      GenerateEat(minitem, maxitem)
    else if (j in [3, 4, 5, 6, 7]) then
      GenerateZNF(minitem, maxitem)
    else
    begin
      minitem := AMMO_BOWS;
      maxitem := AMMO_BOWS;
    end;
    if (minitem <> AMMO_BOWS) and (maxitem <> AMMO_BOWS) then
      GenerateItemsInLabyrinth(minitem, maxitem, 1, 1)
    else
      GenerateItemsInLabyrinth(minitem, maxitem, 1, 1, data.Prisonlevel * 5);
  end;
  GenerateDragStones(minitem, maxitem);
  i := (data.level div 3) + (data.luck div 10);
  GenerateItems(minitem, maxitem, 0, i);
end;

procedure fillrect(x, y, width, height: integer; c: char; col: byte);
var
  i, j: integer;
  dx, dy: shortint;
begin
  dx := 1;
  dy := 1;
  for j := y to height + y - dy do
    for i := x to width + x - dx do
    begin
      if (i in [1..RESOLUTION_X]) and (j in [1..RESOLUTION_Y]) then
      begin
        cur_lev.map[i, j].lev := c;
        cur_lev.map[i, j].color := col;
      end;
    end;
end;

procedure MakeHollow(x, y: byte; IsDoor: boolean);
begin
  if IsDoor then
    SetElement(x, y, 'Door')
  else
    SetElement(x, y, 'Floor');
end;

function CheckSquare(x, y, width, height: integer): boolean;
var
  i, j: integer;
  around: integer;
begin
  around := 0;
  Result := false;
  for j := y to y + height do
  begin
    for i := x to x + width do
    begin
      if (not (i in [2..RESOLUTION_X - 1])) or (not (j in [2..RESOLUTION_Y - 1])) then
        exit
      else if IsType(i, j, 'Floor') then
        exit;
    end;
  end;
  for j := y - 1 to y + height + 1 do
  begin
    if (x > 2) then
      if IsType(x - 1, j, 'Floor') then
        inc(around);
    if ((x + width) < RESOLUTION_X) then
      if IsType(x + width + 1, j, 'Floor') then
        inc(around);
  end;
  for i := x - 1 to x + width + 1 do
  begin
    if (y > 2) then
      if IsType(i, y - 1, 'Floor') then
        inc(around);
    if ((y + height) < RESOLUTION_Y) then
      if IsType(i, y + height + 1, 'Floor') then
        inc(around);
  end;
  CheckSquare := (around = 0);
end;

procedure MakeWall(cx, cy: integer);
begin
  if (cx in [1..RESOLUTION_X]) and (cy in [1..RESOLUTION_Y]) then
    SetElement(cx, cy, 'Wall');
end;

function CheckRoom(x, y: integer): boolean;
var
  i, j: integer;
begin
  CheckRoom := false;
  for j := 0 to Length(arr) - 1 do
    for i := 1 to Length(arr[j]) do
      if not ((x + i - 1) in [2..RESOLUTION_X - 1]) or not ((j + y) in [2..RESOLUTION_Y - 1]) then
        exit
      else if (arr[j][i] <> ' ') and not (IsType(x + i - 1, j + y, 'Wall')) then
        exit;
  CheckRoom := true;
end;

procedure MakeFloor(x, y: byte);
begin
  SetElement(x, y, 'Floor');
end;

function IsLiWall(x, y: integer): integer;
begin
  if not IsType(x, y, 'Wall') then
    Result := 1
  else
    Result := 0;
end;

{$Hints Off}
function VokrugFloor(x, y, dir: integer): integer;
var
  Left, Right, Up, Down: integer;
begin
  Result := 0;
  Left := 0;
  Right := 0;
  Up := 0;
  Down := 0;
  case dir of
    0, 2:
    begin
      Left := IsLiWall(x - 1, y - 1) + IsLiWall(x - 1, y) + IsLiWall(x - 1, y + 1);
      Right := IsLiWall(x + 1, y - 1) + IsLiWall(x + 1, y) + IsLiWall(x + 1, y + 1);
      Up := IsLiWall(x, y - 1);
      Down := IsLiWall(x, y + 1);
      Result := Up + Down;
      case dir of
        0: Result := Result + Left;
        2: Result := Result + Right;
      end;
      exit;
    end;
    1, 3:
    begin
      Left := IsLiWall(x - 1, y);
      Right := IsLiWall(x + 1, y);
      Up := IsLiWall(x - 1, y - 1) + IsLiWall(x, y - 1) + IsLiWall(x + 1, y - 1);
      Down := IsLiWall(x - 1, y + 1) + IsLiWall(x, y + 1) + IsLiWall(x + 1, y + 1);
      Result := Left + Right;
      case dir of
        1: Result := Result + Up;
        3: Result := Result + Down;
      end;
      exit;
    end;
  end;
end;
{$Hints On}

procedure MakeFloorInWall(num, arrnum: integer);
begin
  case arrnum of
    1: inc(walls1[num]);
    2: inc(walls2[num]);
  end;
end;

procedure MakeRazlom(x, y, len, dir, arrnum: integer);
var
  i: integer;
  dx, dy: shortint;
begin
  dx := 0;
  dy := 0;
  case dir of
    0: dx := -1;
    1: dy := -1;
    2: dx := 1;
    3: dy := 1;
  end;
  for i := 1 to len do
    if VokrugFloor(x, y, dir) = 0 then
    begin
      if dir in [0, 2] then
        MakeFloorInWall(y, arrnum)
      else
        MakeFloorInWall(x, arrnum);
      x := x + dx;
      y := y + dy;
    end
    else
      break;
end;

function GenerateRandom(num: integer): integer;
begin
  GenerateRandom := 0;
  case num of
    0: GenerateRandom := Random(2);
    1: GenerateRandom := Random(3) - 1;
    2: GenerateRandom := Random(2) - 1;
  end;
end;

procedure DrawHollow(x, y, dx, dy, len: integer);
var
  cx, cy, i: integer;
begin
  cx := x;
  cy := y;
  for i := 1 to len do
  begin
    SetElement(cx, cy, 'Floor');
    cx := cx + dx;
    cy := cy + dy;
  end;
end;

procedure Burrel(x, y, width, height: integer; num: integer);
var
  cx, cy: integer;
begin
  case num of
    0:
    begin
      cx := x - 1;
      for cy := y to y + height - 1 do
        DrawHollow(cx, cy, -1, 0, walls1[cy - y]);
      for cy := y to y + height - 1 do
        DrawHollow(x + width + 1, cy, 1, 0, walls2[cy - y]);
    end;
    1:
    begin
      for cx := x to x + width - 1 do
        DrawHollow(cx, y - 1, 0, -1, walls1[cx - x]);
      for cx := x to x + width - 1 do
        DrawHollow(cx, y + height + 1, 0, 1, walls2[cx - x]);
    end;
  end;
end;

procedure MakeStrangeWall(x, y, width, height: integer);
var
  d, i, d1: integer;
  cx, cy: integer;
begin
  d := 0;
  d1 := 0;
  cx := 0;
  cy := 0;
  SetLength(walls1, height);
  SetLength(walls2, height);
  for i := 1 to height do
  begin
    walls1[i - 1] := 0;
    walls2[i - 1] := 0;
    d := d + GenerateRandom(d);
    if (d > 0) then
    begin
      cx := x - 1;
      cy := y + i - 1;
      MakeRazlom(cx, cy - y, d, 0, 1);
    end;
    d1 := d1 + GenerateRandom(d1);
    if (d > 0) then
    begin
      cx := x + width + 1;
      cy := y + i - 1;
      MakeRazlom(cx, cy - y, d1, 2, 2);
    end;
  end;
  Burrel(x, y, width, height, 0);
  SetLength(walls1, width);
  SetLength(walls2, width);
  d := 0;
  d1 := 0;
  for i := 1 to width do
  begin
    walls1[i - 1] := 0;
    walls2[i - 1] := 0;
    d := d + GenerateRandom(d);
    if (d > 0) then
    begin
      cx := x + i - 1;
      cy := y - 1;
      MakeRazlom(cx - x, cy, d, 1, 1);
    end;
    d1 := d1 + GenerateRandom(d1);
    if (d > 0) then
    begin
      cx := x + i - 1;
      cy := y + height + 1;
      MakeRazlom(cx - x, cy, d1, 3, 2);
    end;
    Burrel(cx, cy, width, height, 1);
  end;
end;

procedure MakeLitter(x, w, y, h: byte);
var
  b, e: byte;
  ax, ay: byte;
begin
  b := Random((3 - (data.PrisonLevel div 3)) + 2);
  e := Random((3 - (data.PrisonLevel div 3)) + 2);
  while (b <= e) do
  begin
    ax := x + Random(w);
    ay := y + Random(h);
    if ((cur_lev.map[ax, ay].lev = GetFloorChar) and (cur_lev.map[ax, ay].AnObject = #0) and (cur_lev.map[ax, ay].Monster.montype = 0) and (cur_lev.map[ax, ay].item = 0)) then
    begin
      if (Random(2) = 0) then
        cur_lev.map[ax, ay].item := Random(LITTER_MAX - LITTER_MIN + 1) + LITTER_MIN
      else
        cur_lev.map[ax, ay].item := Random(LITTER_PRISON_MAX - LITTER_PRISON_MIN + 1) + LITTER_PRISON_MIN;
      cur_lev.map[ax, ay].ItemCount := 1;
    end;
    inc(b);    
  end;
end;

procedure MakeARoom(acx, acy, hollowx, hollowy: integer; dx, dy: shortint; PredType: aRoomType);
var
  ccx, ccy, ch, cw, i: integer;
  ax, ay: integer;
  wall: integer;
  ddx, ddy: shortint;
  hx, hy: integer;
  cx, cy: integer;
  bx, by: integer;
  RoomType: integer;
  MakeDoor: boolean;
  anPredType: aRoomType;
  i1, j: integer;
  minitem, maxitem: integer;
const
  MAXHALL = 6;
begin
  MakeDoor := StrToBool(inttostr(Random(10) mod 2));
  RoomInDoors := false;
  ccx := 0;
  ccy := 0;
  hx := 0;
  hy := 0;
  cw := 0;
  ch := 0;
  ddx := 0;
  ddy := 0;
  cx := acx;
  cy := acy;
  if Strrooms then
    RoomType := Random(12)
  else
    RoomType := Random(11);
  anPredType := RTRoom;
  if (predType = RTVerticalCoridor) then
  begin
    case RoomType of
      0, 3, 4, 5, 6, 7, 8:
      begin
        cw := random(MAXROOMSIZE) + 2;
        ch := random(MAXROOMSIZE) + 3;
        anPredType := RTRoom;
        if RoomInDoors then
          MakeDoor := true;
      end;
      1:
      begin
        cw := 0;
        ch := Random(MAXHALL) + 1;
        anPredType := RTVerticalCoridor;
      end;
      2, 9, 10:
      begin
        cw := Random(MAXHALL) + 1;
        ch := 0;
        anPredType := RTHorizontalCoridor;
        MakeDoor := false;
      end;
    end;
  end
  else if (predType = RTHorizontalCoridor) then
  begin
    case RoomType of
      0, 3, 4, 5, 6, 7, 8:
      begin
        cw := random(MAXROOMSIZE) + 2;
        ch := random(MAXROOMSIZE) + 3;
        anPredType := RTRoom;
        if RoomInDoors then
          MakeDoor := true;
      end;
      1, 9, 10:
      begin
        cw := 0;
        ch := Random(MAXHALL) + 1;
        anPredType := RTVerticalCoridor;
        MakeDoor := false;
      end;
      2:
      begin
        cw := Random(MAXHALL) + 1;
        ch := 0;
        anPredType := RTHorizontalCoridor;
      end;
    end;
  end
  else if (predType = RTRoom) then
  begin
    case RoomType of
      0, 1, 2, 3, 4:
      begin
        cw := 0;
        ch := Random(MAXHALL) + 1;
        anPredType := RTVerticalCoridor;
      end;
      6, 7, 8, 9, 10:
      begin
        cw := Random(MAXHALL) + 1;
        ch := 0;
        anPredType := RTHorizontalCoridor;
      end;
      5:
      begin
        cw := Random(MAXROOMSIZE) + 2;
        ch := Random(MAXROOMSIZE) + 2;
        anPredType := RTRoom;
      end;
    end;
  end;
  if (anPredType = RTRoom) then
  begin
    if (dx = -1) then
      cx := cx - cw
    else if (dx = 0) then
      cx := cx - random(cw);
    if dy = -1 then
      cy := cy - ch
    else if (dy = 0) then
      cy := cy - random(ch);
  end
  else
  begin
    if (dx = -1) then
      cx := cx - cw;
    if (dy = -1) then
      cy := cy - ch
  end;
  if CheckSquare(cx, cy, cw, ch) then
  begin
    MakeHollow(hollowx, hollowy, MakeDoor);
    FillRect(cx, cy, cw + 1, ch + 1, FLOOR_CHAR, white);
    SetLength(rooms, Length(rooms) + 1);
    rooms[Length(rooms) - 1].x := cx;
    rooms[Length(rooms) - 1].y := cy;
    rooms[Length(rooms) - 1].width := cw;
    rooms[Length(rooms) - 1].height := ch;
    MakeLitter(cx, cw, cy, ch);
    if (anPredType = RTRoom) and ((Random(20) + 1) mod 4 = 0) then
    begin
      GenerateGroupInPrison(cx + Random(cw), cy + Random(ch), 8, 'Floor_water', 2);
    end;
    if ((Random(30) + 1) mod 7 = 0) then
    begin
      ax := cx + Random(cw);
      ay := cy + Random(ch);
      if (not IsType(ax, ay, 'PrisonUp')) and (not IsType(ax, ay, 'PrisonDown') and (cur_lev.map[ax, ay].item = 0)) then
      begin
        GenerateGroupInPrison(ax, ay, 9, 'Floor_blood', 3);
        if (Random(10) mod 2 = 0) then
          SetObject(ax, ay, 'Corpse_examined');
      end;
    end;
    if ((Random(10) + 1) mod 4 = 0) then
    begin
      i1 := Random(data.PrisonLevel div 10) + 1;
      for i1 := i1 downto 1 do
      begin
        j := Random(10);
        if (j in [0, 1]) then
          GenerateMedic(minitem, maxitem)
        else if (j in [2]) then
          GenerateEat(minitem, maxitem)
        else if (j in [3, 4, 5, 6, 7]) then
          GenerateZNF(minitem, maxitem)
        else
        begin
          minitem := AMMO_BOWS;
          maxitem := AMMO_BOWS;
        end;
        bx := cx + Random(cw);
        by := cy + Random(ch);
        if (cur_lev.map[bx, by].lev = GetFloorChar) and (cur_lev.map[bx, by].AnObject = #0) and (cur_lev.map[bx, by].item = 0) then
        begin
          cur_lev.map[bx, by].item := Random(maxitem - minitem + 1) + minitem;
          if (minitem <> AMMO_BOWS) or (maxitem <> AMMO_BOWS) then
            cur_lev.map[bx, by].ItemCount := 1
          else
            cur_lev.map[bx, by].ItemCount := Random(data.PrisonLevel * 5) + 1;
        end;
      end;
    end;
  end
  else
  begin
    if RoomType <> 5 then
      MakeWall(hollowx, hollowy);
    exit;
  end;
  for i := 1 to Random(10) + 8 do
  begin
    if (predType = RTVerticalCoridor) and (anPredType = RTVerticalCoridor) then
      wall := (Random(2) + 1) * 2
    else if (predType = RTHorizontalCoridor) and (anPredType = RTHorizontalCoridor) then
      wall := (Random(2) + 1) * 2 - 1
    else
      wall := random(4) + 1;
    case wall of
      1:
      begin
        ccx := cx - 2;
        if (anPredType in [RTRoom, RTHorizontalCoridor]) then
        begin
          ccy := cy + random(ch);
          if ch > 1 then
            ccy := ccy + random(2);
        end
        else if (anPredType = RTVerticalCoridor) then
        begin
          if Random(10) mod 2 = 0 then
            ccy := cy
          else
            ccy := cy + ch;
        end;
        ddx := -1;
        ddy := 0;
        if IsType(ccx + 1, ccy, 'Wall') then
        begin
          hx := ccx + 1;
          hy := ccy;
        end
        else
        begin
          hx := 0;
          hy := 0;
        end;
      end;
      2:
      begin
        if (anPredType in [RTRoom, RTVerticalCoridor]) then
        begin
          ccx := cx + random(cw);
          if cw > 1 then
            ccx := ccx + random(2);
        end
        else
        begin
          if Random(10) mod 2 = 0 then
            ccx := cx
          else
            ccx := cx + cw;
        end;
        ccy := cy - 2;
        ddx := 0;
        ddy := -1;
        if IsType(ccx, ccy + 1, 'Wall') then
        begin
          hx := ccx;
          hy := ccy + 1;
        end
        else
        begin
          hx := 0;
          hy := 0;
        end;
      end;
      3:
      begin
        ccx := cx + cw + 2;
        if (anPredType in [RTRoom, RTHorizontalCoridor]) then
        begin
          ccy := cy + random(ch);
          if ch > 1 then
            ccy := ccy + random(2);
        end
        else
        begin
          if Random(10) mod 2 = 0 then
            ccy := cy
          else
            ccy := cy + ch;
        end;
        ddx := 1;
        ddy := 0;
        if IsType(ccx - 1, ccy, 'Wall') then
        begin
          hx := ccx - 1;
          hy := ccy;
        end
        else
        begin
          hx := 0;
          hy := 0;
        end;
      end;
      4:
      begin
        if (anPredType in [RTRoom, RTVerticalCoridor]) then
        begin
          ccx := cx + random(cw);
          if cw > 1 then
            ccx := ccx + random(2);
        end
        else
        begin
          if Random(10) mod 2 = 0 then
            ccx := cx
          else
            ccx := cx + cw;
        end;
        ccy := cy + ch + 2;
        ddx := 0;
        ddy := 1;
        if IsType(ccx, ccy - 1, 'Wall') then
        begin
          hx := ccx;
          hy := ccy - 1;
        end
        else
        begin
          hx := 0;
          hy := 0;
        end;
      end;
    end;
    if (hx <> 0) and (hy <> 0) then
      MakeARoom(ccx, ccy, hx, hy, ddx, ddy, anPredType);
  end;
end;

procedure MakeARoom_vault(acx, acy, hollowx, hollowy: integer; dx, dy: shortint; PredType: aRoomType);
var
  ccx, ccy, ch, cw, i: integer;
  ax, ay: integer;
  wall: integer;
  ddx, ddy: shortint;
  hx, hy: integer;
  cx, cy: integer;
  bx, by: integer;
  RoomType: integer;
  MakeDoor: boolean;
  anPredType: aRoomType;
  i1, j: integer;
  minitem, maxitem: integer;
begin
  MakeDoor := StrToBool(inttostr(Random(10) mod 2));
  ccx := 0;
  ccy := 0;
  hx := 0;
  hy := 0;
  ddx := 0;
  ddy := 0;
  ch := 0;
  cw := 0;
  anPredType := RTRoom;
  cx := acx;
  cy := acy;
  if Strrooms then
    RoomType := Random(12)
  else
    RoomType := Random(11);
  if (predType = RTVerticalCoridor) then
  begin
    case RoomType of
      0, 3, 4, 5, 6, 7, 8:
      begin
        cw := random(MAXROOMSIZE) + 2;
        ch := random(MAXROOMSIZE) + 3;
        anPredType := RTRoom;
        if RoomInDoors then
          MakeDoor := true;
      end;
      1:
      begin
        cw := 0;
        ch := random(MAXROOMSIZE) + 4;
        anPredType := RTVerticalCoridor;
      end;
      2, 9, 10:
      begin
        cw := random(MAXROOMSIZE) + 4;
        ch := 0;
        anPredType := RTHorizontalCoridor;
        MakeDoor := false;
      end;
    end;
  end
  else if (predType = RTHorizontalCoridor) then
  begin
    case RoomType of
      0, 3, 4, 5, 6, 7, 8:
      begin
        cw := random(MAXROOMSIZE) + 2;
        ch := random(MAXROOMSIZE) + 3;
        anPredType := RTRoom;
        if RoomInDoors then
          MakeDoor := true;
      end;
      1, 9, 10:
      begin
        cw := 0;
        ch := random(MAXROOMSIZE) + 4;
        anPredType := RTVerticalCoridor;
        MakeDoor := false;
      end;
      2:
      begin
        cw := random(MAXROOMSIZE) + 4;
        ch := 0;
        anPredType := RTHorizontalCoridor;
      end;
    end;
  end
  else if (predType = RTRoom) then
  begin
      MakeDoor := true;
    case RoomType of
      0, 1, 2, 3, 4:
      begin
        cw := 0;
        ch := Random(MAXROOMSIZE) + 2;
        anPredType := RTVerticalCoridor;
      end;
      6, 7, 8, 9, 10:
      begin
        cw := Random(MAXROOMSIZE) + 2;
        ch := 0;
        anPredType := RTHorizontalCoridor;
      end;
      5:
      begin
        cw := Random(MAXROOMSIZE) + 2;
        ch := Random(MAXROOMSIZE) + 2;
        anPredType := RTRoom;
      end;
    end;
  end;
  if (dx = -1) then
    cx := cx - cw
  else if (dx = 0) then
    cx := cx - random(cw);
  if dy = -1 then
    cy := cy - ch
  else if (dy = 0) then
    cy := cy - random(ch);
  if CheckSquare(cx, cy, cw, ch) then
  begin
    MakeHollow(hollowx, hollowy, MakeDoor);
    FillRect(cx, cy, cw + 1, ch + 1, FLOOR_CHAR, white);
    SetLength(rooms, Length(rooms) + 1);
    rooms[Length(rooms) - 1].x := cx;
    rooms[Length(rooms) - 1].y := cy;
    rooms[Length(rooms) - 1].width := cw;
    rooms[Length(rooms) - 1].height := ch;
    if (anPredType = RTRoom) and ((Random(20) + 1) mod 6 = 0) then
      GenerateGroupInPrison(cx + Random(cw), cy + Random(ch), 8, 'Floor_water', 2);
    if (anPredType = RTRoom) and ((Random(30) + 1) mod 25 = 0) then
    begin
      ax := cx + Random(cw);
      ay := cy + Random(ch);
      if (not IsType(ax, ay, 'PrisonUp')) and (not IsType(ax, ay, 'PrisonDown')) then
      begin
        GenerateGroupInPrison(ax, ay, 9, 'Floor_blood', 3);
        if (Random(10) mod 3 = 0) then
          SetObject(ax, ay, 'Corpse_examined');
      end;
    end;
    if (Random(10) mod 4 = 0) then
    begin
      i1 := Random(data.PrisonLevel div 10) + 1;
      for i1 := i1 downto 1 do
      begin
        j := Random(10);
        if (j in [0, 1]) then
          GenerateMedic(minitem, maxitem)
        else if (j in [2]) then
          GenerateEat(minitem, maxitem)
        else if (j in [3, 4, 5, 6, 7]) then
          GenerateZNF(minitem, maxitem)
        else
        begin
          minitem := AMMO_BOWS;
          maxitem := AMMO_BOWS;
        end;
        bx := cx + Random(cw);
        by := cy + Random(ch);
        cur_lev.map[bx, by].item := Random(maxitem - minitem + 1) + minitem;
        if (minitem <> AMMO_BOWS) or (maxitem <> AMMO_BOWS) then
          cur_lev.map[bx, by].ItemCount := 1
        else
          cur_lev.map[bx, by].ItemCount := Random(data.PrisonLevel * 5) + 1;
      end;
    end;
  end
  else
  begin
    if RoomType <> 5 then
      MakeWall(hollowx, hollowy);
    exit;
  end;
  for i := 1 to Random(10) + 8 do
  begin
    if (predType = RTVerticalCoridor) and (anPredType = RTVerticalCoridor) then
      wall := (Random(2) + 1) * 2
    else if (predType = RTHorizontalCoridor) and (anPredType = RTHorizontalCoridor) then
      wall := (Random(2) + 1) * 2 - 1
    else
      wall := random(4) + 1;
    case wall of
      1:
      begin
        ccx := cx - 2;
        ccy := cy + random(ch);
        if ch > 1 then
          ccy := ccy + random(2);
        ddx := -1;
        ddy := 0;
        if IsType(ccx + 1, ccy, 'Wall') then
        begin
          hx := ccx + 1;
          hy := ccy;
        end
        else
        begin
          hx := 0;
          hy := 0;
        end;
      end;
      2:
      begin
        ccx := cx + random(cw);
        if cw > 1 then
          ccx := ccx + random(2);
        ccy := cy - 2;
        ddx := 0;
        ddy := -1;
        if IsType(ccx, ccy + 1, 'Wall') then
        begin
          hx := ccx;
          hy := ccy + 1;
        end
        else
        begin
          hx := 0;
          hy := 0;
        end;
      end;
      3:
      begin
        ccx := cx + cw + 2;
        ccy := cy + random(ch);
        if ch > 1 then
          ccy := ccy + random(2);
        ddx := 1;
        ddy := 0;
        if IsType(ccx - 1, ccy, 'Wall') then
        begin
          hx := ccx - 1;
          hy := ccy;
        end
        else
        begin
          hx := 0;
          hy := 0;
        end;
      end;
      4:
      begin
        ccx := cx + random(cw);
        if cw > 1 then
          ccx := ccx + random(2);
        ccy := cy + ch + 2;
        ddx := 0;
        ddy := 1;
        if IsType(ccx, ccy - 1, 'Wall') then
        begin
          hx := ccx;
          hy := ccy - 1;
        end
        else
        begin
          hx := 0;
          hy := 0;
        end;
      end;
    end;
    if (hx <> 0) and (hy <> 0) then
      MakeARoom(ccx, ccy, hx, hy, ddx, ddy, anPredType);
  end;
end;

function AllFloor: integer;
var
  i, j: integer;
begin
  AllFloor := 0;
  for j := 2 to RESOLUTION_Y - 1 do
    for i := 2 to RESOLUTION_X - 1 do
      if IsType(i, j, 'Floor') then
        inc(Result);
end;

procedure MakeExit;
var
  n: integer;
  x, y: integer;
begin
  n := Random(Length(rooms));
  x := rooms[n].x + Random(rooms[n].width);
  y := rooms[n].y + Random(rooms[n].height);
  cur_lev.map[x, y].AnObject := #0;
  cur_lev.map[x, y].AnObjectColor := 0;
  cur_lev.map[x, y].item := 0;  
  SetElement(x, y, 'PrisonDown');
end;

procedure MakeEntrace;
var
  i: integer;
  x, y: integer;
begin
  i := Random(Length(rooms));
  x := rooms[i].x + Random(rooms[i].width);
  y := rooms[i].y + Random(rooms[i].height);
  cur_lev.map[x, y].AnObject := #0;
  cur_lev.map[x, y].AnObjectColor := 0;
  cur_lev.map[x, y].item := 0;
  SetElement(x, y, 'PrisonUp');
  cur_lev.map[x, y].levAttrz := data.posx * 256 + data.posy;
  data.posx := x;
  data.posy := y;
  globx := x;
  globy := y;
  i := Random(10) + 1;
{  if (i mod 3 = 0) then
    MakeKeyDoor(x, y, true)
  else if (i mod 7 = 0) then
    MakeKeyDoor(x, y, false);}
  if data.PrisonLevel = 1 then
    data.LastLocation := data.location;
  data.location := 'prison' + Inttostr(data.PrisonLevel);
end;

procedure SavePrison;
var
  f: File of level_rec;
begin
  AssignFile(f, MAPFOLDER + data.location + LEV_EXTENSION);
  rewrite(f);
  System.write(f, cur_lev);
  CloseFile(f);
  DoCompress(MAPFOLDER + data.location + LEV_EXTENSION, MAPFOLDER + data.location + LEV_EXTENSION + ARC_EXTENSION);
  Erase(f);
end;

var
  cx, cy, cw, ch: integer;

procedure PlaceItem(num, count: word);
var
  x, y, n: integer;
begin
  repeat
    n := Random(Length(rooms));
    x := rooms[n].x + Random(rooms[n].width);
    y := rooms[n].y + Random(rooms[n].height);
  until (not IsThisAMonster(x, y)) and (cur_lev.map[x, y].item = 0);
  cur_lev.map[x, y].item := num;
  if (num = 0) then
  begin
    readkey;
  end;
  cur_lev.map[x, y].ItemCount := count;
end;

procedure PlaceUniqueItem(num, count: word; Montype: word = 0);
var
  x, y, n: integer;
  enemy: TEnemy;
begin
  repeat
    n := Random(Length(rooms));
    x := rooms[n].x + Random(rooms[n].width);
    y := rooms[n].y + Random(rooms[n].height);
  until (not IsThisAMonster(x, y)) and (cur_lev.map[x, y].item = 0);
  if Montype = 0 then
  begin
    cur_lev.map[x, y].item := num;
    cur_lev.map[x, y].ItemCount := count;
  end
  else
  begin
    mon_info(Montype, enemy);
    cur_lev.map[x, y].Monster.montype := Montype;
    cur_lev.map[x, y].Monster.health := enemy.health;
    cur_lev.map[x, y].Monster.monchar := enemy.character;
    cur_lev.map[x, y].Monster.point := 0;
    cur_lev.map[x, y].Monster.shod := false;
    cur_lev.map[x, y].Monster.Zak := EmptyZakl;
    cur_lev.map[x, y].Monster.item := num;
    cur_lev.map[x, y].Monster.count := 1;
  end;
end;

function AroundDoors(i, j: byte): byte;
begin
  AroundDoors := 0;
  if IsType(i - 1, j, 'Door') then
    inc(Result);
  if IsType(i, j - 1, 'Door') then
    inc(Result);
  if IsType(i + 1, j, 'Door') then
    inc(Result);
  if IsType(i, j + 1, 'Door') then
    inc(Result);
end;

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

procedure ClearDoorRyadom;
var
  i, j: byte;
begin
  for i := 1 to RESOLUTION_X do
    for j := 1 to RESOLUTION_Y do
      if (IsType(i, j, 'Door')) and (AroundDoors(i, j) > 0) then
        SetElement(i, j, 'Wall')
      else if (IsType(i, j, 'Door')) and (IsTypeAround(i, j, 'Floor') <> 2) then
        SetElement(i, j, 'Wall');
end;

function IsSquare(width, height, x, y: integer): boolean;
var
  i, j: integer;
begin
  IsSquare := false;
  for j := 1 to height do
    for i := 1 to width do
      if (not IsType(x + i - 1, y + j - 1, 'Wall')) then
        exit;
  IsSquare := true;
end;

function FindWallSquare(width, height: integer; var x, y: integer): boolean;
var
  i, j: integer;
begin
  FindWallSquare := true;
  x := 0;
  y := 0;
  for j := 1 to RESOLUTION_Y - height do
    for i := 1 to RESOLUTION_X - width do
      if IsSquare(width, height, i, j) then
      begin
        x := i + Random(width);
        y := j + Random(height);
        exit;
      end;
  FindWallSquare := false;
end;

function IsRoom(room: TRoom): boolean;
begin
  IsRoom := ((room.width > 1) and (room.height > 1));
end;

function GenerateRare(var minitem, maxitem: integer): boolean;
var
  templuck: integer;
begin
  templuck := 99 - data.luck * 3 - data.level;
  if (templuck < 1) then
    templuck := 1;
  if ((data.level > 10) and ((Random(100) + 1) mod templuck = 0)) then
  begin
    minitem := RARE_MIN;
    maxitem := RARE_MAX;
    Result := true;
  end
  else
    Result := false;
end;

procedure GenerateTraps(num: Integer);
var
  arr: array of APoint;
  aLen: Integer;
  i, j, k, aType, aVal: Integer;
begin
  if (data.PrisonLevel > 20) then
    num := num div 3
  else if (data.PrisonLevel > 8) then
    num := num div 2;
  SetLength(arr, 0);
  aLen := 0;
  for i := 1 to RESOLUTION_X do
    for j := 1 to RESOLUTION_Y do
      if (not IsBold(i, j) and (cur_lev.map[i, j].AnObject = #0)) then
      begin
        SetLength(arr, aLen + 1);
        arr[aLen].x := i;
        arr[aLen].y := j;
        inc(aLen);
      end;
  for num := num downto Random(num div 3) do
  begin
    k := Random(aLen);
    if (data.PrisonLevel < data.MaxLevel) then
      aType := Random(7)
    else
      aType := Random(6);
    aVal := Random(data.PrisonLevel * 5);
    cur_lev.map[arr[k].x, arr[k].y].EffectType := aType;
    cur_lev.map[arr[k].x, arr[k].y].Effect := aVal;
    for k := k to aLen - 2 do
      arr[k] := arr[k + 1];
    Dec(aLen);
    SetLength(arr, aLen);
  end;
  SetLength(arr, 0);
end;

procedure GeneratePrison(aName: string; StrangeRooms: boolean);
var
  x, y: integer;
  minitem, maxitem: integer;
  i1, j: integer;
  i: integer;
begin
  for y := 1 to RESOLUTION_Y do
    for x := 1 to RESOLUTION_X do
    begin
      cur_lev.map[x, y] := EmptyKletka;
      SetElement(x, y, 'Wall');
    end;
  cur_lev.street := false;
  cur_lev.sleep := true;
  cur_lev.dark := false;
  cur_lev.feeling := '';  // Возможно, в будущем можно будет вставить случайные впечатления
  cur_lev.groza := false;
  cur_lev.LastVisit := 0;
  cur_lev.name := aName;

  SetLength(rooms, 0);
  strrooms := StrangeRooms;
  Clrscr;
  SetLength(arr, 0);
  FillRect(1, 1, RESOLUTION_X, RESOLUTION_Y, WALL_CHAR, white);
  RoomInDoors := not (Random(10) mod 3 = 0);
  while AllFloor = 0 do
  begin
    cw := random(MAXROOMSIZE) + 1;
    ch := random(MAXROOMSIZE) + 1;
    cx := (RESOLUTION_X div 2) - (cw div 2) + random(5) - random(10);
    cy := (RESOLUTION_Y div 2) - (ch div 2) + random(5) - random(10);
    predType := RTVerticalCoridor;
    MakeARoom(cx, cy, 0, 0, 1, 1, predType);
  end;
  GenerateDragStones(minitem, maxitem);
  i := (data.level div 3) + (data.luck div 10);
  GenerateItemsInLabyrinth(minitem, maxitem, 0, i);
  MakeEntrace;
  if (data.PrisonLevel < data.MaxLevel) then
    MakeExit;
  GenerateMonsters(data.PrisonLevel, (((data.level - 1) * LEVELUP_MNOZH) div 3) + data.PrisonLevel + MONSTERS_PACK, data.PrisonLevel + Random(data.PrisonLevel), (data.PrisonLevel * 2) + Random(data.PrisonLevel) + Random(10));
  i1 := GetMaxCount;
  for i1 := i1 downto 1 do
  begin
    j := Random(10) mod 4;
    if (j = 0) then
      GeneratePrimitive(minitem, maxitem)
    else if (j = 1) then
      GenerateWeapon(minitem, maxitem)
    else
      GenerateArmor(minitem, maxitem);
    GenerateItems(minitem, maxitem, 1, 1)
  end;
  GenerateDragStones(minitem, maxitem);
  i := (data.level div 3) + (data.luck div 10);
  GenerateItems(minitem, maxitem, 0, i);
  if GenerateRare(minitem, maxitem) then
    GenerateItems(minitem, maxitem, 1, 1, 1);
  GenerateTraps(Random(data.PrisonLevel * 2));
end;

procedure GenerateVault(aName: string; StrangeRooms: boolean);
var
  x, y: integer;
  minitem, maxitem: integer;
  i1, j: integer;
  i: integer;
begin
  for y := 1 to RESOLUTION_Y do
    for x := 1 to RESOLUTION_X do
      cur_lev.map[x, y] := EmptyKletka;
  cur_lev.street := false;
  cur_lev.sleep := true;
  cur_lev.dark := false;
  cur_lev.feeling := '';  // Возможно, в будущем можно будет вставить случайные впечатления
  cur_lev.groza := false;
  cur_lev.LastVisit := 0;
  cur_lev.name := aName;

  SetLength(rooms, 0);
  strrooms := StrangeRooms;
  Clrscr;
  SetLength(arr, 0);
  FillRect(1, 1, RESOLUTION_X, RESOLUTION_Y, WALL_CHAR, white);
  RoomInDoors := not (Random(10) mod 3 = 0);
  while AllFloor = 0 do
  begin
    cw := random(MAXROOMSIZE) + 1;
    ch := random(MAXROOMSIZE) + 1;
    cx := (RESOLUTION_X div 2) - (cw div 2) + random(5) - random(10);
    cy := (RESOLUTION_Y div 2) - (ch div 2) + random(5) - random(10);
    predType := RTVerticalCoridor;
    MakeARoom_vault(cx, cy, 0, 0, 1, 1, predType);
  end;
  GenerateDragStones(minitem, maxitem);
  i := (data.level div 3) + (data.luck div 10);
  GenerateItems(minitem, maxitem, 0, i);
  MakeEntrace;
  if (data.PrisonLevel < data.MaxLevel) then
    MakeExit;
  GenerateMonsters(data.PrisonLevel, (((data.level - 1) * LEVELUP_MNOZH) div 3) + data.PrisonLevel + MONSTERS_PACK, data.PrisonLevel + Random(data.PrisonLevel), (data.PrisonLevel * 2) + Random(data.PrisonLevel) + Random(10));
  i1 := GetMaxCount;
  for i1 := i1 downto 1 do
  begin
    j := Random(10) mod 4;
    if (j = 0) then
      GeneratePrimitive(minitem, maxitem)
    else if (j = 1) then
      GenerateWeapon(minitem, maxitem)
    else
      GenerateArmor(minitem, maxitem);
    GenerateItems(minitem, maxitem, 1, 1)
  end;
  if GenerateRare(minitem, maxitem) then
    GenerateItems(minitem, maxitem, 1, 1, 1);
  GenerateTraps(Random(data.PrisonLevel * 2));
end;

function IsFor(LocName: string; level, x, y: integer; var anX, anY: integer): string;
var
  i: integer;
begin
  IsFor := '';
  for i := 1 to SpecLocsCount do
    if ((LocName = SpecLocs[i].locname) and (level = SpecLocs[i].level) and (x = SpecLocs[i].x) and (y = SpecLocs[i].y)) then
    begin
      IsFor := SpecLocs[i].aType;
      anX := SpecLocs[i].anX;
      anY := SpecLocs[i].anY;
      exit;
    end;
end;

procedure GenerateCave(aName: string);
var
  Point: APoint;
  i, j, k, minitem, maxitem: integer;
  points: array of APoint;
  anLen: integer;
  x, y: integer;
begin
  GenerateRLCave(true);
  for k := 1 to Random(10) + 1 do
  begin
    if ((Random(100) + 1) mod 3 = 0) then
    begin
      repeat
        Point := GenerateRandomPoint;
      until (not IsType(point.x, point.y, 'PrisonUp')) and (not IsType(point.x, point.y, 'PrisonDown'));
      GenerateGroupInPrison(Point.X, Point.Y, 10, 'Floor_water', 2);
    end;
  end;
  for k := 1 to Random(10) + 1 do
  begin
    if ((Random(30) + 1) mod 5 = 0) then
    begin
      repeat
        Point := GenerateRandomPoint;
      until (not IsType(point.x, point.y, 'PrisonUp')) and (not IsType(point.x, point.y, 'PrisonDown'));
      GenerateGroupInPrison(Point.X, Point.Y, 10, 'Floor_blood', 2);
      if (Random(10) mod 3 = 0) then
        SetObject(Point.x, Point.y, 'Corpse_examined');
    end;
  end;
  for k := 1 to Random(10) + 1 do
  begin
    if ((Random(30) + 1) mod 2 = 0) then
    begin
      repeat
        Point := GenerateRandomPoint;
      until (not IsType(point.x, point.y, 'PrisonUp')) and (not IsType(point.x, point.y, 'PrisonDown'));
      GenerateGroupInPrison(Point.X, Point.Y, 10, 'Floor_ground', 2);
    end;
  end;
  for i := 1 to RESOLUTION_X do
    for j := 1 to RESOLUTION_Y do
    begin
      k := Random(10) + 1;
      if (IsType(i, j, 'Wall') and (AroundType(i, j, 'Floor_ground') > 0)) then
        case k mod 3 of
          0: GenerateGroupInWall(i, j, 16, 'Land', 2);
          2: GenerateGroupInWall(i, j, 14, 'Rock', 3);
        end;
    end;
  for i := 1 to Random(10) do
  begin
    Point := GenerateRandomPoint;
    if (IsType(Point.x, Point.y, 'Floor') and (cur_lev.map[Point.x, Point.y].item = 0)) then
      if (Random(10) mod 2 = 0) then
        SetObject(Point.x, Point.y, 'Litter')
      else
        SetObject(Point.x, Point.y, 'Litter_land');
  end;
  GenerateMonstersInLabyrinth(data.PrisonLevel, (((data.level - 1) * LEVELUP_MNOZH) div 3) + data.PrisonLevel + MONSTERS_PACK, data.PrisonLevel + Random(data.PrisonLevel), (data.PrisonLevel * 2) + Random(data.PrisonLevel) + Random(10));
  i := GetMaxCount;
  for i := i downto 1 do
  begin
    j := Random(10) mod 4;
    if (j = 0) then
      GeneratePrimitive(minitem, maxitem)
    else if (j = 1) then
      GenerateWeapon(minitem, maxitem)
    else
      GenerateArmor(minitem, maxitem);
    GenerateItemsInLabyrinth(minitem, maxitem, 1, 1)
  end;
  i := GetMaxCount * 3;
  for i := i downto 1 do
  begin
    j := Random(10);
    if (j in [0, 1]) then
      GenerateMedic(minitem, maxitem)
    else if (j in [2]) then
      GenerateEat(minitem, maxitem)
    else if (j in [3, 4]) then
      GenerateZNF(minitem, maxitem)
    else if (j in [5, 6, 7]) then
      GenerateItemsInLabyrinth(LITTER_MIN, LITTER_MAX, 2, abs(18 - data.level) + 2)
    else
    begin
      minitem := AMMO_BOWS;
      maxitem := AMMO_BOWS;
    end;
    if (minitem <> AMMO_BOWS) and (maxitem <> AMMO_BOWS) then
      GenerateItemsInLabyrinth(minitem, maxitem, 1, 1)
    else
      GenerateItemsInLabyrinth(minitem, maxitem, 1, 1, data.Prisonlevel * 5);
  end;
  anLen := 0;
  SetLength(points, 0);
  for x := 1 to RESOLUTION_X do
    for y := 1 to RESOLUTION_Y do
      if (IsType(x, y, 'Land') or IsType(x, y, 'WallGround')) then
      begin
        SetLength(points, anLen + 1);
        points[anLen].x := x;
        points[anLen].y := y;
        inc(anLen);
      end;
  GenerateDragStones(minitem, maxitem);
  i := (data.level div 2) + (data.luck div 10) + 1;
  if (anLen = 0) then
    i := 0;
  for i := i downto 1 do
  begin
    x := Random(anLen);
    cur_lev.map[points[x].x, points[x].y].item := Random(maxitem - minitem) + minitem;
    cur_lev.map[points[x].x, points[x].y].ItemCount := 1;
    for x := x to anLen - 2 do
      points[x] := points[x + 1];
    dec(anLen);
  end;
  SetLength(points, 0);
  if (data.PrisonLevel < data.MaxLevel) then
    MakeInLabyrinth('PrisonDown');
  MakeEntraceInLabyrinth;
  cur_lev.street := false;
  cur_lev.sleep := true;
  cur_lev.dark := false;
  cur_lev.feeling := '';  // Возможно, в будущем можно будет вставить случайные впечатления
  cur_lev.groza := false;
  cur_lev.LastVisit := 0;
  cur_lev.name := aName;
  if GenerateRare(minitem, maxitem) then
    GenerateItemsInLabyrinth(minitem, maxitem, 1, 1, 1);
  GenerateTraps(Random(data.level * 2));
end;

procedure GenerateAMine(aName: string);
var
  Point: APoint;
  i, j, k, minitem, maxitem: integer;
  points: array of APoint;
  anLen: integer;
  x, y: integer;
begin
  GenerateMine;
  for k := 1 to Random(10) + 1 do
  begin
    if ((Random(100) + 1) mod 3 = 0) then
    begin
      repeat
        Point := GenerateRandomPoint;
      until (not IsType(point.x, point.y, 'PrisonUp')) and (not IsType(point.x, point.y, 'PrisonDown'));
      GenerateGroupInPrison(Point.X, Point.Y, 10, 'Floor_water', 2);
    end;
  end;
  for k := 1 to Random(10) + 1 do
  begin
    if ((Random(30) + 1) mod 5 = 0) then
    begin
      repeat
        Point := GenerateRandomPoint;
      until (not IsType(point.x, point.y, 'PrisonUp')) and (not IsType(point.x, point.y, 'PrisonDown'));
      GenerateGroupInPrison(Point.X, Point.Y, 10, 'Floor_blood', 2);
      if (Random(10) mod 3 = 0) then
        SetObject(Point.x, Point.y, 'Corpse_examined');
    end;
  end;
  for k := 1 to Random(10) + 1 do
  begin
    if ((Random(30) + 1) mod 2 = 0) then
    begin
      repeat
        Point := GenerateRandomPoint;
      until (not IsType(point.x, point.y, 'PrisonUp')) and (not IsType(point.x, point.y, 'PrisonDown'));
      GenerateGroupInPrison(Point.X, Point.Y, 10, 'Floor_ground', 2);
    end;
  end;
  for i := 1 to RESOLUTION_X do
    for j := 1 to RESOLUTION_Y do
    begin
      k := Random(10) + 1;
      if (IsType(i, j, 'Wall') and (AroundType(i, j, 'Floor') > 0)) then
        case k mod 20 of
          3, 5: GenerateGroupInWall(i, j, 20, 'Land', 2);
          7: GenerateGroupInWall(i, j, 10, 'Rock', 3);
        end;
    end;
  for i := 1 to Random(10) do
  begin
    Point := GenerateRandomPoint;
    if (IsType(Point.x, Point.y, 'Floor') and (cur_lev.map[Point.x, Point.y].item = 0)) then
      if (Random(10) mod 2 = 0) then
        SetObject(Point.x, Point.y, 'Litter')
      else
        SetObject(Point.x, Point.y, 'Litter_land');
  end;
  GenerateMonstersInLabyrinth(data.PrisonLevel, (((data.level - 1) * LEVELUP_MNOZH) div 3) + data.PrisonLevel + MONSTERS_PACK, data.PrisonLevel, (data.PrisonLevel * 2) + Random(data.PrisonLevel));
  i := GetMaxCount;
  for i := i downto 1 do
  begin
    j := Random(10) mod 4;
    if (j = 0) then
      GeneratePrimitive(minitem, maxitem)
    else if (j = 1) then
      GenerateWeapon(minitem, maxitem)
    else
      GenerateArmor(minitem, maxitem);
    GenerateItemsInLabyrinth(minitem, maxitem, 1, 1)
  end;
  i := GetMaxCount * 3;
  for i := i downto 1 do
  begin
    j := Random(10);
    if (j in [0, 1]) then
      GenerateMedic(minitem, maxitem)
    else if (j in [2]) then
      GenerateEat(minitem, maxitem)
    else if (j in [3, 4]) then
      GenerateZNF(minitem, maxitem)
    else if (j in [5, 6, 7]) then
      GenerateItemsInLabyrinth(LITTER_MIN, LITTER_MAX, 2, abs(18 - data.level) + 2)
    else
    begin
      minitem := AMMO_BOWS;
      maxitem := AMMO_BOWS;
    end;
    if (minitem <> AMMO_BOWS) and (maxitem <> AMMO_BOWS) then
      GenerateItemsInLabyrinth(minitem, maxitem, 1, 1)
    else
      GenerateItemsInLabyrinth(minitem, maxitem, 1, 1, data.Prisonlevel * 5);
  end;
  anLen := 0;
  SetLength(points, 0);
  for x := 1 to RESOLUTION_X do
    for y := 1 to RESOLUTION_Y do
      if (IsType(x, y, 'Land') or IsType(x, y, 'WallGround')) then
      begin
        SetLength(points, anLen + 1);
        points[anLen].x := x;
        points[anLen].y := y;
        inc(anLen);
      end;
  GenerateDragStones(minitem, maxitem);
  i := Random((data.level div 2) + (data.luck div 5) + 5);
  if (anLen = 0) then
    i := 0;
  for i := i downto 1 do
  begin
    x := Random(anLen);
    cur_lev.map[points[x].x, points[x].y].item := Random(maxitem - minitem) + minitem;
    cur_lev.map[points[x].x, points[x].y].ItemCount := 1;
    for x := x to anLen - 2 do
      points[x] := points[x + 1];
    dec(anLen);
  end;
  for i := 1 to Random(20) + data.PrisonLevel do
  begin
    if (anLen <= 0) then
      break;
    x := Random(anLen);
    cur_lev.map[points[x].x, points[x].y].item := Random(maxitem - minitem) + minitem;
    cur_lev.map[points[x].x, points[x].y].ItemCount := 1;
    for x := x to anLen - 2 do
      points[x] := points[x + 1];
    dec(anLen);
  end;
  for i := 1 to Random(40) do
  begin
    k := Random(LITTER_PRISON_MAX - LITTER_PRISON_MIN) + LITTER_PRISON_MIN;
    repeat
      point := GenerateRandomPoint;
    until (not IsThisAMonster(point.x, point.y)) and (cur_lev.map[point.x, point.y].item = 0);
    cur_lev.map[point.x, point.y].item := k;
    cur_lev.map[point.x, point.y].ItemCount := 1;
  end;
  SetLength(points, 0);
  if (data.PrisonLevel < data.MaxLevel) then
    MakeInLabyrinth('PrisonDown');
  MakeEntraceInLabyrinth;
  cur_lev.street := false;
  cur_lev.sleep := true;
  cur_lev.dark := false;
  cur_lev.feeling := '';  // Возможно, в будущем можно будет вставить случайные впечатления
  cur_lev.groza := false;
  cur_lev.LastVisit := 0;
  cur_lev.name := aName;
  if GenerateRare(minitem, maxitem) then
    GenerateItemsInLabyrinth(minitem, maxitem, 1, 1, 1);
  GenerateTraps(Random(data.PrisonLevel * 3));
end;

procedure GenerateAShuttle(aName: string);
var
  j, i1, minitem, maxitem: Integer;
begin
  GenerateShuttle(aName);
  MakeEntraceInLabyrinth;
  if (data.PrisonLevel < data.MaxLevel) then
    MakeExit;
  GenerateMonstersInLabyrinth(data.PrisonLevel, (((data.level - 1) * LEVELUP_MNOZH) div 3) + data.PrisonLevel + MONSTERS_PACK, data.PrisonLevel + Random(data.PrisonLevel), (data.PrisonLevel * 2) + Random(data.PrisonLevel) + Random(10));
  i1 := GetMaxCount;
  for i1 := i1 downto 1 do
  begin
    j := Random(10) mod 5;
    if (j = 0) then
      GeneratePrimitive(minitem, maxitem)
    else if (j = 1) then
      GenerateWeapon(minitem, maxitem)
    else if (j = 3) then
      GenerateArmor(minitem, maxitem)
    else
      GenerateLitter(minitem, maxitem);
    GenerateItemsInLabyrinth(minitem, maxitem, 1, 1)
  end;
  if GenerateRare(minitem, maxitem) then
    GenerateItemsInLabyrinth(minitem, maxitem, 1, 1, 1);
end;

procedure GenerateAPrison(aName: string; StrangeRooms: boolean; IsOsv: boolean = true);
var
  s: string;
  f: file of level_rec;
  x, y: integer;
  x1, x2, y1, y2, dx, dy: integer;
begin
  inc(data.PrisonLevel);
  if (data.PrisonLevel = 1) then
    s := IsFor(data.location, data.PrisonLevel, data.posx, data.posy, x, y)
  else
    s := IsFor(data.LastLocation, data.PrisonLevel, data.LastLocationX, data.LastLocationY, x, y);
  if (s = 'prison') then
    GeneratePrison(aName, StrangeRooms)
  else if (s = 'labyrinth') then
    GenerateLabyrinth(aName)
  else if (s = 'cave') then
    GenerateCave(aName)
  else if (s = 'vault') then
    GenerateVault(aName, StrangeRooms)
  else if (s = 'mine') then
    GenerateAMine(aName)
  else if (s = 'shuttle') then
    GenerateAShuttle(aName)
  else if (s <> '') then
    LoadLevelFrom(x, y, s)
  else
    GenerateAMine(aName);
    //GeneratePrison(aName, StrangeRooms);
{  readkey;
  halt;}
  AssignFile(f, MAPFOLDER + 'prison' + inttostr(data.PrisonLevel) + '.lev');
  rewrite(f);
  System.write(f, cur_lev);
  CloseFile(f);
  DoCompress(MAPFOLDER + 'prison' + inttostr(data.PrisonLevel) + '.lev', MAPFOLDER + 'prison' + inttostr(data.PrisonLevel) + '.lev.dat');
  Erase(f);
  if (IsOsv) then
  begin
    clean_all;
    gotoxy(data.posx, data.posy);
    osv;
  end;
end;

end.
