Example #1
0
static void
topten(void)
{
	int uid = getuid();
	int rank, rank0 = -1, rank1 = 0;
	int occ_cnt = PERSMAX;
	struct toptenentry *t0, *t1, *tprev;
	const char *recfile = RECORD;
	const char *reclock = "record_lock";
	int sleepct = 300;
	FILE *rfile;
	int flg = 0;
#define	HUP	if(!done_hup)
	while(link(recfile, reclock) == -1) {
		HUP perror(reclock);
		if(!sleepct--) {
			HUP puts("I give up. Sorry.");
			HUP puts("Perhaps there is an old record_lock around?");
			return;
		}
		HUP printf("Waiting for access to record file. (%d)\n",
			sleepct);
		HUP fflush(stdout);
		sleep(1);
	}
	if(!(rfile = fopen(recfile,"r"))){
		HUP puts("Cannot open record file!");
		goto unlock;
	}
	HUP putchar('\n');

	/* create a new 'topten' entry */
	t0 = newttentry();
	t0->level = dlevel;
	t0->maxlvl = maxdlevel;
	t0->hp = u.uhp;
	t0->maxhp = u.uhpmax;
	t0->points = u.urexp;
	t0->plchar = pl_character[0];
	t0->sex = (flags.female ? 'F' : 'M');
	t0->uid = uid;
	strncpy(t0->name, plname, NAMSZ);
	(t0->name)[NAMSZ] = 0;
	strncpy(t0->death, killer, DTHSZ);
	(t0->death)[DTHSZ] = 0;
	strcpy(t0->date, getdate());

	/* assure minimum number of points */
	if(t0->points < POINTSMIN)
		t0->points = 0;

	t1 = tt_head = newttentry();
	tprev = 0;
	/* rank0: -1 undefined, 0 not_on_list, n n_th on list */
	for(rank = 1; ; ) {
	  if(fscanf(rfile, "%6s %d %d %d %d %d %ld %c%c %[^,],%[^\n]",
		t1->date, &t1->uid,
		&t1->level, &t1->maxlvl,
		&t1->hp, &t1->maxhp, &t1->points,
		&t1->plchar, &t1->sex, t1->name, t1->death) != 11
	  || t1->points < POINTSMIN)
			t1->points = 0;
	  if(rank0 < 0 && t1->points < t0->points) {
		rank0 = rank++;
		if(tprev == 0)
			tt_head = t0;
		else
			tprev->tt_next = t0;
		t0->tt_next = t1;
		occ_cnt--;
		flg++;		/* ask for a rewrite */
	  } else
		tprev = t1;
	  if(t1->points == 0) break;
	  if(
#ifdef PERS_IS_UID
	     t1->uid == t0->uid &&
#else
	     strncmp(t1->name, t0->name, NAMSZ) == 0 &&
#endif /* PERS_IS_UID */
	     t1->plchar == t0->plchar && --occ_cnt <= 0){
		if(rank0 < 0){
			rank0 = 0;
			rank1 = rank;
	HUP printf("You didn't beat your previous score of %ld points.\n\n",
				t1->points);
		}
		if(occ_cnt < 0){
			flg++;
			continue;
		}
	  }
	  if(rank <= ENTRYMAX){
	  	t1 = t1->tt_next = newttentry();
	  	rank++;
	  }
	  if(rank > ENTRYMAX){
		t1->points = 0;
		break;
	  }
	}
	if(flg) {	/* rewrite record file */
		fclose(rfile);
		if(!(rfile = fopen(recfile,"w"))){
			HUP puts("Cannot write record file\n");
			goto unlock;
		}

		if(!done_stopprint) if(rank0 > 0){
		    if(rank0 <= 10)
			puts("You made the top ten list!\n");
		    else
		printf("You reached the %d%s place on the top %d list.\n\n",
			rank0, ordin(rank0), ENTRYMAX);
		}
	}
	if(rank0 == 0) rank0 = rank1;
	if(rank0 <= 0) rank0 = rank;
	if(!done_stopprint) outheader();
	t1 = tt_head;
	for(rank = 1; t1->points != 0; rank++, t1 = t1->tt_next) {
	  if(flg) fprintf(rfile,"%6s %d %d %d %d %d %ld %c%c %s,%s\n",
	    t1->date, t1->uid,
	    t1->level, t1->maxlvl,
	    t1->hp, t1->maxhp, t1->points,
	    t1->plchar, t1->sex, t1->name, t1->death);
	  if(done_stopprint) continue;
	  if(rank > (int)flags.end_top &&
	    (rank < rank0-(int)flags.end_around || rank > rank0+(int)flags.end_around)
	    && (!flags.end_own ||
#ifdef PERS_IS_UID
				  t1->uid != t0->uid ))
#else
				  strncmp(t1->name, t0->name, NAMSZ)))
#endif /* PERS_IS_UID */
	  	continue;
	  if(rank == rank0-(int)flags.end_around &&
	     rank0 > (int)flags.end_top+(int)flags.end_around+1 &&
	     !flags.end_own)
		putchar('\n');
	  if(rank != rank0)
		outentry(rank, t1, 0);
	  else if(!rank1)
		outentry(rank, t1, 1);
	  else {
		int t0lth = outentry(0, t0, -1);
		int t1lth = outentry(rank, t1, t0lth);
		if(t1lth > t0lth) t0lth = t1lth;
		outentry(0, t0, t0lth);
	  }
	}
	if(rank0 >= rank) if(!done_stopprint)
		outentry(0, t0, 1);
	fclose(rfile);
unlock:
	unlink(reclock);
}
Example #2
0
struct nh_topten_entry *
nh_get_topten(int *out_len, char *statusbuf,
              const char * volatile player, int top,
              int around, boolean own)
{
    struct toptenentry *ttlist, newtt;
    struct nh_topten_entry *score_list;
    boolean game_inited = (wiz1_level.dlevel != 0);
    boolean game_complete = game_inited && moves && program_state.gameover;
    int rank = -1;      /* index of the completed game in the topten list */
    int fd, i, j, sel_count;
    boolean *selected, off_list = FALSE;

    statusbuf[0] = '\0';
    *out_len = 0;

    if (!api_entry_checkpoint())
        return NULL;

    if (!game_inited) {
        /* If nh_get_topten() isn't called after a game, we never went through
           initialization. */
        dlb_init();
        init_dungeons();
    }

    if (!player) {
        if (game_complete)
            player = plname;
        else
            player = "";
    }

    fd = open_datafile(RECORD, O_RDONLY, SCOREPREFIX);
    ttlist = read_topten(fd, TTLISTLEN);
    close(fd);
    if (!ttlist) {
        strcpy(statusbuf, "Cannot open record file!");
        api_exit();
        return NULL;
    }

    /* find the rank of a completed game in the score list */
    if (game_complete && !strcmp(player, plname)) {
        fill_topten_entry(&newtt, end_how);

        /* find this entry in the list */
        for (i = 0; i < TTLISTLEN && validentry(ttlist[i]); i++)
            if (!memcmp(&ttlist[i], &newtt, sizeof (struct toptenentry)))
                rank = i;

        if (wizard || discover)
            sprintf(statusbuf,
                    "Since you were in %s mode, your game was not "
                    "added to the score list.", wizard ? "wizard" : "discover");
        else if (rank >= 0 && rank < 10)
            sprintf(statusbuf, "You made the top ten list!");
        else if (rank)
            sprintf(statusbuf, "You reached the %d%s place on the score list.",
                    rank + 1, ordin(rank + 1));
    }

    /* select scores for display */
    sel_count = 0;
    selected = calloc(TTLISTLEN, sizeof (boolean));

    for (i = 0; i < TTLISTLEN && validentry(ttlist[i]); i++) {
        if (top == -1 || i < top)
            selected[i] = TRUE;

        if (own && !strcmp(player, ttlist[i].name))
            selected[i] = TRUE;

        if (rank != -1 && rank - around <= i && i <= rank + around)
            selected[i] = TRUE;

        if (selected[i])
            sel_count++;
    }

    if (game_complete && sel_count == 0) {
        /* didn't make it onto the list and nothing else is selected */
        ttlist[0] = newtt;
        selected[0] = TRUE;
        sel_count++;
        off_list = TRUE;
    }


    score_list = xmalloc(sel_count * sizeof (struct nh_topten_entry));
    memset(score_list, 0, sel_count * sizeof (struct nh_topten_entry));
    *out_len = sel_count;
    j = 0;
    for (i = 0; i < TTLISTLEN && validentry(ttlist[i]); i++) {
        if (selected[i])
            fill_nh_score_entry(&ttlist[i], &score_list[j++], i + 1, i == rank);
    }

    if (off_list) {
        score_list[0].rank = -1;
        score_list[0].highlight = TRUE;
    }

    if (!game_inited) {
        free_dungeon();
        dlb_cleanup();
    }

    free(selected);
    free(ttlist);

    api_exit();
    return score_list;
}