std::unordered_set<tripoint> zone_manager::get_near( const zone_type_id &type, const tripoint &where, int range ) const { const auto &point_set = get_point_set( type ); auto near_point_set = std::unordered_set<tripoint>(); for( auto &point : point_set ) { if( point.z == where.z ) { if( square_dist( point, where ) <= range ) { near_point_set.insert( point ); } } } const auto &vzone_set = get_vzone_set( type ); for( auto &point : vzone_set ) { if( point.z == where.z ) { if( square_dist( point, where ) <= range ) { near_point_set.insert( point ); } } } return near_point_set; }
bool map_item_stack::map_item_stack_sort( const map_item_stack &lhs, const map_item_stack &rhs ) { if( lhs.example->get_category() == rhs.example->get_category() ) { return square_dist( tripoint( 0, 0, 0 ), lhs.vIG[0].pos ) < square_dist( tripoint( 0, 0, 0 ), rhs.vIG[0].pos ); } return lhs.example->get_category() < rhs.example->get_category(); }
/* Height filters width and height should be odd numbers (3,5,7...) */ int surface_height::height_get(int cx, int cy, int width, int height, int *p_list_dist, float *p_list_height, bool center) { tpos x,y; tpos dx = width/2, dy = height/2; int values = 0; for(y = cy-dy; y <= cy+dy; y++) { for(x = cx-dx; x <= cx+dx; x++) { if(!pixel_valid(x, y)) { continue; } if(!center && x == cx && y == dy) { continue; } float height_current = height_get(x, y); if(height_current == HEIGHT_UNSET) { continue; } p_list_height[values] = height_current; p_list_dist[values] = square_dist(x, y, cx, cy); values++; } } return(values); }
int main(void) { int i, j, k; double sigma; freopen("score.txt", "r", stdin); setbuf(stdout, NULL); scanf("%d %d", &N, &M); memset(data, 0, sizeof(data)); memset(avg, 0.0f, sizeof(avg)); for (i = 1; i <= N; i++) for (j = 1; j <= M; j++) scanf("%d", &data[i][j]); #if 0 printf("N = %d M = %d\n", N, M); for (i = 1; i <= N; i++) { for (j = 1; j <= M; j++) printf("%d ", data[i][j]); printf("\n"); } #endif for (i = 1; i <= N; i++) printf("%2dth student's average score is %lf\n", i, average_of_student(i)); for (i = 1; i <= M; i++) printf("%2dth class' average score is %lf\n", i, average_of_class(i)); find_highest(); sigma = square_dist(); printf("The square distance of average score is %lf\n", sigma); return 0; }
int rl_dist(int x1, int y1, int x2, int y2) { if(trigdist) { return trig_dist( x1, y1, x2, y2 ); } return square_dist( x1, y1, x2, y2 ); }
int_slist_t* octree_within_radius(octree_t* tree, point_t* point, real_t radius) { return NULL; #if 0 if (tree->root == NULL) return NULL; // Start with the root. octree_node_t* node = tree->root; real_t pos[3]; pos[0] = point->x, pos[1] = point->y, pos[2] = point->z; real_t r2 = square_dist(pos, node->pos); octree_rect_t rect; int_slist_t* results = int_slist_new(); rect.min[0] = tree->rect->min[0]; rect.max[0] = tree->rect->max[0]; rect.min[1] = tree->rect->min[1]; rect.max[1] = tree->rect->max[1]; rect.min[2] = tree->rect->min[2]; rect.max[2] = tree->rect->max[2]; // Search recursively for the closest node. find_within_radius(tree->root, pos, radius, &rect, results); return results; #endif }
int rl_dist(const tripoint loc1, const tripoint loc2) { if(trigdist) { return trig_dist(loc1, loc2); } return square_dist(loc1, loc2); }
int surface_height::height_get_cross(int cx, int cy, int *p_list_dist, float *p_list_height, bool center) { int i; int values = 0; for(i = center ? 0 : 1; i < (int)(sizeof(cross_list)/sizeof(cross_list[0])); i++) { int x = cx+cross_list[i].x, y = cy+cross_list[i].y; if(!pixel_valid(x, y)) { continue; } float height_current = height_get(x, y); if(height_current == HEIGHT_UNSET) { continue; } p_list_height[values] = height_current; p_list_dist[values] = square_dist(x, y, cx, cy); values++; } return(values); }
std::string direction_suffix( const tripoint& p, const tripoint& q ) { int dist = square_dist( p, q ); if ( dist <= 0 ) { return std::string(); } return string_format( "%d%s", dist, trim( direction_name_short( direction_from( p, q ) ) ).c_str() ); }
REAL SegComp::dist ( ModePrim m0, const SegComp & s1, ModePrim m1 ) const { return sqrt(square_dist(m0,s1,m1)); }
//Trying to pull points out of a tripoint vector is messy and //probably slow, so leaving two full functions for now std::vector <point> line_to(const int x1, const int y1, const int x2, const int y2, int t) { std::vector<point> ret; // Preallocate the number of cells we need instead of allocating them piecewise. const int numCells = square_dist(tripoint(x1, y1, 0),tripoint(x2, y2, 0)); ret.reserve(numCells); const int dx = x2 - x1; const int dy = y2 - y1; point cur; cur.x = x1; cur.y = y1; // Draw point if (dx==0 && dy==0) { ret.push_back(cur); // Should exit here return ret; } // Any ideas why we're multiplying the abs distance by two here? const int ax = abs(dx) << 1; // bitshift one place, functional *2 const int ay = abs(dy) << 1; const int sx = (dx == 0 ? 0 : SGN(dx)), sy = (dy == 0 ? 0 : SGN(dy)); // The old version of this algorithm would generate points on the line and check min/max for each point // to determine whether or not to continue generating the line. Since we already know how many points // we need, this method saves us a half-dozen variables and a few calculations. if (ax == ay) { for (int i = 0; i < numCells; i++) { cur.y += sy; cur.x += sx; ret.push_back(cur); } ; } else if (ax > ay) { for (int i = 0; i < numCells; i++) { if (t > 0) { cur.y += sy; t -= ax; } cur.x += sx; t += ay; ret.push_back(cur); } ; } else { for (int i = 0; i < numCells; i++) { if (t > 0) { cur.x += sx; t -= ay; } cur.y += sy; t += ax; ret.push_back(cur); } ; } return ret; }
static int goal_dist(int pos, signed char goal[BOARDMAX]) { int dist = 10000; int ii; for (ii = BOARDMIN; ii < BOARDMAX; ii++) if (ON_BOARD(ii) && goal[ii]) dist = gg_min(dist, square_dist(ii, pos)); return dist; }
bool map::pl_sees( const int tx, const int ty, const int max_range ) { if (!INBOUNDS(tx, ty)) { return false; } if( max_range >= 0 && square_dist( tx, ty, g->u.posx(), g->u.posy() ) > max_range ) { return false; // Out of range! } return seen_cache[tx][ty]; }
bool map::pl_sees( const tripoint &t, const int max_range ) { if( !inbounds( t ) ) { return false; } if( max_range >= 0 && square_dist( t, g->u.pos3() ) > max_range ) { return false; // Out of range! } // TODO: FoV update return seen_cache[t.x][t.y]; }
bool zone_manager::has_near( const zone_type_id &type, const tripoint &where, int range ) const { const auto &point_set = get_point_set( type ); for( auto &point : point_set ) { if( point.z == where.z ) { if( square_dist( point, where ) <= range ) { return true; } } } const auto &vzone_set = get_vzone_set( type ); for( auto &point : vzone_set ) { if( point.z == where.z ) { if( square_dist( point, where ) <= range ) { return true; } } } return false; }
cata::optional<tripoint> zone_manager::get_nearest( const zone_type_id &type, const tripoint &where, int range ) const { if( range < 0 ) { return cata::nullopt; } tripoint nearest_pos = tripoint( INT_MIN, INT_MIN, INT_MIN ); int nearest_dist = range + 1; const std::unordered_set<tripoint> &point_set = get_point_set( type ); for( const tripoint &p : point_set ) { int cur_dist = square_dist( p, where ); if( cur_dist < nearest_dist ) { nearest_dist = cur_dist; nearest_pos = p; if( nearest_dist == 0 ) { return nearest_pos; } } } const std::unordered_set<tripoint> &vzone_set = get_vzone_set( type ); for( const tripoint &p : vzone_set ) { int cur_dist = square_dist( p, where ); if( cur_dist < nearest_dist ) { nearest_dist = cur_dist; nearest_pos = p; if( nearest_dist == 0 ) { return nearest_pos; } } } if( nearest_dist > range ) { return cata::nullopt; } return nearest_pos; }
bool map::pl_line_of_sight( const tripoint &t, const int max_range ) const { if( !inbounds( t ) ) { return false; } if( max_range >= 0 && square_dist( t, g->u.pos() ) > max_range ) { // Out of range! return false; } const auto &map_cache = get_cache_ref( t.z ); // Any epsilon > 0 is fine - it means lightmap processing visited the point return map_cache.seen_cache[t.x][t.y] > 0.0f; }
//Trying to pull points out of a tripoint vector is messy and //probably slow, so leaving two full functions for now std::vector<point> line_to(const int x1, const int y1, const int x2, const int y2, int t) { std::vector<point> line; // Preallocate the number of cells we need instead of allocating them piecewise. const int numCells = square_dist(tripoint(x1, y1, 0), tripoint(x2, y2, 0)); if( numCells == 0 ) { line.push_back( {x1, y1} ); } else { line.reserve(numCells); bresenham( x1, y1, x2, y2, t, [&line]( const point &new_point ) { line.push_back(new_point); return true; } ); } return line; }
bool map::pl_sees( const tripoint &t, const int max_range ) const { if( !inbounds( t ) ) { return false; } if( max_range >= 0 && square_dist( t, g->u.pos() ) > max_range ) { return false; // Out of range! } const auto &map_cache = get_cache_ref( t.z ); return map_cache.seen_cache[t.x][t.y] > LIGHT_TRANSPARENCY_SOLID + 0.1 && ( map_cache.seen_cache[t.x][t.y] * map_cache.lm[t.x][t.y] > g->u.get_vision_threshold( map_cache.lm[g->u.posx()][g->u.posy()] ) || map_cache.sm[t.x][t.y] > 0.0 ); }
REAL SegComp::_square_dist ( ModePrim m0, const SegComp & s1, ModePrim m1 ) const { REAL res = DBL_MAX; for (INT k=0; k<(int)m1; k++) res = std::min ( res, square_dist(m0,s1.kpts(k)) ); return res; }
std::vector <tripoint> line_to(const tripoint &loc1, const tripoint &loc2, int t, int t2) { std::vector<tripoint> line; // Preallocate the number of cells we need instead of allocating them piecewise. const int numCells = square_dist(loc1, loc2); if( numCells == 0 ) { line.push_back( loc1 ); } else { line.reserve(numCells); bresenham( loc1, loc2, t, t2, [&line]( const tripoint &new_point ) { line.push_back(new_point); return true; } ); } return line; }
// If z == INT_MIN, allow all z-levels std::vector<std::shared_ptr<npc>> overmapbuffer::get_npcs_near_omt( int x, int y, int z, int radius ) { std::vector<std::shared_ptr<npc>> result; for( auto &it : get_overmaps_near( omt_to_sm_copy( x, y ), radius ) ) { auto temp = it->get_npcs( [&]( const npc & guy ) { // Global position of NPC, in submap coordinates tripoint pos = guy.global_omt_location(); if( z != INT_MIN && pos.z != z ) { return false; } return square_dist( x, y, pos.x, pos.y ) <= radius; } ); result.insert( result.end(), temp.begin(), temp.end() ); } return result; }
int obtain( Character& ch ) override { if( !what ) { return INT_MIN; } int mv = 0; //@ todo handle unpacking costs mv += dynamic_cast<player *>( &ch )->item_handling_cost( *what ) * ( square_dist( ch.pos(), location ) + 1 ); mv *= MAP_HANDLING_FACTOR; ch.moves -= mv; int inv = ch.get_item_position( &ch.i_add( *what ) ); remove_item(); return inv; }
// If z == INT_MIN, allow all z-levels std::vector<npc*> overmapbuffer::get_npcs_near_omt(int x, int y, int z, int radius) { std::vector<npc*> result; for( auto &it : get_overmaps_near( omt_to_sm_copy( x, y ), radius ) ) { for( auto &np : it->npcs ) { // Global position of NPC, in submap coordiantes tripoint pos = np->global_omt_location(); if( z != INT_MIN && pos.z != z) { continue; } const int npc_offset = square_dist( x, y, pos.x, pos.y ); if (npc_offset <= radius) { result.push_back(np); } } } return result; }
int obtain_cost( const Character &ch, long qty ) const override { if( !target() ) { return 0; } item obj = *target(); obj = obj.split( qty ); if( obj.is_null() ) { obj = *target(); } int mv = dynamic_cast<const player *>( &ch )->item_handling_cost( obj ); mv *= square_dist( ch.pos(), cur.veh.global_part_pos3( cur.part ) ) + 1; mv *= VEHICLE_HANDLING_FACTOR; //@ todo handle unpacking costs return mv; }
std::vector<npc*> overmapbuffer::get_npcs_near(int x, int y, int z, int radius) { std::vector<npc*> result; for( auto &it : get_overmaps_near( point( x, y ), radius ) ) { for( auto &elem : it->npcs ) { npc *p = elem; // Global position of NPC, in submap coordiantes const tripoint pos = p->global_sm_location(); if (pos.z != z) { continue; } const int npc_offset = square_dist(x, y, pos.x, pos.y); if (npc_offset <= radius) { result.push_back(p); } } } return result; }
std::vector<npc*> overmapbuffer::get_npcs_near_omt(int x, int y, int z, int radius) { std::vector<npc*> result; for(std::list<overmap>::iterator it = overmap_list.begin(); it != overmap_list.end(); ++it) { for (int i = 0; i < it->npcs.size(); i++) { npc *p = it->npcs[i]; // Global position of NPC, in submap coordiantes tripoint pos = p->global_omt_location(); if (pos.z != z) { continue; } const int npc_offset = square_dist(x, y, pos.x, pos.y); if (npc_offset <= radius) { result.push_back(p); } } } return result; }
REAL SegComp::dist(ModePrim mode,Pt2dr pt) const { return sqrt(square_dist(mode,pt)); }
int compute_surroundings(int pos, int apos, int showboard, int *surround_size) { int i, j; int m, n; int k; int dpos; int surrounded; int left_corner[MAX_BOARD]; int right_corner[MAX_BOARD]; int corner[BOARDMAX]; int left_corners = 0, right_corners = 0; int corners = 0; int top_row, bottom_row; int color = board[pos]; int other = OTHER_COLOR(color); int gi = 0; int gj = 0; int stones = 0; int found_some; signed char mf[BOARDMAX]; /* friendly dragon */ signed char mn[BOARDMAX]; /* neighbor dragons */ int sd[BOARDMAX]; /* distances to the goal */ if (DRAGON2(pos).hostile_neighbors == 0) return(0); memset(mf, 0, sizeof(mf)); memset(mn, 0, sizeof(mn)); memset(sd, 0, sizeof(sd)); mark_dragon(pos, mf, 1); /* mark hostile neighbors */ for (k = 0; k < DRAGON2(pos).neighbors; k++) { int nd = DRAGON(DRAGON2(pos).adjacent[k]).origin; if (board[nd] != color) { if (0) gprintf("neighbor: %1m\n", nd); mark_dragon(nd, mn, 1); } } /* descend markings from stones lying on the 2nd and third lines */ for (dpos = BOARDMIN; dpos < BOARDMAX; dpos++) if (ON_BOARD(dpos) && mn[dpos]) { for (k = 0; k < 4; k++) { int d = delta[k]; if (!ON_BOARD(dpos + d)) continue; if (!ON_BOARD(dpos + 2*d)) { if (board[dpos + d] == EMPTY) mn[dpos + d] = 1; } else if (!ON_BOARD(dpos + 3*d)) { if (board[dpos + d] == EMPTY && board[dpos + 2*d] == EMPTY) mn[dpos + 2*d] = 1; } } } /* compute minimum distances to the goal */ for (dpos = BOARDMIN; dpos < BOARDMAX; dpos++) if (ON_BOARD(dpos) && mn[dpos]) sd[dpos] = goal_dist(dpos, mf); /* revise markings */ do { found_some = 0; for (dpos = BOARDMIN; dpos < BOARDMAX; dpos++) if (ON_BOARD(dpos) && mn[dpos] && sd[dpos] > 8) { /* discard markings if we can find 2 stones * that verify : * - it is closer to the goal than we are * - it is closer to us than the goal is * - they are closer to each other than we are to the goal */ for (i = BOARDMIN; i < BOARDMAX; i++) if (ON_BOARD(i) && mn[i] && i != dpos && sd[i] < sd[dpos] && square_dist(i, dpos) < sd[dpos]) { for (j = i + 1; j < BOARDMAX; j++) if (ON_BOARD(j) && mn[j] && j != dpos && sd[j] < sd[dpos] && square_dist(j, dpos) < sd[dpos] && square_dist(i, j) < sd[dpos]) { mn[dpos] = 0; found_some = 1; break; } if (mn[dpos] == 0) break; } } } while (found_some); /* prepare corner array */ for (dpos = BOARDMIN; dpos < BOARDMAX; dpos++) if (ON_BOARD(dpos) && mn[dpos]) corner[corners++] = dpos; /* compute gravity center of the goal */ for (dpos = BOARDMIN; dpos < BOARDMAX; dpos++) if (ON_BOARD(dpos) && mf[dpos]) { gi += I(dpos); gj += J(dpos); stones++; } gi /= stones; gj /= stones; gg = POS(gi, gj); /* sort the corner array */ gg_sort(corner, corners, sizeof(int), compare_angles); /* if apos is not NO_MOVE, mark it. */ if (apos != NO_MOVE) { ASSERT_ON_BOARD1(apos); mn[apos] = 1; } if (showboard == 1) { show_surround_map(mf, mn); } /* find top row of surrounding polyhedron */ top_row = -1; for (m = 0; m < board_size; m++) { if (top_row != -1) break; for (n = 0; n < board_size; n++) if (mn[POS(m, n)]) { left_corner[0] = POS(m, n); top_row = m; break; } } /* find bottom row */ bottom_row = -1; for (m = board_size - 1; m >= 0; m--) { if (bottom_row != -1) break; for (n = 0; n < board_size; n++) if (mn[POS(m, n)]) { bottom_row = m; break; } } /* find the corners on the left side */ for (left_corners = 1; I(left_corner[left_corners-1]) < bottom_row; left_corners++) { int best_found = 0; float best_slope = 0.; int m = I(left_corner[left_corners-1]); int n = J(left_corner[left_corners-1]); for (i = m + 1; i <= bottom_row; i++) for (j = 0; j < board_size; j++) if (mn[POS(i, j)]) { float slope = ((float) (j - n))/((float) (i - m)); if (0) gprintf("(left) at %m, last %m, slope=%f\n", i, j, m, n, slope); if (!best_found || slope < best_slope) { best_found = POS(i, j); best_slope = slope; } } ASSERT_ON_BOARD1(best_found); left_corner[left_corners] = best_found; } for (n = board_size-1; n >= 0; n--) if (mn[POS(top_row, n)]) { right_corner[0] = POS(top_row, n); break; } /* find the corners on the right side */ for (right_corners = 1; I(right_corner[right_corners-1]) < bottom_row; right_corners++) { int best_found = 0; float best_slope = 0.; int m = I(right_corner[right_corners-1]); int n = J(right_corner[right_corners-1]); for (i = m + 1; i <= bottom_row; i++) { for (j = board_size - 1; j >= 0; j--) { if (mn[POS(i, j)]) { float slope = ((float) (j - n))/((float) (i - m)); if (0) gprintf("(right) at %m, last %m, slope=%f\n", i, j, m, n, slope); if (!best_found || slope > best_slope) { best_found = POS(i, j); best_slope = slope; } } } } ASSERT_ON_BOARD1(best_found); right_corner[right_corners] = best_found; } if (0) { for (k = 0; k < left_corners; k++) gprintf("left corner %d: %1m\n", k, left_corner[k]); for (k = 0; k < right_corners; k++) gprintf("right corner %d: %1m\n", k, right_corner[k]); } /* Now mark the interior of the convex hull */ for (n = J(left_corner[0]); n <= J(right_corner[0]); n++) mn[POS(top_row, n)] = 1; for (n = J(left_corner[left_corners-1]); n <= J(right_corner[right_corners-1]); n++) mn[POS(bottom_row, n)] = 1; for (m = top_row+1; m < bottom_row; m++) { int left_boundary = -1, right_boundary = -1; for (k = 1; k < left_corners; k++) { if (I(left_corner[k]) > m) { float ti = I(left_corner[k-1]); float tj = J(left_corner[k-1]); float bi = I(left_corner[k]); float bj = J(left_corner[k]); if (0) gprintf("(left) %d: %1m %1m\n", m, left_corner[k-1], left_corner[k]); /* left edge in this row is on segment (ti,tj) -> (bi, bj) */ /* FIXME: Rewrite this to avoid floating point arithmetic */ left_boundary = ceil(tj + (m - ti) * (bj - tj) / (bi - ti)); break; } } for (k = 1; k < right_corners; k++) { if (I(right_corner[k]) > m) { float ti = I(right_corner[k-1]); float tj = J(right_corner[k-1]); float bi = I(right_corner[k]); float bj = J(right_corner[k]); if (0) gprintf("(right) %d: %1m %1m\n", m, right_corner[k-1], right_corner[k]); /* FIXME: Rewrite this to avoid floating point arithmetic */ right_boundary = floor(tj + (m - ti) * (bj - tj) / (bi - ti)); break; } } for (n = left_boundary; n <= right_boundary; n++) mn[POS(m, n)] = 1; } /* mark the expanded region */ for (dpos = BOARDMIN; dpos < BOARDMAX; dpos++) if (ON_BOARD(dpos) && mn[dpos] == 1) for (k = 0; k < 4; k++) if (ON_BOARD(dpos + delta[k]) && !mn[dpos + delta[k]]) mn[dpos + delta[k]] = 2; /* Mark allied dragons that intersect the (unexpanded) hull. * These must all lie entirely within the hull for the * dragon to be considered surrounded. * * Only neighbor dragons are considered since dragons that * are not neighbors are less likely to be helpful. */ for (dpos = BOARDMIN; dpos < BOARDMAX; dpos++) { int mpos; if (ON_BOARD(dpos) && mn[dpos] == 1 && board[dpos] == color && are_neighbor_dragons(pos, dpos) && !mf[dpos]) { for (mpos = BOARDMIN; mpos < BOARDMAX; mpos++) if (ON_BOARD(mpos) && is_same_dragon(mpos, dpos)) mf[mpos] = 2; } /* A special case * * . X X . * X O . X * X . O O * . O . . * * The O stone hasn't been amalgamated and the surround computations * might think this single stone dragon is surrounded, which in turn * can generate overvaluation of moves around this stone. * Consequently, we allow inclusion of the stones at kosumi distance * in the mf (friendly) array. */ if (ON_BOARD(dpos) && mn[dpos] == 2 && board[dpos] == color && are_neighbor_dragons(pos, dpos) && !mf[dpos]) { for (k = 4; k < 8; k++) if (ON_BOARD(dpos + delta[k]) && board[dpos + delta[k]] == color && mn[dpos + delta[k]] == 1 && board[dpos + delta[k-4]] == EMPTY && board[dpos + delta[(k-3)%4]] == EMPTY) { for (mpos = BOARDMIN; mpos < BOARDMAX; mpos++) if (ON_BOARD(mpos) && is_same_dragon(mpos, dpos)) mf[mpos] = 2; } } } /* determine the surround status of the dragon */ surrounded = SURROUNDED; /* Compute the maximum surround status awarded * If distances between enclosing stones are large, reduce to * WEAKLY_SURROUNDED. If (really) too large, then reduce to 0 * FIXME: constants chosen completely ad hoc. Possibly better tunings * can be found. */ for (k = 0; k < corners - 1; k++) { if (is_edge_vertex(corner[k]) && is_edge_vertex(corner[k+1])) continue; if (square_dist(corner[k], corner[k+1]) > 60) { surrounded = 0; break; } else if (square_dist(corner[k], corner[k+1]) > 27) surrounded = WEAKLY_SURROUNDED; } if (surrounded && (!is_edge_vertex(corner[0]) || !is_edge_vertex(corner[corners-1]))) { if (square_dist(corner[0], corner[corners-1]) > 60) surrounded = 0; else if (square_dist(corner[0], corner[corners-1]) > 27) surrounded = WEAKLY_SURROUNDED; } if (surrounded) for (dpos = BOARDMIN; dpos < BOARDMAX; dpos++) if (mf[dpos]) { if (mn[dpos] == 0) { surrounded = 0; break; } else if (mn[dpos] == 2) surrounded = WEAKLY_SURROUNDED; } /* revise the status for single stone dragons. */ if (stones == 1 && surrounded == WEAKLY_SURROUNDED && mn[pos] == 2) surrounded = 0; /* revise the status if an ikken tobi jumps out. */ if (surrounded) { for (dpos = BOARDMIN; dpos < BOARDMAX && surrounded; dpos++) { if (!ON_BOARD(dpos) || !mf[dpos]) continue; for (k = 0; k < 4; k++) { int up = delta[k]; int right = delta[(k + 1) % 4]; if (board[dpos + up] == EMPTY && board[dpos + 2*up] == color && mn[dpos + 2*up] != 1 && ON_BOARD(dpos + up + right) && board[dpos + up + right] != other && ON_BOARD(dpos + up - right) && board[dpos + up - right] != other) { surrounded = 0; break; } } } } if (showboard == 1 || (showboard == 2 && surrounded)) { show_surround_map(mf, mn); } if (!apos && surrounded && surround_pointer < MAX_SURROUND) { memcpy(surroundings[surround_pointer].surround_map, mn, sizeof(mn)); surroundings[surround_pointer].dragon_number = dragon[pos].id; surround_pointer++; } if (surround_size) { int pos; *surround_size = 0; for (pos = BOARDMIN; pos < BOARDMAX; pos++) if (ON_BOARD(pos) && mn[pos] == 1) (*surround_size)++; } return surrounded; }
static void test_moves_to_squares( std::string monster_type, bool write_data = false ) { std::map<int, statistics> turns_at_distance; std::map<int, statistics> turns_at_slope; std::map<int, statistics> turns_at_angle; // For the regression test we want just enough samples, for data we want a lot more. const int required_samples = write_data ? 100 : 20; const int sampling_resolution = write_data ? 1 : 20; bool not_enough_samples = true; while( not_enough_samples ) { not_enough_samples = false; for( int x = 0; x <= 100; x += sampling_resolution ) { for( int y = 0; y <= 100; y += sampling_resolution ) { const int distance = square_dist({50,50,0}, {x,y,0}); if( distance <= 5 ) { // Very short ranged tests are squirrely. continue; } const int rise = 50 - y; const int run = 50 - x; const float angle = atan2( run, rise ); // Bail out if we already have enough samples for this angle. if( turns_at_angle[angle * 100].n() >= required_samples ) { continue; } // Scale the scaling factor based on the ratio of diagonal to cardinal steps. const float slope = get_normalized_angle( {50, 50}, {x, y} ); const float diagonal_multiplier = 1.0 + (get_option<bool>( "CIRCLEDIST" ) ? (slope * 0.41) : 0.0); turns_at_angle[angle * 100].new_type(); turns_at_slope[slope].new_type(); for( int i = 0; i < 5; ++i ) { const int moves = moves_to_destination( monster_type, {50, 50, 0}, {x, y, 0} ); const int adjusted_moves = moves / (diagonal_multiplier * distance); turns_at_distance[distance].add( adjusted_moves ); turns_at_angle[angle * 100].add( adjusted_moves ); turns_at_slope[slope].add( adjusted_moves ); } if( turns_at_angle[angle * 100].n() < required_samples ) { not_enough_samples = true; } } } } for( const auto &stat_pair : turns_at_distance ) { INFO( "Monster:" << monster_type << " Dist: " << stat_pair.first << " moves: " << stat_pair.second.avg() ); CHECK( stat_pair.second.avg() == Approx(100.0).epsilon(0.1) ); } for( const auto &stat_pair : turns_at_slope ) { INFO( "Monster:" << monster_type << " Slope: " << stat_pair.first << " moves: " << stat_pair.second.avg() << " types: " << stat_pair.second.types() ); CHECK( stat_pair.second.avg() == Approx(100.0).epsilon(0.03) ); } for( auto &stat_pair : turns_at_angle ) { std::stringstream sample_string; for( auto sample : stat_pair.second.get_samples() ) { sample_string << sample << ", "; } INFO( "Monster:" << monster_type << " Angle: " << stat_pair.first << " moves: " << stat_pair.second.avg() << " types: " << stat_pair.second.types() << " samples: " << sample_string.str() ); CHECK( stat_pair.second.avg() == Approx(100.0).epsilon(0.05) ); } if( write_data ) { std::ofstream data; data.open("slope_test_data_" + std::string((trigdist ? "trig_" : "square_")) + monster_type); for( const auto &stat_pair : turns_at_angle ) { data << stat_pair.first << " " << stat_pair.second.avg() << "\n" ; } data.close(); } }