const noFlag* GameWorldBase::GetRoadFlag(MapPoint pt, Direction& dir, unsigned prevDir) const { unsigned i = 0; while(true) { // suchen, wo der Weg weitergeht for(i = 0; i < Direction::COUNT; ++i) { if(i != prevDir && GetPointRoad(pt, Direction::fromInt(i))) break; } if(i == 6) return nullptr; pt = GetNeighbour(pt, Direction::fromInt(i)); // endlich am Ende des Weges und an einer Flagge angekommen? if(GetNO(pt)->GetType() == NOP_FLAG) { dir = Direction(i + 3); return GetSpecObj<noFlag>(pt); } prevDir = (i + 3) % 6; } }
void GameWorldBase::RecalcBQForRoad(const MapPoint pt) { RecalcBQ(pt); for(unsigned i = 3; i < 6; ++i) RecalcBQ(GetNeighbour(pt, Direction::fromInt(i))); }
unsigned GameWorldBase::GetHarborInDir(const MapPoint pt, const unsigned origin_harborId, const ShipDirection& dir, T_IsHarborOk isHarborOk) const { RTTR_Assert(origin_harborId); // Herausfinden, in welcher Richtung sich dieser Punkt vom Ausgangspunkt unterscheidet unsigned char coastal_point_dir = 0xFF; const MapPoint hbPt = GetHarborPoint(origin_harborId); for(unsigned char i = 0; i < 6; ++i) { if(GetNeighbour(hbPt, Direction::fromInt(i)) == pt) { coastal_point_dir = i; break; } } RTTR_Assert(coastal_point_dir != 0xff); unsigned short seaId = GetSeaId(origin_harborId, Direction::fromInt(coastal_point_dir)); const std::vector<HarborPos::Neighbor>& neighbors = GetHarborNeighbors(origin_harborId, dir); for(auto neighbor : neighbors) { if(IsHarborAtSea(neighbor.id, seaId) && isHarborOk(neighbor.id)) return neighbor.id; } // Nichts gefunden return 0; }
std::vector<unsigned short> GameWorldBase::GetFilteredSeaIDsForAttack(const MapPoint targetPt, const std::vector<unsigned short>& usableSeas, const unsigned char player_attacker) const { // Walk to the flag of the bld/harbor. Important to check because in some locations where the coast is north of the harbor this might be // blocked const MapPoint flagPt = GetNeighbour(targetPt, Direction::SOUTHEAST); std::vector<unsigned short> confirmedSeaIds; // Check each possible harbor for(unsigned curHbId = 1; curHbId <= GetNumHarborPoints(); ++curHbId) { const MapPoint harborPt = GetHarborPoint(curHbId); if(CalcDistance(harborPt, targetPt) > SEAATTACK_DISTANCE) continue; // Not attacking this harbor and harbors block? if(targetPt != harborPt && GetGGS().getSelection(AddonId::SEA_ATTACK) == 1) { // Does an enemy harbor exist at current harbor spot? -> Can't attack through this harbor spot const auto* hb = GetSpecObj<nobHarborBuilding>(harborPt); if(hb && GetPlayer(player_attacker).IsAttackable(hb->GetPlayer())) continue; } for(unsigned z = 0; z < 6; ++z) { const unsigned short seaId = GetSeaId(curHbId, Direction::fromInt(z)); if(!seaId) continue; // sea id is not in compare list or already confirmed? -> skip rest if(!helpers::contains(usableSeas, seaId) || helpers::contains(confirmedSeaIds, seaId)) continue; // checks previously tested sea ids to skip pathfinding bool previouslytested = false; for(unsigned k = 0; k < z; k++) { if(seaId == GetSeaId(curHbId, Direction::fromInt(k))) { previouslytested = true; break; } } if(previouslytested) continue; // Can figures reach flag from coast MapPoint coastalPt = GetCoastalPoint(curHbId, seaId); if((flagPt == coastalPt) || FindHumanPath(flagPt, coastalPt, SEAATTACK_DISTANCE) != INVALID_DIR) { confirmedSeaIds.push_back(seaId); // all sea ids confirmed? return without changes if(confirmedSeaIds.size() == usableSeas.size()) return confirmedSeaIds; } } } return confirmedSeaIds; }
std::vector<unsigned> GameWorldBase::GetUsableTargetHarborsForAttack(const MapPoint targetPt, std::vector<bool>& use_seas, const unsigned char player_attacker) const { // Walk to the flag of the bld/harbor. Important to check because in some locations where the coast is north of the harbor this might be // blocked const MapPoint flagPt = GetNeighbour(targetPt, Direction::SOUTHEAST); std::vector<unsigned> harbor_points; // Check each possible harbor for(unsigned curHbId = 1; curHbId <= GetNumHarborPoints(); ++curHbId) { const MapPoint harborPt = GetHarborPoint(curHbId); if(CalcDistance(harborPt, targetPt) > SEAATTACK_DISTANCE) continue; // Not attacking this harbor and harbors block? if(targetPt != harborPt && GetGGS().getSelection(AddonId::SEA_ATTACK) == 1) { // Does an enemy harbor exist at current harbor spot? -> Can't attack through this harbor spot const auto* hb = GetSpecObj<nobHarborBuilding>(harborPt); if(hb && GetPlayer(player_attacker).IsAttackable(hb->GetPlayer())) continue; } // add seaIds from which we can actually attack the harbor bool harborinlist = false; for(unsigned z = 0; z < 6; ++z) { const unsigned short seaId = GetSeaId(curHbId, Direction::fromInt(z)); if(!seaId) continue; // checks previously tested sea ids to skip pathfinding bool previouslytested = false; for(unsigned k = 0; k < z; k++) { if(seaId == GetSeaId(curHbId, Direction::fromInt(k))) { previouslytested = true; break; } } if(previouslytested) continue; // Can figures reach flag from coast const MapPoint coastalPt = GetCoastalPoint(curHbId, seaId); if((flagPt == coastalPt) || FindHumanPath(flagPt, coastalPt, SEAATTACK_DISTANCE) != INVALID_DIR) { use_seas.at(seaId - 1) = true; if(!harborinlist) { harbor_points.push_back(curHbId); harborinlist = true; } } } } return harbor_points; }
bool GameWorldBase::IsFlagAround(const MapPoint& pt) const { for(unsigned i = 0; i < 6; ++i) { if(GetNO(GetNeighbour(pt, Direction::fromInt(i)))->GetBM() == BlockingManner::Flag) return true; } return false; }
bool GameWorldBase::IsOnRoad(const MapPoint& pt) const { for(unsigned roadDir = 0; roadDir < 3; ++roadDir) if(GetRoad(pt, roadDir)) return true; for(unsigned roadDir = 0; roadDir < 3; ++roadDir) if(GetRoad(GetNeighbour(pt, Direction::fromInt(roadDir)), roadDir)) return true; return false; }
unsigned char PreviewMinimap::CalcShading(const MapPoint pt, const std::vector<unsigned char>& altitudes) const { int altitude = altitudes[GetMMIdx(pt)]; MapPoint tmp = MakeMapPoint(GetNeighbour(Point<int>(pt), Direction::NORTHEAST), map_width, map_height); int A = altitudes[GetMMIdx(tmp)] - altitude; tmp = MakeMapPoint(GetNeighbour2(Point<int>(pt), 0), map_width, map_height); int B = altitudes[GetMMIdx(tmp)] - altitude; tmp = MakeMapPoint(GetNeighbour(Point<int>(pt), Direction::WEST), map_width, map_height); int C = altitudes[GetMMIdx(tmp)] - altitude; tmp = MakeMapPoint(GetNeighbour2(Point<int>(pt), 7), map_width, map_height); int D = altitudes[GetMMIdx(tmp)] - altitude; int shadingS2 = 64 + 9 * A - 3 * B - 6 * C - 9 * D; if(shadingS2 > 128) shadingS2 = 128; else if(shadingS2 < 0) shadingS2 = 0; return shadingS2; }
bool GameWorldBase::RoadAlreadyBuilt(const bool /*boat_road*/, const MapPoint start, const std::vector<Direction>& route) { MapPoint tmp(start); for(unsigned i = 0; i < route.size() - 1; ++i) { // Richtiger Weg auf diesem Punkt? if(!GetPointRoad(tmp, route[i])) return false; tmp = GetNeighbour(tmp, route[i]); } return true; }
bool GameWorldBase::IsRoadAvailable(const bool boat_road, const MapPoint pt) const { // Hindernisse if(GetNode(pt).obj) { BlockingManner bm = GetNode(pt).obj->GetBM(); if(bm != BlockingManner::None) return false; } // dont build on the border if(GetNode(pt).boundary_stones[0]) return false; for(unsigned z = 0; z < 6; ++z) { // Roads around charburner piles are not possible if(GetNO(GetNeighbour(pt, Direction::fromInt(z)))->GetBM() == BlockingManner::NothingAround) return false; // Other roads at this point? if(GetPointRoad(pt, Direction::fromInt(z))) return false; } // Terrain (unterscheiden, ob Wasser und Landweg) if(!boat_road) { bool flagPossible = false; for(unsigned char i = 0; i < 6; ++i) { TerrainBQ bq = GetDescription().get(GetRightTerrain(pt, Direction::fromInt(i))).GetBQ(); if(bq == TerrainBQ::DANGER) return false; else if(bq != TerrainBQ::NOTHING) flagPossible = true; } return flagPossible; } else { // Beim Wasserweg muss um den Punkt herum Wasser sein if(!IsWaterPoint(pt)) return false; } return true; }
/// Ist es an dieser Stelle für einen Spieler möglich einen Hafen zu bauen bool GameWorldBase::IsHarborPointFree(const unsigned harborId, const unsigned char player) const { MapPoint hbPos(GetHarborPoint(harborId)); // Überprüfen, ob das Gebiet in einem bestimmten Radius entweder vom Spieler oder gar nicht besetzt ist außer wenn der Hafen und die // Flagge im Spielergebiet liegen MapPoint flagPos = GetNeighbour(hbPos, Direction::SOUTHEAST); if(GetNode(hbPos).owner != player + 1 || GetNode(flagPos).owner != player + 1) { if(CheckPointsInRadius(hbPos, 4, IsPointOwnerDifferent(*this, player), false)) return false; } return GetNode(hbPos).bq == BQ_HARBOR; }
/// Vermisst ein neues Weltmeer von einem Punkt aus, indem es alle mit diesem Punkt verbundenen /// Wasserpunkte mit der gleichen ID belegt und die Anzahl zurückgibt unsigned GameWorld::MeasureSea(const MapPoint pt, const unsigned short sea_id) { // Breitensuche von diesem Punkt aus durchführen std::vector<bool> visited(width_ * height_, false); std::queue< MapPoint > todo; MapPoint start(pt); todo.push(start); // Knoten zählen (Startknoten schon mit inbegriffen) unsigned count = 0; while(!todo.empty()) { MapPoint p = todo.front(); todo.pop(); if(visited[GetIdx(p)]) continue; GetNode(p).sea_id = sea_id; for(unsigned i = 0; i < 6; ++i) { MapPoint pa = GetNeighbour(p, i); // Ist das dort auch ein Meerespunkt? if(!IsSeaPoint(pa)) continue; if(!visited[GetIdx(pa)]) { todo.push(pa); } } visited[GetIdx(p)] = true; ++count; } return count; }
/** This function rebuilds the frame according to datas decoded from the VLD for a P AVC slice. */ void Decode_I_avc( const SPS *Sps, const PPS *Pps, const SLICE *ai_pstSlice, const unsigned char *SliceTable, RESIDU *picture_residu, const STRUCT_PF *ai_struct_pf, const W_TABLES *quantif, NAL *Nal, unsigned char *Y, unsigned char *U, unsigned char *V) { if (!Nal -> NalToSkip){ const short PicSizeInMbs = Sps -> PicSizeInMbs ; const short PicWiInMbs = Sps -> pic_width_in_mbs; const short PicWidthInMbs = Sps -> pic_width_in_mbs + 2; const short offset_L = (PicWidthInMbs << 8) + 16; const short offset_C = (PicWidthInMbs << 6) + 8; short iCurrMbAddr = ai_pstSlice -> first_mb_in_slice ; short iMb_x; short iMb_y; //initialize macroblock position GetMbPosition(iCurrMbAddr, PicWiInMbs, &iMb_x, &iMb_y); Y += offset_L; U += offset_C; V += offset_C; //Loop on all macroblocks for ( ; iCurrMbAddr < PicSizeInMbs ;) { //Initialization of the macroblock neighbourhood GetNeighbour(iCurrMbAddr, iMb_x, PicWiInMbs, PicSizeInMbs, SliceTable, picture_residu, Pps -> constrained_intra_pred_flag); //Construction process for one macroblock decode_MB_I(&Y[(iMb_x + (iMb_y * PicWidthInMbs << 4)) << 4], &U[(iMb_x + (iMb_y * PicWidthInMbs << 3)) << 3], &V[(iMb_x + (iMb_y * PicWidthInMbs << 3)) << 3], Pps, &picture_residu[iCurrMbAddr], PicWidthInMbs << 4, quantif, ai_struct_pf); //Updating the macroblock address iCurrMbAddr = Next_MbAddress(iCurrMbAddr, PicSizeInMbs, PicWiInMbs, SliceTable, &iMb_x, &iMb_y); if ( SliceTable [iCurrMbAddr] == 255 ) { iCurrMbAddr = PicSizeInMbs ; } } } }
/// Return a ship at this position owned by the given player. Prefers ships that need instructions. noShip* GameWorldViewer::GetShip(const MapPoint pt, const unsigned char player) const { noShip* ship = NULL; for (unsigned i = 0; i < 7; ++i) { MapPoint pa; if (i == 6) { pa = pt; } else { pa = GetNeighbour(pt, i); } const std::list<noBase*>& figures = GetFigures(pa); for(std::list<noBase*>::const_iterator it = figures.begin(); it != figures.end(); ++it) { if((*it)->GetGOT() == GOT_SHIP) { noShip* tmp = static_cast<noShip*>(*it); if (tmp->GetPlayer() == player) { if ((tmp->GetPos() == pt) || (tmp->GetDestinationForCurrentMove() == pt)) { if (tmp->IsWaitingForExpeditionInstructions()) { return(tmp); } ship = tmp; } } } } } return(ship); }
/// Ermittelt, ob eine freie Route noch passierbar ist und gibt den Endpunkt der Route zurück bool GameWorldBase::CheckFreeRoute(const MapPoint start, const std::vector<unsigned char>& route, const unsigned pos, FP_Node_OK_Callback IsNodeOK, FP_Node_OK_Callback IsNodeToDestOk, MapPoint* dest, const void* const param) const { MapPoint pt(start); assert(pos < route.size()); for(unsigned i = pos; i < route.size(); ++i) { pt = GetNeighbour(pt, route[i]); if(!IsNodeToDestOk(*this, pt, route[i], param)) return false; if(i < route.size() - 1 && !IsNodeOK(*this, pt, route[i], param)) return false; } if(dest) *dest = pt; return true; }
// Find the position of first neighbour with given type // and whole quantity of such neighbours void GridManager::FindNeighbour(Vector2i p, sep::CellType type, sep::Axis&axis, sep::NeighborType &neighbor, int& quant) { int tmp_quant = 0; sep::CellType e_type; for (int ax = 0; ax <= sep::Y; ax++) { for (int neighb = 0; neighb <= sep::NEXT; neighb++) { if (GetNeighbour(p, (sep::Axis)ax, (sep::NeighborType)neighb, e_type)) { if (e_type == type) { if (!tmp_quant) { neighbor = (sep::NeighborType)neighb; axis = (sep::Axis)ax; } tmp_quant++; } } } } quant = tmp_quant; }
bool GridManager::FindNeighbourWithIndex(Vector2i p, sep::CellType type, int index, sep::Axis&axis, sep::NeighborType &neighbor) { int quant = 0; sep::CellType tmp_type; for (int ax = 0; ax <= sep::Y; ax++) { for (int neighb = 0; neighb <= sep::NEXT; neighb++) { if (GetNeighbour(p, (sep::Axis)ax, (sep::NeighborType)neighb, tmp_type)) { if (tmp_type == type) { if (quant == index) { neighbor = (sep::NeighborType)neighb; axis = (sep::Axis)ax; return true; } quant++; } } } } return false; }
/// Wegfinden ( A* ), O(v lg v) --> Wegfindung auf allgemeinen Terrain (ohne Straßen), für Wegbau und frei herumlaufende Berufe bool GameWorldBase::FindFreePath(const MapPoint start, const MapPoint dest, const bool random_route, const unsigned max_route, std::vector<unsigned char>* route, unsigned* length, unsigned char* first_dir, FP_Node_OK_Callback IsNodeOK, FP_Node_OK_Callback IsNodeToDestOk, const void* param, const bool record) const { // increase currentVisit, so we don't have to clear the visited-states at every run currentVisit++; // if the counter reaches its maxium, tidy up if (currentVisit == std::numeric_limits<unsigned>::max() - 1) { for (unsigned i = 0; i < (maxMapSize * maxMapSize); ++i) { pf_nodes[i].lastVisited = 0; pf_nodes[i].lastVisitedEven = 0; } currentVisit = 1; } std::set<PathfindingPoint> todo; PathfindingPoint::Init(dest, this); // Anfangsknoten einfügen unsigned start_id = MakeCoordID(start); std::pair< std::set<PathfindingPoint>::iterator, bool > ret = todo.insert(PathfindingPoint(start, start_id)); // Und mit entsprechenden Werten füllen pf_nodes[start_id].it_p = ret.first; pf_nodes[start_id].prev = INVALID_PREV; pf_nodes[start_id].lastVisited = currentVisit; pf_nodes[start_id].way = 0; pf_nodes[start_id].dir = 0; // TODO confirm random unsigned rand = (GetIdx(start)) * GAMECLIENT.GetGFNumber() % 6; //RANDOM.Rand(__FILE__, __LINE__, y_start * GetWidth() + x_start, 6); while(!todo.empty()) { // Knoten mit den geringsten Wegkosten auswählen PathfindingPoint best = *todo.begin(); // Knoten behandelt --> raus aus der todo Liste todo.erase(todo.begin()); //printf("x: %u y: %u\n", best.x, best.y); // ID des besten Punktes ausrechnen unsigned best_id = best.id; // Dieser Knoten wurde aus dem set entfernt, daher wird der entsprechende Iterator // auf das Ende (also nicht definiert) gesetzt, quasi als "NULL"-Ersatz pf_nodes[best_id].it_p = todo.end(); // Ziel schon erreicht? Allerdings Null-Weg, wenn Start=Ende ist, verbieten if(dest == best.pt && pf_nodes[best_id].way) { // Ziel erreicht! // Jeweils die einzelnen Angaben zurückgeben, falls gewünscht (Pointer übergeben) if(length) *length = pf_nodes[best_id].way; if(route) route->resize(pf_nodes[best_id].way); // Route rekonstruieren und ggf. die erste Richtung speichern, falls gewünscht for(unsigned z = pf_nodes[best_id].way - 1; best_id != start_id; --z, best_id = pf_nodes[best_id].prev) { if(route) (*route)[z] = pf_nodes[best_id].dir; if(first_dir && z == 0) *first_dir = pf_nodes[best_id].dir; } // Fertig, es wurde ein Pfad gefunden return true; } // Maximaler Weg schon erreicht? In dem Fall brauchen wir keine weiteren Knoten von diesem aus bilden if(pf_nodes[best_id].way == max_route) continue; // Bei Zufälliger Richtung anfangen (damit man nicht immer denselben Weg geht, besonders für die Soldaten wichtig) unsigned start = random_route ? rand : 0; // Knoten in alle 6 Richtungen bilden for(unsigned z = start + 3; z < start + 9; ++z) { unsigned i = z % 6; // Koordinaten des entsprechenden umliegenden Punktes bilden MapPoint na = GetNeighbour(best.pt, i); // ID des umliegenden Knotens bilden unsigned xaid = MakeCoordID(na); // Knoten schon auf dem Feld gebildet? if (pf_nodes[xaid].lastVisited == currentVisit) { // Dann nur ggf. Weg und Vorgänger korrigieren, falls der Weg kürzer ist if(pf_nodes[xaid].it_p != todo.end() && pf_nodes[best_id].way + 1 < pf_nodes[xaid].way) { pf_nodes[xaid].way = pf_nodes[best_id].way + 1; pf_nodes[xaid].prev = best_id; todo.erase(pf_nodes[xaid].it_p); ret = todo.insert(PathfindingPoint(na, xaid)); pf_nodes[xaid].it_p = ret.first; pf_nodes[xaid].dir = i; } // Wir wollen nicht denselben Knoten noch einmal einfügen, daher Abbruch continue; } // Das Ziel wollen wir auf jedenfall erreichen lassen, daher nur diese zusätzlichen // Bedingungen, wenn es nicht das Ziel ist if(na != dest && IsNodeOK) { if(!IsNodeOK(*this, na, i, param)) continue; } // Zusätzliche Bedingungen, auch die das letzte Stück zum Ziel betreffen if(IsNodeToDestOk) { if(!IsNodeToDestOk(*this, na, i, param)) continue; } // Alles in Ordnung, Knoten kann gebildet werden pf_nodes[xaid].lastVisited = currentVisit; pf_nodes[xaid].way = pf_nodes[best_id].way + 1; pf_nodes[xaid].dir = i; pf_nodes[xaid].prev = best_id; ret = todo.insert(PathfindingPoint(na, xaid)); pf_nodes[xaid].it_p = ret.first; } } // Liste leer und kein Ziel erreicht --> kein Weg return false; }
/// Wegfinden ( A* ), O(v lg v) --> Wegfindung auf allgemeinen Terrain (ohne Straßen), für Wegbau und frei herumlaufende Berufe bool GameWorldBase::FindFreePathAlternatingConditions(const MapPoint start, const MapPoint dest, const bool random_route, const unsigned max_route, std::vector<unsigned char>* route, unsigned* length, unsigned char* first_dir, FP_Node_OK_Callback IsNodeOK, FP_Node_OK_Callback IsNodeOKAlternate, FP_Node_OK_Callback IsNodeToDestOk, const void* param, const bool record) const { // increase currentVisit, so we don't have to clear the visited-states at every run currentVisit++; //currentVisitEven++; // if the counter reaches its maxium, tidy up if (currentVisit == std::numeric_limits<unsigned>::max() - 1) { for (unsigned i = 0; i < (maxMapSize * maxMapSize); ++i) { pf_nodes[i].lastVisited = 0; pf_nodes[i].lastVisitedEven = 0; } currentVisit = 1; //currentVisitEven = 1; } std::list<PathfindingPoint> todo; bool prevstepEven=true; //flips between even and odd unsigned stepsTilSwitch=1; PathfindingPoint::Init(dest, this); // Anfangsknoten einfügen unsigned start_id = MakeCoordID(start); todo.push_back(PathfindingPoint(start, start_id)); // Und mit entsprechenden Werten füllen //pf_nodes[start_id].it_p = ret.first; pf_nodes[start_id].prevEven = INVALID_PREV; pf_nodes[start_id].lastVisitedEven = currentVisit; pf_nodes[start_id].wayEven = 0; pf_nodes[start_id].dirEven = 0; //LOG.lprintf("pf: from %i, %i to %i, %i \n", x_start, y_start, x_dest, y_dest); // TODO confirm random unsigned rand = GetIdx(start) * GAMECLIENT.GetGFNumber() % 6; //RANDOM.Rand(__FILE__, __LINE__, y_start * GetWidth() + x_start, 6); while(!todo.empty()) { if(!stepsTilSwitch) //counter for next step and switch condition { prevstepEven=!prevstepEven; stepsTilSwitch=todo.size(); //prevstepEven? LOG.lprintf("pf: even, to switch %i listsize %i ", stepsTilSwitch, todo.size()) : LOG.lprintf("pf: odd, to switch %i listsize %i ", stepsTilSwitch, todo.size()); } //else //prevstepEven? LOG.lprintf("pf: even, to switch %i listsize %i ", stepsTilSwitch, todo.size()) : LOG.lprintf("pf: odd, to switch %i listsize %i ", stepsTilSwitch, todo.size()); stepsTilSwitch--; // Knoten mit den geringsten Wegkosten auswählen PathfindingPoint best = *todo.begin(); // Knoten behandelt --> raus aus der todo Liste todo.erase(todo.begin()); //printf("x: %u y: %u\n", best.x, best.y); // ID des besten Punktes ausrechnen unsigned best_id = best.id; //LOG.lprintf(" now %i, %i id: %i \n", best.x, best.y, best_id); // Dieser Knoten wurde aus dem set entfernt, daher wird der entsprechende Iterator // auf das Ende (also nicht definiert) gesetzt, quasi als "NULL"-Ersatz //pf_nodes[best_id].it_p = todo.end(); // Ziel schon erreicht? Allerdings Null-Weg, wenn Start=Ende ist, verbieten if(dest == best.pt && ((prevstepEven && pf_nodes[best_id].wayEven) || (!prevstepEven && pf_nodes[best_id].way))) { // Ziel erreicht! // Jeweils die einzelnen Angaben zurückgeben, falls gewünscht (Pointer übergeben) if(length) *length = prevstepEven ? pf_nodes[best_id].wayEven : pf_nodes[best_id].way; if(route) prevstepEven? route->resize(pf_nodes[best_id].wayEven) : route->resize(pf_nodes[best_id].way); // Route rekonstruieren und ggf. die erste Richtung speichern, falls gewünscht bool alternate=prevstepEven; for(unsigned z = prevstepEven? pf_nodes[best_id].wayEven - 1 : pf_nodes[best_id].way - 1; best_id != start_id; --z, best_id = alternate? pf_nodes[best_id].prevEven : pf_nodes[best_id].prev, alternate=!alternate) { if(route) (*route)[z] = alternate? pf_nodes[best_id].dirEven : pf_nodes[best_id].dir; if(first_dir && z == 0) *first_dir = pf_nodes[best_id].dirEven; } // Fertig, es wurde ein Pfad gefunden return true; } // Maximaler Weg schon erreicht? In dem Fall brauchen wir keine weiteren Knoten von diesem aus bilden if((prevstepEven && pf_nodes[best_id].wayEven)==max_route || (!prevstepEven && pf_nodes[best_id].way == max_route)) continue; // Bei Zufälliger Richtung anfangen (damit man nicht immer denselben Weg geht, besonders für die Soldaten wichtig) unsigned startDir = random_route ? rand : 0; //LOG.lprintf("pf get neighbor nodes %i, %i id: %i \n", best.x, best.y, best_id); // Knoten in alle 6 Richtungen bilden for(unsigned z = startDir + 3; z < startDir + 9; ++z) { unsigned i = z % 6; // Koordinaten des entsprechenden umliegenden Punktes bilden MapPoint na = GetNeighbour(best.pt, i); // ID des umliegenden Knotens bilden unsigned xaid = MakeCoordID(na); // Knoten schon auf dem Feld gebildet? if ((prevstepEven && pf_nodes[xaid].lastVisited == currentVisit) || (!prevstepEven && pf_nodes[xaid].lastVisitedEven == currentVisit)) { continue; } // Das Ziel wollen wir auf jedenfall erreichen lassen, daher nur diese zusätzlichen // Bedingungen, wenn es nicht das Ziel ist if(na != dest && ((prevstepEven && IsNodeOK) || (!prevstepEven && IsNodeOKAlternate))) { if(prevstepEven) { if(!IsNodeOK(*this, na, i, param)) continue; } else { if (!IsNodeOKAlternate(*this, na, i, param)) continue; MapPoint p = best.pt; std::vector<MapPoint>evenlocationsonroute; bool alternate=prevstepEven; unsigned back_id=best_id; for(unsigned i=pf_nodes[best_id].way-1; i>1; i--, back_id = alternate? pf_nodes[back_id].prevEven : pf_nodes[back_id].prev, alternate=!alternate) // backtrack the plannend route and check if another "even" position is too close { unsigned char pdir = alternate? pf_nodes[back_id].dirEven : pf_nodes[back_id].dir; p = GetNeighbour(p, (pdir+3)%6); if(i%2==0) //even step { evenlocationsonroute.push_back(p); } } bool tooclose=false; //LOG.lprintf("pf from %i, %i to %i, %i now %i, %i ", x_start, y_start, x_dest, y_dest, xa, ya);//\n for(std::vector<MapPoint>::const_iterator it=evenlocationsonroute.begin();it!=evenlocationsonroute.end(); ++it) { //LOG.lprintf("dist to %i, %i ", temp, *it); if(CalcDistance(na, (*it))<2) { tooclose=true; break; } } //LOG.lprintf("\n"); if(CalcDistance(na, start)<2) continue; if(CalcDistance(na, dest)<2) continue; if(tooclose) continue; } } // Zusätzliche Bedingungen, auch die das letzte Stück zum Ziel betreffen if(IsNodeToDestOk) { if(!IsNodeToDestOk(*this, na, i, param)) continue; } // Alles in Ordnung, Knoten kann gebildet werden prevstepEven? pf_nodes[xaid].lastVisited = currentVisit : pf_nodes[xaid].lastVisitedEven = currentVisit; prevstepEven? pf_nodes[xaid].way = pf_nodes[best_id].wayEven + 1: pf_nodes[xaid].wayEven = pf_nodes[best_id].way + 1; prevstepEven? pf_nodes[xaid].dir = i : pf_nodes[xaid].dirEven = i; prevstepEven? pf_nodes[xaid].prev = best_id : pf_nodes[xaid].prevEven = best_id ; todo.push_back(PathfindingPoint(na, xaid)); //pf_nodes[xaid].it_p = ret.first; } } // Liste leer und kein Ziel erreicht --> kein Weg return false; }
void GameWorldBase::RecalcBQAroundPoint(const MapPoint pt) { RecalcBQ(pt); for(unsigned char i = 0; i < 6; ++i) RecalcBQ(GetNeighbour(pt, Direction::fromInt(i))); }
void phgNSBuildPc(NSSolver *ns) { GRID *g = ns->g; SIMPLEX *e; FLOAT *dt = ns->dt; int i, j, q, s, k, l; FLOAT Theta = _nsp->Theta, nu = _nsp->nu, Thet1, nu0 = 0; DOF *tmp_u1 = phgDofNew(g, _nsp->utype, Dim, "tmp u1", func_u); int viscosity_type = ns->viscosity_type; LTYPE ltype = ns->ltype; #if STEADY_STATE assert(fabs(Theta - 1) < 1e-12); Thet1 = 0; Unused(Thet1); Unused(dt); #else Thet1 = 1 - Theta; #endif /* STEADY_STATE */ ForAllElements(g, e) { int M = ns->u[1]->type->nbas; /* num of bases of Velocity */ int N = ns->p[1]->type->nbas; /* num of bases of Pressure */ int order = 2 * DofTypeOrder(ns->p[1], e) + DofTypeOrder(ns->u[1], e) - 1; /* highest order term (u \nabla p, psi) */ FLOAT Ap[N][N], Fp[N][N], Qp[N][N], bufp[N], rhs1 = 1; FLOAT F[M*Dim][M*Dim], B[N][M*Dim], Bt[M*Dim][N]; INT Ip[N]; QUAD *quad; FLOAT vol, det; const FLOAT *w, *p, *vw, *gu, *vTe; quad = phgQuadGetQuad3D(order); vw = phgQuadGetDofValues(e, ns->wind, quad); /* value wind */ gu = phgQuadGetDofValues(e, ns->gradu[1], quad); /* grad u^{n+1} */ if (ns_params->noniter_temp) vTe = phgQuadGetDofValues(e, ns->T[1], quad); /* value temp */ else vTe = phgQuadGetDofValues(e, ns->T[0], quad); /* value temp */ vol = 0; Bzero(Ap); Bzero(Fp); Bzero(Qp); Bzero(F); Bzero(Bt); Bzero(B); Bzero(bufp); p = quad->points; w = quad->weights; for (q = 0; q < quad->npoints; q++) { phgGeomGetCurvedJacobianAtLambda(g, e, p, &det); vol = fabs(det / 6.); for (i = 0; i < N; i++) { const FLOAT *gi = phgQuadGetBasisValues(e, ns->p[1], i, quad) + q; /* phi_i */ const FLOAT *ggi = phgQuadGetBasisCurvedGradient(e, ns->p[1], i, quad, q); /* grad phi_i */ for (j = 0; j < N; j++) { const FLOAT *gj = phgQuadGetBasisValues(e, ns->p[1], j, quad) + q; /* phi_j */ const FLOAT *ggj = phgQuadGetBasisCurvedGradient(e, ns->p[1], j, quad, q); /* grad phi_i */ nu = get_effective_viscosity(gu, *vTe, 0, viscosity_type); if (i == 0 && j == 0) nu0 += nu; #if ICE_BENCH_TEST || \ ESIMINT_TEST || \ HEINO_TEST || \ TEST_CASE == ICE_EXACT || \ TEST_CASE == ICE_GREEN_LAND Unused(dt); /* Note: B Q^-1 Bt ~ Ap(nu=1), * Fp(nu varies) is very different to Ap */ Ap[i][j] += vol*(*w) * INNER_PRODUCT(ggj, ggi); # if USE_QP_ONLY //Qp[i][j] += vol*(*w) * LEN_SCALING * PRES_SCALING /(nu) * (*gj) * (*gi); Qp[i][j] += vol*(*w) * 1. /(EQU_SCALING * nu) * (*gj) * (*gi); /* if (i < NVert && j < NVert) { */ /* Qp[i][j] += vol*(*w) * LEN_SCALING * PRES_SCALING / (nu) * (*gj) * (*gi); */ /* } else if (i == NVert && j == NVert) { */ /* Qp[i][j] += vol*(*w) * LEN_SCALING * PRES_SCALING / (nu) * (*gj) * (*gi); */ /* } */ # else Qp[i][j] += vol*(*w) * (*gj) * (*gi); # endif Fp[i][j] += vol*(*w) * (EQU_SCALING * nu * INNER_PRODUCT(ggj, ggi) ); #elif STEADY_STATE Ap[i][j] += vol*(*w) * INNER_PRODUCT(ggj, ggi); Qp[i][j] += vol*(*w) * (*gj) * (*gi); Fp[i][j] += vol*(*w) * (nu * INNER_PRODUCT(ggj, ggi) * EQU_SCALING ); #elif TIME_DEP_NON Ap[i][j] += vol*(*w) * INNER_PRODUCT(ggj, ggi); Qp[i][j] += vol*(*w) * (*gj) * (*gi); Fp[i][j] += vol*(*w) * ((*gj) * (*gi) / dt[0] + Theta * (nu * INNER_PRODUCT(ggj, ggi) ) ); #else TIME_DEP_LINEAR_ENTRY; /* Unavailable */ #endif /* STEADY_STATE */ } } vw += Dim; gu += DDim; vTe++; w++; p += Dim+1; } /* Map: Element -> system */ for (i = 0; i < N; i++) Ip[i] = phgMapE2L(_pcd->matFp->cmap, 0, e, i); /* * PCD boundary setup I: * Automaticly decide inflow boundary condition using wind direction. * * NOT active. * */ if (FALSE && !_nsp->pin_node) { for (i = 0; i < N; i++) { BOOLEAN flag_inflow = FALSE; for (s = 0; s < NFace; s++) { SHORT bases[NbasFace(ns->p[1])]; FLOAT *coord, vw_[3]; const FLOAT *lam, *normal; if (!(e->bound_type[s] & BDRY_MASK)) //if (!(e->bound_type[s] & INFLOW)) continue; /* boundary face */ phgDofGetBasesOnFace(ns->p[1], e, s, bases); for (j = 0; j < NbasFace(ns->p[1]); j++) if (i == bases[j]) { normal = phgGeomGetFaceOutNormal(g, e, s); coord = phgDofGetElementCoordinates(ns->p[1], e, i); lam = phgGeomXYZ2Lambda(g, e, coord[0], coord[1], coord[2]); phgDofEval(tmp_u1, e, lam, vw_); if (INNER_PRODUCT(vw_, normal) > 1e-8) flag_inflow = TRUE; } } if (flag_inflow) { Bzero(bufp); bufp[i] = 1.0; phgMatAddEntries(_pcd->matAp, 1, Ip + i, N, Ip, bufp); phgMatAddEntries(_pcd->matFp, 1, Ip + i, N, Ip, bufp); //phgMatAddEntries(_pcd->matQp, 1, Ip + i, N, Ip, bufp); phgVecAddEntries(_pcd->rhsScale, 0, 1, Ip + i, &rhs1); } else { /* interior node Or Neumann */ phgMatAddEntries(_pcd->matAp, 1, Ip + i, N, Ip, Ap[i]); phgMatAddEntries(_pcd->matFp, 1, Ip + i, N, Ip, Fp[i]); //phgMatAddEntries(_pcd->matQp, 1, Ip + i, N, Ip, Qp[i]); } phgMatAddEntries(_pcd->matQp, 1, Ip + i, N, Ip, Qp[i]); } } /* * PCD boundary setup II: * Enclose flow: use pinnode boundary. * * Qp is pinned, this is different to open flow. * * */ else if (_nsp->pin_node) { for (i = 0; i < N; i++) { if (phgDofDirichletBC(_pcd->pbc, e, i, NULL, bufp, NULL, DOF_PROJ_NONE)) { #if PIN_AT_ROOT if (g->rank != 0) phgError(1, "Pinned node only on rank 0!\n"); if (e->verts[i] != ns->pinned_node_id) phgError(1, "pinned node [%d] & [%d] doesn't coincide when build pc!\n", e->verts[i], ns->pinned_node_id); #else if (GlobalVertex(g, e->verts[i]) != ns->pinned_node_id) phgError(1, "pinned node [%d] & [%d] doesn't coincide when build pc!\n", e->verts[i], ns->pinned_node_id); #endif /* PIN_AT_ROOT */ phgMatAddEntries(_pcd->matAp, 1, Ip + i, N, Ip, bufp); phgMatAddEntries(_pcd->matFp, 1, Ip + i, N, Ip, bufp); phgMatAddEntries(_pcd->matQp, 1, Ip + i, N, Ip, bufp); phgVecAddEntries(_pcd->rhsScale, 0, 1, Ip + i, &rhs1); } else { /* interior node Or Neumann */ phgMatAddEntries(_pcd->matAp, 1, Ip + i, N, Ip, Ap[i]); phgMatAddEntries(_pcd->matFp, 1, Ip + i, N, Ip, Fp[i]); phgMatAddEntries(_pcd->matQp, 1, Ip + i, N, Ip, Qp[i]); } } } /* * PCD boundary setup III: * Open flow: there could be varies kinds of combination on seting up * boundary conditon, but Inflow:Robin & Outflow:scaled Dirich is * prefered. See Ref[2]. * * */ else { for (i = 0; i < N; i++) { /*****************/ /* Inflow */ /*****************/ #warning PCD B.C.: Step 2.1. build mat, all neumann, add dirich entries if (FALSE && phgDofDirichletBC(_pcd->dof_inflow, e, i, NULL, bufp, NULL, DOF_PROJ_NONE)) { phgMatAddEntries(_pcd->matAp, 1, Ip + i, N, Ip, bufp); phgMatAddEntries(_pcd->matFp, 1, Ip + i, N, Ip, bufp); phgMatAddEntries(_pcd->matQp, 1, Ip + i, N, Ip, bufp); phgVecAddEntries(_pcd->rhsScale, 0, 1, Ip + i, &rhs1); } else if (FALSE && phgDofDirichletBC(_pcd->dof_outflow, e, i, NULL, bufp, NULL, DOF_PROJ_NONE) && !(phgDofGetElementBoundaryType(ns->p[1], e, i) & INFLOW) ) { ERROR_MSG("Fp, Qp"); nu = get_effective_viscosity(NULL, 0, 0, viscosity_type); phgMatAddEntries(_pcd->matAp, 1, Ip + i, N, Ip, bufp); bufp[i] *= EQU_SCALING * nu; phgMatAddEntries(_pcd->matFp, 1, Ip + i, N, Ip, bufp); phgVecAddEntries(_pcd->rhsScale, 0, 1, Ip + i, &rhs1); //phgMatAddEntries(_pcd->matQp, 1, Ip + i, N, Ip, bufp); } else if (FALSE && phgDofDirichletBC(_pcd->pbc, e, i, NULL, bufp, NULL, DOF_PROJ_NONE)) { phgMatAddEntries(_pcd->matAp, 1, Ip + i, N, Ip, bufp); phgMatAddEntries(_pcd->matFp, 1, Ip + i, N, Ip, bufp); phgMatAddEntries(_pcd->matQp, 1, Ip + i, N, Ip, bufp); phgVecAddEntries(_pcd->rhsScale, 0, 1, Ip + i, &rhs1); } else if (FALSE) { /* interior node Or Neumann */ ERROR_MSG("Fp, Qp"); phgMatAddEntries(_pcd->matAp, 1, Ip + i, N, Ip, Ap[i]); phgMatAddEntries(_pcd->matFp, 1, Ip + i, N, Ip, Fp[i]); //phgMatAddEntries(_pcd->matQp, 1, Ip + i, N, Ip, Qp[i]); } /******************/ /* No bdry */ /******************/ //phgMatAddEntries(_pcd->matFp, 1, Ip + i, N, Ip, Fp[i]); phgMatAddEntries(_pcd->matQp, 1, Ip + i, N, Ip, Qp[i]); } } if (0) { /* Special term <[[p_i]], [[p_j]]> */ int face; nu0 /= quad->npoints; for (face = 0; face < NFace; face++) { FLOAT area = phgGeomGetFaceArea(g, e, face); //FLOAT value = {area, -area}; FLOAT values[2] = {vol * 1. /(EQU_SCALING * nu0), -vol * 1. /(EQU_SCALING * nu0)}; SIMPLEX *e_neigh; phgMatAddEntries(_pcd->matQp, 1, Ip+NVert, 1, Ip+NVert, values); if ((e_neigh = GetNeighbour(e, face)) != NULL) { INT Ip_neigh = phgMapE2L(_pcd->matFp->cmap, 0, e_neigh, NVert); phgMatAddEntries(_pcd->matQp, 1, Ip+NVert, 1, &Ip_neigh, values + 1); } } } } /* end element */
void GameWorld::Scan(glArchivItem_Map* map) { width_ = map->getHeader().getWidth(); //-V807 height_ = map->getHeader().getHeight(); lt = LandscapeType(map->getHeader().getGfxSet()); Init(); // Dummy-Hafenpos für Index 0 einfügen // ask Oliverr why! // -> I just did, the dummy is so that the harbor "0" might be used for ships with no particular destination // poc: if you ever remove this dummy go to GameWorldBase::CalcDistanceToNearestHarbor and fix the loop to include the first harbor again (think Ive seen other instances of dummyadjusted loops as well...) GameWorldBase::HarborPos dummy(MapPoint(0, 0)); harbor_pos.push_back(dummy); // Andere Sachen setzen MapPoint pt(0, 0); for(pt.y = 0; pt.y < height_; ++pt.y) { for(pt.x = 0; pt.x < width_; ++pt.x) { MapNode& node = GetNode(pt); node.roads[2] = node.roads[1] = node.roads[0] = 0; node.roads_real[2] = node.roads_real[1] = node.roads_real[0] = false; node.altitude = map->GetMapDataAt(MAP_ALTITUDE, pt.x, pt.y); // Aufpassen, dass die Terrainindizes im Rahmen liegen, ansonsten 0 nehmen, unbekanntes Terrain (Bsp. // Karte "Drachenebene") unsigned char t1 = map->GetMapDataAt(MAP_TERRAIN1, pt.x, pt.y), t2 = map->GetMapDataAt(MAP_TERRAIN2, pt.x, pt.y); // Hafenplatz? if(TerrainData::IsHarborSpot(t1)) { GameWorldBase::HarborPos p(pt); node.harbor_id = harbor_pos.size(); harbor_pos.push_back(p); } else node.harbor_id = 0; node.t1 = TerrainData::MapIdx2Terrain(t1); node.t2 = TerrainData::MapIdx2Terrain(t2); node.resources = map->GetMapDataAt(MAP_RESOURCES, pt.x, pt.y); // Wasser? if(node.resources == 0x20 || node.resources == 0x21) { // TODO: Berge hatten komische Wasserbeeinflussung // ggf 0-4 Wasser setzen if( (node.t1 == TT_DESERT || node.t2 == TT_DESERT) || TerrainData::IsWater(node.t1) || TerrainData::IsWater(node.t2) ) node.resources = 0; // Kein Wasser, in der Wüste, da isses trocken! else if( (node.t1 == TT_STEPPE || node.t2 == TT_STEPPE) ) node.resources = 0x23; // 2 Wasser else if( (node.t1 == TT_SAVANNAH || node.t2 == TT_SAVANNAH) ) node.resources = 0x25; // 4 Wasser else node.resources = 0x27; // 7 Wasser } node.reserved = false; node.owner = 0; for(unsigned i = 0; i < 4; ++i) node.boundary_stones[i] = 0; node.sea_id = 0; // FOW-Zeug initialisieren for(unsigned i = 0; i < GAMECLIENT.GetPlayerCount(); ++i) { MapNode::FoWData& fow = node.fow[i]; switch(GAMECLIENT.GetGGS().exploration) { case GlobalGameSettings::EXP_DISABLED: { fow.visibility = VIS_VISIBLE; } break; case GlobalGameSettings::EXP_CLASSIC: { fow.visibility = VIS_INVISIBLE; } break; case GlobalGameSettings::EXP_FOGOFWAR: { fow.visibility = VIS_INVISIBLE; } break; case GlobalGameSettings::EXP_FOGOFWARE_EXPLORED: { fow.visibility = VIS_FOW; } break; } fow.last_update_time = 0; fow.object = NULL; fow.roads[0] = fow.roads[1] = fow.roads[2] = 0; fow.owner = 0; for(unsigned z = 0; z < 4; ++z) fow.boundary_stones[z] = 0; } } } std::vector< MapPoint > headquarter_positions; // Objekte auslesen for(pt.y = 0; pt.y < height_; ++pt.y) { for(pt.x = 0; pt.x < width_; ++pt.x) { unsigned int pos = GetIdx(pt); unsigned char lc = map->GetMapDataAt(MAP_LANDSCAPE, pt.x, pt.y); switch(map->GetMapDataAt(MAP_TYPE, pt.x, pt.y)) { // Player Startpos (provisorisch) case 0x80: { headquarter_positions.push_back(pt); if(lc < GAMECLIENT.GetPlayerCount()) { GetPlayer(lc).hqPos = pt; nodes[pos].obj = NULL; } } break; // Baum 1-4 case 0xC4: { if(lc >= 0x30 && lc <= 0x3D) nodes[pos].obj = new noTree(pt, 0, 3); else if(lc >= 0x70 && lc <= 0x7D) nodes[pos].obj = new noTree(pt, 1, 3); else if(lc >= 0xB0 && lc <= 0xBD) nodes[pos].obj = new noTree(pt, 2, 3); else if(lc >= 0xF0 && lc <= 0xFD) nodes[pos].obj = new noTree(pt, 3, 3); else { LOG.lprintf("Unbekannter Baum1-4 auf x=%d, y=%d: id=%d (0x%0X)\n", pt.x, pt.y, lc, lc); nodes[pos].obj = NULL; } } break; // Baum 5-8 case 0xC5: { if(lc >= 0x30 && lc <= 0x3D) nodes[pos].obj = new noTree(pt, 4, 3); else if(lc >= 0x70 && lc <= 0x7D) nodes[pos].obj = new noTree(pt, 5, 3); else if(lc >= 0xB0 && lc <= 0xBD) nodes[pos].obj = new noTree(pt, 6, 3); else if(lc >= 0xF0 && lc <= 0xFD) nodes[pos].obj = new noTree(pt, 7, 3); else { LOG.lprintf("Unbekannter Baum5-8 auf x=%d, y=%d: id=%d (0x%0X)\n", pt.x, pt.y, lc, lc); nodes[pos].obj = NULL; } } break; // Baum 9 case 0xC6: { if(lc >= 0x30 && lc <= 0x3D) nodes[pos].obj = new noTree(pt, 8, 3); else { LOG.lprintf("Unbekannter Baum9 auf x=%d, y=%d: id=%d (0x%0X)\n", pt.x, pt.y, lc, lc); nodes[pos].obj = NULL; } } break; // Sonstiges Naturzeug ohne Funktion, nur zur Dekoration case 0xC8: { /// @todo mis0bobs unvollständig (dieses lagerzelt), 4 und 5 überhaupt nicht erwähnt // mis1bobs, 2 und 3 sind vollständig eingebaut // Objekte aus der map_?_z.lst if(lc <= 0x0A) nodes[pos].obj = new noEnvObject(pt, 500 + lc); // "wasserstein" aus der map_?_z.lst else if(lc == 0x0B) nodes[pos].obj = new noStaticObject(pt, 500 + lc); // Objekte aus der map_?_z.lst else if(lc >= 0x0C && lc <= 0x0F) nodes[pos].obj = new noEnvObject(pt, 500 + lc); // Objekte aus der map.lst else if(lc >= 0x10 && lc <= 0x14) nodes[pos].obj = new noEnvObject(pt, 542 + lc - 0x10); // gestrandetes Schiff (mis0bobs, unvollständig) else if(lc == 0x15) nodes[pos].obj = new noStaticObject(pt, (lc - 0x15) * 2, 0, 1); // das Tor aus der map_?_z.lst else if(lc == 0x16) nodes[pos].obj = new noStaticObject(pt, 560, 0xFFFF, 2); // das geöffnete Tor aus map_?_z.lst else if(lc == 0x17) nodes[pos].obj = new noStaticObject(pt, 561, 0xFFFF, 2); // Stalagmiten (mis1bobs) else if(lc >= 0x18 && lc <= 0x1E) nodes[pos].obj = new noStaticObject(pt, (lc - 0x18) * 2, 1); // toter Baum (mis1bobs) else if(lc >= 0x1F && lc <= 0x20) nodes[pos].obj = new noStaticObject(pt, 20 + (lc - 0x1F) * 2, 1); // Gerippe (mis1bobs) else if(lc == 0x21) nodes[pos].obj = new noEnvObject(pt, 30, 1); // Objekte aus der map.lst else if(lc >= 0x22 && lc <= 0x27) nodes[pos].obj = new noEnvObject(pt, 550 + lc - 0x22); // Objekte aus der map.lst else if(lc >= 0x28 && lc <= 0x2B) nodes[pos].obj = new noEnvObject(pt, 556 + lc - 0x28); // die "kaputten" Gebäuderuinen usw (mis2bobs) else if(lc >= 0x2C && lc <= 0x2D) nodes[pos].obj = new noStaticObject(pt, (lc - 0x2C) * 2, 2); else if(lc == 0x2E) nodes[pos].obj = new noStaticObject(pt, (lc - 0x2C) * 2, 2, 1); else if(lc == 0x2F) nodes[pos].obj = new noStaticObject(pt, (lc - 0x2C) * 2, 2, 2); else if(lc == 0x30) nodes[pos].obj = new noEnvObject(pt, (lc - 0x2C) * 2, 2); // der Wikinger (mis3bobs) else if(lc == 0x31) nodes[pos].obj = new noStaticObject(pt, 0, 2); else { LOG.lprintf("Unbekanntes Naturzeug auf x=%d, y=%d: id=%d (0x%0X)\n", pt.x, pt.y, lc, lc); nodes[pos].obj = NULL; } } break; // Granit Typ 1 case 0xCC: { if(lc >= 0x01 && lc <= 0x06) nodes[pos].obj = new noGranite(GT_1, lc - 1); else { LOG.lprintf("Unbekannter Granit1 auf x=%d, y=%d: id=%d (0x%0X)\n", pt.x, pt.y, lc, lc); nodes[pos].obj = NULL; } } break; // Granit Typ 2 case 0xCD: { if(lc >= 0x01 && lc <= 0x06) nodes[pos].obj = new noGranite(GT_2, lc - 1); else { LOG.lprintf("Unbekannter Granit2 auf x=%d, y=%d: id=%d (0x%0X)\n", pt.x, pt.y, lc, lc); nodes[pos].obj = NULL; } } break; // Nichts case 0: { nodes[pos].obj = NULL; } break; default: { /*LOG.lprintf("Unbekanntes Objekt %d (0x%0X) auf x=%d, y=%d: id=%d (0x%0X)\n", map->map_type[y*width+x], map->map_type[y*width+x], x, y, lc, lc); */ nodes[pos].obj = NULL; } break; } } } // BQ mit nichts erstmal inititalisieren (HQ-Setzen berechnet diese neu und braucht sie) for(pt.y = 0; pt.y < height_; ++pt.y) { for(pt.x = 0; pt.x < width_; ++pt.x) { SetBQ(pt, BQ_NOTHING); } } //random locations? -> randomize them :) if (GAMECLIENT.GetGGS().random_location) { ptrdiff_t (*p_myrandom)(ptrdiff_t) = myRandom; std::random_shuffle(headquarter_positions.begin(), headquarter_positions.end(), p_myrandom); for (unsigned i = 0; i < GAMECLIENT.GetPlayerCount(); ++i) { GetPlayer(i).hqPos = headquarter_positions.at(i); } } // HQ setzen for(unsigned i = 0; i < GAMECLIENT.GetPlayerCount(); ++i) { // Existiert überhaupt ein HQ? if(GetPlayer(i).hqPos.x != 0xFFFF) { if(GetPlayer(i).ps == PS_OCCUPIED || GetPlayer(i).ps == PS_KI) { nobHQ* hq = new nobHQ(GetPlayer(i).hqPos, i, GetPlayer(i).nation); SetNO(hq, GetPlayer(i).hqPos); GetPlayer(i).AddWarehouse(reinterpret_cast<nobBaseWarehouse*>(hq)); } /*else GetNode(GetPlayer(i).hqx,GetPlayer(i).hqy).obj = 0;*/ } } // Tiere auslesen for(pt.y = 0; pt.y < height_; ++pt.y) { for(pt.x = 0; pt.x < width_; ++pt.x) { unsigned pos = GetIdx(pt); // Tiere setzen Species species; switch(map->GetMapDataAt(MAP_ANIMALS, pt.x, pt.y)) { // TODO: Welche ID ist Polarbär? case 1: species = Species(SPEC_RABBITWHITE+RANDOM.Rand(__FILE__, __LINE__, 0, 2)); break; // zufällige Hasenart nehmen case 2: species = SPEC_FOX; break; case 3: species = SPEC_STAG; break; case 4: species = SPEC_DEER; break; case 5: species = SPEC_DUCK; break; case 6: species = SPEC_SHEEP; break; default: species = SPEC_NOTHING; break; } if(species != SPEC_NOTHING) { noAnimal* animal = new noAnimal(species, pt); AddFigure(animal, pt); // Loslaufen animal->StartLiving(); } /// 4 Fische setzen if(map->GetMapDataAt(MAP_RESOURCES, pos) > 0x80 && map->GetMapDataAt(MAP_RESOURCES, pos) < 0x90) GetNode(pt).resources = 0x84; } } /// Weltmeere vermessen for(pt.y = 0; pt.y < height_; ++pt.y) { for(pt.x = 0; pt.x < width_; ++pt.x) { // Noch kein Meer an diesem Punkt? if(!GetNode(pt).sea_id) { // Aber trotzdem Teil eines noch nicht vermessenen Meeres? if(IsSeaPoint(pt)) { unsigned sea_size = MeasureSea(pt, seas.size()); seas.push_back(Sea(sea_size)); } } } } /// Die Meere herausfinden, an die die Hafenpunkte grenzen for(unsigned i = 0; i < harbor_pos.size(); ++i) { for(unsigned z = 0; z < 6; ++z) harbor_pos[i].cps[z].sea_id = IsCoastalPoint(GetNeighbour(harbor_pos[i].pos, z)); } // Nachbarn der einzelnen Hafenplätze ermitteln CalcHarborPosNeighbors(); /// Schatten und BQ berechnen for(pt.y = 0; pt.y < height_; ++pt.y) { for(pt.x = 0; pt.x < width_; ++pt.x) { RecalcShadow(pt); SetBQ(pt, GAMECLIENT.GetPlayerID()); } } /// Bei FoW und aufgedeckt müssen auch die ersten FoW-Objekte erstellt werden if(GAMECLIENT.GetGGS().exploration == GlobalGameSettings::EXP_FOGOFWARE_EXPLORED) { for(pt.y = 0; pt.y < height_; ++pt.y) { for(pt.x = 0; pt.x < width_; ++pt.x) { // Alle Spieler durchgehen for(unsigned i = 0; i < GAMECLIENT.GetPlayerCount(); ++i) { // An der Stelle FOW für diesen Spieler? if(GetNode(pt).fow[i].visibility == VIS_FOW) SaveFOWNode(pt, i); } } } } }