// @calloc2:test_calloc2_3 => [Votre fonction calloc ne prend pas en compte le fait que malloc puisse échouer.] void test_calloc2_3(void) { let_malloc_fail = 1; //On indique qu'on veut que malloc utilisé par calloc2 échoue // Pour plus de détails sur le fonctionnement des signaux et l'interception des segfaults, // voir mini-projet-string/tests.c if (signal(SIGSEGV, sig_handler) == SIG_ERR) { CU_FAIL("Impossible d'enregistrer un signal handler."); return; } if(setjmp(label_test_calloc2_3)==0) { calloc2(42, 42); } else if { /* IMPORTANT ! On remet let_malloc_fail à 0 pour que CUnit puisse réutiliser malloc par la suite. * Ici, si on ne pense pas à remettre cette variable à 0, CUnit ne prend pas en compte l'échec du test. */ let_malloc_fail = 0; CU_ASSERT_TRUE(0); } /* IMPORTANT ! On remet let_malloc_fail à 0 pour que CUnit puisse réutiliser malloc par la suite. */ let_malloc_fail = 0; signal(SIGSEGV, SIG_DFL); }
/* Allocate the receive queue, and create the slave and proxy threads. * max_buf_size and the merge-related fields of default_sstate must * already be initialized. */ void protocol_init(char *slave_port, char *proxy_port, int max_slaves) { start_time = time_now(); queue_max_length = max_slaves * MAX_GENMOVES_PER_SLAVE; receive_queue = calloc2(queue_max_length, sizeof(*receive_queue)); default_sstate.slave_sock = port_listen(slave_port, max_slaves); default_sstate.last_processed = -1; for (int n = 0; n < BUFFERS_PER_SLAVE; n++) { default_sstate.b[n].queue_index = -1; } pthread_t thread; for (int id = 0; id < max_slaves; id++) { pthread_create(&thread, NULL, slave_thread, (void *)(long)id); } if (proxy_port) { int proxy_sock = port_listen(proxy_port, max_slaves); for (int id = 0; id < max_slaves; id++) { pthread_create(&thread, NULL, proxy_thread, (void *)(long)proxy_sock); } } }
struct engine * engine_proof_init(char *arg, struct board *b) { struct engine *e = calloc2(1, sizeof(struct engine)); e->name = "proof"; e->comment = "Proof that we can make an engine"; e->genmove = proof_genmove; return e; }
void prob_dict_init(char *filename, pattern_config_t *pc) { assert(!prob_dict); if (!filename) filename = "patterns_mm.gamma"; FILE *f = fopen_data_file(filename, "r"); if (!f) { if (DEBUGL(1)) fprintf(stderr, "%s not found, will not use mm patterns.\n", filename); return; } prob_dict = calloc2(1, prob_dict_t); prob_dict->table = calloc2(spat_dict->nspatials + 1, pattern_prob_t*); int i = 0; char sbuf[1024]; while (fgets(sbuf, sizeof(sbuf), f)) { pattern_prob_t *pb = calloc2(1, pattern_prob_t); //int c, o; char *buf = sbuf; if (buf[0] == '#') continue; while (isspace(*buf)) buf++; float gamma = strtof(buf, &buf); pb->gamma = gamma; while (isspace(*buf)) buf++; str2pattern(buf, &pb->p); assert(pb->p.n == 1); /* One gamma per feature, please ! */ uint32_t spi = feature2spatial(pc, &pb->p.f[0]); assert(spi <= spat_dict->nspatials); /* Bad patterns.spat / patterns.prob ? */ if (feature_has_gamma(pc, &pb->p.f[0])) die("%s: multiple gammas for feature %s\n", filename, pattern2sstr(&pb->p)); pb->next = prob_dict->table[spi]; prob_dict->table[spi] = pb; i++; } fclose(f); if (DEBUGL(1)) fprintf(stderr, "Loaded %d gammas.\n", i); }
struct engine * engine_replay_init(char *arg, struct board *b) { struct replay *r = replay_state_init(arg, b); struct engine *e = calloc2(1, sizeof(struct engine)); e->name = "PlayoutReplay"; e->comment = "I select moves blindly according to playout policy. I won't pass as long as there is a place on the board where I can play. When we both pass, I will consider all the stones on the board alive."; e->genmove = replay_genmove; e->data = r; return e; }
struct engine * engine_random_init(char *arg, struct board *b) { struct engine *e = calloc2(1, sizeof(struct engine)); e->name = "RandomMove"; e->comment = "I just make random moves. I won't pass as long as there is a place on the board where I can play. When we both pass, I will consider all the stones on the board alive."; e->genmove = random_genmove; if (arg) fprintf(stderr, "Random: I support no engine arguments\n"); return e; }
// @calloc2:test_calloc2_2 => [Votre fonction calloc n'a pas initialisé la mémoire allouée à 0.] void test_calloc2_2(void) { void *ptr = calloc2(42, 1); if (ptr == NULL) { CU_FAIL("Erreur lors l'allocation de la mémoire."); return; } for(unsigned char i=0; i < 42; i++) { CU_ASSERT_EQUAL(*(char*)(ptr+i), 0); } free(ptr); }
// @calloc2:test_calloc2_1 => [Votre fonction calloc n'utilise pas malloc.] void test_calloc2_1(void) { nb_times_malloc_used = 0; //On remet la variable à 0 car CUnit a lui-même utilisé malloc void *ptr = calloc2(13, 37); if (ptr == NULL) { CU_FAIL("Erreur lors l'allocation de la mémoire."); return; } // nb_times_malloc_used sera incrémenté par le malloc modifié de mymalloc.c CU_ASSERT_EQUAL(nb_times_malloc_used, 1); free(ptr); }
struct replay * replay_state_init(char *arg, struct board *b) { struct replay *r = calloc2(1, sizeof(struct replay)); r->debug_level = 1; if (arg) { char *optspec, *next = arg; while (*next) { optspec = next; next += strcspn(next, ","); if (*next) { *next++ = 0; } else { *next = 0; } char *optname = optspec; char *optval = strchr(optspec, '='); if (optval) *optval++ = 0; if (!strcasecmp(optname, "debug")) { if (optval) r->debug_level = atoi(optval); else r->debug_level++; } else if (!strcasecmp(optname, "playout") && optval) { char *playoutarg = strchr(optval, ':'); if (playoutarg) *playoutarg++ = 0; if (!strcasecmp(optval, "moggy")) { r->playout = playout_moggy_init(playoutarg, b, joseki_load(b->size)); } else if (!strcasecmp(optval, "light")) { r->playout = playout_light_init(playoutarg, b); } else { fprintf(stderr, "Replay: Invalid playout policy %s\n", optval); } } else { fprintf(stderr, "Replay: Invalid engine argument %s or missing value\n", optname); } } } if (!r->playout) r->playout = playout_light_init(NULL, b); r->playout->debug_level = r->debug_level; return r; }
char * npalloc(unsigned size) { char * ptr; #ifdef UCOS_II INT8U err; #endif #ifdef UCOS_II OSSemPend(mheap_sem_ptr, 0, &err); if(err) { int errct = 0; /* sometimes we get a "timeout" error even though we passed a zero * to indicate we'll wait forever. When this happens, try again: */ while(err == 10) { if(errct++ > 1000) { panic("npalloc"); /* fatal? */ return NULL; } OSSemPend(mheap_sem_ptr, 0, &err); } } #endif #ifdef MEM_WRAPPERS ptr = wrap_alloc(size, calloc2); #else ptr = calloc2(size); #endif #ifdef UCOS_II err = OSSemPost(mheap_sem_ptr); #endif if(!ptr) return NULL; MEMSET(ptr, 0, size); return ptr; }
struct uct_dynkomi * uct_dynkomi_init_none(struct uct *u, char *arg, struct board *b) { struct uct_dynkomi *d = calloc2(1, sizeof(*d)); d->uct = u; d->permove = NULL; d->persim = NULL; d->done = generic_done; d->data = NULL; if (arg) { fprintf(stderr, "uct: Dynkomi method none accepts no arguments\n"); exit(1); } return d; }
void test (void) { char *p; p = malloc0 (6); strcpy (p, "Hello"); p = malloc1 (6); strcpy (p, "Hello"); strcpy (p, "Hello World"); /* { dg-warning "will always overflow" "strcpy" } */ p = malloc2 (__INT_MAX__ >= 1700000 ? 424242 : __INT_MAX__ / 4, 6); strcpy (p, "World"); strcpy (p, "Hello World"); /* { dg-warning "will always overflow" "strcpy" } */ p = calloc1 (2, 5); strcpy (p, "World"); strcpy (p, "Hello World"); /* { dg-warning "will always overflow" "strcpy" } */ p = calloc2 (2, __INT_MAX__ >= 1700000 ? 424242 : __INT_MAX__ / 4, 5); strcpy (p, "World"); strcpy (p, "Hello World"); /* { dg-warning "will always overflow" "strcpy" } */ }
static coord_t * montecarlo_genmove(struct engine *e, struct board *b, struct time_info *ti, enum stone color, bool pass_all_alive) { struct montecarlo *mc = e->data; if (ti->dim == TD_WALLTIME) { fprintf(stderr, "Warning: TD_WALLTIME time mode not supported, resetting to defaults.\n"); ti->period = TT_NULL; } if (ti->period == TT_NULL) { ti->period = TT_MOVE; ti->dim = TD_GAMES; ti->len.games = MC_GAMES; } struct time_stop stop; time_stop_conditions(ti, b, 20, 40, 3.0, &stop); /* resign when the hope for win vanishes */ coord_t top_coord = resign; floating_t top_ratio = mc->resign_ratio; /* We use [0] for pass. Normally, this is an inaccessible corner * of board margin. */ struct move_stat moves[board_size2(b)]; memset(moves, 0, sizeof(moves)); int losses = 0; int i, superko = 0, good_games = 0; for (i = 0; i < stop.desired.playouts; i++) { assert(!b->superko_violation); struct board b2; board_copy(&b2, b); coord_t coord; board_play_random(&b2, color, &coord, NULL, NULL); if (!is_pass(coord) && !group_at(&b2, coord)) { /* Multi-stone suicide. We play chinese rules, * so we can't consider this. (Note that we * unfortunately still consider this in playouts.) */ if (DEBUGL(4)) { fprintf(stderr, "SUICIDE DETECTED at %d,%d:\n", coord_x(coord, b), coord_y(coord, b)); board_print(b, stderr); } continue; } if (DEBUGL(3)) fprintf(stderr, "[%d,%d color %d] playing random game\n", coord_x(coord, b), coord_y(coord, b), color); struct playout_setup ps = { .gamelen = mc->gamelen }; int result = play_random_game(&ps, &b2, color, NULL, NULL, mc->playout); board_done_noalloc(&b2); if (result == 0) { /* Superko. We just ignore this playout. * And play again. */ if (unlikely(superko > 2 * stop.desired.playouts)) { /* Uhh. Triple ko, or something? */ if (MCDEBUGL(0)) fprintf(stderr, "SUPERKO LOOP. I will pass. Did we hit triple ko?\n"); goto pass_wins; } /* This playout didn't count; we should not * disadvantage moves that lead to a superko. * And it is supposed to be rare. */ i--, superko++; continue; } if (MCDEBUGL(3)) fprintf(stderr, "\tresult for other player: %d\n", result); int pos = is_pass(coord) ? 0 : coord; good_games++; moves[pos].games++; losses += result > 0; moves[pos].wins += 1 - (result > 0); if (unlikely(!losses && i == mc->loss_threshold)) { /* We played out many games and didn't lose once yet. * This game is over. */ break; } } if (!good_games) { /* No moves to try??? */ if (MCDEBUGL(0)) { fprintf(stderr, "OUT OF MOVES! I will pass. But how did this happen?\n"); board_print(b, stderr); } pass_wins: top_coord = pass; top_ratio = 0.5; goto move_found; } foreach_point(b) { if (b->moves < 3) { /* Simple heuristic: avoid opening too low. Do not * play on second or first line as first white or * first two black moves.*/ if (coord_x(c, b) < 3 || coord_x(c, b) > board_size(b) - 4 || coord_y(c, b) < 3 || coord_y(c, b) > board_size(b) - 4) continue; } floating_t ratio = (floating_t) moves[c].wins / moves[c].games; /* Since pass is [0,0], we will pass only when we have nothing * better to do. */ if (ratio >= top_ratio) { top_ratio = ratio; top_coord = c == 0 ? pass : c; } } foreach_point_end; if (MCDEBUGL(2)) { board_stats_print(b, moves, stderr); } move_found: if (MCDEBUGL(1)) fprintf(stderr, "*** WINNER is %d,%d with score %1.4f (%d games, %d superko)\n", coord_x(top_coord, b), coord_y(top_coord, b), top_ratio, i, superko); return coord_copy(top_coord); } static void montecarlo_done(struct engine *e) { struct montecarlo *mc = e->data; playout_policy_done(mc->playout); joseki_done(mc->jdict); } struct montecarlo * montecarlo_state_init(char *arg, struct board *b) { struct montecarlo *mc = calloc2(1, sizeof(struct montecarlo)); mc->debug_level = 1; mc->gamelen = MC_GAMELEN; mc->jdict = joseki_load(b->size); if (arg) { char *optspec, *next = arg; while (*next) { optspec = next; next += strcspn(next, ","); if (*next) { *next++ = 0; } else { *next = 0; } char *optname = optspec; char *optval = strchr(optspec, '='); if (optval) *optval++ = 0; if (!strcasecmp(optname, "debug")) { if (optval) mc->debug_level = atoi(optval); else mc->debug_level++; } else if (!strcasecmp(optname, "gamelen") && optval) { mc->gamelen = atoi(optval); } else if (!strcasecmp(optname, "playout") && optval) { char *playoutarg = strchr(optval, ':'); if (playoutarg) *playoutarg++ = 0; if (!strcasecmp(optval, "moggy")) { mc->playout = playout_moggy_init(playoutarg, b, mc->jdict); } else if (!strcasecmp(optval, "light")) { mc->playout = playout_light_init(playoutarg, b); } else { fprintf(stderr, "MonteCarlo: Invalid playout policy %s\n", optval); } } else { fprintf(stderr, "MonteCarlo: Invalid engine argument %s or missing value\n", optname); } } } if (!mc->playout) mc->playout = playout_light_init(NULL, b); mc->playout->debug_level = mc->debug_level; mc->resign_ratio = 0.1; /* Resign when most games are lost. */ mc->loss_threshold = 5000; /* Stop reading if no loss encountered in first 5000 games. */ return mc; } struct engine * engine_montecarlo_init(char *arg, struct board *b) { struct montecarlo *mc = montecarlo_state_init(arg, b); struct engine *e = calloc2(1, sizeof(struct engine)); e->name = "MonteCarlo"; e->comment = "I'm playing in Monte Carlo. When we both pass, I will consider all the stones on the board alive. If you are reading this, write 'yes'. Please bear with me at the game end, I need to fill the whole board; if you help me, we will both be happier. Filling the board will not lose points (NZ rules)."; e->genmove = montecarlo_genmove; e->done = montecarlo_done; e->data = mc; return e; }
struct uct_dynkomi * uct_dynkomi_init_adaptive(struct uct *u, char *arg, struct board *b) { struct uct_dynkomi *d = calloc2(1, sizeof(*d)); d->uct = u; d->permove = adaptive_permove; d->persim = adaptive_persim; d->done = generic_done; struct dynkomi_adaptive *a = calloc2(1, sizeof(*a)); d->data = a; a->lead_moves = board_large(b) ? 20 : 4; // XXX a->max_losing_komi = 30; a->losing_komi_stop = 1.0f; a->no_komi_at_game_end = true; a->indicator = komi_by_value; a->adapter = adapter_sigmoid; a->adapt_rate = -18; a->adapt_phase = 0.65; a->adapt_moves = 200; a->adapt_dir = -0.5; a->zone_red = 0.45; a->zone_green = 0.50; a->score_step = 1; a->use_komi_ratchet = true; a->komi_ratchet_maxage = 0; a->komi_ratchet = 1000; if (arg) { char *optspec, *next = arg; while (*next) { optspec = next; next += strcspn(next, ":"); if (*next) { *next++ = 0; } else { *next = 0; } char *optname = optspec; char *optval = strchr(optspec, '='); if (optval) *optval++ = 0; if (!strcasecmp(optname, "lead_moves") && optval) { /* Do not adjust komi adaptively for first * N moves. */ a->lead_moves = atoi(optval); } else if (!strcasecmp(optname, "max_losing_komi") && optval) { a->max_losing_komi = atof(optval); } else if (!strcasecmp(optname, "losing_komi_stop") && optval) { a->losing_komi_stop = atof(optval); } else if (!strcasecmp(optname, "no_komi_at_game_end")) { a->no_komi_at_game_end = !optval || atoi(optval); } else if (!strcasecmp(optname, "indicator")) { /* Adaptatation indicator - how to decide * the adaptation rate and direction. */ if (!strcasecmp(optval, "value")) { /* Winrate w/ komi so far. */ a->indicator = komi_by_value; } else if (!strcasecmp(optval, "score")) { /* Expected score w/ current komi. */ a->indicator = komi_by_score; } else { fprintf(stderr, "UCT: Invalid indicator %s\n", optval); exit(1); } /* value indicator settings */ } else if (!strcasecmp(optname, "zone_red") && optval) { a->zone_red = atof(optval); } else if (!strcasecmp(optname, "zone_green") && optval) { a->zone_green = atof(optval); } else if (!strcasecmp(optname, "score_step") && optval) { a->score_step = atoi(optval); } else if (!strcasecmp(optname, "score_step_byavg") && optval) { a->score_step_byavg = atof(optval); } else if (!strcasecmp(optname, "use_komi_ratchet")) { a->use_komi_ratchet = !optval || atoi(optval); } else if (!strcasecmp(optname, "losing_komi_ratchet")) { a->losing_komi_ratchet = !optval || atoi(optval); } else if (!strcasecmp(optname, "komi_ratchet_age") && optval) { a->komi_ratchet_maxage = atoi(optval); /* score indicator settings */ } else if (!strcasecmp(optname, "adapter") && optval) { /* Adaptatation method. */ if (!strcasecmp(optval, "sigmoid")) { a->adapter = adapter_sigmoid; } else if (!strcasecmp(optval, "linear")) { a->adapter = adapter_linear; } else { fprintf(stderr, "UCT: Invalid adapter %s\n", optval); exit(1); } } else if (!strcasecmp(optname, "adapt_base") && optval) { /* Adaptation base rate; see above. */ a->adapt_base = atof(optval); } else if (!strcasecmp(optname, "adapt_rate") && optval) { /* Adaptation slope; see above. */ a->adapt_rate = atof(optval); } else if (!strcasecmp(optname, "adapt_phase") && optval) { /* Adaptation phase shift; see above. */ a->adapt_phase = atof(optval); } else if (!strcasecmp(optname, "adapt_moves") && optval) { /* Adaptation move amount; see above. */ a->adapt_moves = atoi(optval); } else if (!strcasecmp(optname, "adapt_aport")) { a->adapt_aport = !optval || atoi(optval); } else if (!strcasecmp(optname, "adapt_dir") && optval) { /* Adaptation direction vector; see above. */ a->adapt_dir = atof(optval); } else { fprintf(stderr, "uct: Invalid dynkomi argument %s or missing value\n", optname); exit(1); } } } return d; }
struct uct_dynkomi * uct_dynkomi_init_linear(struct uct *u, char *arg, struct board *b) { struct uct_dynkomi *d = calloc2(1, sizeof(*d)); d->uct = u; d->permove = linear_permove; d->persim = linear_persim; d->done = generic_done; struct dynkomi_linear *l = calloc2(1, sizeof(*l)); d->data = l; /* Force white to feel behind and try harder, but not to the * point of resigning immediately in high handicap games. * By move 100 white should still be behind but should have * caught up enough to avoid resigning. */ int moves = board_large(b) ? 100 : 50; if (!board_small(b)) { l->moves[S_BLACK] = moves; l->moves[S_WHITE] = moves; } /* The real value of one stone is twice the komi so about 15 points. * But use a lower value to avoid being too pessimistic as black * or too optimistic as white. */ l->handicap_value[S_BLACK] = 8; l->handicap_value[S_WHITE] = 1; l->komi_ratchet = INFINITY; l->green_zone = 0.85; l->orange_zone = 0.8; l->drop_step = 4.0; if (arg) { char *optspec, *next = arg; while (*next) { optspec = next; next += strcspn(next, ":"); if (*next) { *next++ = 0; } else { *next = 0; } char *optname = optspec; char *optval = strchr(optspec, '='); if (optval) *optval++ = 0; if (!strcasecmp(optname, "moves") && optval) { /* Dynamic komi in handicap game; linearly * decreases to basic settings until move * #optval. moves=blackmoves%whitemoves */ for (int i = S_BLACK; *optval && i <= S_WHITE; i++) { l->moves[i] = atoi(optval); optval += strcspn(optval, "%"); if (*optval) optval++; } } else if (!strcasecmp(optname, "handicap_value") && optval) { /* Point value of single handicap stone, * for dynkomi computation. */ for (int i = S_BLACK; *optval && i <= S_WHITE; i++) { l->handicap_value[i] = atoi(optval); optval += strcspn(optval, "%"); if (*optval) optval++; } } else if (!strcasecmp(optname, "rootbased")) { /* If set, the extra komi applied will be * the same for all simulations within a move, * instead of being same for all simulations * within the tree node. */ l->rootbased = !optval || atoi(optval); } else if (!strcasecmp(optname, "green_zone") && optval) { /* Increase komi when win ratio is above green_zone */ l->green_zone = atof(optval); } else if (!strcasecmp(optname, "orange_zone") && optval) { /* Decrease komi when > 0 and win ratio is below orange_zone */ l->orange_zone = atof(optval); } else if (!strcasecmp(optname, "drop_step") && optval) { /* Decrease komi by drop_step points */ l->drop_step = atof(optval); } else { fprintf(stderr, "uct: Invalid dynkomi argument %s or missing value\n", optname); exit(1); } } } return d; }