コード例 #1
0
ファイル: clzones.cpp プロジェクト: KrazyTheFox/Cataclysm-DDA
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;
}
コード例 #2
0
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();
}
コード例 #3
0
ファイル: surface_height.cpp プロジェクト: AspireONE/berusky2
/*
  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);
}
コード例 #4
0
ファイル: 7.14.score.c プロジェクト: hclife/linux-bash
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;
}
コード例 #5
0
ファイル: line.cpp プロジェクト: AndClayton/Cataclysm-DDA
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 );
}
コード例 #6
0
ファイル: octree.c プロジェクト: drhansj/polymec-dev
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
}
コード例 #7
0
ファイル: line.cpp プロジェクト: Dogeturtle/Cataclysm-DDA
int rl_dist(const tripoint loc1, const tripoint loc2)
{
    if(trigdist) {
        return trig_dist(loc1, loc2);
    }
    return square_dist(loc1, loc2);
}
コード例 #8
0
ファイル: surface_height.cpp プロジェクト: AspireONE/berusky2
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);
}
コード例 #9
0
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() );
}
コード例 #10
0
ファイル: dist.cpp プロジェクト: rpankka/micmac
REAL  SegComp::dist
      (
          ModePrim m0,
          const SegComp & s1,
          ModePrim m1
      ) const
{
    return sqrt(square_dist(m0,s1,m1));
}
コード例 #11
0
ファイル: line.cpp プロジェクト: Dogeturtle/Cataclysm-DDA
//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;
}
コード例 #12
0
ファイル: surround.c プロジェクト: Daimas/elygo-bots
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;
}
コード例 #13
0
ファイル: lightmap.cpp プロジェクト: masajame7/Cataclysm-DDA
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];
}
コード例 #14
0
ファイル: lightmap.cpp プロジェクト: masajame7/Cataclysm-DDA
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];
}
コード例 #15
0
ファイル: clzones.cpp プロジェクト: KrazyTheFox/Cataclysm-DDA
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;
}
コード例 #16
0
ファイル: clzones.cpp プロジェクト: KrazyTheFox/Cataclysm-DDA
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;
}
コード例 #17
0
ファイル: lightmap.cpp プロジェクト: yowshi/Cataclysm-DDA
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;
}
コード例 #18
0
//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;
}
コード例 #19
0
ファイル: lightmap.cpp プロジェクト: Madnus/Cataclysm-DDA
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 );
}
コード例 #20
0
ファイル: dist.cpp プロジェクト: rpankka/micmac
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;
}
コード例 #21
0
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;
}
コード例 #22
0
// 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;
}
コード例 #23
0
    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;
    }
コード例 #24
0
// 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;
}
コード例 #25
0
        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;
        }
コード例 #26
0
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;
}
コード例 #27
0
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;
}
コード例 #28
0
ファイル: dist.cpp プロジェクト: rpankka/micmac
REAL  SegComp::dist(ModePrim  mode,Pt2dr   pt) const
{
    return sqrt(square_dist(mode,pt));
}
コード例 #29
0
ファイル: surround.c プロジェクト: Daimas/elygo-bots
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;
}
コード例 #30
0
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();
    }
}