uint32_t pc::wear_in(uint32_t slot)
{
  object *tmp;
  uint32_t i;

  if (!in[slot] || !in[slot]->is_equipable()) {
    return 1;
  }

  /* Rings are tricky since there are two slots.  We will alwas favor *
   * an empty slot, and if there is no empty slot, we'll use the      *
   * first slot.                                                      */
  i = in[slot]->get_eq_slot_index();
  if (eq[i] &&
      ((eq[i]->get_type() == objtype_RING) &&
       !eq[i + 1])) {
    i++;
  }

  tmp = in[slot];
  in[slot] = eq[i];
  eq[i] = tmp;

  io_queue_message("You wear %s.", eq[i]->get_name());

  recalculate_speed();

  return 0;
}
uint32_t pc::pick_up(dungeon_t *d)
{
  object *o;

  while (has_open_inventory_slot() &&
         d->objmap[position[dim_y]][position[dim_x]]) {
    io_queue_message("You pick up %s.",
                     d->objmap[position[dim_y]][position[dim_x]]->get_name());
    in[get_first_open_inventory_slot()] =
      from_pile(d, position);
  }

  for (o = d->objmap[position[dim_y]][position[dim_x]];
       o;
       o = o->get_next()) {
    io_queue_message("You have no room for %s.", o->get_name());
  }

  return 0;
}
uint32_t pc::remove_eq(uint32_t slot)
{
  if (!eq[slot]                      ||
      !in[slot]->is_removable() ||
      !has_open_inventory_slot()) {
    io_queue_message("You can't remove %s, because you have nowhere to put it.",
                     eq[slot]->get_name());

    return 1;
  }

  io_queue_message("You remove %s.", eq[slot]->get_name());

  in[get_first_open_inventory_slot()] = eq[slot];
  eq[slot] = NULL;


  recalculate_speed();

  return 0;
}
void pc::DoBombCombat(dungeon_t *d, character* c)
{
int i, j;
int damage = 100;
int damageSplash = (damage / 2);
int dmgUsed = 0;

    for(i = (character_get_y(c) - 1); i <= (character_get_y(c) + 1); i++)
    {
        for(j = (character_get_x(c) - 1); j <= (character_get_x(c) + 1); j++)
        {
            if(d->charmap[i][j] && d->charmap[i][j] != d->the_pc)
            {
                if(i == character_get_y(c) && j == character_get_x(c))
                {
                    dmgUsed = damage;
                }
                else
                {
                    dmgUsed = damageSplash;
                }
                io_queue_message("You hit the %s for %d.", d->charmap[i][j]->name, dmgUsed);

                if (dmgUsed >= d->charmap[i][j]->hp)
                {
                    io_queue_message("The %s dies.", d->charmap[i][j]->name);
                    d->charmap[i][j]->hp = 0;
                    d->charmap[i][j]->alive = 0;
                    d->num_monsters--;
                    charpair(d->charmap[i][j]->position) = NULL;
                }
                else
                {
                     d->charmap[i][j]->hp -= dmgUsed;
                }
            }
        }
    }
}
uint32_t pc::destroy_in(uint32_t slot)
{
  if (!in[slot] || !in[slot]->is_destructable()) {
    return 1;
  }

  io_queue_message("You destroy %s.", in[slot]->get_name());

  delete in[slot];
  in[slot] = NULL;

  return 0;
}
uint32_t pc::drop_in(dungeon_t *d, uint32_t slot)
{
  if (!in[slot] || !in[slot]->is_dropable()) {
    return 1;
  }

  io_queue_message("You drop %s.", in[slot]->get_name());

  in[slot]->to_pile(d, position);
  in[slot] = NULL;

  return 0;
}
void pc::DoRangedCombat(dungeon_t *d, character* c)
{
int i;
int damage = 0;
int defenderDodge = c->dodge;
int defenderDef = c->defence;
int blocked = 0;
float defMultipler;

  if(rand()%100 + 1 > defenderDodge)
  {
    for (i = 2; i < num_eq_slots; i++) {
      if (d->the_pc->eq[i]) {
        damage += d->the_pc->eq[i]->roll_dice();
      }
    }
     blocked = damage;
     defMultipler = ((float)100 / (float)(100 + defenderDef));
     damage = (damage * defMultipler);
     blocked = blocked - damage;
     io_queue_message("you hit the %s for %d. It blocked %d damage.", c->name, damage, blocked);

    if (damage >= c->hp) {
    c->hp = 0;
    c->alive = 0;
    d->num_monsters--;
    charpair(c->position) = NULL;
    io_queue_message("The %s dies.", c->name);
    } else {
        c->hp -= damage;
    }
  }
  else
  {
     io_queue_message("The %s dodged your ranged attack", c->name);
  }
}
示例#8
0
void io_handle_input(dungeon_t *d)
{
  uint32_t fail_code;
  int key;

  do {
    switch (key = getch()) {
    case '7':
    case 'y':
    case KEY_HOME:
      fail_code = move_pc(d, 7);
      break;
    case '8':
    case 'k':
    case KEY_UP:
      fail_code = move_pc(d, 8);
      break;
    case '9':
    case 'u':
    case KEY_PPAGE:
      fail_code = move_pc(d, 9);
      break;
    case '6':
    case 'l':
    case KEY_RIGHT:
      fail_code = move_pc(d, 6);
      break;
    case '3':
    case 'n':
    case KEY_NPAGE:
      fail_code = move_pc(d, 3);
      break;
    case '2':
    case 'j':
    case KEY_DOWN:
      fail_code = move_pc(d, 2);
      break;
    case '1':
    case 'b':
    case KEY_END:
      fail_code = move_pc(d, 1);
      break;
    case '4':
    case 'h':
    case KEY_LEFT:
      fail_code = move_pc(d, 4);
      break;
    case '5':
    case ' ':
    case KEY_B2:
      fail_code = 0;
      break;
    case '>':
      fail_code = move_pc(d, '>');
      break;
    case '<':
      fail_code = move_pc(d, '<');
      break;
    case 'S':
      d->save_and_exit = 1;
      character_reset_turn(d->pc);
      fail_code = 0;
      break;
    case 'Q':
      /* Extra command, not in the spec.  Quit without saving.          */
      d->quit_no_save = 1;
      fail_code = 0;
      break;
    case 'T':
      /* New command.  Display the distances for tunnelers.             */
      io_display_tunnel(d);
      fail_code = 1;
      break;
    case 'D':
      /* New command.  Display the distances for non-tunnelers.         */
      io_display_distance(d);
      fail_code = 1;
      break;
    case 'H':
      /* New command.  Display the hardnesses.                          */
      io_display_hardness(d);
      fail_code = 1;
      break;
    case 's':
      /* New command.  Return to normal display after displaying some   *
       * special screen.                                                */
      io_display(d);
      fail_code = 1;
      break;
    case 'g':
      /* Teleport the PC to a random place in the dungeon.              */
      io_teleport_pc(d);
      fail_code = 0;
      break;
    case 'm':
      io_list_monsters(d);
      fail_code = 1;
      break;
    case 'a':
      io_display_all(d);
      fail_code = 1;
      break;
    case 'q':
      /* Demonstrate use of the message queue.  You can use this for *
       * printf()-style debugging (though gdb is probably a better   *
       * option.  Not that it matterrs, but using this command will  *
       * waste a turn.  Set fail_code to 1 and you should be able to *
       * figure out why I did it that way.                           */
      io_queue_message("This is the first message.");
      io_queue_message("Since there are multiple messages, "
                       "you will see \"more\" prompts.");
      io_queue_message("You can use any key to advance through messages.");
      io_queue_message("Normal gameplay will not resume until the queue "
                       "is empty.");
      io_queue_message("Long lines will be truncated, not wrapped.");
      io_queue_message("io_queue_message() is variadic and handles "
                       "all printf() conversion specifiers.");
      io_queue_message("Did you see %s?", "what I did there");
      io_queue_message("When the last message is displayed, there will "
                       "be no \"more\" prompt.");
      io_queue_message("Have fun!  And happy printing!");
      fail_code = 0;
      break;
    default:
      /* Also not in the spec.  It's not always easy to figure out what *
       * key code corresponds with a given keystroke.  Print out any    *
       * unhandled key here.  Not only does it give a visual error      *
       * indicator, but it also gives an integer value that can be used *
       * for that key in this (or other) switch statements.  Printed in *
       * octal, with the leading zero, because ncurses.h lists codes in *
       * octal, thus allowing us to do reverse lookups.  If a key has a *
       * name defined in the header, you can use the name here, else    *
       * you can directly use the octal value.                          */
      mvprintw(0, 0, "Unbound key: %#o ", key);
      fail_code = 1;
    }
  } while (fail_code);
}
示例#9
0
int main(int argc, char *argv[])
{
  dungeon_t d;
  time_t seed;
  struct timeval tv;
  int32_t i;
  uint32_t do_load, do_save, do_seed, do_image, do_save_seed,
           do_save_image, do_place_pc;
  uint32_t long_arg;
  char *save_file;
  char *load_file;
  char *pgm_file;

  memset(&d, 0, sizeof (d));

  /* Default behavior: Seed with the time, generate a new dungeon, *
   * and don't write to disk.                                      */
  do_load = do_save = do_image = do_save_seed =
    do_save_image = do_place_pc = 0;
  do_seed = 1;
  save_file = load_file = NULL;
  d.max_monsters = MAX_MONSTERS;
  d.max_objects = MAX_OBJECTS;
  
  /* The project spec requires '--load' and '--save'.  It's common  *
   * to have short and long forms of most switches (assuming you    *
   * don't run out of letters).  For now, we've got plenty.  Long   *
   * forms use whole words and take two dashes.  Short forms use an *
    * abbreviation after a single dash.  We'll add '--rand' (to     *
   * specify a random seed), which will take an argument of it's    *
   * own, and we'll add short forms for all three commands, '-l',   *
   * '-s', and '-r', respectively.  We're also going to allow an    *
   * optional argument to load to allow us to load non-default save *
   * files.  No means to save to non-default locations, however.    *
   * And the final switch, '--image', allows me to create a dungeon *
   * from a PGM image, so that I was able to create those more      *
   * interesting test dungeons for you.                             */
 
 if (argc > 1) {
    for (i = 1, long_arg = 0; i < argc; i++, long_arg = 0) {
      if (argv[i][0] == '-') { /* All switches start with a dash */
        if (argv[i][1] == '-') {
          argv[i]++;    /* Make the argument have a single dash so we can */
          long_arg = 1; /* handle long and short args at the same place.  */
        }
        switch (argv[i][1]) {
        case 'r':
          if ((!long_arg && argv[i][2]) ||
              (long_arg && strcmp(argv[i], "-rand")) ||
              argc < ++i + 1 /* No more arguments */ ||
              !sscanf(argv[i], "%lu", &seed) /* Argument is not an integer */) {
            usage(argv[0]);
          }
          do_seed = 0;
          break;
        case 'l':
          if ((!long_arg && argv[i][2]) ||
              (long_arg && strcmp(argv[i], "-load"))) {
            usage(argv[0]);
          }
          do_load = 1;
          if ((argc > i + 1) && argv[i + 1][0] != '-') {
            /* There is another argument, and it's not a switch, so *
             * we'll treat it as a save file and try to load it.    */
            load_file = argv[++i];
          }
          break;
        case 's':
          if ((!long_arg && argv[i][2]) ||
              (long_arg && strcmp(argv[i], "-save"))) {
            usage(argv[0]);
          }
          do_save = 1;
          if ((argc > i + 1) && argv[i + 1][0] != '-') {
            /* There is another argument, and it's not a switch, so *
             * we'll save to it.  If it is "seed", we'll save to    *
	     * <the current seed>.rlg327.  If it is "image", we'll  *
	     * save to <the current image>.rlg327.                  */
	    if (!strcmp(argv[++i], "seed")) {
	      do_save_seed = 1;
	      do_save_image = 0;
	    } else if (!strcmp(argv[i], "image")) {
	      do_save_image = 1;
	      do_save_seed = 0;
	    } else {
	      save_file = argv[i];
	    }
          }
          break;
        case 'i':
          if ((!long_arg && argv[i][2]) ||
              (long_arg && strcmp(argv[i], "-image"))) {
            usage(argv[0]);
          }
          do_image = 1;
          if ((argc > i + 1) && argv[i + 1][0] != '-') {
            /* There is another argument, and it's not a switch, so *
             * we'll treat it as a save file and try to load it.    */
            pgm_file = argv[++i];
          }
          break;
        case 'n':
          if ((!long_arg && argv[i][2]) ||
              (long_arg && strcmp(argv[i], "-nummon")) ||
              argc < ++i + 1 /* No more arguments */ ||
              !sscanf(argv[i], "%hu", &d.max_monsters)) {
            usage(argv[0]);
          }
          break;
        case 'p':
          /* PC placement makes no effort to avoid placing *
           * the PC inside solid rock.                     */
          if ((!long_arg && argv[i][2]) ||
              (long_arg && strcmp(argv[i], "-pc"))) {
            usage(argv[0]);
          }
          if ((d.PC->position[dim_y] = atoi(argv[++i])) < 1 ||
              d.PC->position[dim_y] > DUNGEON_Y - 2         ||
              (d.PC->position[dim_x] = atoi(argv[++i])) < 1 ||
              d.PC->position[dim_x] > DUNGEON_X - 2)         {
            fprintf(stderr, "Invalid PC position.\n");
            usage(argv[0]);
          }
          do_place_pc = 1;
          break;
        case 'o':
          if ((!long_arg && argv[i][2]) ||
              (long_arg && strcmp(argv[i], "-objcount")) ||
              argc < ++i + 1 /* No more arguments */ ||
              !sscanf(argv[i], "%hu", &d.max_objects)) {
            usage(argv[0]);
          }
          break;
         default:
          usage(argv[0]);
        }
      } else { /* No dash */
        usage(argv[0]);
      }
    }
  }

  if (do_seed) {
    /* Allows me to generate more than one dungeon *
     * per second, as opposed to time().           */
    gettimeofday(&tv, NULL);
    seed = (tv.tv_usec ^ (tv.tv_sec << 20)) & 0xffffffff;
  }

  srand(seed);

  parse_descriptions(&d);
  io_init_terminal();
  init_dungeon(&d);

  if (do_load) {
    read_dungeon(&d, load_file);
  } else if (do_image) {
    read_pgm(&d, pgm_file);
  } else {
    gen_dungeon(&d);
  }

  config_pc(&d);
  gen_monsters(&d);
  gen_objects(&d);
  pc_observe_terrain(d.PC, &d);

  io_display(&d);
  io_queue_message("Seed is %u.", seed);
  while (pc_is_alive(&d) && dungeon_has_npcs(&d) && !d.quit) {
    do_moves(&d);
  }
  io_display(&d);

  io_reset_terminal();
  
  if (do_save) {
    if (do_save_seed) {
       /* 10 bytes for number, dot, extention and null terminator. */
      save_file = (char *) malloc(18);
      sprintf(save_file, "%ld.rlg327", seed);
    }
    if (do_save_image) {
      if (!pgm_file) {
	fprintf(stderr, "No image file was loaded.  Using default.\n");
	do_save_image = 0;
      } else {
	/* Extension of 3 characters longer than image extension + null. */
	save_file = (char *) malloc(strlen(pgm_file) + 4);
	strcpy(save_file, pgm_file);
	strcpy(strchr(save_file, '.') + 1, "rlg327");
      }
    }
    write_dungeon(&d, save_file);

    if (do_save_seed || do_save_image) {
      free(save_file);
    }
  }

  printf("%s", pc_is_alive(&d) ? victory : tombstone);
  printf("You defended your life in the face of %u deadly beasts.\n"
         "You avenged the cruel and untimely murders of %u "
         "peaceful dungeon residents.\n",
         d.PC->kills[kill_direct], d.PC->kills[kill_avenged]);

  if (pc_is_alive(&d)) {
    /* If the PC is dead, it's in the move heap and will get automatically *
     * deleted when the heap destructs.  In that case, we can't call       *
     * delete_pc(), because it will lead to a double delete.               */
    character_delete(d.PC);
  }

  delete_dungeon(&d);
  destroy_descriptions(&d);

  return 0;
}