Exemple #1
0
void CStarmap::AddBase(const Sector &sector, BYTE propTech)
{
	AssertBotE(sector.on_map());

	// merken, dass Sektor einen Außenposten besitzt; falls der Außenposten schon vorhanden ist, die folgende
	// Berechnung trotzdem durchführen, da eine andere <code>rangeMap</code> vorgegeben sein könnte.
	if (!IsBase(sector)) m_lBases.push_back(sector);

	// --- Map mit Entfernungen aktualisieren ---
	this->CalcRangeMap(propTech);

	// lokale Rangemap durchlaufen
	for (char x = -m_RangeMap.x0; x < m_RangeMap.w - m_RangeMap.x0; x++)
		for (char y = -m_RangeMap.y0; y < m_RangeMap.h - m_RangeMap.y0; y++)
		{
			Sector pt(sector.x + x, sector.y + y);
			if (pt.is_in_rect(0, 0, STARMAP_SECTORS_HCOUNT, STARMAP_SECTORS_VCOUNT))
			{
				// Wert überschreiben, wenn der neue Einfluss größer ist
				m_Range.at(CoordsToIndex(pt.x, pt.y)) = max(m_Range.at(CoordsToIndex(pt.x, pt.y)), GetRangeMapValue(x, y));
			}
		}

	// pathStart zurücksetzen, damit sämtliche Wege beim nächsten Aufruf von
	// CalcPath() neu berechnet werden
	pathStart = Sector();

#ifdef DEBUG_AI_BASE_DEMO
	// ACHTUNG: verwenden i. A. falsche RangeMap!
	RecalcRangePoints();
	RecalcConnectionPoints();
	RecalcTargetPoints();
#endif
}
Exemple #2
0
void CStarmap::Select(const Sector &sector)
{
	if (sector.x > -1 && sector.y > -1)
	{
		AssertBotE(sector.on_map());
		m_Selection = sector;
	}
}
Exemple #3
0
Sector CStarmap::GetClickedSector(const CPoint &pt)
{
	Sector result;
	result.x = result.y = -1;

	// wenn innerhalb der Karte geklickt, dann Koordinaten umrechnen
	if (PT_IN_RECT(pt, 0, 0, STARMAP_TOTALWIDTH, STARMAP_TOTALHEIGHT))
	{
		result.x = pt.x / STARMAP_SECTOR_WIDTH;
		result.y = pt.y / STARMAP_SECTOR_HEIGHT;
		AssertBotE(result.on_map());
	}

	return result;
}
Exemple #4
0
void CStarmap::AddKnownSystem(const Sector &sector)
{
	AssertBotE(sector.on_map());
	AssertBotE(m_bAICalculation);
	if (!m_bAICalculation || !sector.is_in_rect(0, 0, STARMAP_SECTORS_HCOUNT, STARMAP_SECTORS_VCOUNT)) return;

	// prüfen, ob Ziel bereits in Liste vorhanden ist
	for (std::list<Sector>::const_iterator it = m_lAIKnownSystems.begin(); it != m_lAIKnownSystems.end(); ++it)
		if (*it == sector)
			return;

	// sonst hinzufügen
	m_lAIKnownSystems.push_back(sector);

#ifdef DEBUG_AI_BASE_DEMO
	// Bewertung für Ausbreitungsrichtungen aktualisieren
	// ACHTUNG: Berechnung hier nicht notwendig
	RecalcTargetPoints();
#endif
}
Exemple #5
0
Sector CStarmap::CalcPath(const Sector &pos, const Sector &target, unsigned char range,
	unsigned char speed, CArray<Sector> &path)
{
	AssertBotE(pos.on_map());
	AssertBotE(target.on_map());

	// bisherige Einträge von path löschen
	path.RemoveAll();

	// gegebene Parameter prüfen
	if (pos == target								// Start == Ziel
		|| range < 1 || range > 3
		|| m_Range.at(CoordsToIndex(pos.x, pos.y)) < range			// Start außerhalb des Gebiets der Reichweite
		|| m_Range.at(CoordsToIndex(target.x, target.y)) < range		// Ziel außerhalb der Reichweite
		|| speed < 1)
	{
		return Sector();
	}

	// Array zur Berechnung der Koordinaten sämtlicher Nachbarn eines Sektors (schräg/gerade abwechselnd,
	// mit schräg beginnend)
	Sector neighbours[8] = {Sector(-1, -1), Sector(0, -1), Sector(1, -1), Sector(1, 0), Sector(1, 1),
		Sector(0, 1), Sector(-1, 1), Sector(-1, 0)};

	// Berechnung neu beginnen?
	if (pos != pathStart || range != pathRange)
	{
		// pathMap zurücksetzen
		for (int j = 0; j < STARMAP_SECTORS_VCOUNT; j++)
			for (int i = 0; i < STARMAP_SECTORS_HCOUNT; i++)
			{
				/*PathSector *tmp = &(pathMap.at(CoordsToIndex(i, j)));
				tmp->used = false;
				tmp->distance = 0.;
				tmp->hops = 0;
				tmp->parent.x = tmp->parent.y = -1;

				tmp->position.x = i; // für Zugriff aus leafList heraus merken
				tmp->position.y = j;*/
				const int index = CoordsToIndex(i, j);
				pathMap.at(index).used=false;
				pathMap.at(index).distance=0;
				pathMap.at(index).hops=0;
				pathMap.at(index).parent.x=-1;
				pathMap.at(index).parent.y=-1;
				pathMap.at(index).position.x=i;
				pathMap.at(index).position.y=j;
			}

		// leaves zurücksetzen
		leaves.Clear();

		// Startknoten zur Liste der auszuwählenden Blätter hinzufügen
		leaves.Add(&(pathMap.at(CoordsToIndex(pos.x, pos.y))));

		// Parameter merken
		pathStart = pos;
		pathRange = range;
	}

	// ist der Weg zum angegebenen Ziel bereits bekannt?
	if (pathMap.at(CoordsToIndex(target.x, target.y)).parent.x == -1 || pathMap.at(CoordsToIndex(target.x, target.y)).parent.y == -1)
	{
		// kürzeste Wege zu allen anderen Knoten bestimmen, bis uns der Zielknoten über den Weg läuft
		bool found = false;
		while (!found)
		{
			// Zeiger auf ein neues Blatt mit einer kürzesten Gesamtentfernung zum
			// Start-Sektor ermitteln
			PathSector *next = leaves.PopFirst();
			if (!next) return Sector(); // keine Knoten mehr, Zielknoten ist nicht erreichbar
			if (next->used) continue; // Knoten wurde schonmal gewählt

			// Knoten als ausgewählt markieren
			next->used = true;

			// bisher noch nicht ausgewählte Nachbarn innerhalb der Reichweite in leaves
			// eintragen;
			// die Nachbarn müssen auch eingetragen werden, wenn next bereits der Zielknoten ist,
			// da der nächste Aufruf von CalcPath() die Zwischenergebnisse wiederverwendet
			for (int i = 0; i < 8; i++)
			{
				// Koordinaten des Nachbarn ermitteln (Sektoren nur betrachten, wenn sie
				// noch auf der Starmap liegen!)
				Sector npos = next->position + neighbours[i];
				if (!npos.is_in_rect(0, 0, STARMAP_SECTORS_HCOUNT, STARMAP_SECTORS_VCOUNT))
					continue;

				// nur Nachbarn betrachten, die noch nicht ausgewählt wurden und innerhalb der
				// Reichweite liegen
				PathSector *neighb = &(pathMap.at(CoordsToIndex(npos.x, npos.y)));
				if (neighb->used || m_Range.at(CoordsToIndex(npos.x, npos.y)) < range)
					continue;

				// kann der Nachbar über next auf einem kürzeren Weg als bisher erreicht werden,
				// dann die bisherige Info überschreiben
				double distance = next->distance + ((i % 2) ? WEIGHT_DIR : WEIGHT_DIAG);
				// Anomalien beachten
				distance += m_BadMapModifiers.at(next->position.x + next->position.y * STARMAP_SECTORS_HCOUNT);

				if (neighb->distance == 0. || distance < neighb->distance)
				{
					// (distance ist für alle anderen Sektoren außer dem Start-Sektor > 0.,
					// der Wert 0. weist darauf hin, dass distance noch nicht gesetzt wurde)

					neighb->distance = distance;
					neighb->hops = next->hops + 1;
					neighb->parent = next->position;

					// den Knoten in leaves neu einsortieren (derselbe Knoten ist evtl. unter
					// einer anderen Entfernung früher bereits einsortiert worden; da nun die
					// Entfernung aber kürzer ist, wird das neu einsortierte Element zuerst
					// gewählt; liefert die Liste eines der vorher eingeordneten Elemente, ist
					// dessen used-Feld bereits true und es wird sofort mit dem nächsten Eintrag
					// fortgesetzt);
					// @TODO besser wäre es, den früher einsortierten Knoten zu entfernen
					leaves.Add(neighb);
				}
			}

			if (next->position == target) found = true; // Zielknoten gefunden
		}
	}

	// Ziel gefunden; Weg vom Ziel bis zum Startknoten zurück verfolgen,
	// dabei von hinten beginnend in Array eintragen
	Sector next = target;
	int idx = pathMap.at(CoordsToIndex(target.x, target.y)).hops;
	AssertBotE(idx >= 1);

	path.SetSize(idx); // Größe des Arrays setzen (= Länge des Weges)

	while (next.x > -1 && next.y > -1 && --idx >= 0) // Start-Sektor nicht mit eintragen
	{
		AssertBotE(next.on_map());
		path[idx] = next;
		next = pathMap.at(CoordsToIndex(next.x, next.y)).parent;
	}
	AssertBotE(idx == -1);

	// entsprechend speed den nächsten Knoten des Weges zurückgeben; bzw. den Zielknoten,
	// wenn der Weg kürzer ist
	return path[min(speed - 1, path.GetUpperBound())];
}
Exemple #6
0
CPoint CStarmap::GetSectorCoords(const Sector& sector)
{
	AssertBotE(sector.on_map());
	return CPoint(sector.x * STARMAP_SECTOR_WIDTH, sector.y * STARMAP_SECTOR_HEIGHT);
}