int random_number_in_range (int min, int max) { TRACEINW("(min=%d max=%d)", min, max); int width = max - min + 1; int res = min + (random() % width); TRACEOUTW("%d", res); return res; }
void add_grain_on_random_square (int radius, int seed) { TRACEINW("(radius=%d seed=%d)", radius, seed); srandom(seed); int random_x = random_number_in_range(-radius, radius); int random_y = random_number_in_range(-radius, radius); TRACEMESS("Add 1 grain on (%d,%d)", random_x, random_y); add_grains_on_square(random_x, random_y, 1); TRACEOUT; }
void read_longint_val_in_range (char * s, long int * val, long int range_min, long int range_max, const char * varname) /* varname is used for error messages */ { TRACEINW("(\"%s\",min=%ld,max=%ld)", s, range_min, range_max); char * endptr = NULL; long int res = strtol(s, &endptr, 10); if (*endptr != '\0') { cantcontinue("ERROR: value \"%s\" for %s is not a number.\n", s, varname); } else if (errno == ERANGE) { cantcontinue("ERROR: value \"%s\" for %s cannot be scanned as a long int.\n", s, varname); } else if ((res < range_min) || (res > range_max)) { cantcontinue("ERROR: value %ld for %s not in valid range %ld..%ld.\n", res, varname, range_min, range_max); } val[0] = res; TRACEOUTW("%s=%ld", varname, *val); }
void collapse (int x, int y) { assert (cboard[x*ydim+y] > 3); TRACEINW("(x=%d, y=%d)", x, y); add_grains_on_square (x,y,-4); add_grains_on_square (x+1,y,1); add_grains_on_square (x-1,y,1); add_grains_on_square (x,y+1,1); add_grains_on_square (x,y-1,1); if (nbsteps == ULLONG_MAX) { cantcontinue("ERROR: Max number of steps UINTMAX = %llu reached. I must stop.\n", ULLONG_MAX); } nbsteps++; TRACEOUT; }
void display_the_board (FILE * f, bool withvars) { TRACEINW("(f=%p)", f); TRACESIGNEDMESS ("c0=%d c1=%d c2=%d c3=%d", count0, count1, count2, count3); #ifdef DEBUG_BINARY_BOARD dump_current_memmatrix (stdout); #endif /* DEBUG_BINARY_BOARD */ int x, y; int wid = xmax - xmin + 1; fputc('+', f); fprint_n_char(wid, '-', f); fputc('+', f); fterpri(f); for (y = ymax+1; y-- > ymin;) { /* downward loop :-( */ fputc('|', f); for (x = xmin; x <= xmax; x++) { fputc (char_for_val(cboard[x*ydim+y]), f); } fputc('|', f); fterpri(f); } fputc('+', f); fprint_n_char(wid, '-', f); fputc('+', f); fterpri(f); if (withvars) display_board_vars(f); TRACEOUT; }
/* ADD_GRAINS_ON_SQUARE modifies the board by adding DELTA (can be 0) on X,Y. Maintains counts. No collapse. New val ≥ 4 are stacked in waiting list (no checking if new val ≠ prev val) Prev val ≥ 4 are assumed to have been unstacked by caller */ void add_grains_on_square (int x, int y, int delta) { TRACEINW("(x=%d, y=%d, delta=%d)", x, y, delta); // dump_waitinglist(stdout, true); if ((x < xmin) || (x > xmax) || (y < ymin) || (y > ymax)) { TRACEMESS ("have to enlarge"); enlarge_envelop_for (x,y); } int * p = cboard + x*ydim + y; int val = *p; assert ((val + delta >= 0) || (val == UNUSEDSQ)); switch (val) {//update count case 0: assert(count0 > 0); count0--; break; case 1: assert(count1 > 0); count1--; break; case 2: assert(count2 > 0); count2--; break; case 3: assert(count3 > 0); count3--; break; case UNUSEDSQ: val=0; area++; break; /* needs real val in later computation */ default: assert(val>3); /* do nothing */ } mass += delta; val += delta; *p = val; switch (val) { case 0: assert(count0 < INT_MAX); count0++; break; case 1: assert(count1 < INT_MAX); count1++; break; case 2: assert(count2 < INT_MAX); count2++; break; case 3: assert(count3 < INT_MAX); count3++; break; default: assert(val>3); /* only stackin when val goes 3->4, 7->8, ... Other options are 5->6, 8->4 etc. */ if ((val%4 == 0) && (delta == 1)) stackin_waiting(x,y); break; } #ifdef TRACE if ((terminal_mode != false) && (anim_level >= 2)) dump_waitinglist(stdout, false); #endif /* TRACE */ TRACEOUT; }
/* #define MAX_STACK_SIZE ((size_t)5*K10) : Crashes for M=6257180 */ #define MAX_STACK_SIZE ((size_t)M1) /* 10^6 */ void alloc_waitlist (size_t nbslots) { TRACEINW("(%zu)", nbslots); // dump_waitinglist (stdout, true); if (nbslots <= waiting_nbslots) { cantcontinue("ERROR: %s(%zu): arg is below current=%zu.\n", __func__, nbslots, waiting_nbslots); } else if (nbslots > MAX_STACK_SIZE) { cantcontinue("ERROR: %s(%zu): arg is largest than max allowed=%zu.\n", __func__, nbslots, MAX_STACK_SIZE); } int delta = (waitlist_inited ? wait_curr - waitinglist : 0); waitinglist = realloc(waitinglist, nbslots * 2 * sizeof(int)); if (errno == ENOMEM) { cantcontinue("ERROR: %s(%zu): alloc failed.\n", __func__, nbslots); /* NB: if realloc fails, old waitinglist has not been free'd */ } assert (waitinglist != NULL); waiting_nbslots = nbslots; wait_max = waitinglist + nbslots*2; wait_curr = waitinglist + delta; // dump_waitinglist (stdout, true); TRACEOUT; }
/* This updates xmin &c. so that (x,y) is contained */ void enlarge_envelop_for (int x, int y) { TRACEINW("(x=%d y=%d)", x, y); bool pushed = false; #ifdef DEBUG_BINARY_BOARD printf ("! memmatrix before enlarging at (%d,%d):\n", x, y); dump_current_memmatrix (stdout); display_the_board (stdout, true); #endif /* DEBUG_BINARY_BOARD */ if (x < xmin) { xmin = x; pushed = true; } else if (x > xmax) { xmax = x; pushed = true; } if (y < ymin) { ymin = y; pushed = true; } else if (y > ymax) { ymax = y; pushed = true; } if (pushed != false) { if (xmax - xmin >= diam) diam = xmax - xmin + 1; if (ymax - ymin >= diam) diam = ymax - ymin + 1; if (diam > max_dim) cantcontinue("Max_dim = %d reached. Am not allowed to enlarge board...\n", max_dim); while ( (x+xdepl < 0) || (x+xdepl >= xdim) || (y+ydepl < 0) || (y+ydepl >= ydim) ) { enlarge_underlying_mat (); /* push xdim, ydim */ } } #ifdef DEBUG_BINARY_BOARD printf ("! memmatrix after enlarging at (%d,%d):\n", x, y); dump_current_memmatrix (stdout); display_the_board (stdout, true); #endif /* DEBUG_BINARY_BOARD */ if (cursing_mode) { display_cursing_dims (); } TRACEOUT; }