Beispiel #1
0
void rungame(void)
{
    int ret, role = initrole, race = initrace, gend = initgend, align = initalign;
    int fd = -1;
    char plname[BUFSZ];
    fnchar filename[1024];
    fnchar savedir[BUFSZ];
    long t;

    if (!get_gamedir(SAVE_DIR, savedir)) {
        curses_raw_print("Could not find where to put the logfile for a new game.");
        return;
    }

    if (!player_selection(&role, &race, &gend, &align, random_player))
        return;

    strncpy(plname, settings.plname, PL_NSIZ);
    /* The player name is set to "wizard" (again) in nh_start_game, so setting
     * it here just prevents wizmode player from being asked for a name. */
    if (ui_flags.playmode == MODE_WIZARD)
        strcpy(plname, "wizard");

    while (!plname[0])
        curses_getline("what is your name?", plname);
    if (plname[0] == '\033') /* canceled */
        return;

    t = (long)time(NULL);
#if defined(WIN32)
    snwprintf(filename, 1024, L"%ls%ld_%hs.nhgame", savedir, t, plname);
#else
    snprintf(filename, 1024, "%s%ld_%s.nhgame", savedir, t, plname);
#endif
    fd = sys_open(filename, O_TRUNC | O_CREAT | O_RDWR, FILE_OPEN_MASK);
    if (fd == -1) {
        curses_raw_print("Could not create the logfile.");
        return;
    }

    create_game_windows();
    if (!nh_start_game(fd, plname, role, race, gend, align, ui_flags.playmode)) {
        destroy_game_windows();
        close(fd);
        return;
    }

    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);
}
Beispiel #2
0
void
replay_commandloop(int fd)
{
    int key, move, count;
    char buf[BUFSZ], qbuf[BUFSZ];
    nh_bool ret, firsttime = TRUE;
    struct nh_replay_info rinfo;
    struct nh_cmd_arg noarg;
    struct nh_cmd_desc *cmd;

    create_game_windows();
    if (!nh_view_replay_start(fd, &curses_replay_windowprocs, &rinfo))
        return;
    load_keymap();

    while (1) {
        draw_msgwin();
        curses_update_status(NULL);
        draw_sidebar();
        draw_replay_info(&rinfo);
        if (firsttime)
            show_replay_help();
        firsttime = FALSE;

        key = get_map_key(TRUE);
        switch (key) {
            /* step forward */
        case KEY_RIGHT:
        case ' ':
            ret = nh_view_replay_step(&rinfo, REPLAY_FORWARD, 1);
            draw_replay_info(&rinfo);
            if (ret == FALSE) {
                key =
                    curses_msgwin("You have reached the end of this game. "
                                  "Go back or press ESC to exit.");
                if (key == KEY_ESC)
                    goto out;
            }
            break;

            /* step backward */
        case KEY_LEFT:
            nh_view_replay_step(&rinfo, REPLAY_BACKWARD, 1);
            draw_replay_info(&rinfo);
            break;

        case KEY_ESC:
            goto out;

        case 'g':
            strncpy(qbuf, "What move do you want to jump to?", BUFSZ);
            if (rinfo.max_moves > 0)
                sprintf(qbuf + strlen(qbuf), " (Max: %d)", rinfo.max_moves);

            curses_getline(qbuf, buf);
            if (buf[0] == '\033' || !(move = atoi(buf)))
                break;
            nh_view_replay_step(&rinfo, REPLAY_GOTO, move);
            break;

        case KEY_F(12):        /* timetest! */
            if (allow_timetest())
                timetest(fd, &rinfo);
            break;

        default:
            count = 0;
            noarg.argtype = CMD_ARG_NONE;
            cmd = keymap[key];
            if (!cmd)
                break;
            if (cmd->flags & CMD_UI)
                handle_internal_cmd(&cmd, &noarg, &count);
            if (cmd)
                nh_command(cmd->name, count, &noarg);
            break;
        }
    }

out:
    nh_view_replay_finish();
    free_keymap();
    destroy_game_windows();
    cleanup_messages();
}
Beispiel #3
0
static void msgtype_edit_rule(struct nh_msgtype_rules *mt_rules, int ruleno)
{
    struct nh_msgtype_rule *rule;
    /* Menu variables. */
    struct nh_menuitem *items;
    int icount, menusize, selected[1], n;

    rule = &mt_rules->rules[ruleno];

    menusize = 5;
    items = malloc(sizeof(struct nh_menuitem) * menusize);

    do {
	char buf[BUFSZ], query[BUFSZ];
	int i;
	icount = 0;

	sprintf(buf, "Position:\t[%d]", ruleno + 1);
	add_menu_item(items, menusize, icount, 1, buf, 0, 0);

	sprintf(buf, "Action:\t[%s]", msgtype_action_string(rule->action));
	add_menu_item(items, menusize, icount, 2, buf, 0, 0);

	sprintf(buf, "Pattern:\t[%s]", rule->pattern);
	add_menu_item(items, menusize, icount, 3, buf, 0, 0);

	add_menu_txt(items, menusize, icount, "", MI_TEXT);
	add_menu_item(items, menusize, icount, 4, "Delete this match", '!', 0);

	n = curses_display_menu(items, icount, "Edit match:", PICK_ONE, selected);
	if (n > 0) {
	    switch (selected[0]) {
	    case 1:	/* change position */
		{
		    int newpos;
		    struct nh_msgtype_rule tmprule;

		    sprintf(query, "New match position: (1 - %d, currently %d)",
			    mt_rules->num_rules, ruleno + 1);
		    buf[0] = '\0';
		    curses_getline(query, buf);
		    if (!*buf || *buf == '\033')
			break;

		    newpos = atoi(buf);
		    if (newpos <= 0 || newpos > mt_rules->num_rules) {
			curses_msgwin("Invalid match position.");
			break;
		    }

		    newpos--;
		    if (newpos == ruleno)
			break;

		    tmprule = mt_rules->rules[ruleno];
		    /* Shuffle rules in-between. */
		    if (newpos > ruleno) {
			for (i = ruleno; i < newpos; i++)
			    mt_rules->rules[i] = mt_rules->rules[i + 1];
		    } else {
			for (i = ruleno; i > newpos; i--)
			    mt_rules->rules[i] = mt_rules->rules[i - 1];
		    }
		    mt_rules->rules[newpos] = tmprule;

		    /* Exit menu do-while (n > 0) */
		    n = 0;
		}
		break;

	    case 2:	/* change action */
		rule->action = get_msgtype_action(rule->action);
		break;

	    case 3:	/* change pattern */
		snprintf(query, BUFSZ, "New match pattern: (currently \"%s\")",
			 rule->pattern);
		buf[0] = '\0';
		curses_getline(query, buf);
		if (*buf != '\033') {
		    /* Replace the same chars as msgtype_to_string to reduce
		     * player surprise when loading a game and viewing msgtypes. */
		    for (i = 0; i < sizeof(buf); i++) {
			if (buf[i] == '"' || buf[i] == '|' || buf[i] == ';')
			    buf[i] = '?';
		    }
		    strncpy(rule->pattern, buf, sizeof(rule->pattern));
		}
		rule->pattern[sizeof(rule->pattern) - 1] = '\0';
		break;

	    case 4:	/* delete match */
		/* Shuffle rules down. */
		for (i = ruleno; i < mt_rules->num_rules - 1; i++)
		    mt_rules->rules[i] = mt_rules->rules[i + 1];
		mt_rules->num_rules--;
		mt_rules->rules = realloc(mt_rules->rules, mt_rules->num_rules *
					  sizeof(struct nh_msgtype_rule));
		/* Exit menu do-while (n > 0) */
		n = 0;
		break;

	    default:
		curses_msgwin("无效的消息类型匹配目录选择。");
	    }
	}
    } while (n > 0);

    free(items);
}
Beispiel #4
0
static void edit_ap_rule(struct nh_autopick_option *desc,
			 struct nh_autopickup_rules *ar, int ruleno)
{
    struct nh_autopickup_rule *r = &ar->rules[ruleno];
    struct nh_autopickup_rule tmprule;
    struct nh_menuitem *items;
    int i, icount, size = 7, n, selected[1], newpos;
    char query[BUFSZ], buf[BUFSZ], *classname;
    
    items = malloc(sizeof(struct nh_menuitem) * size);
    
    do {
	icount = 0;
	sprintf(buf, "rule position:\t[%d]", ruleno + 1);
	add_menu_item(items, size, icount, 1, buf, 0, 0);
	
	sprintf(buf, "name pattern:\t[%s]", r->pattern);
	add_menu_item(items, size, icount, 2, buf, 0, 0);
	
	classname = NULL;
	for (i = 0; i < desc->numclasses && !classname; i++)
	    if (desc->classes[i].id == r->oclass)
		classname = desc->classes[i].caption;
	sprintf(buf, "object type:\t[%s]", classname);
	add_menu_item(items, size, icount, 3, buf, 0, 0);
	
	sprintf(buf, "beatitude:\t[%s]", bucnames[r->buc]);
	add_menu_item(items, size, icount, 4, buf, 0, 0);
	
	sprintf(buf, "action:\t[%s]", r->action == AP_GRAB ? "GRAB" : "LEAVE");
	add_menu_item(items, size, icount, 5, buf, 0, 0);
	add_menu_txt(items, size, icount, "", MI_TEXT);
	add_menu_item(items, size, icount, 6, "delete this rule", 'x', 0);
	
	n = curses_display_menu(items, icount, "Edit rule:", PICK_ONE, selected);
	if (n <= 0)
	    break;
	
	switch (selected[0]) {
	    /* move this rule */
	    case 1:
		sprintf(query, "New rule position: (1 - %d), currently: %d",
			ar->num_rules, ruleno + 1);
		buf[0] = '\0';
		curses_getline(query, buf);
		if (!*buf || *buf == '\033')
		    break;
		newpos = atoi(buf);
		if (newpos <= 0 || newpos > ar->num_rules) {
		    curses_msgwin("Invalid rule position.");
		    break;
		}
		newpos--;
		if (newpos == ruleno)
		    break;
		
		tmprule = ar->rules[ruleno];
		/* shift the rules around */
		if (newpos > ruleno) {
		    for (i = ruleno; i < newpos; i++)
			ar->rules[i] = ar->rules[i+1];
		} else {
		    for (i = ruleno; i > newpos; i--)
			ar->rules[i] = ar->rules[i-1];
		}
		ar->rules[newpos] = tmprule;
		goto out;
		
	    /* edit the pattern */
	    case 2:
		sprintf(query, "New name pattern (empty matches everything):");
		buf[0] = '\0';
		curses_getline(query, buf);
		if (*buf != '\033')
		    strncpy(r->pattern, buf, sizeof(r->pattern));
		r->pattern[sizeof(r->pattern)-1] = '\0';
		break;
	    
	    /* edit object class match */
	    case 3:
		r->oclass = get_autopickup_oclass(desc, r->oclass);
		break;
	    
	    /* edit beatitude match */
	    case 4:
		r->buc = get_autopickup_buc(r->buc);
		break;
		
	    /* toggle action */
	    case 5:
		if (r->action == AP_GRAB)
		    r->action = AP_LEAVE;
		else
		    r->action = AP_GRAB;
		break;
		
	    /* delete */
	    case 6:
		for (i = ruleno; i < ar->num_rules - 1; i++)
		    ar->rules[i] = ar->rules[i+1];
		ar->num_rules--;
		ar->rules = realloc(ar->rules, ar->num_rules * sizeof(struct nh_autopickup_rule));
		goto out; /* break just beaks the switch .. doh */
	}
	
    } while (n > 0);
out:
    free(items);
}
Beispiel #5
0
/* get a new value of the appropriate type for the given option */
static nh_bool get_option_value(struct win_menu *mdat, int idx)
{
    char buf[BUFSZ], query[BUFSZ];
    union nh_optvalue value;
    struct nh_option_desc *option, *optlist;
    int listid = mdat->items[idx].id >> 10;
    int id = mdat->items[idx].id & 0x1ff;
    char strbuf[BUFSZ];
    int prev_optstyle = settings.optstyle;
    
    switch (listid) {
	case ACT_BIRTH_OPTS:
	    optlist = nh_get_options(ACTIVE_BIRTH_OPTIONS); break;
	case CUR_BIRTH_OPTS:
	    optlist = nh_get_options(CURRENT_BIRTH_OPTIONS); break;
	case GAME_OPTS:
	    optlist = nh_get_options(GAME_OPTIONS); break;
	case UI_OPTS:
	    optlist = curses_options; break;
	    
	default:
	    return FALSE;
    }
    
    option = &optlist[id];
    value.s = strbuf;
    
    switch ((int)option->type) {
	case OPTTYPE_BOOL:
	    select_boolean_value(&value, option);
	    break;
	    
	case OPTTYPE_INT:
	    sprintf(query, "New value for %s (number from %d to %d)",
		    option->name, option->i.min, option->i.max);
	    sprintf(buf, "%d", value.i);
	    curses_getline(query, buf);
	    if (buf[0] == '\033')
		return FALSE;
	    sscanf(buf, "%d", &value.i);
	    break;
	    
	case OPTTYPE_ENUM:
	    select_enum_value(&value, option);
	    break;
	    
	case OPTTYPE_STRING:
	    sprintf(query, "New value for %s (text)", option->name);
	    curses_getline(query, value.s);
	    if (value.s[0] == '\033')
		return FALSE;
	    break;
	    
	case OPTTYPE_AUTOPICKUP_RULES:
	    show_autopickup_menu(option);
	    return FALSE;
	    
	case OPTTYPE_MSGTYPE:
	    show_msgtype_menu(option);
	    return FALSE;
	    
	case OPTTYPE_KEYMAP:
	    show_keymap_menu(FALSE);
	    return FALSE;
	    
	default:
	    return FALSE;
    }
    
    if (!nh_set_option(option->name, value, FALSE)) {
	sprintf(strbuf, "new value for %s rejected", option->name);
	curses_msgwin(strbuf);
    } else
	print_option_string(option, mdat->items[idx].caption);
    
    /* special case: directly redo option menu appearance */
    if (settings.optstyle != prev_optstyle)
	return TRUE;
    
    return FALSE;
}
Beispiel #6
0
static void
edit_ap_rule(struct nh_autopick_option *desc, struct nh_autopickup_rules *ar,
             int ruleno)
{
    struct nh_autopickup_rule *r = &ar->rules[ruleno];
    struct nh_autopickup_rule tmprule;
    struct nh_menulist menu;
    int i, selected[1], newpos, allocsize;
    char query[BUFSZ], buf[BUFSZ];
    const char *classname;

    do {
        init_menulist(&menu);

        snprintf(buf, ARRAY_SIZE(buf), "rule position:\t[%d]", ruleno + 1);
        add_menu_item(&menu, 1, buf, 0, 0);

        snprintf(buf, ARRAY_SIZE(buf), "name pattern:\t[%s]", r->pattern);
        add_menu_item(&menu, 2, buf, 0, 0);

        classname = NULL;
        for (i = 0; i < desc->numclasses && !classname; i++)
            if (desc->classes[i].id == r->oclass)
                classname = desc->classes[i].caption;
        snprintf(buf, ARRAY_SIZE(buf), "object type:\t[%s]", classname);
        add_menu_item(&menu, 3, buf, 0, 0);

        snprintf(buf, ARRAY_SIZE(buf), "beatitude:\t[%s]", bucnames[r->buc]);
        add_menu_item(&menu, 4, buf, 0, 0);

        snprintf(buf, ARRAY_SIZE(buf), "action:\t[%s]", r->action == AP_GRAB ? "GRAB" : "LEAVE");
        add_menu_item(&menu, 5, buf, 0, 0);
        add_menu_txt(&menu, "", MI_TEXT);
        add_menu_item(&menu, 6, "delete this rule", 'x', 0);

        curses_display_menu(&menu, "Edit rule:", PICK_ONE, PLHINT_RIGHT,
                            selected, curses_menu_callback);
        if (*selected == CURSES_MENU_CANCELLED)
            return;

        switch (selected[0]) {
            /* move this rule */
        case 1:
            snprintf(query, ARRAY_SIZE(query), "New rule position: (1 - %d), currently: %d",
                    ar->num_rules, ruleno + 1);
            newpos = ar->num_rules;
            curses_getline(query, &newpos, rule_position_callback);
            newpos--;
            if (newpos == ruleno || newpos < 0)
                break;

            tmprule = ar->rules[ruleno];
            /* shift the rules around */
            if (newpos > ruleno) {
                for (i = ruleno; i < newpos; i++)
                    ar->rules[i] = ar->rules[i + 1];
            } else {
                for (i = ruleno; i > newpos; i--)
                    ar->rules[i] = ar->rules[i - 1];
            }
            ar->rules[newpos] = tmprule;
            return;

            /* edit the pattern */
        case 2:
            snprintf(query, ARRAY_SIZE(query), "New name pattern (empty matches everything):");
            curses_getline(query, r->pattern, rule_pattern_callback);
            break;

            /* edit object class match */
        case 3:
            r->oclass = get_autopickup_oclass(desc, r->oclass);
            break;

            /* edit beatitude match */
        case 4:
            r->buc = get_autopickup_buc(r->buc);
            break;

            /* toggle action */
        case 5:
            if (r->action == AP_GRAB)
                r->action = AP_LEAVE;
            else
                r->action = AP_GRAB;
            break;

            /* delete */
        case 6:
            for (i = ruleno; i < ar->num_rules - 1; i++)
                ar->rules[i] = ar->rules[i + 1];
            ar->num_rules--;
            allocsize = ar->num_rules;
            if (allocsize < 1)
                allocsize = 1;
            ar->rules =
                realloc(ar->rules,
                        allocsize * sizeof (struct nh_autopickup_rule));
            return;
        }

    } while (1);
}
Beispiel #7
0
/* get a new value of the appropriate type for the given option */
static nh_bool
query_new_value(struct win_menu *mdat, int idx)
{
    struct nh_option_desc *option, *optlist;
    struct nh_option_desc optioncopy;
    struct nh_option_desc *optioncopy_p = &optioncopy;
    int listid = mdat->items[idx].id >> 10;
    int id = mdat->items[idx].id & 0x1ff;
    int prev_optstyle = settings.optstyle;
    enum nh_menupaging prev_menupaging = settings.menupaging;
    nh_bool prev_menuborder = settings.whichframes != FRAME_NONE;
    nh_bool ret = FALSE;

    switch (listid) {
    case BIRTH_OPTS:
    case CREATION_OPTS:
    case GAME_OPTS:
        optlist = curses_get_nh_opts();
        break;
    case UI_OPTS:
        optlist = curses_options;
        break;

    default:
        return FALSE;
    }

    option = &optlist[id];
    /* optioncopy holds the new option we're planning to set */
    optioncopy = *option;

    switch ((int)optioncopy.type) {
    case OPTTYPE_BOOL:
        select_boolean_value(&optioncopy.value, &optioncopy);
        break;

    case OPTTYPE_INT:
        if (optioncopy.i.min >= -2147483647-1 &&
            optioncopy.i.max <= 2147483647)
        {
            /* Maximum length of a number as text is 11 chars */
            char query[11 + 1 + strlen(optioncopy.name) +
                       sizeof "New value for  (number from  to )"];
            sprintf(query, "New value for %s (number from %d to %d)",
                    optioncopy.name, optioncopy.i.min, optioncopy.i.max);
            curses_getline(query, &optioncopy_p, getlin_option_callback);
        }
        break;

    case OPTTYPE_ENUM:
        select_enum_value(&optioncopy.value, option);
        break;

    case OPTTYPE_STRING:
        if (!strcmp(optioncopy.name, "tileset")) {
            select_tileset_value(&optioncopy.value, option);
        } else {
            char query[strlen(optioncopy.name) + 1 +
                       sizeof "New value for  (text)"];
            sprintf(query, "New value for %s (text)", optioncopy.name);
            optioncopy.value.s = NULL;
            curses_getline(query, &optioncopy_p, getlin_option_callback);
        }
        break;

    case OPTTYPE_AUTOPICKUP_RULES:
        show_autopickup_menu(option);
        goto free;

    case OPTTYPE_KEYMAP:
        show_keymap_menu(FALSE);
        goto free;

    default:
        goto free;
    }

    /* getlin_option_callback NULLs out optioncopy_p to indicate that setting
       was cancelled */
    if (optioncopy_p && !curses_set_option(optioncopy.name, optioncopy.value)) {
        char query[strlen(optioncopy.name) + 1 +
                   sizeof "new value for  rejected"];
        sprintf(query, "new value for %s rejected", optioncopy.name);
        curses_msgwin(query, krc_notification);
    } else if (optioncopy_p) {
        if (listid != UI_OPTS) {
            curses_free_nh_opts(optlist);
            optlist = curses_get_nh_opts();
            option = &optlist[id];
        }

        print_option_string(option, mdat->items[idx].caption);
    }

    /* We need to deallocate any string that might have been allocated by
       the getlin callback. */
    if (optioncopy.type == OPTTYPE_STRING && optioncopy.value.s)
        free(optioncopy.value.s);

    /* If we're changing the option menu appearance, or if we changed game
       options, we need to reload and redraw the menu. */
    if (settings.optstyle != prev_optstyle ||
        settings.menupaging != prev_menupaging ||
        (settings.whichframes != FRAME_NONE) != prev_menuborder ||
        (game_is_running && listid != UI_OPTS))
        ret = TRUE;

free:
    if (listid != UI_OPTS)
        curses_free_nh_opts(optlist);

    return ret;
}