Ejemplo n.º 1
0
bool player::create(game *g, character_type type, std::string tempname)
{
 weapon = item(g->itypes["null"], 0);
 
 g->u.prof = profession::generic();

 WINDOW* w = newwin(25, 80, (TERMY > 25) ? (TERMY-25)/2 : 0, (TERMX > 80) ? (TERMX-80)/2 : 0);

 int tab = 0, points = 38;
 if (type != PLTYPE_CUSTOM) {
  switch (type) {
   case PLTYPE_RANDOM: {
    str_max = rng(6, 12);
    dex_max = rng(6, 12);
    int_max = rng(6, 12);
    per_max = rng(6, 12);
    points = points - str_max - dex_max - int_max - per_max;
    if (str_max > HIGH_STAT)
     points -= (str_max - HIGH_STAT);
    if (dex_max > HIGH_STAT)
     points -= (dex_max - HIGH_STAT);
    if (int_max > HIGH_STAT)
     points -= (int_max - HIGH_STAT);
    if (per_max > HIGH_STAT)
     points -= (per_max - HIGH_STAT);

    int num_gtraits = 0, num_btraits = 0, rn, tries;
    while (points < 0 || rng(-3, 20) > points) {
     if (num_btraits < MAX_TRAIT_POINTS && one_in(3)) {
      tries = 0;
      do {
       rn = random_bad_trait();
       tries++;
      } while ((has_trait(rn) ||
              num_btraits - traits[rn].points > MAX_TRAIT_POINTS) && tries < 5);
      if (tries < 5) {
       toggle_trait(rn);
       points -= traits[rn].points;
       num_btraits -= traits[rn].points;
      }
     } else {
      switch (rng(1, 4)) {
       case 1: if (str_max > 5) { str_max--; points++; } break;
       case 2: if (dex_max > 5) { dex_max--; points++; } break;
       case 3: if (int_max > 5) { int_max--; points++; } break;
       case 4: if (per_max > 5) { per_max--; points++; } break;
      }
     }
    }
    while (points > 0) {
     switch (rng((num_gtraits < MAX_TRAIT_POINTS ? 1 : 5), 9)) {
     case 1:
     case 2:
     case 3:
     case 4:
      rn = random_good_trait();
      if (!has_trait(rn) && points >= traits[rn].points &&
          num_gtraits + traits[rn].points <= MAX_TRAIT_POINTS) {
       toggle_trait(rn);
       points -= traits[rn].points;
       num_gtraits += traits[rn].points;
      }
      break;
     case 5:
      switch (rng(1, 4)) {
       case 1: if (str_max < HIGH_STAT) { str_max++; points--; } break;
       case 2: if (dex_max < HIGH_STAT) { dex_max++; points--; } break;
       case 3: if (int_max < HIGH_STAT) { int_max++; points--; } break;
       case 4: if (per_max < HIGH_STAT) { per_max++; points--; } break;
      }
      break;
     case 6:
     case 7:
     case 8:
     case 9:
      rn = random_skill();

      Skill *aSkill = Skill::skill(rn);
      int level = skillLevel(aSkill);

      if (level < points) {
        points -= level + 1;
        skillLevel(aSkill).level(level + 2);
      }
      break;
     }
    }
   } break;
   case PLTYPE_TEMPLATE: {
    std::ifstream fin;
    std::stringstream filename;
    filename << "data/" << tempname << ".template";
    fin.open(filename.str().c_str());
    if (!fin.is_open()) {
     debugmsg("Couldn't open %s!", filename.str().c_str());
     return false;
    }
    std::string(data);
    getline(fin, data);
    load_info(g, data);
    points = 0;
   } break;
  }
  tab = 3;
 } else
  points = OPTIONS[OPT_INITIAL_POINTS];

 do {
  werase(w);
  wrefresh(w);
  switch (tab) {
   case 0: tab += set_stats      (w, g, this, points); break;
   case 1: tab += set_traits     (w, g, this, points); break;
   case 2: tab += set_profession (w, g, this, points); break;
   case 3: tab += set_skills     (w, g, this, points); break;
   case 4: tab += set_description(w, g, this, points); break;
  }
 } while (tab >= 0 && tab < 5);
 delwin(w);

 if (tab < 0)
  return false;

 // Character is finalized.  Now just set up HP, &c
 for (int i = 0; i < num_hp_parts; i++) {
  hp_max[i] = calc_HP(str_max, has_trait(PF_TOUGH));
  hp_cur[i] = hp_max[i];
 }
 if (has_trait(PF_GLASSJAW)) {
  hp_max[hp_head] = int(hp_max[hp_head] * .85);
  hp_cur[hp_head] = hp_max[hp_head];
 }
 if (has_trait(PF_SMELLY))
  scent = 800;
 if (has_trait(PF_ANDROID)) {
  std::map<std::string,bionic_data*>::iterator random_bionic = bionics.begin();
  std::advance(random_bionic,rng(0,bionics.size()-1));
  add_bionic(random_bionic->first);// Other
  if (bionics[my_bionics[0].id]->power_cost > 0) {
   add_bionic(bionic_id(power_source_bionics[rng(0,power_source_bionics.size())]));	// Power Source
   max_power_level = 10;
   power_level = 10;
  } else {
   bionic_id tmpbio;
   do
   tmpbio = bionic_id(unpowered_bionics[rng(0, unpowered_bionics.size())]);
   while (bionics[tmpbio]->power_cost > 0);
   add_bionic(tmpbio);
   max_power_level = 0;
   power_level = 0;
  }

/* CHEATER'S STUFF

  add_bionic(bionic_id(rng(0, "bio_ethanol")));	// Power Source
  for (int i = 0; i < 5; i++)
   add_bionic(bionic_id(rng("bio_memory", max_"bio_start" - 1)));// Other
  max_power_level = 80;
  power_level = 80;

End of cheatery */
 }

 if (has_trait(PF_MARTIAL_ARTS)) {
  itype_id ma_type;
  do {
   int choice = menu("Pick your style:",
                     "Karate", "Judo", "Aikido", "Tai Chi", "Taekwondo", NULL);
   if (choice == 1)
    ma_type = "style_karate";
   if (choice == 2)
    ma_type = "style_judo";
   if (choice == 3)
    ma_type = "style_aikido";
   if (choice == 4)
    ma_type = "style_tai_chi";
   if (choice == 5)
    ma_type = "style_taekwondo";
   item tmpitem = item(g->itypes[ma_type], 0);
   full_screen_popup(tmpitem.info(true).c_str());
  } while (!query_yn("Use this style?"));
  styles.push_back(ma_type);
 }
 ret_null = item(g->itypes["null"], 0);
 if (!styles.empty())
  weapon = item(g->itypes[ styles[0] ], 0, ':');
 else
  weapon   = item(g->itypes["null"], 0);
 
 item tmp; //gets used several times

 std::vector<std::string> prof_items = g->u.prof->items();
 for (std::vector<std::string>::const_iterator iter = prof_items.begin(); iter != prof_items.end(); ++iter) {
  item tmp = item(g->itypes.at(*iter), 0, 'a' + worn.size());
  if (tmp.is_armor()) {
   if (tmp.has_flag(IF_VARSIZE))
    tmp.item_flags |= mfb(IF_FIT);      
   worn.push_back(tmp);
  } else {
   inv.push_back(tmp);
  }

  // if we start with drugs, need to start strongly addicted, too
  if (tmp.is_food()) {
   it_comest *comest = dynamic_cast<it_comest*>(tmp.type);
   if (comest->add != ADD_NULL) {
    addiction add(comest->add, 10);
    g->u.addictions.push_back(add);
   }
  }
 }

// The near-sighted get to start with glasses.
 if (has_trait(PF_MYOPIC)) {
  tmp = item(g->itypes["glasses_eye"], 0, 'a' + worn.size());
  worn.push_back(tmp);
 }
// And the far-sighted get to start with reading glasses.
 if (has_trait(PF_HYPEROPIC)) {
  tmp = item(g->itypes["glasses_reading"], 0, 'a' + worn.size());
  worn.push_back(tmp);
 }
// Likewise, the asthmatic start with their medication.
 if (has_trait(PF_ASTHMA)) {
  tmp = item(g->itypes["inhaler"], 0, 'a' + worn.size());
  inv.push_back(tmp);
 }
// Basic starter gear, added independently of profession.
 tmp = item(g->itypes["pockknife"], 0,'a' + worn.size());
  inv.push_back(tmp);
 tmp = item(g->itypes["matches"], 0,'a' + worn.size());
  inv.push_back(tmp);
// make sure we have no mutations
 for (int i = 0; i < PF_MAX2; i++)
  my_mutations[i] = false;
 return true;
}
Ejemplo n.º 2
0
bool Player::create_new_character()
{
  Window w_newch(0, 0, 80, 24);
  cuss::interface i_newch;
  if (!i_newch.load_from_file(CUSS_DIR + "/i_newchar_stats.cuss")) {
    return false;
  }

  New_char_screen cur_screen = NCS_STATS;

  Stat_selected cur_stat = STATSEL_STR;
  int* stat_value = &(stats.strength);

/* We need to set up a list of traits which does NOT include the placeholder / 
 * marker "traits" like TRAIT_MAX_GOOD and TRAIT_MAX_NEUTRAL etc.
 */
  std::vector<Trait_id> selectable_traits;
  for (int i = 1; i < TRAIT_MAX_BAD; i++) {
    if (i != TRAIT_MAX_GOOD && i != TRAIT_MAX_NEUTRAL) {
      selectable_traits.push_back( Trait_id(i) );
    }
  }

  std::vector<std::string> traits_list     = get_trait_list     (this);
  std::vector<std::string> profession_list = get_profession_list(this);

  name = "";

  int points = 4;
  int num_traits = 0;

  i_newch.ref_data("num_points", &points);

  i_newch.ref_data("num_strength",     &stats.strength);
  i_newch.ref_data("num_dexterity",    &stats.dexterity);
  i_newch.ref_data("num_perception",   &stats.perception);
  i_newch.ref_data("num_intelligence", &stats.intelligence);
  i_newch.set_data("text_description", get_stat_description(cur_stat));

  i_newch.set_data("text_strength",     "<c=ltblue>Strength<c=/>");
  i_newch.set_data("text_dexterity",    "<c=ltgray>Dexterity<c=/>");
  i_newch.set_data("text_perception",   "<c=ltgray>Perception<c=/>");
  i_newch.set_data("text_intelligence", "<c=ltgray>Intelligence<c=/>");

  bool done = false;

  while (!done) {  // We'll exit this function via keypresses, always
// Always set num_points!

    i_newch.draw(&w_newch);
    w_newch.refresh();

    long ch = getch();
    bool changed_screen = false;

    if (ch == '<') {
      cur_screen = New_char_screen( cur_screen - 1 );
      if (cur_screen == NCS_CANCEL) {
        if (query_yn("Cancel character creation?")) {
          return false;
        }
        cur_screen = NCS_STATS;
      } else {
        changed_screen = true;
      }
    } else if (ch == '>') {
      cur_screen = New_char_screen( cur_screen + 1 );
      if (cur_screen == NCS_DONE) {
        std::string reason_for_fail;
        if (points > 0) {
          reason_for_fail += "\nYou have unspent points!";
        }
        if (profession == NULL) {
          reason_for_fail += "\nYou didn't choose a profession!";
        }
        if (name.empty()) {
          reason_for_fail += "\nYour name is blank!";
        }
        if (!reason_for_fail.empty()) {
          popup("Wait, you can't start the game yet!%s",
                reason_for_fail.c_str());
        } else if (query_yn("Complete character and start the game?")) {
          done = true;
        }
        cur_screen = NCS_DESCRIPTION;
      } else {
        changed_screen = true;
      }
    } else {
// We should be doing this with cuss keybindings, but... that gets complex.
// Maybe one day I'll update cuss to be more friendly.
      switch (cur_screen) {

        case NCS_STATS: {
          bool changed_stat = false;
          switch (ch) {
            case '2':
            case 'j':
            case KEY_DOWN:
              if (cur_stat == STATSEL_INT) {
                cur_stat = STATSEL_STR;
              } else {
                cur_stat = Stat_selected( cur_stat + 1 );
              }
              changed_stat = true;
              break;

            case '8':
            case 'k':
            case KEY_UP:
              if (cur_stat == STATSEL_STR) {
                cur_stat = STATSEL_INT;
              } else {
                cur_stat = Stat_selected( cur_stat - 1 );
              }
              changed_stat = true;
              break;

            case '4':
            case 'h':
            case KEY_LEFT:
              if (*stat_value > 4) {
                if (*stat_value > 16) {
                  points++; // Stats above 16 cost 2 points, so get extra back
                }
                points++;
                (*stat_value)--;
              }
              break;

            case '6':
            case 'l':
            case KEY_RIGHT: {
              int point_req = (*stat_value >= 16 ? 2 : 1);
              if (*stat_value < 20 && points >= point_req) {
                points -= point_req;
                (*stat_value)++;
              }
            } break;
          } // switch (ch)

          if (changed_stat) { // Update stat_value
            i_newch.set_data("text_strength",    "<c=ltgray>Strength<c=/>");
            i_newch.set_data("text_dexterity",   "<c=ltgray>Dexterity<c=/>");
            i_newch.set_data("text_perception",  "<c=ltgray>Perception<c=/>");
            i_newch.set_data("text_intelligence","<c=ltgray>Intelligence<c=/>");

            i_newch.set_data("text_description",
                             get_stat_description(cur_stat));
            switch (cur_stat) {
              case STATSEL_STR:
                stat_value = &(stats.strength);
                i_newch.set_data("text_strength",
                                 "<c=ltblue>Strength<c=/>");
                break;
              case STATSEL_DEX:
                stat_value = &(stats.dexterity);
                i_newch.set_data("text_dexterity",
                                 "<c=ltblue>Dexterity<c=/>");
                break;
              case STATSEL_PER:
                stat_value = &(stats.perception);
                i_newch.set_data("text_perception",
                                 "<c=ltblue>Perception<c=/>");
                break;
              case STATSEL_INT:
                stat_value = &(stats.intelligence);
                i_newch.set_data("text_intelligence",
                                 "<c=ltblue>Intelligence<c=/>");
                break;
            }
          }
        } break;

        case NCS_TRAITS: {
          switch (ch) {
            case '2':
            case 'j':
            case KEY_DOWN:
            {
              i_newch.add_data("list_traits", 1);
              int sel = i_newch.get_int("list_traits");
              Trait_id cur_trait = selectable_traits[sel];
              i_newch.set_data("num_cost", abs(trait_cost(cur_trait)));
              if (trait_cost(cur_trait) >= 0) {
                i_newch.set_data("text_cost", "<c=yellow>Cost:<c=/>");
              } else {
                i_newch.set_data("text_cost", "<c=yellow>Earns:<c=/>");
              }
              if (trait_cost(cur_trait) > points) {
                i_newch.set_data("num_cost", c_red);
              } else {
                i_newch.set_data("num_cost", c_white);
              }
              i_newch.set_data("text_description",
                               trait_description(cur_trait));
            } break;

            case '8':
            case 'k':
            case KEY_UP:
            {
              i_newch.add_data("list_traits", -1);
              int sel = i_newch.get_int("list_traits");
              Trait_id cur_trait = selectable_traits[sel];
              i_newch.set_data("num_cost", abs(trait_cost(cur_trait)));
              if (trait_cost(cur_trait) >= 0) {
                i_newch.set_data("text_cost", "<c=yellow>Cost:<c=/>");
              } else {
                i_newch.set_data("text_cost", "<c=yellow>Earns:<c=/>");
              }
              if (trait_cost(cur_trait) > points) {
                i_newch.set_data("num_cost", c_red);
              } else {
                i_newch.set_data("num_cost", c_white);
              }
              i_newch.set_data("text_description",
                               trait_description(cur_trait));
            } break;

            case '\n':
            case ' ':
            {
              int sel = i_newch.get_int("list_traits");
              Trait_id cur_trait = selectable_traits[sel];
              if (has_trait(cur_trait)) {
                traits[cur_trait] = false;
                points += trait_cost(cur_trait);
                num_traits--;
                traits_list = get_trait_list(this);
              } else if (points >= trait_cost(cur_trait) && num_traits < 5){
                traits[cur_trait] = true;
                points -= trait_cost(cur_trait);
                num_traits++;
                traits_list = get_trait_list(this);
              }
              i_newch.set_data("num_traits_left", 5 - num_traits);
              if (num_traits >= 5) {
                i_newch.set_data("num_traits_left", c_red);
              }
            } break;

          } // switch (ch)
        } break;

        case NCS_PROFESSION: {
          switch (ch) {
            case '2':
            case 'j':
            case KEY_DOWN:
            {
              i_newch.add_data("list_professions", 1);
              std::string prof_name = i_newch.get_str("list_professions");
              prof_name = remove_color_tags(prof_name);
              Profession* cur_prof = PROFESSIONS.lookup_name(prof_name);
              if (!cur_prof) {
                debugmsg("No such profession as '%s'!", prof_name.c_str());
                return false;
              }
              i_newch.set_data("text_description", cur_prof->description);
            } break;

            case '8':
            case 'k':
            case KEY_UP:
            {
              i_newch.add_data("list_professions", -1);
              std::string prof_name = i_newch.get_str("list_professions");
              prof_name = remove_color_tags(prof_name);
              Profession* cur_prof = PROFESSIONS.lookup_name(prof_name);
              if (!cur_prof) {
                debugmsg("No such profession as '%s'!", prof_name.c_str());
                return false;
              }
              i_newch.set_data("text_description", cur_prof->description);
            } break;

            case '\n':
            case ' ':
            {
              std::string prof_name = i_newch.get_str("list_professions");
              prof_name = remove_color_tags(prof_name);
              Profession* cur_prof = PROFESSIONS.lookup_name(prof_name);
              if (!cur_prof) {
                debugmsg("No such profession as '%s'!", prof_name.c_str());
                return false;
              }
              set_profession(cur_prof);
              profession_list = get_profession_list(this);
            } break;

          } // switch (ch)
        } break;

        case NCS_DESCRIPTION: {
          if (ch == '/') {
            male = !male;
            if (male) {
              i_newch.set_data("text_male",   "<c=yellow>Male<c=/>");
              i_newch.set_data("text_female", "<c=dkgray>Female<c=/>");
            } else {
              i_newch.set_data("text_male",   "<c=dkgray>Male<c=/>");
              i_newch.set_data("text_female", "<c=yellow>Female<c=/>");
            }
          } else {
/* Let the interface handle name entry; this includes cursor movement,
 * backspace, etc.  The only downside is that this allows entry of "invalid"
 * name characters like "'&^%$#@ etc.  Bad?
 */
            cuss::element* entry = i_newch.find_by_name("entry_name");
            entry->handle_keypress(ch);
          }
            
        } break;

      } // switch (cur_screen)
    } // key pressed isn't '<' or '>'

    if (changed_screen) {
      std::string filename = CUSS_DIR + "/i_newchar_";
      switch (cur_screen) {
        case NCS_STATS:       filename += "stats.cuss";       break;
        case NCS_TRAITS:      filename += "traits.cuss";      break;
        case NCS_PROFESSION:  filename += "profession.cuss";  break;
        case NCS_DESCRIPTION: filename += "description.cuss"; break;
      }
      if (!i_newch.load_from_file(filename)) {
        return false;
      }

      i_newch.ref_data("num_points", &points);

      switch (cur_screen) {

        case NCS_STATS:
          cur_stat = STATSEL_STR;
          i_newch.set_data("text_strength",     "<c=ltblue>Strength<c=/>");
          i_newch.set_data("text_dexterity",    "<c=ltgray>Dexterity<c=/>");
          i_newch.set_data("text_perception",   "<c=ltgray>Perception<c=/>");
          i_newch.set_data("text_intelligence", "<c=ltgray>Intelligence<c=/>");
          i_newch.ref_data("num_strength",     &stats.strength);
          i_newch.ref_data("num_dexterity",    &stats.dexterity);
          i_newch.ref_data("num_perception",   &stats.perception);
          i_newch.ref_data("num_intelligence", &stats.intelligence);
          i_newch.set_data("text_description", get_stat_description(cur_stat));
          break;

        case NCS_TRAITS: {
          i_newch.select("list_traits");
          i_newch.ref_data("list_traits", &traits_list);
          int sel = i_newch.get_int("list_traits");
          Trait_id cur_trait = selectable_traits[sel];
          i_newch.set_data("text_description", trait_description(cur_trait));
          i_newch.set_data("num_cost", abs(trait_cost(cur_trait)));
          if (trait_cost(cur_trait) >= 0) {
            i_newch.set_data("text_cost", "<c=yellow>Cost:<c=/>");
          } else {
            i_newch.set_data("text_cost", "<c=yellow>Earns:<c=/>");
          }
          if (trait_cost(cur_trait) > points) {
            i_newch.set_data("num_cost", c_red);
          } else {
            i_newch.set_data("num_cost", c_white);
          }
          i_newch.set_data("num_traits_left", 5 - num_traits);
          if (num_traits >= 5) {
            i_newch.set_data("num_traits_left", c_red);
          }
        } break;

        case NCS_PROFESSION: {
          i_newch.select("list_professions");
          i_newch.ref_data("list_professions", &profession_list);
          std::string prof_name = i_newch.get_str("list_professions");
          prof_name = remove_color_tags(prof_name);
          Profession* cur_prof = PROFESSIONS.lookup_name(prof_name);
          if (!cur_prof) {
            debugmsg("No such profession as '%s'!", prof_name.c_str());
            return false;
          }
          i_newch.set_data("text_description", cur_prof->description);
        } break;

        case NCS_DESCRIPTION:
          i_newch.ref_data("entry_name", &name);
          if (male) {
            i_newch.set_data("text_male",   "<c=yellow>Male<c=/>");
            i_newch.set_data("text_female", "<c=dkgray>Female<c=/>");
          } else {
            i_newch.set_data("text_male",   "<c=dkgray>Male<c=/>");
            i_newch.set_data("text_female", "<c=yellow>Female<c=/>");
          }
          break;
      } // switch (cur_screen)
    } // if (changed_screen)
  }

// Now set up our skills and equipment based on our profession
  if (!profession) {
    debugmsg("Character creation finished without a profession!");
    return false;
  }
  std::vector<Item_type_chance> prof_items = profession->items.item_types;
  for (int i = 0; i < prof_items.size(); i++) {
    int count = prof_items[i].number;
    Item tmp_it(prof_items[i].item);
    for (int i = 0; i < count; i++) {
      if (tmp_it.get_item_class() == ITEM_CLASS_CLOTHING) {
        items_worn.push_back(tmp_it);
      } else {
        inventory.push_back(tmp_it);
      }
    }
  }

  skills = profession->skills;

// The "Durable" trait needs to be set up here.
  if (has_trait(TRAIT_DURABLE)) {
    for (int i = 0; i < HP_PART_MAX; i++) {
      current_hp[i] = 115;
      max_hp[i] = 115;
    }
  }

// Myopic characters get free glasses
  if (has_trait(TRAIT_MYOPIC)) {
    Item_type* glasses = ITEM_TYPES.lookup_name("glasses");
    if (!glasses) {
      debugmsg("No item 'glasses' exists - required for the Myopic trait!");
      return false;
    }
    Item tmp_it(glasses);
    items_worn.push_back(tmp_it);
  }

  return true;
}
Ejemplo n.º 3
0
bool player::create(game *g, character_type type, std::string tempname)
{
 weapon = item(g->itypes["null"], 0);

 g->u.prof = profession::generic();

 WINDOW* w = newwin(FULL_SCREEN_HEIGHT, FULL_SCREEN_WIDTH,
                    (TERMY > FULL_SCREEN_HEIGHT) ? (TERMY-FULL_SCREEN_HEIGHT)/2 : 0,
                    (TERMX > FULL_SCREEN_WIDTH) ? (TERMX-FULL_SCREEN_WIDTH)/2 : 0);

 int tab = 0, points = 38, max_trait_points = 12;
 if (type != PLTYPE_CUSTOM) {
  switch (type) {
   case PLTYPE_RANDOM: {
    str_max = rng(6, 12);
    dex_max = rng(6, 12);
    int_max = rng(6, 12);
    per_max = rng(6, 12);
    points = points - str_max - dex_max - int_max - per_max;
    if (str_max > HIGH_STAT)
     points -= (str_max - HIGH_STAT);
    if (dex_max > HIGH_STAT)
     points -= (dex_max - HIGH_STAT);
    if (int_max > HIGH_STAT)
     points -= (int_max - HIGH_STAT);
    if (per_max > HIGH_STAT)
     points -= (per_max - HIGH_STAT);

    int num_gtraits = 0, num_btraits = 0, rn, tries;
    while (points < 0 || rng(-3, 20) > points) {
     if (num_btraits < max_trait_points && one_in(3)) {
      tries = 0;
      do {
       rn = random_bad_trait();
       tries++;
      } while ((has_trait(rn) ||
              num_btraits - traits[rn].points > max_trait_points) && tries < 5);
      if (tries < 5) {
       toggle_trait(rn);
       points -= traits[rn].points;
       num_btraits -= traits[rn].points;
      }
     } else {
      switch (rng(1, 4)) {
       case 1: if (str_max > 5) { str_max--; points++; } break;
       case 2: if (dex_max > 5) { dex_max--; points++; } break;
       case 3: if (int_max > 5) { int_max--; points++; } break;
       case 4: if (per_max > 5) { per_max--; points++; } break;
      }
     }
    }
    while (points > 0) {
     switch (rng((num_gtraits < max_trait_points ? 1 : 5), 9)) {
     case 1:
     case 2:
     case 3:
     case 4:
      rn = random_good_trait();
      if (!has_trait(rn) && points >= traits[rn].points &&
          num_gtraits + traits[rn].points <= max_trait_points) {
       toggle_trait(rn);
       points -= traits[rn].points;
       num_gtraits += traits[rn].points;
      }
      break;
     case 5:
      switch (rng(1, 4)) {
       case 1: if (str_max < HIGH_STAT) { str_max++; points--; } break;
       case 2: if (dex_max < HIGH_STAT) { dex_max++; points--; } break;
       case 3: if (int_max < HIGH_STAT) { int_max++; points--; } break;
       case 4: if (per_max < HIGH_STAT) { per_max++; points--; } break;
      }
      break;
     case 6:
     case 7:
     case 8:
     case 9:
      rn = random_skill();

      Skill *aSkill = Skill::skill(rn);
      int level = skillLevel(aSkill);

      if (level < points) {
        points -= level + 1;
        skillLevel(aSkill).level(level + 2);
      }
      break;
     }
    }
   } break;
   case PLTYPE_TEMPLATE: {
    std::ifstream fin;
    std::stringstream filename;
    filename << "data/" << tempname << ".template";
    fin.open(filename.str().c_str());
    if (!fin.is_open()) {
     debugmsg("Couldn't open %s!", filename.str().c_str());
     return false;
    }
    std::string(data);
    getline(fin, data);
    load_info(g, data);
    points = 0;
   } break;
  }
  tab = NEWCHAR_TAB_MAX;
 } else
  points = OPTIONS[OPT_INITIAL_POINTS];
  max_trait_points = OPTIONS[OPT_MAX_TRAIT_POINTS];

 do {
  werase(w);
  wrefresh(w);
  switch (tab) {
   case 0: tab += set_stats      (w, g, this, points); break;
   case 1: tab += set_traits     (w, g, this, points, max_trait_points); break;
   case 2: tab += set_profession (w, g, this, points); break;
   case 3: tab += set_skills     (w, g, this, points); break;
   case 4: tab += set_description(w, g, this, points); break;
  }
 } while (tab >= 0 && tab <= NEWCHAR_TAB_MAX);
 delwin(w);

 if (tab < 0)
  return false;

 // Character is finalized.  Now just set up HP, &c
 for (int i = 0; i < num_hp_parts; i++) {
  hp_max[i] = calc_HP(str_max, has_trait(PF_TOUGH));
  hp_cur[i] = hp_max[i];
 }
 if (has_trait(PF_HARDCORE)) {
  for (int i = 0; i < num_hp_parts; i++) {
   hp_max[i] = int(hp_max[i] * .25);
   hp_cur[i] = hp_max[i];
  }
 } if (has_trait(PF_GLASSJAW)) {
  hp_max[hp_head] = int(hp_max[hp_head] * .80);
  hp_cur[hp_head] = hp_max[hp_head];
 }
 if (has_trait(PF_SMELLY))
  scent = 800;
 if (has_trait(PF_ANDROID)) {
  bionic_id first_bio;
  do {
   first_bio = g->random_good_bionic();
  } while (bionics[first_bio]->power_cost > 10);
  add_bionic(first_bio);
  add_bionic(bionic_id(power_source_bionics[rng(0,power_source_bionics.size()-1)]));	// Power Source
  max_power_level = 10;
  power_level = 10;
 }

 if (has_trait(PF_MARTIAL_ARTS)) {
  itype_id ma_type;
  do {
   int choice = menu(false, _("Pick your style:"),
                     _("Karate"), _("Judo"), _("Aikido"), _("Tai Chi"),
                     _("Taekwondo"), NULL);
   if (choice == 1)
    ma_type = "style_karate";
   if (choice == 2)
    ma_type = "style_judo";
   if (choice == 3)
    ma_type = "style_aikido";
   if (choice == 4)
    ma_type = "style_tai_chi";
   if (choice == 5)
    ma_type = "style_taekwondo";
   item tmpitem = item(g->itypes[ma_type], 0);
   full_screen_popup(tmpitem.info(true).c_str());
  } while (!query_yn(_("Use this style?")));
  styles.push_back(ma_type);
  style_selected=ma_type;
 }

    if (has_trait(PF_MARTIAL_ARTS2)) {
  itype_id ma_type;
  do {
   int choice = menu(false, _("Pick your style:"),
                     _("Capoeira"), _("Krav Maga"), _("Muay Thai"),
                     _("Ninjutsu"), _("Zui Quan"), NULL);
   if (choice == 1)
    ma_type = "style_capoeira";
   if (choice == 2)
    ma_type = "style_krav_maga";
   if (choice == 3)
    ma_type = "style_muay_thai";
   if (choice == 4)
    ma_type = "style_ninjutsu";
   if (choice == 5)
    ma_type = "style_zui_quan";
   item tmpitem = item(g->itypes[ma_type], 0);
   full_screen_popup(tmpitem.info(true).c_str());
  } while (!query_yn(_("Use this style?")));
  styles.push_back(ma_type);
  style_selected=ma_type;
 }
 if (has_trait(PF_MARTIAL_ARTS3)) {
  itype_id ma_type;
  do {
   int choice = menu(false, _("Pick your style:"),
                     _("Tiger"), _("Crane"), _("Leopard"), _("Snake"),
                     _("Dragon"), NULL);
   if (choice == 1)
    ma_type = "style_tiger";
   if (choice == 2)
    ma_type = "style_crane";
   if (choice == 3)
    ma_type = "style_leopard";
   if (choice == 4)
    ma_type = "style_snake";
   if (choice == 5)
    ma_type = "style_dragon";
   item tmpitem = item(g->itypes[ma_type], 0);
   full_screen_popup(tmpitem.info(true).c_str());
  } while (!query_yn(_("Use this style?")));
  styles.push_back(ma_type);
  style_selected=ma_type;
 }
 if (has_trait(PF_MARTIAL_ARTS4)) {
  itype_id ma_type;
  do {
   int choice = menu(false, _("Pick your style:"),
                     _("Centipede"), _("Viper"), _("Scorpion"), _("Lizard"),
                     _("Toad"), NULL);
   if (choice == 1)
    ma_type = "style_centipede";
   if (choice == 2)
    ma_type = "style_venom_snake";
   if (choice == 3)
    ma_type = "style_scorpion";
   if (choice == 4)
    ma_type = "style_lizard";
   if (choice == 5)
    ma_type = "style_toad";
   item tmpitem = item(g->itypes[ma_type], 0);
   full_screen_popup(tmpitem.info(true).c_str());
  } while (!query_yn(_("Use this style?")));
  styles.push_back(ma_type);
  style_selected=ma_type;
 }
 ret_null = item(g->itypes["null"], 0);
 weapon = get_combat_style();
 
 
 item tmp; //gets used several times

 std::vector<std::string> prof_items = g->u.prof->items();
 for (std::vector<std::string>::const_iterator iter = prof_items.begin(); iter != prof_items.end(); ++iter)
 {
    tmp = item(item_controller->find_template(*iter), 0);
    inv.push_back(tmp);
 }

 std::vector<addiction> prof_addictions = g->u.prof->addictions();
 for (std::vector<addiction>::const_iterator iter = prof_addictions.begin(); iter != prof_addictions.end(); ++iter)
 {
     g->u.addictions.push_back(*iter);
 }

 // Grab the skills from the profession, if there are any
 profession::StartingSkillList prof_skills = g->u.prof->skills();
 for (profession::StartingSkillList::const_iterator iter = prof_skills.begin(); 
      iter != prof_skills.end(); ++iter)
 {
     assert(Skill::skill(iter->first));
     if (Skill::skill(iter->first))
     {
        g->u.boost_skill_level(iter->first, iter->second);
     }
 }

 // Those who are both near-sighted and far-sighted start with bifocal glasses.
 if (has_trait(PF_HYPEROPIC) && has_trait(PF_MYOPIC))
 {
    tmp = item(g->itypes["glasses_bifocal"], 0);
    inv.push_back(tmp);
 }
 // The near-sighted start with eyeglasses.
 else if (has_trait(PF_MYOPIC))
 {
    tmp = item(g->itypes["glasses_eye"], 0);
    inv.push_back(tmp);
 }
 // The far-sighted start with reading glasses.
 else if (has_trait(PF_HYPEROPIC))
 {
    tmp = item(g->itypes["glasses_reading"], 0);
    inv.push_back(tmp);
 }

// Likewise, the asthmatic start with their medication.
 if (has_trait(PF_ASTHMA)) {
  tmp = item(g->itypes["inhaler"], 0);
  inv.push_back(tmp);
 }
// Basic starter gear, added independently of profession.
 tmp = item(g->itypes["pockknife"], 0);
  inv.push_back(tmp);
 tmp = item(g->itypes["matches"], 0);
  inv.push_back(tmp);
// make sure we have no mutations
 for (int i = 0; i < PF_MAX2; i++)
  if (!has_base_trait(i))
	my_mutations[i] = false;
	
	// Equip any armor from our inventory. If we are unable to wear some of it due to encumberance, it will silently fail.
    std::vector<item*> tmp_inv;
    inv.dump(tmp_inv);
    
    for(std::vector<item*>::iterator i = tmp_inv.begin(); i != tmp_inv.end(); ++i)
    {
        if( (*i)->is_armor())
        {
            if( (*i)->has_flag("VARSIZE"))
            {
                (*i)->item_tags.insert("FIT");
            }
            // It might be more elegant to use player::wear_item, but then we have to implement our own inventory removal.
            wear(g, (*i)->invlet, false);
        }
    }

 // Ensure that persistent morale effects (e.g. Optimist) are present at the start.
 apply_persistent_morale();
 return true;
}