Example #1
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();
}
Example #2
0
static nh_bool option_change_callback(struct nh_option_desc *option)
{
    if (!strcmp(option->name, "classic_status") ||
	!strcmp(option->name, "darkmsg") ||
	!strcmp(option->name, "frame") ||
	!strcmp(option->name, "frame_hp_color") ||
	!strcmp(option->name, "status3") ||
	!strcmp(option->name, "sidebar")) {
	rebuild_ui();
	return TRUE;
    }
    else if (!strcmp(option->name, "showexp") ||
	!strcmp(option->name, "showscore") ||
	!strcmp(option->name, "time")) {
	curses_update_status(NULL);
    }
    else if (!strcmp(option->name, "darkroom") ||
	!strcmp(option->name, "hilite_peaceful") ||
	!strcmp(option->name, "hilite_pet") ||
	!strcmp(option->name, "mapcolors")) {
	draw_map(player.x, player.y);
    }
    else if (!strcmp(option->name, "darkgray")) {
	set_darkgray();
	draw_map(player.x, player.y);
    }
    else if (!strcmp(option->name, "dungeon_name")) {
	settings.dungeon_name = option->value.e;
	rebuild_ui();
    }
    else if (!strcmp(option->name, "menu_headings")) {
	settings.menu_headings = option->value.e;
    }
    else if (!strcmp(option->name, "graphics")) {
	settings.graphics = option->value.e;
	switch_graphics(option->value.e);
	if (ui_flags.ingame) {
	    draw_map(player.x, player.y);
	    redraw_game_windows();
	}
    }
    else if (!strcmp(option->name, "scores_top")) {
	settings.end_top = option->value.i;
    }
    else if (!strcmp(option->name, "scores_around")) {
	settings.end_around = option->value.i;
    }
    else if (!strcmp(option->name, "optstyle")) {
	settings.optstyle = option->value.e;
    }
    else if (!strcmp(option->name, "msgheight")) {
	settings.msgheight = option->value.i;
	rebuild_ui();
    }
    else if (!strcmp(option->name, "msghistory")) {
	settings.msghistory = option->value.i;
	alloc_hist_array();
    }
#if defined(PDCURSES) && defined(WIN32)
    else if (!strcmp(option->name, "win_width")) {
	settings.win_width = option->value.i;
	resize_term(settings.win_height, settings.win_width);
	handle_resize();
    }
    else if (!strcmp(option->name, "win_height")) {
	settings.win_height = option->value.i;
	resize_term(settings.win_height, settings.win_width);
	handle_resize();
    }
#endif
    else if (!strcmp(option->name, "name")) {
	if (option->value.s)
	    strcpy(settings.plname, option->value.s);
	else
	    settings.plname[0] = '\0';
    }
    else
	return FALSE;
    
    return TRUE;
}
Example #3
0
static void
timetest(int fd, struct nh_replay_info *rinfo)
{
    char buf[BUFSZ];
    hp_time t_start, t_end;
    long ms;
    int mmax, initial, revpos;

    initial = rinfo->moves;
    nh_view_replay_step(rinfo, REPLAY_GOTO, 0);

    /* run forward */
    gettime(&t_start);
    while (rinfo->actions < rinfo->max_actions) {
        nh_view_replay_step(rinfo, REPLAY_FORWARD, 1);
        curses_update_status(NULL);
        draw_replay_info(rinfo);
        doupdate();
    }
    draw_msgwin();
    gettime(&t_end);
    ms = clock_delta_ms(&t_start, &t_end);
    snprintf(buf, BUFSZ,
             "%d actions replayed with display in %ld ms. (%ld actions/sec)",
             rinfo->max_actions, ms, rinfo->max_actions * 1000 / ms);
    curses_msgwin(buf);

    /* reset the entire replay state to delete checkpoints */
    mmax = rinfo->moves;        /* max_moves may not be available if this is a
                                   replay of a crashed game */
    nh_view_replay_finish();
    nh_view_replay_start(fd, &curses_replay_windowprocs, rinfo);

    /* run forward without showing the map etc. */
    gettime(&t_start);
    nh_view_replay_step(rinfo, REPLAY_GOTO, mmax);
    gettime(&t_end);
    ms = clock_delta_ms(&t_start, &t_end);
    snprintf(buf, BUFSZ,
             "%d actions replayed without display in %ld ms. (%ld actions/sec)",
             rinfo->actions, ms, rinfo->actions * 1000 / ms);
    curses_msgwin(buf);

    /* run backward */
    revpos = rinfo->actions;
    gettime(&t_start);
    while (rinfo->actions > 0 && revpos < rinfo->actions + 1000) {
        nh_view_replay_step(rinfo, REPLAY_BACKWARD, 1);
        curses_update_status(NULL);
        draw_msgwin();
        draw_replay_info(rinfo);
        doupdate();
    }
    gettime(&t_end);
    ms = clock_delta_ms(&t_start, &t_end);
    snprintf(buf, BUFSZ,
             "%d actions replayed backward with display in %ld ms. (%ld actions/sec)",
             revpos - rinfo->actions, ms,
             (revpos - rinfo->actions) * 1000 / ms);
    curses_msgwin(buf);

    nh_view_replay_step(rinfo, REPLAY_GOTO, initial);
}
Example #4
0
int
curses_getpos(int *x, int *y, nh_bool force, const char *goal)
{
    int result = 0;
    int cx, cy;
    int key, dx, dy;
    int sidx;
    static const char pick_chars[] = " \r\n.,;:";
    static const int pick_vals[] = {1, 1, 1, 1, 2, 3, 4};
    const char *cp;
    char printbuf[BUFSZ];
    char *matching = NULL;
    enum nh_direction dir;
    struct coord *monpos = NULL;
    int moncount, monidx;
    int firstmove = 1;

    werase(statuswin);
    mvwaddstr(statuswin, 0, 0,
              "Move the cursor with the direction keys. Press "
              "the letter of a dungeon symbol");
    mvwaddstr(statuswin, 1, 0,
              "to select it or use m to move to a nearby "
              "monster. Finish with one of .,;:");
    wrefresh(statuswin);

    cx = *x >= 1 ? *x : player.x;
    cy = *y >= 0 ? *y : player.y;
    wmove(mapwin, cy, cx - 1);

    while (1) {
        if (!firstmove) {
            struct nh_desc_buf descbuf;
            int mx = 0, my = 0;

            nh_describe_pos(cx, cy, &descbuf, NULL);

            werase(statuswin);
            place_desc_message(statuswin, &mx, &my, descbuf.effectdesc);
            place_desc_message(statuswin, &mx, &my, descbuf.invisdesc);
            place_desc_message(statuswin, &mx, &my, descbuf.mondesc);
            place_desc_message(statuswin, &mx, &my, descbuf.objdesc);
            place_desc_message(statuswin, &mx, &my, descbuf.trapdesc);
            place_desc_message(statuswin, &mx, &my, descbuf.bgdesc);
            wrefresh(statuswin);

            wmove(mapwin, cy, cx - 1);
        }
        firstmove = 0;
        dx = dy = 0;
        key = get_map_key(FALSE);
        if (key == KEY_ESC) {
            cx = cy = -10;
            result = -1;
            break;
        }

        if ((cp = strchr(pick_chars, (char)key)) != 0) {
            /* '.' => 0, ',' => 1, ';' => 2, ':' => 3 */
            result = pick_vals[cp - pick_chars];
            break;
        }

        dir = key_to_dir(key);
        if (dir != DIR_NONE) {
            dx = xdir[dir];
            dy = ydir[dir];
        } else if ((dir = key_to_dir(tolower((char)key))) != DIR_NONE) {
            /* a shifted movement letter */
            dx = xdir[dir] * 8;
            dy = ydir[dir] * 8;
        }

        if (dx || dy) {
            /* truncate at map edge */
            if (cx + dx < 1)
                dx = 1 - cx;
            if (cx + dx > COLNO - 1)
                dx = COLNO - 1 - cx;
            if (cy + dy < 0)
                dy = -cy;
            if (cy + dy > ROWNO - 1)
                dy = ROWNO - 1 - cy;
            cx += dx;
            cy += dy;
            goto nxtc;
        }

        if (key == 'm') {
            if (!monpos) {
                int i, j;

                moncount = 0;
                for (i = 0; i < ROWNO; i++)
                    for (j = 0; j < COLNO; j++)
                        if (display_buffer[i][j].mon &&
                            (j != player.x || i != player.y))
                            moncount++;
                monpos = malloc(moncount * sizeof (struct coord));
                monidx = 0;
                for (i = 0; i < ROWNO; i++)
                    for (j = 0; j < COLNO; j++)
                        if (display_buffer[i][j].mon &&
                            (j != player.x || i != player.y)) {
                            monpos[monidx].x = j;
                            monpos[monidx].y = i;
                            monidx++;
                        }
                monidx = 0;
                qsort(monpos, moncount, sizeof (struct coord),
                      compare_coord_dist);
            }

            if (moncount) {     /* there is at least one monster to move to */
                cx = monpos[monidx].x;
                cy = monpos[monidx].y;
                monidx = (monidx + 1) % moncount;
            }
        } else {
            int k = 0, tx, ty;
            int pass, lo_x, lo_y, hi_x, hi_y;

            matching = malloc(default_drawing->num_bgelements);
            memset(matching, 0, default_drawing->num_bgelements);
            for (sidx = default_drawing->bg_feature_offset;
                 sidx < default_drawing->num_bgelements; sidx++)
                if (key == default_drawing->bgelements[sidx].ch)
                    matching[sidx] = (char)++k;
            if (k) {
                for (pass = 0; pass <= 1; pass++) {
                    /* pass 0: just past current pos to lower right; pass 1:
                       upper left corner to current pos */
                    lo_y = (pass == 0) ? cy : 0;
                    hi_y = (pass == 0) ? ROWNO - 1 : cy;
                    for (ty = lo_y; ty <= hi_y; ty++) {
                        lo_x = (pass == 0 && ty == lo_y) ? cx + 1 : 1;
                        hi_x = (pass == 1 && ty == hi_y) ? cx : COLNO - 1;
                        for (tx = lo_x; tx <= hi_x; tx++) {
                            k = display_buffer[ty][tx].bg;
                            if (k && matching[k]) {
                                cx = tx;
                                cy = ty;
                                goto nxtc;
                            }
                        }       /* column */
                    }   /* row */
                }       /* pass */
                sprintf(printbuf, "Can't find dungeon feature '%c'.",
                        (char)key);
                curses_msgwin(printbuf);
            } else {
                sprintf(printbuf, "Unknown direction%s.",
                        !force ? " (ESC to abort)" : "");
                curses_msgwin(printbuf);
            }
        }
        if (force)
            goto nxtc;
        cx = -1;
        cy = 0;
        result = 0;     /* not -1 */
        break;

    nxtc:
        wmove(mapwin, cy, cx - 1);
        wrefresh(mapwin);
    }

    *x = cx;
    *y = cy;
    if (monpos)
        free(monpos);
    if (matching)
        free(matching);
    curses_update_status(NULL); /* clear the help message */
    return result;
}