Re: [CODE] Help with Introduction/Memory Code?

From: Thomas Arp (t_arp@stofanet.dk)
Date: 08/14/02


From: "Mathew Earle Reuther" <graymere@zipcon.net>
> Changes made thusfar:
>
> Added to struct player_special_data in structs.h:
>      int *memory;        /* PC's memory for intro system         */

Change this to a long:
      long *memory;        /* PC's memory for intro system         */

>
>
> Added to db.c:
>   (in load_char):
>           } else if(!strcmp(tag, "Mem ")) {
>             ch->player_specials->memory = fbgetstring(fl);

What you get here is a char *, pointing to a string. What you want
to do is copy the way tongues/affs/saving throws are saved, and do this:
         else if(!strcmp(tag, "Mem ")) {
           /* here you could free the old list, if you wish */
           /* allocate room for the memories */
           CREATE(ch->player_specials->memory, long, num+1);
           /* first line is number of remembered people */
           ch->player_specials->memory[0] = (long)num;
           for(i = 1; i <= num; i++) {
             fbgetline(fl, line);
             sscanf(line, "%ld", &lnum);
/* here could be a check to see if that player even exist anymore */
             ch->player_specials->memory[i] = lnum;
           }
         }
>   (in save_char):
>       if(ch->player_specials->memory && *ch->player_specials->memory) {
>         strcpy(buf, ch->player_specials->memory);
>         fbprintf(fl, "Mem : %s\n", buf);
>       }
>
Again, this saves a string, if you're lucky. Since memory is a pointer
to a place in memory, there is no saying what the string would be,
or if it would be NULL terminated.
I'd suggest saving as above:
       if(ch->player_specials->memory) {
          fbprintf(fl, "Mem : %ld\n", ch->player_specials->memory[0]);
          for (i = 1; i <= ch->player_specials->memory[0]; i++)
            fbprintf(fl, "%ld\n", ch->player_specials->memory[i];
       }
>
> Created a memory.c file containing the following code:
>
>   /* Does ch know victim? */
>   bool knows_char(struct char_data *ch, struct char_data *victim)
>   {
      int i, bot, mid, top;
>
>     /* Characters always know NPCs and IMMORTALS and vice versa */
>     if (IS_NPC(ch) || IS_NPC(victim) || (GET_LEVEL(ch) >= LVL_IMMORT)
>                    || (GET_LEVEL(victim) >= LVL_IMMORT))
>       return TRUE;
>
      if (!ch->player_specials->memory)
        return FALSE;
>
>     /* Simple sequential search. If the data was sorted, a binary search
>        could be attempted */
      /* indeed - so the list is sorted */
      bot = 1;
      top = ch->player_specials->memory[0];

      /* perform binary search */
      for (;;) {
        mid = (bot + top) / 2;

        if (bot>=top)
          return FALSE;
        if (ch->player_specials->memory[mid] = GET_IDNUM(victim);
          return TRUE;
        if (ch->player_specials->memory[mid] > GET_IDNUM(victim))
          top = mid - 1;
        else
          bot = mid + 1;
       }

>     return FALSE;
>   }
>
>   /* Add victim to ch's know list */
>   void add_know(struct char_data *ch, struct char_data *victim)
>   {
      int i, found = 0;
>
>     if (knows_char(ch,victim))
>       return;

      /* simple case first */
      if (!ch->player_specials->memory) {
        CREATE(ch->player_specials->memory, int, 2);
        ch->player_specials->memory[0] = 1;
        ch->player_specials->memory[1] = GET_IDNUM(victim);
        return;
      }

      ch->player_specials->memory[0]++;
      /* number of remembered + index -> +1*/
      RECREATE(ch->player_specials->memory, int,
               ch->player_specials->memory[0]+1);

      for (i = ch->player_specials->memory[0]+1;i > 1; i--) {
        if (ch->player_specials->memory[i-1] < GET_IDNUM(victim)) {
          ch->player_specials->memory[i] = GET_IDNUM(victim);
          found = i;
        } else
          ch->player_specials->memory[i] =
              ch->player_specials->memory[i-1]

      }

      if (!found)
        ch->player_specials->memory[1] = GET_IDNUM(victim);
>   }
>
> Questions:
>
> Is malloc() the correct method of memory allocation to use in add_know?
> (And of course, free() afterwards?)
>

You should use the circle CREATE and RECREATE macros, as above.
This does some simple error checking for you.

> Why do I get a warning for comparing a pointer to an integer in this line
> of knows_char():
>     for (i = 1; i < ch->player_specials->memory; i++)

Because ch->player_specials->memory is a pointer to an int. You really
wanted
     for (i = 1; i <= ch->player_specials->memory[0]; i++)

>
> Did I add the int *memory to the right structure? (And is int* memory;
> correct in the first place?)
>
As I noted above, a list of idnums should be the same type as idnum, long.

> Am I saving and loading the data to the pfile (ASCII, of course) in a
> manner which will allow it to function in the intended manner?

No. The things that could go wrong are too numerous to mention. You need
to save things to a known format, and then read them from the same known
format.

The changes above are mailercode only. Use with caution, and be prepared
for fire, crashes, automobile accidents etc.

Welcor

--
   +---------------------------------------------------------------+
   | FAQ: http://qsilver.queensu.ca/~fletchra/Circle/list-faq.html |
   | Archives: http://post.queensu.ca/listserv/wwwarch/circle.html |
   | Newbie List:  http://groups.yahoo.com/group/circle-newbies/   |
   +---------------------------------------------------------------+



This archive was generated by hypermail 2b30 : 06/25/03 PDT