(*~\Глагол\Отделы\Игры\Шашки\~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
(**)                         ОТДЕЛ Доска;
(*============================================================================*)
(* Программа игры в русские шашки (8х8) на языке Глагол (www.glagol.nad.ru).  *)
(*                                                                            *)
(* НАЗНАЧЕНИЕ: представление доски для игрока (человека),                     *)
(*             отображение перемещения фигур,                                 *)
(*             получение приказаний от человека.                              *)
(* ПРИМЕЧАНИЯ: человек играет всегда нижними.                                 *)
(*============================================================================*)

ИСПОЛЬЗУЕТ
  Игра,
(*
  Ввод    ИЗ "....\Отделы\Обмен\",
  Окно    ИЗ "....\Отделы\Обмен\",

  Поле    ИЗ "....\Отделы\Поле\",
  Надел   ИЗ "....\Отделы\Поле\";
*)
  Ввод    ИЗ "..\..\..\Отделы\Обмен\",
  Окно    ИЗ "..\..\..\Отделы\Обмен\",

  Поле    ИЗ "..\..\..\Отделы\Поле\",
  Надел   ИЗ "..\..\..\Отделы\Поле\";

ПОСТ
  Оборотень- = ОТКЛ;
                   (* размеры клетки, знакомест *)
  ширинаКлетки=2; 
  высотаКлетки=1;
                   (* используемые цвета *)
  цвЧернойКлетки = 3;
  цвБелойКлетки  =15;
  цвЧернойШашки  = 0;
  цвБелойШашки   =15;
  цвУказки       = 7;
  цвХодов        = 8;
  цвПрозрачный   = -1;

ПЕР
  нижниеБелые- :КЛЮЧ;      (* у человека белые фигуры      *)
  думаютНижние-:КЛЮЧ;      (* думает человек               *)
  указка:ЦЕЛ;              (* n выделенной на доске клетки *)
   ходок:ЦЕЛ;               (* n фигуры для хода, или 0     *)
   ходов:ЦЕЛ;               (* ходов у ходока               *)
         (*- для экрана -*)
ВИД
  Доступ- = ДОСТУП К Вид;
                     Вид- = НАБОР (Надел.Вид)
                            КОН;
  нПосылка- = НАБОР (Ввод.нПосылка)
              КОН;
ПЕР
  доскаД:Доска.Доступ;
   полеД: Поле.Доступ;  (* доступ к экранному полю *)

(*----------------------------------------------------------------------------*)
ЗАДАЧА РисоватьКлетку(n,фон:ЦЕЛ);
(*
 * Цель:  единственная задача для отрисовки клетки доски
 * До:    <n>   - местоположение клетки
 *        <фон> - цвет фона выделенной клетки, или цвПрозрачный
 *)
ПЕР
  x,y:ЦЕЛ;             (* положение клетки на доске *)
  лк,вс,пк,нс:ЦЕЛ;     (* экранное положение 2-х противоположных углов клетки *)
  цвет:ЦЕЛ;            (* цвет фигуры *)
  рисунок:ЦЕПЬ[ширинаКлетки*высотаКлетки+1];    (* значки изображающие фигуру *)
  признаки:МНОЖ;
УКАЗ
  x:=Игра.NвX[n];
  y:=Игра.NвY[n];
  признаки:=Игра.позиция[n];
  ЕСЛИ
       фон = цвПрозрачный
  ТО
    ЕСЛИ
         НЕ ЧЕТ(x+y)
    ТО
      фон:=цвБелойКлетки
    ИНАЧЕ
      фон:=цвЧернойКлетки
    КОН
  КОН;
  ЕСЛИ признаки # {} ТО
    ЕСЛИ
          (   (Игра.нижние В признаки) И    нижниеБелые)
        ИЛИ
          (НЕ (Игра.нижние В признаки) И НЕ нижниеБелые)
    ТО
      цвет:=цвБелойШашки 
    ИНАЧЕ
      цвет:=цвЧернойШашки
    КОН;
    ЕСЛИ Игра.дамка В признаки ТО
      рисунок:="<>"
    ИНАЧЕ
      рисунок:="#25C4#25BA"
    КОН
  ИНАЧЕ
    цвет:=0;
    рисунок:="  "
  КОН;
  УВЕЛИЧИТЬ(цвет,фон*16);
<*ЕСЛИ Оборотень ТО*>
  лк:=доскаД.лк+(8-x)*ширинаКлетки;
  вс:=доскаД.вс+(y-1)*высотаКлетки;
<*ИНАЧЕ*>
  лк:=доскаД.лк+(x-1)*ширинаКлетки;
  вс:=доскаД.вс+(8-y)*высотаКлетки;
<*КОН*>
  пк:=лк+ширинаКлетки-1;
  нс:=вс+высотаКлетки-1;
  Окно.Цвет(вс,лк,нс,пк,ВЗНАК(цвет));
  Окно.ЦепьЗнаков(вс,лк,нс,пк,рисунок)
КОН РисоватьКлетку;

(*----------------------------------------------------------------------------*)
ЗАДАЧА РисоватьПозицию;                      (* Цель:  перерисовать всю доску *)
ПЕР
  x,y:ЦЕЛ;
УКАЗ
  ОТ y:=1 ДО 8 ВЫП
    ОТ x:=1 ДО 8 ВЫП
      РисоватьКлетку(Игра.XYвN[x,y],цвПрозрачный)
    КОН
  КОН
КОН РисоватьПозицию;

(*----------------------------------------------------------------------------*)
ЗАДАЧА РисоватьХоды(фон:ЦЕЛ);
ПЕР
  нхода:ЦЕЛ;
УКАЗ
  ОТ нхода:=0 ДО ходов-1 ВЫП
    РисоватьКлетку(Игра.ходы[нхода].кудаN,фон)
  КОН
КОН РисоватьХоды;

(*----------------------------------------------------------------------------*)
ЗАДАЧА ПеренестиУказку(n:ЦЕЛ);
УКАЗ
  РисоватьКлетку(указка,цвПрозрачный);
  РисоватьХоды(цвХодов);
  указка:=n;
  РисоватьКлетку(указка,цвУказки)
КОН ПеренестиУказку;

(*----------------------------------------------------------------------------*)
ЗАДАЧА СменитьХодока(n:ЦЕЛ);
УКАЗ
                               (* убираем старого ходока *)
  РисоватьХоды(цвПрозрачный);
  ходок:=0;
                               (* строим нового ходока *)
  ходов:=0;
  Игра.НайтиУдарные(ходов);
  ЕСЛИ
       ходов = 0
  ТО
    Игра.НайтиТихиеИзN(n,ходов)
  ИНАЧЕ
    ходов:=0;
    Игра.НайтиУдарныеИзN(n,ходов)
  КОН;
  ЕСЛИ
       ходов > 0
  ТО
    РисоватьХоды(цвХодов);
    ходок:=n
  КОН
КОН СменитьХодока;

(*----------------------------------------------------------------------------*)
ЗАДАЧА Ход(ход+:Игра.нХод);
(*
 * Цель:  полуход человека и ответный полуход машины
 * До:    <ход> - полуход человека
 *)
ПЕР
  посылка:нПосылка;
УКАЗ
  полеД.Приём(полеД,посылка); (* выключаем секундомер нижних  *)
  думаютНижние:=ОТКЛ;
  полеД.Приём(полеД,посылка); (* включаем секундомер верхних  *)
  Игра.ХодНижних(ход);
  РисоватьПозицию;
  ходов:=0;

  Игра.ХодВерхних;
  РисоватьПозицию;
  полеД.Приём(полеД,посылка); (* выключаем секундомер верхних *)
  думаютНижние:=ВКЛ;
  полеД.Приём(полеД,посылка)  (* включаем секундомер нижних   *)
КОН Ход;

(*----------------------------------------------------------------------------*)
ЗАДАЧА ВыбралКлетку(n:ЦЕЛ);
(*
 * Цель:  сообразить, что делать, если человек выбрал эту клетку
 *)
ПЕР
  нхода:ЦЕЛ;
УКАЗ
  ЕСЛИ
       Игра.нижние В Игра.позиция[n]
  ТО
    СменитьХодока(n)
  ИНАЧЕ
                                     (* поиск в ходах *)
    ОТ нхода:=0 ДО ходов-1 ВЫП
      ЕСЛИ
           Игра.ходы[нхода].кудаN = n
      ТО                             (* нашли *)
        Ход(Игра.ходы[нхода]);
        ВОЗВРАТ
      КОН
    КОН
  КОН
КОН ВыбралКлетку;

(*----------------------------------------------------------------------------*)
ЗАДАЧА                                             (* (Доска.Вид <- Надел.Вид)*)(* приём посылок из вне (снаружи) *)
       Приём(наделД:Надел.Доступ;
           посылка+:Ввод.нПосылка); (* = Пустой.Вид; - абстрактный опорный набор *)
(*
 * обработка посланий от человека
 *)
ПЕР
  x,y,n:ЦЕЛ;
    код:ЦЕЛ;
УКАЗ                                                        (* преобразование
          наделД               из Надел.Доступ в
                 Доска.Доступ  <- Надел.Доступ <- Рамка.Доступ *)
  доскаД:=наделД(Доска.Доступ);
                                                            (* преобразование
                 полеД              из Рамка.Доступ в
                       Поле.Доступ  <- Рамка.Доступ *)
   полеД:=наделД.полеД(Поле.Доступ);
                             (* анализ многоформия (полиморфизма) у <посылка> *)
  ДЛЯ      посылка ВИДА
  | Поле.нОтрисовка:
      РисоватьПозицию;
      ЕСЛИ
           доскаД.состояние = Надел.состВыбран
      ТО
        РисоватьХоды(цвХодов);
        ПеренестиУказку(указка)
      КОН 
  | Ввод.нОтКлавиш:
      x:=Игра.NвX[указка];
      y:=Игра.NвY[указка];
      код:=посылка.код;
           посылка.код:=0; (* скорее всего отработаем посылку *)

      ВЫБРАТЬ
              код
      ИЗ
        (* стрелки *)
<*ЕСЛИ Оборотень ТО*>
      | 27H: ЕСЛИ x > 1 ТО УМЕНЬШИТЬ(x) КОН            
      | 25H: ЕСЛИ x < 8 ТО УВЕЛИЧИТЬ(x) КОН
      | 26H: ЕСЛИ y > 1 ТО УМЕНЬШИТЬ(y) КОН            
      | 28H: ЕСЛИ y < 8 ТО УВЕЛИЧИТЬ(y) КОН
<*ИНАЧЕ*>
      | 25H: ЕСЛИ x > 1 ТО УМЕНЬШИТЬ(x) КОН            
      | 27H: ЕСЛИ x < 8 ТО УВЕЛИЧИТЬ(x) КОН
      | 28H: ЕСЛИ y > 1 ТО УМЕНЬШИТЬ(y) КОН            
      | 26H: ЕСЛИ y < 8 ТО УВЕЛИЧИТЬ(y) КОН
<*КОН*>
      | 20H,0DH: ВыбралКлетку(указка)  
      ИНАЧЕ
        посылка.код:=код;
        ВОЗВРАТ
      КОН;
      ПеренестиУказку(Игра.XYвN[x,y])

  | Ввод.нОтМышки:
      ЕСЛИ
           посылка.события = {}
      ТО                                     (* просто нажали мышку *)
<*ЕСЛИ Оборотень ТО*>
        x:=8-(посылка.к ДЕЛИТЬ ширинаКлетки);
        y:=  (посылка.с ДЕЛИТЬ высотаКлетки)+1;
<*ИНАЧЕ*>
        x:=  (посылка.к ДЕЛИТЬ ширинаКлетки)+1;
        y:=8-(посылка.с ДЕЛИТЬ высотаКлетки);
<*КОН*>
        n:=Игра.XYвN[x,y];
        ВыбралКлетку(n);
        ПеренестиУказку(n)
      КОН
  ИНАЧЕ
  КОН             
КОН Приём;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА                                                           (*(Доска.Вид)*)
       НачатьЗаново-;
УКАЗ                                            (* подготовиться к новой игре *)
  нижниеБелые:=НЕ нижниеБелые;
  указка:=34;
  ходок:=0;
  ходов:=0;
  ЕСЛИ
       нижниеБелые
  ТО
    думаютНижние:=ВКЛ;
    Игра.СторонаХода(Игра.нижние)
  ИНАЧЕ
    Ход(Игра.пустойХод)
  КОН
КОН НачатьЗаново;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА                                                           (*(Доска.Вид)*)
       Создать-(вс,лк:ЦЕЛ):Доступ;
УКАЗ
  СОЗДАТЬ(доскаД);
  Надел.Подготовить(доскаД,вс,лк,высотаКлетки*8,ширинаКлетки*8,{Надел.признакВыбираемый},Приём);
  ВОЗВРАТ доскаД
КОН Создать;

(*-ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss-*)
УКАЗ
  указка:=34;
  нижниеБелые:=ОТКЛ
КОН Доска.
