nh_bool player_selection(int *out_role, int *out_race, int *out_gend, int *out_align, int randomall, nh_bool tutorial) { struct nh_menuitem *items; int icount, size; int i, k, n, listlen, id; char pick4u = 'n', thisch, lastch = 0; char pbuf[QBUFSZ], plbuf[QBUFSZ]; struct nh_listitem list[LISTSZ]; /* need enough space for lists of roles or races */ char listbuffers[LISTSZ][256]; int pick_list[2]; int initrole, initrace, initgend, initalign; const struct nh_roles_info *ri = nh_get_roles(); if (tutorial) return tutorial_player_selection(out_role, out_race, out_gend, out_align); initrole = *out_role; initrace = *out_race; initalign = *out_align; initgend = *out_gend; if (initrole == ROLE_NONE) initrole = ri->def_role; if (initrace == ROLE_NONE) initrace = ri->def_race; if (initgend == ROLE_NONE) initgend = ri->def_gend; if (initalign == ROLE_NONE) initalign = ri->def_align; validate_character_presets(ri, &initrole, &initrace, &initgend, &initalign); for (i = 0; i < LISTSZ; i++) { listbuffers[i][0] = '\0'; list[i].caption = listbuffers[i]; } srandom(time(NULL)); /* Should we randomly pick for the player? */ if (!randomall && (initrole == ROLE_NONE || initrace == ROLE_NONE || initgend == ROLE_NONE || initalign == ROLE_NONE)) { char *prompt = nh_build_plselection_prompt(pbuf, QBUFSZ, initrole, initrace, initgend, initalign); pick4u = curses_yn_function(prompt, "ynq", 'y'); if (pick4u != 'y' && pick4u != 'n') return FALSE; } nh_root_plselection_prompt(plbuf, QBUFSZ - 1, initrole, initrace, initgend, initalign); icount = 0; size = 10; items = malloc(sizeof(struct nh_menuitem) * size); /* Select a role, if necessary */ /* if pre-selected race/gender/alignment are still set after * validate_character_presets we know they're OK */ if (initrole < 0) { listlen = get_valid_roles(ri, initrace, initgend, initalign, list, LISTSZ); /* Process the choice */ if (pick4u == 'y' || initrole == ROLE_RANDOM || randomall) { /* Pick a random role */ initrole = list[random() % listlen].id; } else { /* Prompt for a role */ for (i = 0; i < listlen; i++) { id = list[i].id + 1; /* list[i].id starts at 0 */ thisch = tolower((unsigned char)*list[i].caption); if (thisch == lastch) thisch = toupper((unsigned char)thisch); add_menu_item(items, size, icount, id, list[i].caption + 2, thisch, 0); lastch = thisch; } pick_list[0] = id = list[random() % listlen].id+1; add_menu_item(items, size, icount, id, "随机", '*', 0); add_menu_item(items, size, icount, -1, "退出", 'q', 0); sprintf(pbuf, "为你的%s选择一个角色", plbuf); n = curses_display_menu(items, icount, pbuf, PICK_ONE, pick_list); /* Process the choice */ if (n == -1 || pick_list[0] == -1) goto give_up; /* Selected quit */ initrole = pick_list[0] - 1; icount = 0; } nh_root_plselection_prompt(plbuf, QBUFSZ - 1, initrole, initrace, initgend, initalign); } /* Select a race, if necessary */ if (initrace < 0) { listlen = get_valid_races(ri, initrole, initgend, initalign, list, LISTSZ); if (pick4u == 'y' || initrace == ROLE_RANDOM || randomall) { initrace = list[random() % listlen].id; } else { /* pick4u == 'n' */ /* Count the number of valid races */ k = list[0].id; /* valid race */ /* Permit the user to pick, if there is more than one */ if (listlen > 1) { for (i = 0; i < listlen; i++) { id = list[i].id + 1; add_menu_item(items, size, icount, id, list[i].caption + 2, list[i].caption[0], 0); } pick_list[0] = id = list[random() % listlen].id+1; add_menu_item(items, size, icount, id, "随机", '*', 0); add_menu_item(items, size, icount, -1, "退出", 'q', 0); sprintf(pbuf, "为你的%s选择一个种族", plbuf); n = curses_display_menu(items, icount, pbuf, PICK_ONE, pick_list); if (n == -1 || pick_list[0] == -1) goto give_up; /* Selected quit */ k = pick_list[0] - 1; icount = 0; } initrace = k; } nh_root_plselection_prompt(plbuf, QBUFSZ - 1, initrole, initrace, initgend, initalign); } /* Select a gender, if necessary */ if (initgend < 0) { listlen = get_valid_genders(ri, initrole, initrace, initalign, list, LISTSZ); if (pick4u == 'y' || initgend == ROLE_RANDOM || randomall) { initgend = list[random() % listlen].id; } else { /* pick4u == 'n' */ /* Count the number of valid genders */ k = list[0].id; /* valid gender */ /* Permit the user to pick, if there is more than one */ if (listlen > 1) { for (i = 0; i < listlen; i++) { id = list[i].id + 1; add_menu_item(items, size, icount, id, list[i].caption + 2, list[i].caption[0], 0); } pick_list[0] = id = list[random() % listlen].id+1; add_menu_item(items, size, icount, id, "随机", '*', 0); add_menu_item(items, size, icount, -1, "退出", 'q', 0); sprintf(pbuf, "为你的%s选择一个性别", plbuf); n = curses_display_menu(items, icount, pbuf, PICK_ONE, pick_list); if (n == -1 || pick_list[0] == -1) goto give_up; /* Selected quit */ k = pick_list[0] - 1; icount = 0; } initgend = k; } nh_root_plselection_prompt(plbuf, QBUFSZ - 1, initrole, initrace, initgend, initalign); } /* Select an alignment, if necessary */ if (initalign < 0) { listlen = get_valid_aligns(ri, initrole, initrace, initgend, list, LISTSZ); if (pick4u == 'y' || initalign == ROLE_RANDOM || randomall) { initalign = list[random() % listlen].id; } else { /* pick4u == 'n' */ /* Count the number of valid alignments */ k = list[0].id; /* valid alignment */ /* Permit the user to pick, if there is more than one */ if (listlen > 1) { for (i = 0; i < listlen; i++) { id = list[i].id + 1; add_menu_item(items, size, icount, id, list[i].caption + 2, list[i].caption[0], 0); } pick_list[0] = id = list[random() % listlen].id+1; add_menu_item(items, size, icount, id, "随机", '*', 0); add_menu_item(items, size, icount, -1, "退出", 'q', 0); sprintf(pbuf, "为你的%s选择一个阵营", plbuf); n = curses_display_menu(items, icount, pbuf, PICK_ONE, pick_list); if (n == -1 || pick_list[0] == -1) goto give_up; /* Selected quit */ k = pick_list[0] - 1; } initalign = k; } } *out_role = initrole; *out_race = initrace; *out_gend = initgend; *out_align = initalign; free(items); return TRUE; give_up: free(items); return FALSE; }
nh_bool loadgame(void) { char buf[BUFSZ]; fnchar savedir[BUFSZ], filename[1024], **files; struct nh_menuitem *items; int size, icount, fd, i, n, ret, pick[1]; enum nh_log_status status; struct nh_game_info gi; if (!get_gamedir(SAVE_DIR, savedir)) { curses_raw_print("Could not find or create the save directory."); return FALSE; } files = list_gamefiles(savedir, &size); if (!size) { curses_msgwin("No saved games found."); return FALSE; } icount = 0; items = malloc(size * sizeof(struct nh_menuitem)); for (i = 0; i < size; i++) { fd = sys_open(files[i], O_RDWR, FILE_OPEN_MASK); status = nh_get_savegame_status(fd, &gi); close(fd); describe_game(buf, status, &gi); add_menu_item(items, size, icount, (status == LS_IN_PROGRESS) ? 0 : icount + 1, buf, 0, FALSE); } n = curses_display_menu(items, icount, "saved games", PICK_ONE, pick); free(items); filename[0] = '\0'; if (n > 0) fnncat(filename, files[pick[0]-1], sizeof(filename)/sizeof(fnchar)-1); for (i = 0; i < icount; i++) free(files[i]); free(files); if (n <= 0) return FALSE; fd = sys_open(filename, O_RDWR, FILE_OPEN_MASK); create_game_windows(); if (nh_restore_game(fd, NULL, FALSE) != GAME_RESTORED) { destroy_game_windows(); close(fd); if (curses_yn_function("Failed to load the save. Do you wish to delete the file?", "yn", 'n') == 'y') unlink(filename); return FALSE; } load_keymap(); /* need to load the keymap after the game has been started */ ret = commandloop(); free_keymap(); close(fd); destroy_game_windows(); cleanup_messages(); game_ended(ret, filename); return TRUE; }