$MACRO RP TRANS;
{*******************************MULTI-EDIT MACRO******************************

Name:  RP    ( russian pusher - altrnative name of Soko-Ban )

Description: программа продолжает славную серию реализаций игрушки
             Soko-Ban на различных языках программирования
             от Insight corp.,
             представляя Multi-Edit...

               (C) Copyright 1991 by Insight corp.
******************************************************************************}

  { Несколько слов о соглашениях именования переменных в языке, 
  облегчающих программирования.

  Поскольку регистр в именах переменных - неважен, имена принято нагружать 
  дополнительным смыслом. а именно:
    если все буквы в имени переменной - большие, то данная переменная 
    используется как константа;
    собственно переменные в MultiEdit обозначаются одним или несколькими
    словами, написанными через символ подчеркивание, все слова начинаются 
    с большой буквы;
    если в переменной до символа подчеркивания две больших буквы, а дальше
    - маленькие, то данная переменная будет формальным параметром в 
    функции                                                            }

  Def_Int( F_KEY, F_ESC, F_RESTART, F_LEFT, F_RIGHT, F_UP, F_DOWN,
       C_CTRL_BIT, C_BIT_MASK,
       S_FREE_PLACE, SB_FREE_PLACE, S_MAN, SB_MAN, S_WALL, SB_WALL,
       S_BOX, SB_BOX );

  F_KEY   := 256;

  F_ESC   := 27;              F_RESTART := 32;
  F_LEFT  := F_KEY + $4b;
  F_RIGHT := F_KEY + $4d;
  F_UP    := F_KEY + $48;
  F_DOWN  := F_KEY + $50;

  C_CTRL_BIT := $80;
  C_BIT_MASK := $7f;


  S_FREE_PLACE := 0;        SB_FREE_PLACE := C_CTRL_BIT + S_FREE_PLACE;
  S_MAN        := 1;        SB_MAN        := C_CTRL_BIT + S_MAN;
  S_WALL       := 9;        SB_WALL       := C_CTRL_BIT + S_WALL;
  S_BOX        := 4;        SB_BOX        := C_CTRL_BIT + S_BOX;


  Def_Int( i, j,
           Man_X, Man_Y,
           Kbrd_Key,
           Score_New, Score_All
           ) ;
  Def_Int( SS_x, SS_y, SS_d, SS_type,
           MV_x, MV_y
           );

  { задаем длину массива: 20 * 31 = 620 }
  Def_Str( Maze[ 620 ], GF[ 620 ],
         SS_char[ 2 ] );


  Put_Box( 5, 4, 70, 20, RED, WHITE,
           ь Soko-Ban game /Multi-Edit version/ ь, TRUE );
  Beep;

{-----------------------------------------------------------------------------}

 { исходное поле игры }
 {                      0        1         2         3   }
 {                      1234567890123456789012345678901  }
        Maze :=        ь000000000000000000000000000000ь;
        Maze := Maze + ь000000099999000000000000000000ь;
        Maze := Maze + ь000000090009000000000000000000ь;
        Maze := Maze + ь000000094009000000000000000000ь;
        Maze := Maze + ь000009990049990000000000000000ь;
        Maze := Maze + ь000009004004090000000000000000ь;
        Maze := Maze + ь000999090999090000099999900000ь;
        Maze := Maze + ь000900090999099999990033900000ь;
        Maze := Maze + ь000904004000000000000033900000ь;
        Maze := Maze + ь000999990999909199990033900000ь;
        Maze := Maze + ь000000090000009990099999900000ь;
        Maze := Maze + ь000000099999999000000000000000ь;
        Maze := Maze + ь000000000000000000000000000000ь;

 {----------------------- считывание лабиринта -----------------------}
  Score_All := 0;
  Score_New := 0;

  Def_Char( Crnt );
  i := 0;
  while ( i <= 12 ) do
    j := 1;
    while ( j <= 30 ) do
      SS_x := j;
      SS_y := i;
      Crnt := Copy( Maze, j+(i*30), 1 );
           if      ( Crnt = ь0ь ) then
                   SS_d := S_FREE_PLACE;
           else if ( Crnt = ь9ь ) then
                   SS_d := S_WALL;
           else if ( Crnt = ь4ь ) then
                   SS_d := S_BOX;
           else if ( Crnt = ь3ь ) then
                   SS_d := Sb_free_place;
                   Score_All := Score_All + 1;
           else if ( Crnt = ь7ь ) then
                   SS_d := SB_BOX;
                   Score_All := Score_All + 1;
                   Score_New := Score_New + 1;
           else if ( Crnt = ь1ь ) then
                   SS_d := S_MAN;
                   Man_X := j;
                   Man_Y := i;
           else if ( Crnt = ь2ь ) then
                   SS_d := Sb_MAN;
                   Man_X := j;
                   Man_Y := i;
                   Score_All := Score_All + 1;
           end; end; end; end; end; end; end;
      call Sprite_Show;
      j := j+1;
    end;
    i := i+1;
  end;
{---------------------------------------------------------------------}

  Write( ь Left/Right/Down/Up - moving  Esc/Space - exit ь,
            14, 19, RED, WHITE );
  Beep; Beep;
  { основной цикл игрушки }

  Def_Int( Game_Yes );

  Game_Yes := TRUE;
  while ( Game_Yes ) do
    SS_x := Man_X; SS_Y := Man_Y; SS_d := S_MAN;
    call Sprite_show;

    Read_Key;   { введем символ }
    if ( Key1 = 0 ) then
         Kbrd_Key := F_KEY + key2;
    else Kbrd_Key := Key1;    end;

    SS_x := Man_X; SS_y := Man_Y; SS_d := S_FREE_PLACE;
    call Sprite_Show;

        if      ( Kbrd_Key = F_LEFT ) then
                MV_x := -1; MV_y := 0;
                call Moving;
        else if ( Kbrd_Key = F_RIGHT ) then
                MV_x := 1; MV_y :=  0;
                call Moving;
        else if ( Kbrd_Key = F_UP ) then
                MV_x := 0; MV_y := -1;
                call Moving;
        else if ( Kbrd_Key = F_DOWN ) then
                MV_x :=  0; MV_y := 1;
                call Moving;
        end; end; end; end;

    if ( ( Score_New = Score_All )
       or ( Kbrd_Key = F_ESC ) or ( Kbrd_Key = F_RESTART ) ) then
       Game_Yes := FALSE;
    end;
  end;
{-----------------------------------------------------------------------------}


  if ( Score_New = Score_All ) then
      Write( ьммммммммммммм ***   maладец!  *** мммммммммммммь,
             14, 19, RED, WHITE );
  else
      Write( ьммммммммммммм *** слаб-б-бак! *** мммммммммммммь,
             14, 19, RED, WHITE );
  end;

  Beep; Beep; Beep;
  Read_Key;

  Kill_Box;


goto End_Of_Macro;
{-----------------------------------------------------------------------------}


{************************MULTI-EDIT MACRO SUBROUTINE**************************

Subroutine Name:

Subroutine Description:


******************************************************************************}

Sprite_Show: { подпрограмма вывода спрайта /локальная/
                 SS_x - координата по горизонтали
                 SS_y - координата по вертикали
                 SS_d - данное }
      if ( Ascii(Copy( GF, SS_y*30+SS_x, 1) ) = SB_BOX ) then
         if ( SS_d <> S_BOX ) then
            Score_New := Score_New - 1;
      end; end;
      if ( (Ascii(Copy( GF, SS_y*30+SS_x, 1) )
         and  C_CTRL_BIT ) <> 0  )  then
         if (SS_d = S_BOX ) then
            Score_New := Score_New + 1;
      end; end;

      GF := Str_Ins( Char( (Ascii(Copy( GF, SS_y*30+SS_x, 1 ))
                              and C_CTRL_BIT ) or (SS_d) ),
                     Str_del( GF, SS_y*30+SS_x, 1),
                     SS_y*30+SS_x
                   );

      { выводим спрайт на экран /бывшая sprite_out/ }
      SS_type := Ascii( Copy( GF, SS_y*30+SS_x, 1 ) );
      if      ( SS_type = S_FREE_PLACE ) then
              SS_char := ь  ь;
      else if ( SS_type = SB_FREE_PLACE ) then
              SS_char := ь. ь;
      else if (( SS_type = S_MAN ) or (SS_type = SB_MAN )) then
              SS_char := ь><ь;
      else if (( SS_type = S_WALL ) or (SS_type = SB_WALL )) then
              SS_char := Char( 178 ) + Char( 178 );
      else if ( SS_type = S_BOX ) then
              SS_char := ь<>ь;
      else if ( SS_type = SB_BOX ) then
              SS_char := Char( 17 ) + Char( 16 );
      end; end; end; end; end; end;

      Write( SS_char, 5 +(SS_x*2), 5+SS_y, RED, WHITE );

      ret;

{************************MULTI-EDIT MACRO SUBROUTINE**************************

Subroutine Name:

Subroutine Descroption:



******************************************************************************}

Moving: { процедура верификации перемещения двигателя
             /MV_x смещение координаты по горизонтали
             /MV_y смещение координаты по вертикали
          }
      { свободно ли следующее поле }
      if ( Ascii( Copy( GF, (Man_Y+MV_y)*30+(Man_X+MV_x), 1))
         and C_BIT_MASK = S_FREE_PLACE  ) then

         Man_X := Man_X + MV_x;
         Man_Y := Man_Y + MV_y;
      else { проверим, может это ящик }
         if ( Ascii( Copy( GF, (Man_Y+MV_y)*30+(man_x+MV_x), 1))
            and C_BIT_MASK = S_BOX   ) then

            if ( Ascii( Copy( GF, (Man_Y+(MV_y*2))*30+(Man_X+(MV_x*2)), 1))
               and C_BIT_MASK = S_FREE_PLACE ) then

               { переместить двигатель и ящик в данном направлении }
               SS_x := Man_X + MV_x;
               SS_y := Man_Y + MV_y;
               SS_d := S_FREE_PLACE;
               call Sprite_Show;
               SS_x := Man_X + (MV_x*2);
               SS_y := Man_Y + (MV_y*2);
               SS_d := S_BOX;
               call Sprite_Show;
               Man_X := Man_X + MV_x;
               Man_Y := Man_Y + mv_y;
            end;
         end;
      end;
      ret;
{-----------------------------------------------------------------------------}

End_Of_Macro:
END_MACRO;