Форум TeamX
   Home   Members  
Pages: [1] |   Go Down
 
Author Topic: Изменяем синтаксис скриптов ф2, с помощью препроцессора.  (Read 263 times)
Jordan
Пользователь
Posts: 416

476228895
Изменяем синтаксис скриптов ф2, с помощью препроцессора.
« on: 19 July 2011, 00:37:17 »

Доброй ночи! На часах 10 минут первого, а мы начинаем.

Многим наверно сложно читать такой код

Code:
   if (local_var(LVAR_Personal_Enemy) == 1) then begin
       call Node998;
   end
   else if (dude_iq <= 3) then begin
       start_gdialog(NAME,self_obj,4,-1,-1);
       gSay_Start;
           call Node002;
       gSay_End;
       end_dialogue;
   end
   else if (critter_is_armed(dude_obj)) then begin
      call Node012;
   end
   else if( global_var(GVAR_BH_JAIL) == JAIL_STEALTH ) then
      call Node015;
     
   else begin
       start_gdialog(NAME,self_obj,4,-1,-1);
       gSay_Start;
         if( local_var(LVAR_Herebefore) == 0 ) then
             call Node001;
         else
            call Node013;
       gSay_End;
       end_dialogue;
   end
   set_local_var( LVAR_Herebefore, 1 );

Много begin'ов. Как в паскале.
С помощью препроцессора можно сделать синтаксис похожим на modul'у

Этот же код

Code:
   IF (local_var(LVAR_Personal_Enemy) == 1) THEN
      CALL Node998;
   ELSIF (dude_iq <= 3) THEN
      start_gdialog(NAME,self_obj,4,-1,-1);
      gSay_Start;
         call Node002;
      gSay_End;
      end_dialogue;
   ELSIF (critter_is_armed(dude_obj)) THEN
      CALL Node012;
   ELSIF( global_var(GVAR_BH_JAIL) == JAIL_STEALTH ) THEN
      CALL Node015;
   ELSE
      start_gdialog(NAME,self_obj,4,-1,-1);
      gSay_Start;
         IF( local_var(LVAR_Herebefore) == 0 ) THEN
            CALL Node001;
         ELSE
            CALL Node013;
         END
      gSay_End;
      end_dialogue;
   END
   set_local_var( LVAR_Herebefore, 1 );

Скопируйте в скрипт
Code:
#define THEN  then begin
#define ELSIF end else if
#define ELSE  end else begin
#define DO     do begin //для цикла


Теперь не нужно писать begin после then, но каждый then должен закрываться end'ом.
Но только не в условии ELSIF.

Пример
было
Code:
   if( local_var(LVAR_Herebefore) == 0 ) then
      display_msg(mstr(100));
   else
      display_msg(mstr(101));

стало

Code:
   IF( local_var(LVAR_Herebefore) == 0 ) THEN
      display_msg(mstr(100));
   ELSE
      display_msg(mstr(101));
   END

Пример с ELSIF

Code:
  IF (LSpeech) THEN
    Option(101,Node001);
  ELSIF (ASpeech) THEN
    Option(102,Node003);
  ELSIF (HSpeech) THEN
    Option(103,Node004);
  END

  WHILE (I < 50) DO

  END

Проблемы: fgeck выдаёт ошибку и не может распарсить скрипт на процедуры.

Воспрянет Россия, из праха отцов
Расправятся крылья, миллионов сердец
Поднимут все головы и грудью вздохнут
И громка скажут, что пришли
Мы пришли, со столетней войны
KLIMaka
Пользователь
Posts: 72


Re: Изменяем синтаксис скриптов ф2, с помощью препроцессора.
« Reply #1 on: 20 July 2011, 12:04:43 »

На самом деле не все так хорошо как кажется. Совершенно копеешная выгода в отсутствии begin`а (вообще не пойму чем он тебе не понравился, ведь код все равно конструктивно не изменяется) выливается в очень серьезные проблемы. Если обязательное завершение блока END'ом, даже если он состоит из одного стейтмента, - это еще как-то можно пережить,  то непонятные сообщения компилятора об ошибках в тех местах, в которых их на самом деле нет - это уже никуда не годится. Дело в том, что если ты благодаря элементарной мышечной памяти вобьешь BEGIN после THEN, или благополучно все таки не закроешь блок END`ом то получишь очень интересное сообщение об ошибке, и то место в котором это сообщение возникнет не дает совершенно никаких намеков на то, где же искать реальную ошибку. А если ты еще и объявил эти макросы где то глубоко в заголовках и благополучно о них забыл, то эта проблема вообще станет нерешаемой, ты облысеешь пока все BEGIN - END  проверишь, убедишься что с ними все в порядке, потом еще пять раз проверишь, но это все счастье все равно компилироваться не будет. На самом деле такое изменение синтаксиса можно сравнить с бородатым программерским приколом типа: #define NULL rand() % 2 которым можно взорвать мозг своему ближайшему коллеге. К этому всему конечно можно привыкнуть и т.д., но это по-сути смена шила на мыло - убрали необязательный BEGIN добавили обязательный END.
Rainman
Пользователь
Posts: 69

301104000
Re: Изменяем синтаксис скриптов ф2, с помощью препроцессора.
« Reply #2 on: 21 July 2011, 11:19:49 »

KLIMaka прав, читаемость куска кода c двадцатью условиями и под-условиями решается только грамотным форматированием и коментированием... Например, в следующем куске простая подмена имен блоков читаемость никак не улучшит :

Code:
procedure timed_event_p_proc
begin
     if fixed_param == 1 and not (combat_is_initialized) then begin
        if (game_time_hour >= time_to_work_1 and game_time_hour < time_to_repose) or (game_time_hour >= time_to_work_2 and game_time_hour < time_to_sleep) then begin // work time
           if art_anim(obj_art_fid(self_obj)) == 48 or art_anim(obj_art_fid(self_obj)) == 49 then begin // if sleep
              critter_injure(self_obj, 2 bwor 8388608);
              reg_anim_func(2, self_obj);
              reg_anim_func(1, 1);
              if art_anim(obj_art_fid(self_obj)) == 48 then
                 reg_anim_animate(self_obj,37,-1);
              else
                 reg_anim_animate(self_obj,36,-1);
              reg_anim_func(3, 0);
           end else begin // if already waked up
               if self_tile != work_tile_1 and self_tile != work_tile_2 and self_tile != work_tile_3 and self_tile != work_tile_4 and\
               self_tile != work_tile_5 and self_tile != work_tile_6 then begin // if not at work tile
                  work_tile_chois := random(1, 6);
                  reg_anim_func(2, self_obj);
                  reg_anim_func(1, 1);
                  if work_tile_chois == 1 then
                     reg_anim_obj_move_to_tile(self_obj, work_tile_1, -1);
                  if work_tile_chois == 2 then
                     reg_anim_obj_move_to_tile(self_obj, work_tile_2, -1);
                  if work_tile_chois == 3 then
                     reg_anim_obj_move_to_tile(self_obj, work_tile_3, -1);
                  if work_tile_chois == 4 then
                     reg_anim_obj_move_to_tile(self_obj, work_tile_4, -1);
                  if work_tile_chois == 5 then
                     reg_anim_obj_move_to_tile(self_obj, work_tile_5, -1);
                  if work_tile_chois == 6 then
                     reg_anim_obj_move_to_tile(self_obj, work_tile_6, -1);
                  reg_anim_func(3, 0);
               end else begin // if already at work
                  reg_anim_func(2, self_obj);
                  reg_anim_func(1, 1);
                  if random(1, 2) ==  1 then
                     reg_anim_animate(self_obj, 0, -1);
                  reg_anim_animate(self_obj, 10, -1);
                  if random(1, 2) ==  1 then
                     reg_anim_animate(self_obj, 0, -1);
                  reg_anim_func(3, 0);
               end
           end
        end // work time ends here
        else begin // if not at work time begins here
           if game_time_hour >= time_to_repose and game_time_hour < time_to_work_2 then begin // if at repose time
              if tile_distance(self_tile, local_var(LVAR_home_tile)) < max_distance then begin
                 reg_anim_func(2, self_obj);
                 reg_anim_func(1, 1);
                 reg_anim_obj_move_to_tile(self_obj, tile_num_in_direction(self_tile, random(0, 5), (random(5, tile_distance(self_tile, local_var(LVAR_home_tile)) + 3))), -1);
                 reg_anim_func(3, 0);
              end else begin
                 reg_anim_func(2, self_obj);
                 reg_anim_func(1, 1);
                 reg_anim_obj_move_to_tile(self_obj, tile_num_in_direction(local_var(LVAR_home_tile), random(0, 5), (random(2, 4))), -1);
                 reg_anim_func(3, 0);
              end
           end // if at repose time ends here
           else begin // at sleep time begins here
           if self_tile != local_var(LVAR_home_tile) then begin
              reg_anim_func(2, self_obj);
              reg_anim_func(1, 1);
              reg_anim_obj_move_to_tile(self_obj, local_var(LVAR_home_tile), -1);
              if random(1, 2) == 1 then begin
                 reg_anim_animate_reverse(self_obj,36,-1);
                 reg_anim_animate(self_obj,49,-1);
              end else begin
                 reg_anim_animate_reverse(self_obj,37,-1);
                 reg_anim_animate(self_obj,48,-1);
              end
              reg_anim_func(3, 0);
              critter_injure(self_obj, 2);
           end else
           begin
              if art_anim(obj_art_fid(self_obj)) != 48 and art_anim(obj_art_fid(self_obj)) != 49 then
              begin
                 reg_anim_func(2, self_obj);
                 reg_anim_func(1, 1);
                 if random(1, 2) == 1 then
                 begin
                    reg_anim_animate_reverse(self_obj,36,-1);
                    reg_anim_animate(self_obj,49,-1);
                 end else
                 begin
                    reg_anim_animate_reverse(self_obj,37,-1);
                    reg_anim_animate(self_obj,48,-1);
                 end
                 reg_anim_func(3, 0);
                 critter_injure(self_obj, 2);
              end
           end
        end // at sleep time ends here
        end // if not at work time ends here
        animation_is_called := 0;
     end
end

Наш большой пост апокалиптический проект "Олимп 2207"
http://olympus2207.com
Pages: [1] |   Go Up