(*~\Глагол\Отделы\Игры\Тетрис\~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
(**)                          ОТДЕЛ Игра;
(*============================================================================*)
(* НАЗНАЧЕНИЕ: алгоритм игры "Тетрис"                                         *)
(*============================================================================*)

ПОСТ
  Кирпичей-  = 7;
  Пустоцвет- = 7H;
                   (* состояния кирпича *)
  состНовый-  = 0;
  состПадает- = 1;
  состУпор-   = 2;

ПЕР
  состояние-:ЦЕЛ;  (* состояние кирпича *)
      слоёв-:ЦЕЛ;  (* число заполненных слоёв *)

ПОСТ               (* размеры ящика *)
  Высота = 23;
  Ширина = 10;

ВИД
  Кирпич = РЯД 5,5 ИЗ КЛЮЧ;
    Ящик = РЯД Ширина,Высота ИЗ ЦЕЛ;

  ВидЗадачиРисоватьКлетку = ЗАДАЧА(x,y,цвет:ЦЕЛ);

ПЕР
  кирпичи:РЯД Кирпичей ИЗ Кирпич; 

  ящик0:Ящик;   (* изображение без кирпича *) 
  ящик :Ящик;   (* изображение с кирпичом  *) 
  следВид:ЦЕЛ;  (* вид следующего кирпича  *)
  следЦвет:ЦЕЛ; (* цвет следующего кирпича *)
  упал:КЛЮЧ;    (* упал ли кирпич?         *)

  (* свойства кирпича *)

   кирпич:Кирпич;(* геометрическая форма     *)
      X,Y:ЦЕЛ;   (* координаты               *)
     цвет:ЦЕЛ;   (* цвет                     *)
  квадрат:КЛЮЧ;  (* ВКЛ, если ненадо вращать *)
  
  зРисоватьКлетку:ВидЗадачиРисоватьКлетку;

(*-----------------------------------------локальная ЗАДАЧА-------------------*)
ЗАДАЧА
       УстановитьВ(ящик+:Ящик);
ПЕР
  x,y:ЦЕЛ;
УКАЗ                                            (* установить кирпич в <ящик> *)
  ОТ y:=0 ДО 4 ВЫП
    ОТ x:=0 ДО 4 ВЫП
      ЕСЛИ кирпич[x,y] ТО
        ящик[X+x,Y+y]:=цвет
      КОН
    КОН
  КОН
КОН УстановитьВ;

(*-----------------------------------------локальная ЗАДАЧА-------------------*)
ЗАДАЧА
       НеПоместился(Xn,Yn:ЦЕЛ):КЛЮЧ;
(*
 * изменить положение кирпича, если для этого есть свободное место
 *)
ПЕР
  x,y,xk,yk:ЦЕЛ;
  допЯщик:Ящик;
УКАЗ
  ЕСЛИ упал ТО
    ВОЗВРАТ ВКЛ
  КОН;
                          (* задеваем стенки или другие кирпичи ? *)
  ОТ y:=0 ДО 4 ВЫП
    ОТ x:=0 ДО 4 ВЫП
      ЕСЛИ
           кирпич[x,y]
      ТО 
        xk:=Xn+x;         (* координаты клетки в ящике *)
        yk:=Yn+y;
        ЕСЛИ
             (xk < 0)
           ИЛИ
             (xk >= Ширина)
           ИЛИ
             (yk < 0)
           ИЛИ
             (yk >= Высота)
           ИЛИ
             (ящик0[xk,yk] # Пустоцвет)
        ТО
          ВОЗВРАТ ВКЛ
        КОН
      КОН
    КОН
  КОН;
                    (* перемещаем кирпич в новое положение *)
  X:=Xn; 
  Y:=Yn;
                    (* отрисовываем изменения *)
  допЯщик:=ящик0;
  УстановитьВ(допЯщик);

  ОТ y:=0 ДО Высота-1 ВЫП
    ОТ x:=0 ДО Ширина-1 ВЫП
      ЕСЛИ
           ящик[x,y] # допЯщик[x,y]
      ТО
        зРисоватьКлетку(x,y,допЯщик[x,y]);
        ящик[x,y]:=допЯщик[x,y]
      КОН
    КОН
  КОН;
  ВОЗВРАТ ОТКЛ
КОН НеПоместился;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       ПовернутьКирпич-();
ПЕР
  допКирпич:Кирпич;
  x,y:ЦЕЛ;
УКАЗ
  ЕСЛИ
       НЕ квадрат
  ТО
    допКирпич:=кирпич;

    ОТ y:=0 ДО 4 ВЫП
      ОТ x:=0 ДО 4 ВЫП
        кирпич[x,y]:=допКирпич[4-y,x]
      КОН
    КОН;
    ЕСЛИ
         НеПоместился(X,Y)
    ТО
        кирпич:=допКирпич
    КОН
  КОН
КОН ПовернутьКирпич;

(*-----------------------------------------локальная ЗАДАЧА-------------------*)
ЗАДАЧА
       Уплотнить();
ПЕР
        x,y,yn:ЦЕЛ;
  безПропусков:КЛЮЧ;
УКАЗ                                          (* уплотнение заполненных строк *)
        yn:=Высота-1;
  ОТ y:=yn ДО 0 ПО -1 ВЫП
    безПропусков:=ВКЛ;
    ОТ x:=0 ДО Ширина-1 ВЫП

           ящик0[x,yn]:=ящик0[x,y];
      ЕСЛИ
           ящик0[x,yn] = Пустоцвет
      ТО 
        безПропусков:=ОТКЛ 
      КОН;
      ЕСЛИ
           yn # y
      ТО 
        ящик0[x][y]:=Пустоцвет 
      КОН
    КОН;
    ЕСЛИ безПропусков ТО 
      УВЕЛИЧИТЬ(слоёв)
    ИНАЧЕ
      УМЕНЬШИТЬ(yn) 
    КОН
  КОН
КОН Уплотнить;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       Переход-();
УКАЗ                                             (* переход в новое состояние *)
  ЕСЛИ
       состояние = Игра.состПадает
  ТО
    ЕСЛИ
         НеПоместился(X,Y+1)
    ТО
      УстановитьВ(ящик0);
      Уплотнить();
      состояние:=Игра.состНовый;
      упал:=ВКЛ
    КОН
  АЕСЛИ
        состояние = Игра.состНовый
  ТО
      упал:=ОТКЛ;
    ЕСЛИ
         НеПоместился(X,Y)
    ТО
      состояние:=Игра.состУпор
    ИНАЧЕ
      состояние:=Игра.состПадает
    КОН
  КОН;
КОН Переход;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       КирпичВлево-();
ПЕР
  кл:КЛЮЧ;
УКАЗ                                                   (* перемещения кирпича *)
  кл:=НеПоместился(X-1,Y)
КОН КирпичВлево;

ЗАДАЧА КирпичВправо-();
ПЕР
  кл:КЛЮЧ;
УКАЗ
  кл:=НеПоместился(X+1,Y)
КОН КирпичВправо;

ЗАДАЧА КирпичУронить-();
УКАЗ
  ПОКА состояние = Игра.состПадает ВЫП Переход() КОН
КОН КирпичУронить;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       НовыйКирпич-(следВид0,следЦвет0:ЦЕЛ);
ПЕР
  x,y:ЦЕЛ;
УКАЗ
  (* нарисуем в стороне будущий кирпич *)
  ОТ y:=1 ДО 4 ВЫП
    ОТ x:=1 ДО 4 ВЫП
      ЕСЛИ кирпичи[следВид0][x,y] ТО
        зРисоватьКлетку(x+Ширина,y,следЦвет0)
      ИНАЧЕ
        зРисоватьКлетку(x+Ширина,y,70H)
      КОН
    КОН
  КОН;
                           (* подготовим новый кирпич *)
    кирпич:=кирпичи[следВид];
      цвет:=следЦвет;
   квадрат:=следВид = 0;
   следВид:=следВид0;
  следЦвет:=следЦвет0;
  X:=(Ширина-3) ДЕЛИТЬ 2;
  Y:=-1;
КОН НовыйКирпич;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       НачатьЗаново-();
ПЕР
  x,y:ЦЕЛ;
УКАЗ                                            (* подготовиться к новой игре *)
  слоёв:=0;
  состояние:=Игра.состНовый;
  упал:=ОТКЛ;
                          (* чистим ящик *)
  ОТ y:=0 ДО Высота-1 ВЫП
    ОТ x:=0 ДО Ширина-1 ВЫП
      ящик [x,y]:=1H;
      ящик0[x,y]:=Пустоцвет
    КОН
  КОН
КОН НачатьЗаново;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       Подготовить-(ЗАДАЧА_рисоватьКлетку:ВидЗадачиРисоватьКлетку);
(*
 * первоначальная подготовка переменных отдела
 *)
ПЕР
  n,x,y:ЦЕЛ;
УКАЗ
  зРисоватьКлетку:=ЗАДАЧА_рисоватьКлетку;
  следВид:=0; 
  следЦвет:=0C0H;
                           (* задаем форму кирпичей *)
  ОТ n:=0 ДО Кирпичей-1 ВЫП
    ОТ x:=0 ДО 4 ВЫП
      ОТ y:=0 ДО 4 ВЫП
        кирпичи[n][x,y]:=ОТКЛ
      КОН
    КОН
  КОН;
  кирпичи[0][1,1]:=ВКЛ; кирпичи[0][2,1]:=ВКЛ; кирпичи[0][1,2]:=ВКЛ; кирпичи[0][2,2]:=ВКЛ;
  кирпичи[1][1,2]:=ВКЛ; кирпичи[1][2,1]:=ВКЛ; кирпичи[1][2,2]:=ВКЛ; кирпичи[1][2,3]:=ВКЛ;
  кирпичи[2][1,1]:=ВКЛ; кирпичи[2][2,1]:=ВКЛ; кирпичи[2][2,2]:=ВКЛ; кирпичи[2][2,3]:=ВКЛ;
  кирпичи[3][1,3]:=ВКЛ; кирпичи[3][2,1]:=ВКЛ; кирпичи[3][2,2]:=ВКЛ; кирпичи[3][2,3]:=ВКЛ;
  кирпичи[4][1,2]:=ВКЛ; кирпичи[4][1,3]:=ВКЛ; кирпичи[4][2,1]:=ВКЛ; кирпичи[4][2,2]:=ВКЛ;
  кирпичи[5][1,1]:=ВКЛ; кирпичи[5][1,2]:=ВКЛ; кирпичи[5][2,2]:=ВКЛ; кирпичи[5][2,3]:=ВКЛ;
  кирпичи[6][2,1]:=ВКЛ; кирпичи[6][2,2]:=ВКЛ; кирпичи[6][2,3]:=ВКЛ; кирпичи[6][2,4]:=ВКЛ;
КОН Подготовить;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       КонецИгры-(ЗАДАЧА_ожидание:ЗАДАЧА(время:ЦЕЛ));
ПЕР
  с,к:ЦЕЛ;
УКАЗ
  слоёв:=0;
  состояние:=Игра.состНовый;
  упал:=ОТКЛ;
  ОТ с:=Высота-1 ДО 0 ПО -1 ВЫП
    ОТ к:=0 ДО Ширина-1 ВЫП
      ящик [к,с]:=1H;
      ящик0[к,с]:=Пустоцвет;
      зРисоватьКлетку(к,с,80H)
    КОН;
    ЗАДАЧА_ожидание(100)
  КОН;
  ОТ с:=0 ДО Высота-1 ВЫП
    ОТ к:=0 ДО Ширина-1 ВЫП
      зРисоватьКлетку(к,с,Пустоцвет)
    КОН;
    ЗАДАЧА_ожидание(100)
  КОН
КОН КонецИгры;

КОН Игра.
