[MobProgs] Fix

From: Akuma/Chris Baggett/DOOMer (doomer@BAYOU.COM)
Date: 12/30/97


>adding in new features, and fixing a couple (seriously, only a couple :)
>bugs..
I've got one bugfix that I'm sure a few people would love.
I've had the following problem with MobProgs before.
given following mobprog: (labels so that i can explain the problem)
greet_prog 100
if something           // if#1
   if something else   // if#2
      goto this        // Statement 1
   else                // else#1
      if not something         // if #3
         say not something     // Statement 2
      else                     // else 2
         say something         // Statement 3
      endif                    // endif 1
   endif                       // endif 2
else                           // else 3
  say something weird          // Statement 4
endif                          // endif 3
-- prog is executed,  if#1 is TRUE, if #2 is TRUE, everything is fine.
         try this one though
     if #1 is FALSE, logic would dictate we would goto else #3, right?
  well, according to the default way mobprogs are done, it's not so,
  the FIRST else statement after the FALSE if will get executed up until
endif, then it'll return.    -- simple (?maybe?) fix:
I'm not sure what everyone's term is of Hack, but i think this is sortof a
hack.
I had to use an extra (recursively passed) variable to get it to work right.
anyway.  in mobprog.cpp at the top with all the function proto's
change  (- = remove, + = add)
char * mprog_process_if        (char* ifchck, char* com_list,
                                       struct char_data* mob, struct
char_data* actor,
                                       struct obj_data* obj, void* vo,
-                                       struct char_data* rndm);
+                                       struct char_data *rndm, bool
Skip_To_Endif);
// Note: Change the function also, not just the proto
IN mprog_process_if the first section like this of the function after
*null = '\0';
   /* check for trueness of the ifcheck */
-  if ((legal = mprog_do_ifchck(ifchck, mob, actor, obj, vo, rndm)))
-    if(legal != 0)
+// Skip_To_Endif lets us no if we should process commands or not
+//   for sake of nested if/else/if/else/endif/endif 's
+  if (!Skip_To_Endif &&
+         (legal = mprog_do_ifchck(ifchck, mob, actor, obj, vo, rndm)))
+    {
+    if(legal != -1)    // Not Error (ie TRUE or FALSE)
       flag = TRUE;
     else
       return null;
+    }
--- All the ifchck's return -1 on error anyway, i don't know why they did
    it the way they did before.
        bug ("Mob: %d no commands after IF/OR", mob_index[mob->nr].virtual);
        return null;
       }
       morebuf = one_argument(cmnd,buf);
       if (!str_cmp(buf, "or"))
       {
-        if ((legal = mprog_do_ifchck(morebuf,mob,actor,obj,vo,rndm)))
-          if (legal != 0)
+        if (!Skip_To_Endif &&
+             (legal = mprog_do_ifchck(morebuf,mob,actor,obj,vo,rndm)))
+          {
+           if (legal != -1)   // legal must be 1
             flag = TRUE;
           else
             return null;
         }
+      }
and after
     for (; ;) /*ifcheck was true, do commands but ignore else to endif*/
     {
         if (!str_cmp(buf, "if"))
          {
-          com_list =
mprog_process_if(morebuf,com_list,mob,actor,obj,vo,rndm);
+           // We WANT to Skip commands if
+           // the previous 'if' wanted to, but if it didn't we shouldn't
+           // b/c we were successful
+          com_list = mprog_process_if(morebuf,com_list,mob,actor,obj,vo,rndm,
+                      Skip_To_Endif);
           return null;
and after
           while (str_cmp(buf, "endif"))
           {
+        // To Process Correct handling of if's in elses
+        // ie we WANT to NOT process commands, b/c this is an else->endif
+        // section, and the ifchck was successful
+          if (!str_cmp(buf, "if"))
+              com_list = mprog_process_if(morebuf, com_list,
mob,actor,obj,vo,rndm,
+                           TRUE);
               cmnd     = com_list;
               com_list = mprog_next_command(com_list);
               while (*cmnd == ' ')   cmnd++;
.
.
              morebuf = one_argument(cmnd, buf);
           }
       return com_list;
     }
+        if (!Skip_To_Endif)
         mprog_process_cmnd(cmnd, mob, actor, obj, vo, rndm);
         cmnd     = com_list;
         com_list = mprog_next_command(com_list);
         while (*cmnd == ' ')   cmnd++;
and next:
   else /*false ifcheck, find else and do existing commands or quit at endif*/
     {
       while ((str_cmp(buf, "else")) && (str_cmp(buf,"endif")))
         {
+  // We want to correctly process all following else/if sections,
+  // so we skip ALL following if's up until the "else" or "endif"
+  // section b/c this ifchck was FALSE
+        if (!str_cmp(buf, "if"))
+            com_list = mprog_process_if(morebuf, com_list,mob,actor,
+                                     obj,vo,rndm,TRUE);
         cmnd     = com_list;
         com_list = mprog_next_command(com_list);
         while (*cmnd == ' ')
           cmnd++;
and next:
       for (; ;) /*process the post-else commands until an endif is found.*/
         {
-        if (!str_cmp(buf, "if"))
-          {
-            com_list = mprog_process_if(morebuf, com_list, mob, actor,
-                                        obj, vo, rndm);
-            while (*cmnd == ' ') cmnd++;
-            if (*com_list == '\0')  return null;
-            cmnd     = com_list;
-            com_list = mprog_next_command(com_list);
-            morebuf  = one_argument(cmnd,buf);
-            continue;
-          }
         if (!str_cmp(buf, "else"))
---------
         if (!str_cmp(buf, "break"))
           return null;
         if (!str_cmp(buf, "endif"))
           return com_list;
+        if (!Skip_To_Endif)
         mprog_process_cmnd(cmnd, mob, actor, obj, vo, rndm);
+    // for correct handling of post-else if statements up until
+    // the endif.  If we previously didn't want to process commands, we still
+    // don't.  otherwise, we DO
+        if (!str_cmp(buf, "if"))
+             com_list = mprog_process_if(morebuf, com_list,
mob,actor,obj,vo,rndm,
+                                  Skip_To_Endif);
         cmnd     = com_list;
         com_list = mprog_next_command(com_list);
and in mprog_driver():
   command_list = tmpcmndlst;
   cmnd         = command_list;
   command_list = mprog_next_command(command_list);
   while (*cmnd != '\0')
     {
       morebuf = one_argument(cmnd, buf);
       if (!str_cmp(buf, "if"))
         command_list = mprog_process_if(morebuf, command_list, mob,
-                                      actor, obj, vo, rndm);
+                                      actor, obj, vo, rndm, FALSE);
----------------
that should allow for correct if/else/if/else/endif/endif
handling.
it even takes care of any possible OR errors ( we don't have many or's
in our progs)
anyway, have fun, code on, and chill out.

Akuma the Raging Coder

  +------------------------------------------------------------+
  | "The poets talk about love, but what I talk about is DOOM, |
  |      because in the end, DOOM is all that counts." -       |
  |   Alex Machine/George Stark/Stephen King, The Dark Half    |
  |        "Nothing is IMPOSSIBLE, Just IMPROBABLE"            |
  |   "Easier Said Than Done, But Better Done Than Said..."    |
  +------------------------------------------------------------+


     +------------------------------------------------------------+
     | Ensure that you have read the CircleMUD Mailing List FAQ:  |
     | http://democracy.queensu.ca/~fletcher/Circle/list-faq.html |
     +------------------------------------------------------------+



This archive was generated by hypermail 2b30 : 12/08/00 PST