boolean nh_exit_game(int exit_type) { boolean log_disabled = iflags.disable_log; if (!api_entry_checkpoint()) { /* not sure anything in here can actually call panic */ iflags.disable_log = log_disabled; return TRUE; /* terminate was called, so exit is successful */ } program_state.forced_exit = TRUE; /* clean up after viewing a game replay */ if (program_state.viewing) nh_view_replay_finish(); xmalloc_cleanup(); iflags.disable_log = TRUE; if (program_state.game_running) { switch (exit_type) { case EXIT_REQUEST_SAVE: dosave(); /* will ask "really save?" and, if 'y', eventually call terminate. */ break; case EXIT_FORCE_SAVE: dosave0(TRUE); terminate(); break; case EXIT_REQUEST_QUIT: done2(); break; case EXIT_FORCE_QUIT: done(QUIT); break; /* not reached */ case EXIT_PANIC: /* freeing things should be safe */ freedynamicdata(); dlb_cleanup(); panic("UI problem."); break; } iflags.disable_log = log_disabled; api_exit(); return FALSE; } iflags.disable_log = log_disabled; /* calling terminate() will get us out of nested contexts safely, eg: * UI_cmdloop -> nh_command -> UI_update_screen (problem happens here) -> nh_exit_game * will jump all the way back to UI_cmdloop */ terminate(); api_exit(); /* not reached */ return TRUE; }
static void ccmd_view_finish(json_t * params) { void *iter; iter = json_object_iter(params); if (iter) exit_client("non-empty parameter list for view_finish"); nh_view_replay_finish(); client_msg("view_finish", json_object()); }
void nhnet_view_replay_finish(void) { if (!nhnet_active()) return nh_view_replay_finish(); xmalloc_cleanup(); alt_windowprocs = windowprocs; if (!api_entry()) return; send_receive_msg("view_finish", json_object()); api_exit(); }
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(); }
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); }