Пример #1
0
void calc_next_move(const struct plane *p, const int srow, const int scol,
                    int *alt, const struct xyz target, int *bearing,
                    const bool cleared_exit, struct frame *frame) {
    // Avoid obstacles.  Obstacles are:  The boundary except for the
    // target exit at alt==9, adjacency with another plane (props have
    // to check this at t+1 and t+2), within 2 of an exit at alt 6-8 if
    // it's cleared the exit, the exclusion area of an airport at alt <= 2.

    // Incur a penalty for matching the bearing/altitude of a
    // blocking airplane (because it'll just continue to block).
    struct blp blocking_planes[BLP_MAX];
    int n_blp = 0;

    int nalt;

    const bool trace = (p->id == 'j' && srow == 1 && scol == 9 && *alt == 9 &&
                  bearings[*bearing].aircode == '<' &&
                  target.row == 0 && target.col == 29 && target.alt == 9);

    // If the plane's at the airport, it can only hold or take off.
    if (*alt == 0) {
        struct xy rc = apply(srow, scol, *bearing);
        frame->cand[0].bearing = frame->cand[1].bearing = *bearing;
        frame->cand[0].alt = 0;  frame->cand[1].alt = 1;
        if (adjacent_another_plane(rc, 1, p->isjet, frame->opc_start).alt > 0) {
            // Can't take off, can only hold.
            frame->n_cand = 1;
        } else {
            *alt = 1;
            frame->n_cand = 2;
        }
        return;
    }

    frame->n_cand = 0;
    for (int turn = -2; turn <= 2; turn++) {
        int nb = (*bearing + turn) & 7;
        struct xy rc = apply(srow, scol, nb);
        if (rc.row < 0 || rc.col < 0 ||
                rc.row >= board_height || rc.col >= board_width)
            continue;
        bool on_boundary = (rc.row == 0 || rc.row == board_height-1 ||
                            rc.col == 0 || rc.col == board_width-1);
        for (nalt = *alt-1; nalt <= *alt+1; nalt++) {
            if (nalt == 0 || nalt == 10)
                continue;
            if (target.alt == 9 && nalt == 9 &&
                    rc.row == target.row && rc.col == target.col) {
                // Reached the proper exit gate.  Can't collide here,
                // planes just immediately disappear.
                new_cand(frame, nb, nalt, -10*MATCHCOURSE_PENALTY);
                break;
            }
            if (on_boundary)    // ... and not at the target exit
                continue;
            if (cleared_exit && p->target_airport &&
                    in_airport_excl(rc, nalt, p->target_num))
                continue;
            if (nalt == 1 && p->target_airport &&
                    rc.row == target.row && rc.col == target.col &&
                    in_airport_excl(apply(srow, scol, -1), *alt, p->target_num))
                continue;
            struct blp adjacent_plane =
                adjacent_another_plane(rc, nalt, p->isjet, frame->opc_start);

            if (adjacent_plane.alt > 0) {
                add_blocking_plane(blocking_planes, &n_blp, adjacent_plane);
                tracelog(trace, "Candidate move to (%d, %d, %d) bearing %s "
                                "blocked by %s plane at altitude %d "
                                "bearing %s\n",
                         rc.row, rc.col, nalt, bearings[nb].shortname,
                         adjacent_plane.isjet ? "jet" : "prop",
                         adjacent_plane.alt,
                         bearings[adjacent_plane.bearing].shortname);
                continue;
            }
            if (cleared_exit && (rc.row <= 2 || rc.row >= board_height - 3 ||
                                 rc.col <= 2 || rc.col >= board_width - 3) &&
                    ((p->target_airport && nalt >= 6) ||
                     (!p->target_airport && nalt != 9)))
                continue;
            bool aligned = planes_aligned(rc, nalt, p->isjet, frame->opc_start);
            int penalty = aligned ? MATCHCOURSE_PENALTY/2 : 0;
            int distance = penalty + cdist(rc.row, rc.col, nalt, target, p,
                                           srow, scol);
            new_cand(frame, nb, nalt, distance);
            tracelog(trace, "Adding candidate move to (%d, %d, %d) bearing %s "
                            "distance=%d\n", rc.row, rc.col, nalt,
                     bearings[nb].longname, distance);
        }
    }
    assert(frame->n_cand <= 15);
    if (frame->n_cand == 0) {
        tracelog(trace, "Warning: Can't find safe path for plane '%c'\n",
                 p->id);
        *alt = -1;
        return;
    }
    tracelog(trace, "Checking %d candidate moves against %d blocking planes.\n",
             frame->n_cand, n_blp);
    for (int i = 0; i < frame->n_cand; i++) {
        for (int j = 0; j < n_blp; j++) {
             if (frame->cand[i].bearing != blocking_planes[j].bearing ||
                    p->isjet != blocking_planes[j].isjet) {
                tracelog(trace, "Not applying matchcourse penalty: "
                                "%s c_bearing %s vs. %s b_bearing %s "
                                "(%d/%d vs. %d/%d)\n",
                         p->isjet ? "jet" : "prop",
                         bearings[frame->cand[i].bearing].shortname,
                         blocking_planes[j].isjet ? "jet" : "prop",
                         bearings[blocking_planes[j].bearing].shortname,
                         frame->cand[i].bearing, p->isjet,
                         blocking_planes[j].bearing, blocking_planes[j].isjet);
                continue;
             }
             int da = abs(frame->cand[i].alt - blocking_planes[j].alt);
             if (da == 0) {
                tracelog(trace, "Applying matchcourse penalty to plane %c "
                                "bearing %s.\n",
                         p->id, bearings[blocking_planes[j].bearing].longname);
                frame->cand[i].distance += MATCHCOURSE_PENALTY;
             } else if (da == 1) {
                tracelog(trace, "Applying minor matchcourse penalty to "
                                "plane %c bearing %s.\n",
                         p->id, bearings[blocking_planes[j].bearing].longname);
                frame->cand[i].distance += MATCHCOURSE_PENALTY/10;
             } else {
                tracelog(trace, "Not applying matchcourse penalty: "
                                "c_alt %d vs. b_alt %d\n",
                         frame->cand[i].alt, blocking_planes[j].alt);
             }
        }
    }
    qsort(frame->cand, frame->n_cand, sizeof(*frame->cand), distcmp);

    int old_dist = cdist(srow, scol, *alt, target, p, srow, scol);
    if (frame->cand[frame->n_cand-1].distance > old_dist) {
        // We're being pushed away from the destination.  Apply the
        // alt change bonus and re-sort.
        for (int i = 0; i < frame->n_cand; i++) {
            for (int j = 0; j < n_blp; j++) {
                if (*alt == blocking_planes[j].alt &&
                        frame->cand[i].alt != blocking_planes[j].alt)
                    frame->cand[i].distance -= CHANGEALT_BONUS;
            }
        }
        qsort(frame->cand, frame->n_cand, sizeof(*frame->cand), distcmp);
    }

    *bearing = frame->cand[frame->n_cand-1].bearing;
    *alt = frame->cand[frame->n_cand-1].alt;
}
Пример #2
0
bool Plane::Move(int time)
{
    if (time >= nextMove)
    {
        fuel--;
        nextMove += speed;
        if (circling)
        {
            switch(heading)
            {
                int n;
                case east:
                    n = cdist(position.x+1, position.y);
                    if (n > circleDist)
                    {
                        n = cdist(position.x+1, position.y+1);
                        if (n > circleDist)
                            heading = northeast;
                        else
                            heading = southeast;
                    }
                    break;
                case southeast:
                    n = cdist(position.x+1, position.y+1);
                    if (n > circleDist)
                    {
                        n = cdist(position.x, position.y+1);
                        if (n > circleDist)
                            heading = east;
                        else
                            heading = south;
                    }
                    break;
                case south:
                    n = cdist(position.x, position.y+1);
                    if (n > circleDist)
                    {
                        n = cdist(position.x+1, position.y+1);
                        if (n > circleDist)
                            heading = southwest;
                        else
                            heading = southeast;
                    }
                    break;
                case southwest:
                    n = cdist(position.x-1, position.y+1);
                    if (n > circleDist)
                    {
                        n = cdist(position.x-1, position.y);
                        if (n > circleDist)
                            heading = south;
                        else
                            heading = west;
                    }
                    break;
                case west:
                    n = cdist(position.x-1, position.y);
                    if (n > circleDist)
                    {
                        n = cdist(position.x-1, position.y+1);
                        if (n > circleDist)
                            heading = northwest;
                        else
                            heading = southwest;
                    }
                    break;
                case northwest:
                    n = cdist(position.x-1, position.y-1);
                    if (n > circleDist)
                    {
                        n = cdist(position.x-1, position.y);
                        if (n > circleDist)
                            heading = north;
                        else
                            heading = west;
                    }
                    break;
                case north:
                    n = cdist(position.x, position.y-1);
                    if (n > circleDist)
                    {
                        n = cdist(position.x+1, position.y-1);
                        if (n > circleDist)
                            heading = northwest;
                        else
                            heading = northeast;
                    }
                    break;
                case northeast:
                    n = cdist(position.x+1, position.y-1);
                    if (n > circleDist)
                    {
                        n = cdist(position.x+1, position.y);
                        if (n > circleDist)
                            heading = north;
                        else
                            heading = west;
                    }
                    break;
            }
        }
        else if (rotate < 0) 
        {
            rotate++;
            heading = heading-1;
            if (heading < 0)
                heading += 8;
        }
        else if (rotate > 0)
        {
            rotate --;
            heading = heading + 1;
            if (heading >= 8)
                heading -= 8;
        }
        switch(heading)
        {
            case east:
                MoveDelta (1, 0);
                break;
            case southeast:
                MoveDelta (1, 1);
                break;
            case south:
                MoveDelta (0, 1);
                break;
            case southwest:
                MoveDelta (-1, 1);
                break;
            case west:
                MoveDelta (-1, 0);
                break;
            case northwest:
                MoveDelta (-1, -1);
                break;
            case north:
                MoveDelta (0, -1);
                break;
            case northeast:
                MoveDelta (1, -1);
                break;
        }
        return true;
    }
    return false;
}
Пример #3
0
static double ApproxEarthMoversMetric(
	vector<double>	&dd,
	int				wi,
	int				hi )
{
// find powers of 2 that are big enough

	int	w = CeilPow2( wi ),
		h = CeilPow2( hi );

	vector<double>	d( w*h, 0.0 );

	CopyRaster( &d[0], w, &dd[0], wi, wi, hi );

	UnnormHaarTf2D( d, w, h );

//	PrintVectorAsMat( stdout, d, 8 );

	vector<int>	cdist( w, 1 );
	vector<int>	rdist( h, 1 );
	int			mask;

	mask = w >> 1;  // only works for w = 2^n

	for( int x = 1; x < w; ++x ) {

		for( int tmp = x; !(tmp & mask); tmp <<= 1 )
			cdist[x] <<= 1;
	}

	mask = h >> 1;  // only works for h = 2^n

	for( int y = 1; y < h; ++y ) {

		for( int tmp = y; !(tmp & mask); tmp <<= 1 )
			rdist[y] <<= 1;
	}

// use of 1 as lower bound is right;
// do not care about sums, only differences

	double	approx = 0.0;  // approximate Earth Mover's metric

	for( int x = 1; x < w; ++x ) {

		for( int y = 1; y < h; ++y ) {

			int		dx		= cdist[x];
			int		dy		= rdist[y];
			double	dist	= min( dx, dy );

			if( dist < 0 ) {

				printf(
				"x %d, y %d, dx %d, dy %d, dist %f, d[x+w*y] %f\n",
				x, y, dx, dy, dist, d[x + w*y] );
			}

			approx += dist * abs( d[x + w*y] );
		}
	}

// this should never happen

	if( approx < 0 ) {

		printf(
		"##Negative metric?  wi=%d, hi=%d"
		"\nColumn dists: ", wi, hi );

		for( int x = 1; x < w; ++x )
			printf( "%d ", cdist[x] );

		printf( "\nRow dists: " );

		for( int y = 1; y < h; ++y )
			printf( "%d ", rdist[y] );

		printf( "\n" );

		exit( 42 );
	}

// Normalize:
// - divide by 2 deltas per move unit.
// - divide by N pixels (per pixel cost).
// - divide by Poisson noise on area N.

	int		N = wi * hi;

	approx /= 2.0 * N * sqrt( N );

	printf(
	"Approximate EM metric %f for %d points.\n",
	approx, N );

	return approx;
}