Re: [LONG] Avatar and decapitate code with graveyard from "George" at Sep 3, 98 06:08:48 pm

From: Andrew Helm (ashe@IGLOU.COM)
Date: 09/04/98


On Wed, 2 Sep 1998, David Sun wrote:
>ACMD(do_speedwalk)
[snip snip]
>}

I agree that looking over other people's code is a great way
to learn. Since you provided a heavily optimized version
of speedwalk I'll go for a more modular one. I rewrote
your function to handle extra spaces and two-letter directions.
Two-letter directions are recognized by a space before and
after them.

Also, the dirs_abbrev variable needs to be added to constants.c
with the appropriate values.


#define SW_NONE         0
#define SW_REPEAT       1
#define SW_DIR          2

#define SW_MAXREPEAT    32

int find_dir(char *dir) {
  int i;

  /* ASSUMPTION: the defines for dirs are set up to
   *   match the order of dir_abbrevs
   */
  for (i = 0; i < NUM_OF_DIRS; ++i)
    if ((**(dir_abbrevs + i) != '\n') && !str_cmp(dir, *(dir_abbrevs + i)))
      return i;

  return NOWHERE;
}


int get_swtoken(const char **s1, int *token) {
  char *s2;
  int spaces = 0;

  /* check for leading spaces */
  if (isspace(**s1)) {
    spaces = 1;
    while (**s1 && isspace(**s1))
      ++(*s1);
  }

  /* no more tokens, we're done */
  if (!**s1)
    return SW_NONE;

  /* check for a number */
  s2 = buf;
  while (**s1 && isdigit(**s1)) {
    *s2++ = **s1;
    ++(*s1);
  }
  *s2 = '\0';
  if (*buf) {
    *token = atoi(buf);
    if (*token < 1)
      *token = 1;
    else if (*token > SW_MAXREPEAT)
      *token = SW_MAXREPEAT;
    return SW_REPEAT;
  }

  /* check for a direction
   * Note: although this will work on muds with only single-letter
   *  directions you might want to save time by taking out the
   *  two-letter direction check
   */
  s2 = buf;
  *s2++ = **s1;
  ++(*s1);
  if (spaces && **s1 && (!*(*s1 + 1) || isspace(*(*s1 + 1)))) {
    *s2++ = **s1;
    ++(*s1);
  }
  *s2 = '\0';
  *token = find_dir(buf);

  /* if it looked like a two-letter dir but wasn't then try again
   * with a single-letter dir
   */
  if ((*token == NOWHERE) && spaces) {
    *(--s2) = '\0';
    --(*s1);
    *token = find_dir(buf);
  }

  if (*token != NOWHERE)
     return SW_DIR;
  else
     return get_swtoken(s1, token);
}


ACMD(do_speedwalk) {
  const char *s;
  int repeat = 1, token;

  act("You calmly prepare to speedwalk.", FALSE, ch, 0, 0, TO_CHAR);
  act("$n shouts, \"Go, go Speed Racer, goOOo!\"", TRUE, ch, 0, 0, TO_ROOM);

  s = (const char *)argument;
  while(*s) {
    switch(get_swtoken(&s, &token)) {
      case SW_NONE:
        break;

      case SW_REPEAT:
        repeat = token;
        break;

      case SW_DIR:
        /* Add delays/movement costs inside the while loop
         * Don't forget to check the return value of perform_move()
         * before subtracting movement points
         */
        while (repeat-- > 0)
          perform_move(ch, token, 1);
        repeat = 1;
        break;

      default:
        log("SYSERR:%s:%d: unknown token in do_speedwalk\r\n",
            __FILE__, __LINE__);
        send_to_char("There was an error processing your speedwalk.\r\n"
                     "Please report this to an imm using the bug command.\r\n",
                     ch);
        return;
    }
  }

  act("You arrive at your destination a bit out of breath.",
      FALSE, ch, 0, 0, TO_CHAR);
  act("$n bursts into the room and utters something about Marathon "
      "before collapsing on the ground, dead.", TRUE, ch, 0, 0, TO_ROOM);
}

>...and here's another one...
>
>ACMD(do_hiscore)
>{
[snip snip]
>};
>
>i know there is no cookie-cutter walkthrough here, but you should know
>where everything goes, and to add a few extra defines. btw, the hiscore
>was written a while back, and can be really improved upon. feel free to
>do so and submit.

A few random thoughts on how to do a better highscore function. Scanning
the playerfile every time is probably a bad idea. Scan the pfile once
at startup and make an array of the hiscore struct with a healthy
amount of room at the end so the array need not be resized each
time a new player is created. Make an array of pointers to hiscore
structs. Sort the array of pointers rather than the array of hiscore
structs. Scan all the players and update their entries only when a
player does a do_hiscore. Update a player's entry when they quit,
idle out, etc. Also of note is the strong possibility that the
players' hiscores won't be in random order since older players tend
to be at the beginning and newer players at the end.


Thanks for sharing your code! I enjoyed reading it, and I hope
you find mine useful as well. Comments are welcome.


     +------------------------------------------------------------+
     | 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/15/00 PST