Esempio n. 1
0
VisitResult ResourceUnitFinder::Visit(TerrainTraversal &terrainTraversal, const Vec2i &pos, const Vec2i &from)
{
	if (!worker.Player->AiEnabled && !Map.Field(pos)->playerInfo.IsExplored(*worker.Player)) {
		return VisitResult_DeadEnd;
	}

	CUnit *mine = Map.Field(pos)->UnitCache.find(res_finder);

	if (mine && mine != *resultMine && MineIsUsable(*mine)) {
		ResourceUnitFinder::ResourceUnitFinder_Cost cost;

		cost.SetFrom(*mine, deposit, check_usage);
		if (cost < bestCost) {
			*resultMine = mine;

			if (cost.IsMin()) {
				return VisitResult_Finished;
			}
			bestCost = cost;
		}
	}
	if (CanMoveToMask(pos, movemask)) { // reachable
		if (terrainTraversal.Get(pos) < maxRange) {
			return VisitResult_Ok;
		} else {
			return VisitResult_DeadEnd;
		}
	} else { // unreachable
		return VisitResult_DeadEnd;
	}
}
Esempio n. 2
0
VisitResult NearReachableTerrainFinder::Visit(TerrainTraversal &terrainTraversal, const Vec2i &pos, const Vec2i &from)
{
	//Wyrmgus start
//	if (!player.AiEnabled && !Map.Field(pos)->playerInfo.IsExplored(player)) {
	if (!Map.Field(pos)->playerInfo.IsExplored(player)) {
	//Wyrmgus end
		return VisitResult_DeadEnd;
	}
	// Look if found what was required.
	if (CanMoveToMask(pos, movemask)) {
		if (resPos) {
			*resPos = from;
		}
		return VisitResult_Finished;
	}
	if (Map.Field(pos)->CheckMask(resmask)) { // reachable
		if (terrainTraversal.Get(pos) <= maxDist) {
			return VisitResult_Ok;
		} else {
			return VisitResult_DeadEnd;
		}
	} else { // unreachable
		return VisitResult_DeadEnd;
	}
}
Esempio n. 3
0
VisitResult AiForceRallyPointFinder::Visit(TerrainTraversal &terrainTraversal, const Vec2i &pos, const Vec2i &from)
{
	const int minDist = 15;
	if (AiEnemyUnitsInDistance(*startUnit.Player, NULL, pos, minDist) == false
		&& Distance(pos, startPos) <= abs(distance - minDist)) {
		*resultPos = pos;
		return VisitResult_Finished;
	}
	if (CanMoveToMask(pos, movemask)) { // reachable
		return VisitResult_Ok;
	} else { // unreachable
		return VisitResult_DeadEnd;
	}
}
Esempio n. 4
0
VisitResult UnitFinder::Visit(TerrainTraversal &terrainTraversal, const Vec2i &pos, const Vec2i &from)
{
	if (!player.AiEnabled && !Map.Field(pos)->playerInfo.IsExplored(player)) {
		return VisitResult_DeadEnd;
	}
	// Look if found what was required.
	CUnit *unit = FindUnitAtPos(pos);
	if (unit) {
		*unitP = unit;
		return VisitResult_Finished;
	}
	if (CanMoveToMask(pos, movemask)) { // reachable
		if (terrainTraversal.Get(pos) <= maxDist) {
			return VisitResult_Ok;
		} else {
			return VisitResult_DeadEnd;
		}
	} else { // unreachable
		return VisitResult_DeadEnd;
	}
}
Esempio n. 5
0
static int AiFindMiningPlace(const CUnit &worker,
                             const CUnitType &type,
                             int nx, int ny,
                             Vec2i *dpos,
                             int resource)
{
    const Vec2i offset[] = {{0, -1}, {-1, 0}, {1, 0}, {0, 1}, {-1, -1}, {1, -1}, {-1, 1}, {1, 1}};
    Vec2i pos;
    Vec2i rpos;
    int wp;
    int ep;
    unsigned char *m;
    CUnit *mine;

    pos.x = (nx != -1 ? nx : worker.tilePos.x);
    pos.y = (ny != -1 ? ny : worker.tilePos.y);
    int size = Map.Info.MapWidth * Map.Info.MapHeight / 4;
    Vec2i *points = new Vec2i[size];

    //
    // Make movement matrix. FIXME: can create smaller matrix.
    //
    unsigned char *morg = MakeMatrix();
    int w = Map.Info.MapWidth + 2;
    unsigned char *matrix = morg + w + w + 2;

    points[0] = pos;
    int rp = 0;
    //if(worker->tilePos == pos)
    matrix[pos.x + pos.y * w] = 1; // mark start point
    ep = wp = 1; // start with one point

    int mask = worker.Type->MovementMask;

    //
    // Pop a point from stack, push all neighbors which could be entered.
    //
    for (;;) {
        while (rp != ep) {
            rpos = points[rp];
            for (int i = 0; i < 8; ++i) { // mark all neighbors
                pos = rpos + offset[i];
                m = matrix + pos.x + pos.y * w;
                if (*m) { // already checked
                    continue;
                }
                //
                // Look if there is a mine area
                //
                if ((mine = ResourceOnMap(pos, resource, false)) &&
                        AiFindBuildingPlace2(worker, type, mine->tilePos.x, mine->tilePos.y, dpos)) {
                    delete[] morg;
                    delete[] points;
                    return 1;
                }

                if (CanMoveToMask(pos, mask)) { // reachable
                    *m = 1;
                    points[wp] = pos; // push the point
                    if (++wp >= size) { // round about
                        wp = 0;
                    }
                } else { // unreachable
                    *m = 99;
                }
            }
            if (++rp >= size) { // round about
                rp = 0;
            }
        }

        //
        // Continue with next frame.
        //
        if (rp == wp) { // unreachable, no more points available
            break;
        }
        ep = wp;
    }

    delete[] morg;
    delete[] points;
    return 0;
}
Esempio n. 6
0
/**
**  Find free building place for lumber mill. (flood fill version)
**
**  @param worker  Worker to build building.
**  @param type    Type of building.
**  @param nx      Start search X position (if == -1 then unit X pos used).
**  @param ny      Start search X position (if == -1 then unit X pos used).
**  @param dpos    Pointer for position returned.
**
**  @return        True if place found, false if not found.
**
**  @todo          FIXME: This is slow really slow, using two flood
**                 fills, is not a perfect solution.
*/
static int AiFindLumberMillPlace(const CUnit &worker, const CUnitType &type,
                                 int nx, int ny, Vec2i *dpos)
{
    const Vec2i offset[] = {{0, -1}, {-1, 0}, {1, 0}, {0, 1}, {-1, -1}, {1, -1}, {-1, 1}, {1, 1}};
    Vec2i *points;
    int size;
    Vec2i rpos;
    int mask;
    int wp;
    int rp;
    int ep;
    int i;
    int w;
    unsigned char *m;
    unsigned char *morg;
    unsigned char *matrix;
    Vec2i pos;

    pos.x = nx != -1 ? nx : worker.tilePos.x;
    pos.y = ny != -1 ? ny : worker.tilePos.y;
    size = Map.Info.MapWidth * Map.Info.MapHeight / 4;
    points = new Vec2i[size];

    //
    // Make movement matrix.
    //
    morg = MakeMatrix();
    w = Map.Info.MapWidth + 2;
    matrix = morg + w + w + 2;

    points[0] = pos;
    rp = 0;
    matrix[pos.x + pos.y * w] = 1; // mark start point
    ep = wp = 1; // start with one point

    mask = worker.Type->MovementMask;

    //
    // Pop a point from stack, push all neightbors which could be entered.
    //
    for (;;) {
        while (rp != ep) {
            rpos = points[rp];
            for (i = 0; i < 8; ++i) { // mark all neighbors
                pos = rpos + offset[i];
                m = matrix + pos.x + pos.y * w;
                if (*m) { // already checked
                    continue;
                }
                //
                // Look if there is wood
                //
                if (Map.ForestOnMap(pos)) {
                    if (AiFindBuildingPlace2(worker, type, pos.x, pos.y, dpos)) {
                        delete[] morg;
                        delete[] points;
                        return 1;
                    }
                }

                if (CanMoveToMask(pos, mask)) { // reachable
                    *m = 1;
                    points[wp] = pos; // push the point
                    if (++wp >= size) { // round about
                        wp = 0;
                    }
                } else { // unreachable
                    *m = 99;
                }
            }

            if (++rp >= size) { // round about
                rp = 0;
            }
        }

        //
        // Continue with next frame.
        //
        if (rp == wp) { // unreachable, no more points available
            break;
        }
        ep = wp;
    }

    delete[] morg;
    delete[] points;
    return 0;
}
Esempio n. 7
0
/**
**  Find building place for hall. (flood fill version)
**
**  The best place:
**  1) near to goldmine.
**  !2) near to wood.
**  !3) near to worker and must be reachable.
**  4) no enemy near it.
**  5) no hall already near
**  !6) enough gold in mine
**
**  @param worker  Worker to build building.
**  @param type    Type of building.
**  @param nx      Start search X position (if == -1 then unit X pos used).
**  @param ny      Start search Y position (if == -1 then unit Y pos used).
**  @param dpos    Pointer for position returned.
**
**  @return        True if place found, false if not found.
**
**  @todo          FIXME: This is slow really slow, using
**                 two flood fills, is not a perfect solution.
*/
static int AiFindHallPlace(const CUnit &worker,
                           const CUnitType &type,
                           int nx, int ny,
                           Vec2i *dpos,
                           int resource = GoldCost)
{
    const Vec2i offset[] = {{0, -1}, {-1, 0}, {1, 0}, {0, 1}, {-1, -1}, {1, -1}, {-1, 1}, {1, 1}};
    Vec2i *points;
    int size;
    Vec2i pos;
    Vec2i rpos;
    int mask;
    int wp;
    int rp;
    int ep;
    int w;
    unsigned char *m;
    unsigned char *morg;
    unsigned char *matrix;
    CUnit *mine;

    pos.x = (nx != -1 ? nx : worker.tilePos.x);
    pos.y = (ny != -1 ? ny : worker.tilePos.y);
    size = Map.Info.MapWidth * Map.Info.MapHeight / 4;
    points = new Vec2i[size];

    //
    // Make movement matrix. FIXME: can create smaller matrix.
    //
    morg = MakeMatrix();
    w = Map.Info.MapWidth + 2;
    matrix = morg + w + w + 2;

    points[0] = pos;
    rp = 0;
    matrix[pos.x + pos.y * w] = 1; // mark start point
    ep = wp = 1; // start with one point

    mask = worker.Type->MovementMask;

    //
    // Pop a point from stack, push all neighbors which could be entered.
    //
    for (;;) {
        while (rp != ep) {
            rpos = points[rp];
            for (int i = 0; i < 8; ++i) { // mark all neighbors
                pos = rpos + offset[i];
                m = matrix + pos.x + pos.y * w;
                if (*m) { // already checked
                    continue;
                }
                //
                // Look if there is a mine
                //
                if ((mine = ResourceOnMap(pos, resource))) {
                    int buildings;
                    int j;
                    int nunits;
                    CUnit *units[UnitMax];

                    buildings = 0;

                    //
                    // Check units around mine
                    //
                    Vec2i minpos = {mine->tilePos.x - 5, mine->tilePos.y - 5};
                    Vec2i maxpos = {mine->tilePos.x + mine->Type->TileWidth + 5,
                                    mine->tilePos.y + mine->Type->TileHeight + 5
                                   };
                    Map.FixSelectionArea(minpos, maxpos);
                    nunits = Map.SelectFixed(minpos, maxpos, units);
                    for (j = 0; j < nunits; ++j) {
                        // Enemy near mine
                        if (AiPlayer->Player->Enemy &
                                (1 << units[j]->Player->Index)) {
                            break;
                        }
                        // Town hall near mine
                        if (units[j]->Type->CanStore[resource]) {
                            break;
                        }
                        // Town hall may not be near but we may be using it, check
                        // for 2 buildings near it and assume it's been used
                        if (units[j]->Type->Building &&
                                !units[j]->Type->GivesResource == resource) {
                            ++buildings;
                            if (buildings == 2) {
                                break;
                            }
                        }
                    }
                    if (j == nunits) {
                        if (AiFindBuildingPlace2(worker, type, pos.x, pos.y, dpos)) {
                            delete[] morg;
                            delete[] points;
                            return 1;
                        }
                    }
                }

                if (CanMoveToMask(pos, mask)) { // reachable
                    *m = 1;
                    points[wp] = pos; // push the point
                    if (++wp >= size) { // round about
                        wp = 0;
                    }
                } else { // unreachable
                    *m = 99;
                }
            }
            if (++rp >= size) { // round about
                rp = 0;
            }
        }

        //
        // Continue with next frame.
        //
        if (rp == wp) { // unreachable, no more points available
            break;
        }
        ep = wp;
    }

    delete[] morg;
    delete[] points;
    return 0;
}
Esempio n. 8
0
/**
**  Find free building place. (flood fill version)
**
**  @param worker  Worker to build building.
**  @param type    Type of building.
**  @param ox      Original X position to try building
**  @param oy      Original Y position to try building
**  @param dpos    Pointer for position returned.
**
**  @return        True if place found, false if no found.
*/
static int AiFindBuildingPlace2(const CUnit &worker, const CUnitType &type, int ox, int oy, Vec2i *dpos)
{
    const Vec2i offset[] = {{0, -1}, {-1, 0}, {1, 0}, {0, 1}, {-1, -1}, {1, -1}, {-1, 1}, {1, 1}};
    Vec2i *points;
    int size;
    Vec2i pos = {ox, oy};
    Vec2i rpos;
    int mask;
    int wp;
    int rp;
    int ep;
    unsigned char *m;
    Vec2i backupPos = {-1, -1};
    bool backupok;

    //
    // Look if we can build at current place.
    //
    if (CanBuildUnitType(&worker, type, pos, 1) &&
            !AiEnemyUnitsInDistance(worker.Player, NULL, pos, 8)) {
        if (AiCheckSurrounding(worker, type, pos.x, pos.y, backupok)) {
            *dpos = pos;
            return 1;
        } else if (backupok) {
            backupPos = pos;
        }
    }

    size = Map.Info.MapWidth * Map.Info.MapHeight / 4;
    points = new Vec2i[size];

    //
    //  Make movement matrix.
    //
    unsigned char *matrix = CreateMatrix();
    const int w = Map.Info.MapWidth + 2;

    mask = worker.Type->MovementMask;
    // Ignore all possible mobile units.
    mask &= ~(MapFieldLandUnit | MapFieldAirUnit | MapFieldSeaUnit);

    points[0] = pos;
    // also use the bottom right
    if ((type.TileWidth > 1 || type.TileHeight > 1) &&
            pos.x + type.TileWidth - 1 < Map.Info.MapWidth &&
            pos.y + type.TileHeight - 1 < Map.Info.MapHeight) {
        points[1].x = pos.x + type.TileWidth - 1;
        points[1].y = pos.y + type.TileHeight - 1;
        ep = wp = 2; // start with two points
    } else {
        ep = wp = 1; // start with one point
    }
    matrix += w + w + 2;
    rp = 0;
    matrix[pos.x + pos.y * w] = 1; // mark start point

    //
    // Pop a point from stack, push all neighbours which could be entered.
    //
    for (;;) {
        while (rp != ep) {
            rpos = points[rp];
            for (int i = 0; i < 8; ++i) { // mark all neighbors
                pos = rpos + offset[i];
                m = matrix + pos.x + pos.y * w;
                if (*m) { // already checked
                    continue;
                }

                //
                // Look if we can build here and no enemies nearby.
                //
                if (CanBuildUnitType(&worker, type, pos, 1) &&
                        !AiEnemyUnitsInDistance(worker.Player, NULL, pos, 8)) {
                    if (AiCheckSurrounding(worker, type, pos.x, pos.y, backupok)) {
                        *dpos = pos;
                        delete[] points;
                        return 1;
                    } else if (backupok && backupPos.x == -1) {
                        backupPos = pos;
                    }
                }

                if (CanMoveToMask(pos, mask)) { // reachable
                    *m = 1;
                    points[wp] = pos; // push the point
                    if (++wp >= size) { // round about
                        wp = 0;
                    }
                } else { // unreachable
                    *m = 99;
                }
            }

            if (++rp >= size) { // round about
                rp = 0;
            }
        }

        //
        // Continue with next frame.
        //
        if (rp == wp) { // unreachable, no more points available
            break;
        }
        ep = wp;
    }
    delete[] points;

    if (backupPos.x != -1) {
        *dpos = backupPos;
        return 1;
    }
    return 0;
}
Esempio n. 9
0
/**
**  Can move to this point, applying mask.
**
**  @param pos   map tile position.
**  @param mask  Mask for movement to apply.
**
**  @return      True if could be entered, false otherwise.
*/
bool CheckedCanMoveToMask(const Vec2i &pos, int mask)
{
	return Map.Info.IsPointOnMap(pos) && CanMoveToMask(pos, mask);
}