image_contents_t *diskcontents_block_read(vdrive_t *vdrive) { image_contents_t *contents; BYTE buffer[256]; int retval; image_contents_file_list_t *lp; machine_drive_flush(); if (vdrive == NULL) return NULL; retval = vdrive_bam_read_bam(vdrive); if (retval < 0) { vdrive_internal_close_disk_image(vdrive); return NULL; } contents = image_contents_new(); memcpy(contents->name, vdrive->bam + vdrive->bam_name, IMAGE_CONTENTS_NAME_LEN); contents->name[IMAGE_CONTENTS_NAME_LEN] = 0; memcpy(contents->id, vdrive->bam + vdrive->bam_id, IMAGE_CONTENTS_ID_LEN); contents->id[IMAGE_CONTENTS_ID_LEN] = 0; contents->blocks_free = (int)vdrive_bam_free_block_count(vdrive); vdrive->Curr_track = vdrive->Dir_Track; vdrive->Curr_sector = vdrive->Dir_Sector; lp = NULL; contents->file_list = NULL; circular_check_init(); while (1) { BYTE *p; int j; retval = vdrive_read_sector(vdrive, buffer, vdrive->Curr_track, vdrive->Curr_sector); if (retval != 0 || circular_check(vdrive->Curr_track, vdrive->Curr_sector)) { /*image_contents_destroy(contents);*/ vdrive_internal_close_disk_image(vdrive); circular_check_free(); return contents/*NULL*/; } for (p = buffer, j = 0; j < 8; j++, p += 32) if (p[SLOT_TYPE_OFFSET] != 0) { image_contents_file_list_t *new_list; int i; new_list = lib_malloc(sizeof(image_contents_file_list_t)); new_list->size = ((int)p[SLOT_NR_BLOCKS] + ((int)p[SLOT_NR_BLOCKS + 1] << 8)); for (i = 0; i < IMAGE_CONTENTS_FILE_NAME_LEN; i++) new_list->name[i] = p[SLOT_NAME_OFFSET + i]; new_list->name[IMAGE_CONTENTS_FILE_NAME_LEN] = 0; new_list->name[i] = 0; sprintf((char *)new_list->type, "%c%s%c", (p[SLOT_TYPE_OFFSET] & CBMDOS_FT_CLOSED ? ' ' : '*'), cbmdos_filetype_get(p[SLOT_TYPE_OFFSET] & 0x07), (p[SLOT_TYPE_OFFSET] & CBMDOS_FT_LOCKED ? '<' : ' ')); new_list->next = NULL; if (lp == NULL) { new_list->prev = NULL; contents->file_list = new_list; lp = contents->file_list; } else { new_list->prev = lp; lp->next = new_list; lp = new_list; } } if (buffer[0] == 0) break; vdrive->Curr_track = (int)buffer[0]; vdrive->Curr_sector = (int)buffer[1]; } vdrive_internal_close_disk_image(vdrive); circular_check_free(); return contents; }
void mlrate(double mean, FILE *fdiag) { double maxchange; /* The max change of one turn. */ size_t pcount, gcount, rcount; /* Player, game, and removed counters. */ size_t wcount, lcount; /* Win/loss counters. */ double wsum, lsum; /* Weighted sums. */ size_t globturns = 0; /* Counts the turns of the outer loop. */ size_t hcount[10]; /* Handicap game counters. */ player_t p; /* A player. */ piter_t piter; /* An iterator over players. */ char *pflags; assert(0.0 < mean && mean < RANK_MAXIMUM); pflags = (char *)malloc(player_count()); if (pflags == NULL) errex("malloc(%lu) failed", player_count()); memset(pflags, 0, player_count()); /* Assign a start rating for every player. */ player_start(&piter); while ((p = player_next(&piter)) != NO_PLAYER) if (!player_get_rated(p) && !player_get_ignore(p)) { player_set_rank(p, mean); player_set_rated(p, 1); } /* Remove players with no wins or no losses against other rated ** players; then again and again, until no more can be removed. ** While we're at it, count some statistics as well. */ do { pcount = gcount = rcount = 0; hcount[0] = hcount[1] = hcount[2] = hcount[3] = hcount[4] = hcount[5] = hcount[6] = hcount[7] = hcount[8] = hcount[9] = 0; player_start(&piter); while ((p = player_next(&piter)) != NO_PLAYER) if (player_get_rated(p) && !player_get_ignore(p)) { game_t g; giter_t giter; unsigned oppcount = 0; wcount = lcount = 0; wsum = lsum = 0.0; player_games_start(p, &giter); while ((g = player_games_next(&giter)) != NO_GAME) if (game_weight(g) > 0.0) { double a = game_advantage(g); if (a >= 10.0) hcount[0] += 1; else if (a >= 1.0) hcount[(unsigned)floor(a)] += 1; if (p == game_winner(g) && player_get_rated(game_loser(g))) { wcount += 1; wsum += game_weight(g); if (!pflags[game_loser(g)]) { pflags[game_loser(g)] = 1; oppcount += 1; } } else if (p == game_loser(g) && player_get_rated(game_winner(g))) { lcount += 1; lsum += game_weight(g); if (!pflags[game_winner(g)]) { pflags[game_winner(g)] = 1; oppcount += 1; } } else game_set_weight(g, 0.0); } else game_set_weight(g, 0.0); if (wsum < 0.25 || lsum < 0.25 || oppcount < 3) { player_set_rated(p, 0); rcount += 1; } else { pcount += 1; gcount += wcount + lcount; } player_set_ratedgames(p, wcount, lcount); player_set_wratedgames(p, wsum, lsum); /* Clear flags. */ player_games_start(p, &giter); while ((g = player_games_next(&giter)) != NO_GAME) pflags[game_loser(g)] = pflags[game_winner(g)] = 0; } } while (rcount > 0); player_gc_games(); if (fdiag) { int i; fprintf(fdiag, "\nRemaining:\n%6lu players\n%6lu games\n\n", (unsigned long)pcount, (unsigned long)gcount/2); for (i = 1 ; i <= 9 ; i++) fprintf(fdiag, "Advantage %2d: %5lu games\n", i, (unsigned long)hcount[i]); fprintf(fdiag, "Advantage >=10: %5lu games\n\n", (unsigned long)hcount[0]); } if (pcount == 0 || gcount == 0) errex("No player or no games"); /* ** The outer loop. */ do { /* while (maxchange > CHANGE_LIMIT && globturns < GLOBAL_TURNS_MAX); */ int maxp = 0; pcount = 0; maxchange = 0.0; globturns += 1; /* ** Loop over all players. */ player_start(&piter); while ((p = player_next(&piter)) != NO_PLAYER) { /* ** We use bisection to find the root of the derivative (the maximum). */ irank_t r, oldrank; irank_t ileft = RANK_MINIMUM, iright = RANK_MAXIMUM; if (!player_get_rated(p) || player_get_ignore(p)) continue; /* ** Inner (bisection) loop. */ pcount += 1; r = oldrank = player_get_rank(p); do { /* while (iright - ileft > CLOSE_ENOUGH); */ game_t g; double sum = 0.0; giter_t giter; player_games_start(p, &giter); while ((g = player_games_next(&giter)) != NO_GAME) { player_t opp; double diff; if (p == game_winner(g)) { opp = game_loser(g); if (player_get_rated(opp)) { diff = RANK_DIFF(r, player_get_rank(opp)) + game_advantage(g); sum += dP(diff, 1) * game_weight(g); } } else { opp = game_winner(g); if (player_get_rated(opp)) { diff = RANK_DIFF(r, player_get_rank(opp)) - game_advantage(g); sum += dP(diff, 0) * game_weight(g); } } } if (sum > 0.0) iright = r; /* Root's somewhere to the left. */ else ileft = r; /* Root's somewhere to the right. */ r = (iright + ileft)/2; } while (iright - ileft > CLOSE_ENOUGH); if (r > oldrank) { if (r - oldrank > maxchange) { maxchange = r - oldrank; maxp = p; } } else { if (oldrank - r > maxchange) { maxchange = oldrank - r; maxp = p; } } player_set_rank(p, r); } /* while ((p = player_next())) */ #ifdef MAXP fprintf(stderr, "\n--- Maxp: %s rank=%g ww=%g wl=%g w=%u l=%u rg=%u\n", player_get_name(maxp), player_get_rank(maxp), player_get_wwins(maxp), player_get_wlosses(maxp), player_get_wins(maxp), player_get_losses(maxp), player_get_ratedgames(maxp)); #endif if (globturns > 100) circular_check(maxp); if (fdiag) { fprintf(fdiag, " %3lu: %6.3f", (unsigned long)globturns, maxchange); if (globturns % 5) fflush(fdiag); else fputc('\n', fdiag); } } while (maxchange > CHANGE_LIMIT && globturns < GLOBAL_TURNS_MAX); if (fdiag) { if (globturns % 5) fputc('\n', fdiag); fputc('\n', fdiag); } if (globturns == GLOBAL_TURNS_MAX) errex("Aborted after maximum %u turns\n", GLOBAL_TURNS_MAX); if (pflags != NULL) free(pflags); }