static Subsidy *FindSubsidyPassengerRoute() { assert(Subsidy::CanAllocateItem()); const Town *src = Town::GetRandom(); if (src->population < SUBSIDY_PAX_MIN_POPULATION || src->pct_pass_transported > SUBSIDY_MAX_PCT_TRANSPORTED) { return NULL; } const Town *dst = Town::GetRandom(); if (dst->population < SUBSIDY_PAX_MIN_POPULATION || src == dst) { return NULL; } if (DistanceManhattan(src->xy, dst->xy) > SUBSIDY_MAX_DISTANCE) return NULL; if (CheckSubsidyDuplicate(CT_PASSENGERS, ST_TOWN, src->index, ST_TOWN, dst->index)) return NULL; Subsidy *s = new Subsidy(); s->cargo_type = CT_PASSENGERS; s->src_type = s->dst_type = ST_TOWN; s->src = src->index; s->dst = dst->index; return s; }
/* Calcs the heuristic to the target station or tile. For train stations, it * takes into account the direction of approach. */ static int32 NPFCalcStationOrTileHeuristic(AyStar *as, AyStarNode *current, OpenListNode *parent) { NPFFindStationOrTileData *fstd = (NPFFindStationOrTileData*)as->user_target; NPFFoundTargetData *ftd = (NPFFoundTargetData*)as->user_path; TileIndex from = current->tile; TileIndex to = fstd->dest_coords; uint dist; /* for train-stations, we are going to aim for the closest station tile */ if (as->user_data[NPF_TYPE] != TRANSPORT_WATER && fstd->station_index != INVALID_STATION) to = CalcClosestStationTile(fstd->station_index, from, fstd->station_type); if (as->user_data[NPF_TYPE] == TRANSPORT_ROAD) { /* Since roads only have diagonal pieces, we use manhattan distance here */ dist = DistanceManhattan(from, to) * NPF_TILE_LENGTH; } else { /* Ships and trains can also go diagonal, so the minimum distance is shorter */ dist = NPFDistanceTrack(from, to); } DEBUG(npf, 4, "Calculating H for: (%d, %d). Result: %d", TileX(current->tile), TileY(current->tile), dist); if (dist < ftd->best_bird_dist) { ftd->best_bird_dist = dist; ftd->best_trackdir = (Trackdir)current->user_data[NPF_TRACKDIR_CHOICE]; } return dist; }
/** * Add a node to the component and create empty edges associated with it. Set * the station's last_component to this component. Calculate the distances to all * other nodes. The distances to _all_ nodes are important as the demand * calculator relies on their availability. * @param st New node's station. * @return New node's ID. */ NodeID LinkGraph::AddNode(const Station *st) { const GoodsEntry &good = st->goods[this->cargo]; NodeID new_node = this->Size(); this->nodes.Append(); /* Avoid reducing the height of the matrix as that is expensive and we * most likely will increase it again later which is again expensive. */ this->edges.Resize(new_node + 1U, max(new_node + 1U, this->edges.Height())); this->nodes[new_node].Init(st->index, HasBit(good.acceptance_pickup, GoodsEntry::GES_ACCEPTANCE)); BaseEdge *new_edges = this->edges[new_node]; /* Reset the first edge starting at the new node */ new_edges[new_node].next_edge = INVALID_NODE; for (NodeID i = 0; i <= new_node; ++i) { uint distance = DistanceManhattan(st->xy, Station::Get(this->nodes[i].station)->xy); new_edges[i].Init(distance); this->edges[i][new_node].Init(distance); } return new_node; }
/** * Checks if the source and destination of a subsidy are inside the distance limit. * @param src_type Type of \a src. * @param src Index of source. * @param dst_type Type of \a dst. * @param dst Index of destination. * @return True if they are inside the distance limit. */ static bool CheckSubsidyDistance(SourceType src_type, SourceID src, SourceType dst_type, SourceID dst) { TileIndex tile_src = (src_type == ST_TOWN) ? Town::Get(src)->xy : Industry::Get(src)->location.tile; TileIndex tile_dst = (dst_type == ST_TOWN) ? Town::Get(dst)->xy : Industry::Get(dst)->location.tile; return (DistanceManhattan(tile_src, tile_dst) <= SUBSIDY_MAX_DISTANCE); }
static const Depot *FindClosestShipDepot(const Vehicle *v, uint max_distance) { /* Find the closest depot */ const Depot *depot; const Depot *best_depot = NULL; /* If we don't have a maximum distance, i.e. distance = 0, * we want to find any depot so the best distance of no * depot must be more than any correct distance. On the * other hand if we have set a maximum distance, any depot * further away than max_distance can safely be ignored. */ uint best_dist = max_distance == 0 ? UINT_MAX : max_distance + 1; FOR_ALL_DEPOTS(depot) { TileIndex tile = depot->xy; if (IsShipDepotTile(tile) && IsTileOwner(tile, v->owner)) { uint dist = DistanceManhattan(tile, v->tile); if (dist < best_dist) { best_dist = dist; best_depot = depot; } } } return best_depot; }
/** * Tries to create a passenger subsidy between two towns. * @return True iff the subsidy was created. */ bool FindSubsidyPassengerRoute() { if (!Subsidy::CanAllocateItem()) return false; Town *src = Town::GetRandom(); if (src->cache.population < SUBSIDY_PAX_MIN_POPULATION || src->GetPercentTransported(CT_PASSENGERS) > SUBSIDY_MAX_PCT_TRANSPORTED) { return false; } const Town *dst = NULL; if (CargoHasDestinations(CT_PASSENGERS)) { /* Try to get a town from the demand destinations. */ CargoLink *link = src->GetRandomLink(CT_PASSENGERS, false); if (link == src->cargo_links[CT_PASSENGERS].End()) return NULL; if (link->dest != NULL && link->dest->GetType() != ST_TOWN) return NULL; dst = static_cast<const Town *>(link->dest); } if (dst == NULL) dst = Town::GetRandom(); if (dst->cache.population < SUBSIDY_PAX_MIN_POPULATION || src == dst) { return false; } if (DistanceManhattan(src->xy, dst->xy) > SUBSIDY_MAX_DISTANCE) return false; if (CheckSubsidyDuplicate(CT_PASSENGERS, ST_TOWN, src->index, ST_TOWN, dst->index)) return false; CreateSubsidy(CT_PASSENGERS, ST_TOWN, src->index, ST_TOWN, dst->index); return true; }
/** * Recomputes Station::industries_near, list of industries possibly * accepting cargo in station's catchment radius */ void Station::RecomputeIndustriesNear() { this->industries_near.Clear(); if (this->rect.IsEmpty()) return; RectAndIndustryVector riv = { this->GetCatchmentRect(), &this->industries_near }; /* Compute maximum extent of acceptance rectangle wrt. station sign */ TileIndex start_tile = this->xy; uint max_radius = max( max(DistanceManhattan(start_tile, TileXY(riv.rect.left, riv.rect.top)), DistanceManhattan(start_tile, TileXY(riv.rect.left, riv.rect.bottom))), max(DistanceManhattan(start_tile, TileXY(riv.rect.right, riv.rect.top)), DistanceManhattan(start_tile, TileXY(riv.rect.right, riv.rect.bottom))) ); CircularTileSearch(&start_tile, 2 * max_radius + 1, &FindIndustryToDeliver, &riv); }
/* This example shows how three different distance metrics calculate the same three points. Euclidean Distance pos1->pos2: 5.20 pos2->pos3: 5.20 pos3->pos1: 10.39 Manhattan Distance pos1->pos2: 9.00 pos2->pos3: 9.00 pos3->pos1: 18.00 Chebyshev Distance pos1->pos2: 3.00 pos2->pos3: 3.00 pos3->pos1: 6.00 */ void ExampleDistance(int argIndex, int argc, char **argv) { double pos1[3] = { 1.0, 2.0, 3.0 }; double pos2[3] = { 4.0, 5.0, 6.0 }; double pos3[3] = { 7.0, 8.0, 9.0 }; printf("Euclidean Distance\n"); printf("pos1->pos2: %.2f\n", DistanceEuclidean(pos1,0,pos2,0,3)); printf("pos2->pos3: %.2f\n", DistanceEuclidean(pos2,0,pos3,0,3)); printf("pos3->pos1: %.2f\n", DistanceEuclidean(pos3,0,pos1,0,3)); printf("\nManhattan Distance\n"); printf("pos1->pos2: %.2f\n", DistanceManhattan(pos1,0,pos2,0,3)); printf("pos2->pos3: %.2f\n", DistanceManhattan(pos2,0,pos3,0,3)); printf("pos3->pos1: %.2f\n", DistanceManhattan(pos3,0,pos1,0,3)); printf("\nChebyshev Distance\n"); printf("pos1->pos2: %.2f\n", DistanceChebyshev(pos1,0,pos2,0,3)); printf("pos2->pos3: %.2f\n", DistanceChebyshev(pos2,0,pos3,0,3)); printf("pos3->pos1: %.2f\n", DistanceChebyshev(pos3,0,pos1,0,3)); }
/** * Find a deleted waypoint close to a tile. * @param tile to search from * @param str the string to get the 'type' of * @param cid previous owner of the waypoint * @return the deleted nearby waypoint */ static Waypoint *FindDeletedWaypointCloseTo(TileIndex tile, StringID str, CompanyID cid) { Waypoint *wp, *best = NULL; uint thres = 8; FOR_ALL_WAYPOINTS(wp) { if (!wp->IsInUse() && wp->string_id == str && wp->owner == cid) { uint cur_dist = DistanceManhattan(tile, wp->xy); if (cur_dist < thres) { thres = cur_dist; best = wp; } } } return best; }
/** * Tries to create a passenger subsidy between two towns. * @return True iff the subsidy was created. */ bool FindSubsidyPassengerRoute() { if (!Subsidy::CanAllocateItem()) return false; const Town *src = Town::GetRandom(); if (src->cache.population < SUBSIDY_PAX_MIN_POPULATION || src->GetPercentTransported(CT_PASSENGERS) > SUBSIDY_MAX_PCT_TRANSPORTED) { return false; } const Town *dst = Town::GetRandom(); if (dst->cache.population < SUBSIDY_PAX_MIN_POPULATION || src == dst) { return false; } if (DistanceManhattan(src->xy, dst->xy) > SUBSIDY_MAX_DISTANCE) return false; if (CheckSubsidyDuplicate(CT_PASSENGERS, ST_TOWN, src->index, ST_TOWN, dst->index)) return false; CreateSubsidy(CT_PASSENGERS, ST_TOWN, src->index, ST_TOWN, dst->index); return true; }
/** * This function will activate a search around a central tile, looking for some houses * that fit the requested characteristics * @param parameter that is given by the callback. * bits 0..6 radius of the search * bits 7..8 search type i.e.: 0 = houseID/ 1 = classID/ 2 = grfID * @param tile TileIndex from which to start the search * @param house the HouseID that is associated to the house, the callback is called for * @return the Manhattan distance from the center tile, if any, and 0 if failure */ static uint32 GetDistanceFromNearbyHouse(uint8 parameter, TileIndex tile, HouseID house) { static TestTileOnSearchProc * const search_procs[3] = { SearchNearbyHouseID, SearchNearbyHouseClass, SearchNearbyHouseGRFID, }; TileIndex found_tile = tile; uint8 searchtype = GB(parameter, 6, 2); uint8 searchradius = GB(parameter, 0, 6); if (searchtype >= lengthof(search_procs)) return 0; // do not run on ill-defined code if (searchradius < 1) return 0; // do not use a too low radius SearchNearbyHouseData nbhd; nbhd.hs = HouseSpec::Get(house); nbhd.north_tile = tile + GetHouseNorthPart(house); // modifies 'house'! /* Use a pointer for the tile to start the search. Will be required for calculating the distance*/ if (CircularTileSearch(&found_tile, 2 * searchradius + 1, search_procs[searchtype], &nbhd)) { return DistanceManhattan(found_tile, tile); } return 0; }
static Subsidy *FindSubsidyCargoRoute() { assert(Subsidy::CanAllocateItem()); const Industry *i = Industry::GetRandom(); if (i == NULL) return NULL; CargoID cargo; int trans, total; /* Randomize cargo type */ if (i->produced_cargo[1] != CT_INVALID && HasBit(Random(), 0)) { cargo = i->produced_cargo[1]; trans = i->last_month_pct_transported[1]; total = i->last_month_production[1]; } else { cargo = i->produced_cargo[0]; trans = i->last_month_pct_transported[0]; total = i->last_month_production[0]; } /* Quit if no production in this industry * or if the pct transported is already large enough */ if (total == 0 || trans > SUBSIDY_MAX_PCT_TRANSPORTED || cargo == CT_INVALID) return NULL; /* Don't allow passengers subsidies from industry */ const CargoSpec *cs = CargoSpec::Get(cargo); if (cs->town_effect == TE_PASSENGERS) return NULL; SourceType dst_type; SourceID dst; if (cs->town_effect == TE_GOODS || cs->town_effect == TE_FOOD) { /* The destination is a town */ dst_type = ST_TOWN; const Town *t = Town::GetRandom(); /* Only want big towns */ if (t->population < SUBSIDY_CARGO_MIN_POPULATION) return NULL; if (DistanceManhattan(i->location.tile, t->xy) > SUBSIDY_MAX_DISTANCE) return NULL; dst = t->index; } else { /* The destination is an industry */ dst_type = ST_INDUSTRY; const Industry *i2 = Industry::GetRandom(); /* The industry must accept the cargo */ if (i2 == NULL || i == i2 || (cargo != i2->accepts_cargo[0] && cargo != i2->accepts_cargo[1] && cargo != i2->accepts_cargo[2])) { return NULL; } if (DistanceManhattan(i->location.tile, i2->location.tile) > SUBSIDY_MAX_DISTANCE) return NULL; dst = i2->index; } if (CheckSubsidyDuplicate(cargo, ST_INDUSTRY, i->index, dst_type, dst)) return NULL; Subsidy *s = new Subsidy(); s->cargo_type = cargo; s->src_type = ST_INDUSTRY; s->src = i->index; s->dst_type = dst_type; s->dst = dst; return s; }
static void ShipController(Ship *v) { uint32 r; const byte *b; Direction dir; Track track; TrackBits tracks; v->tick_counter++; v->current_order_time++; if (v->HandleBreakdown()) return; if (v->vehstatus & VS_STOPPED) return; ProcessOrders(v); v->HandleLoading(); if (v->current_order.IsType(OT_LOADING)) return; if (CheckShipLeaveDepot(v)) return; v->ShowVisualEffect(); if (!ShipAccelerate(v)) return; GetNewVehiclePosResult gp = GetNewVehiclePos(v); if (v->state != TRACK_BIT_WORMHOLE) { /* Not on a bridge */ if (gp.old_tile == gp.new_tile) { /* Staying in tile */ if (v->IsInDepot()) { gp.x = v->x_pos; gp.y = v->y_pos; } else { /* Not inside depot */ r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y); if (HasBit(r, VETS_CANNOT_ENTER)) goto reverse_direction; /* A leave station order only needs one tick to get processed, so we can * always skip ahead. */ if (v->current_order.IsType(OT_LEAVESTATION)) { v->current_order.Free(); SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP); /* Test if continuing forward would lead to a dead-end, moving into the dock. */ DiagDirection exitdir = VehicleExitDir(v->direction, v->state); TileIndex tile = TileAddByDiagDir(v->tile, exitdir); if (TrackStatusToTrackBits(GetTileTrackStatus(tile, TRANSPORT_WATER, 0, exitdir)) == TRACK_BIT_NONE) goto reverse_direction; } else if (v->dest_tile != 0) { /* We have a target, let's see if we reached it... */ if (v->current_order.IsType(OT_GOTO_WAYPOINT) && DistanceManhattan(v->dest_tile, gp.new_tile) <= 3) { /* We got within 3 tiles of our target buoy, so let's skip to our * next order */ UpdateVehicleTimetable(v, true); v->IncrementRealOrderIndex(); v->current_order.MakeDummy(); } else { /* Non-buoy orders really need to reach the tile */ if (v->dest_tile == gp.new_tile) { if (v->current_order.IsType(OT_GOTO_DEPOT)) { if ((gp.x & 0xF) == 8 && (gp.y & 0xF) == 8) { VehicleEnterDepot(v); return; } } else if (v->current_order.IsType(OT_GOTO_STATION)) { v->last_station_visited = v->current_order.GetDestination(); /* Process station in the orderlist. */ Station *st = Station::Get(v->current_order.GetDestination()); if (st->facilities & FACIL_DOCK) { // ugly, ugly workaround for problem with ships able to drop off cargo at wrong stations ShipArrivesAt(v, st); v->BeginLoading(); } else { // leave stations without docks right aways v->current_order.MakeLeaveStation(); v->IncrementRealOrderIndex(); } } } } } } } else { /* New tile */ if (!IsValidTile(gp.new_tile)) goto reverse_direction; DiagDirection diagdir = DiagdirBetweenTiles(gp.old_tile, gp.new_tile); assert(diagdir != INVALID_DIAGDIR); tracks = GetAvailShipTracks(gp.new_tile, diagdir); if (tracks == TRACK_BIT_NONE) goto reverse_direction; /* Choose a direction, and continue if we find one */ track = ChooseShipTrack(v, gp.new_tile, diagdir, tracks); if (track == INVALID_TRACK) goto reverse_direction; b = _ship_subcoord[diagdir][track]; gp.x = (gp.x & ~0xF) | b[0]; gp.y = (gp.y & ~0xF) | b[1]; /* Call the landscape function and tell it that the vehicle entered the tile */ r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y); if (HasBit(r, VETS_CANNOT_ENTER)) goto reverse_direction; if (!HasBit(r, VETS_ENTERED_WORMHOLE)) { v->tile = gp.new_tile; v->state = TrackToTrackBits(track); /* Update ship cache when the water class changes. Aqueducts are always canals. */ WaterClass old_wc = GetEffectiveWaterClass(gp.old_tile); WaterClass new_wc = GetEffectiveWaterClass(gp.new_tile); if (old_wc != new_wc) v->UpdateCache(); } v->direction = (Direction)b[2]; } } else { /* On a bridge */ if (!IsTileType(gp.new_tile, MP_TUNNELBRIDGE) || !HasBit(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) { v->x_pos = gp.x; v->y_pos = gp.y; v->UpdatePosition(); if ((v->vehstatus & VS_HIDDEN) == 0) v->Vehicle::UpdateViewport(true); return; } } /* update image of ship, as well as delta XY */ v->x_pos = gp.x; v->y_pos = gp.y; v->z_pos = GetSlopePixelZ(gp.x, gp.y); getout: v->UpdatePosition(); v->UpdateViewport(true, true); return; reverse_direction: dir = ReverseDir(v->direction); v->direction = dir; goto getout; }
static void ShipController(Ship *v) { uint32 r; const byte *b; Direction dir; Track track; TrackBits tracks; v->tick_counter++; v->current_order_time++; if (v->breakdown_ctr != 0) { if (v->breakdown_ctr <= 2) { HandleBrokenShip(v); return; } if (!v->current_order.IsType(OT_LOADING)) v->breakdown_ctr--; } if (v->vehstatus & VS_STOPPED) return; ProcessOrders(v); v->HandleLoading(); if (v->current_order.IsType(OT_LOADING)) return; CheckShipLeaveDepot(v); if (!ShipAccelerate(v)) return; GetNewVehiclePosResult gp = GetNewVehiclePos(v); if (v->state != TRACK_BIT_WORMHOLE) { /* Not on a bridge */ if (gp.old_tile == gp.new_tile) { /* Staying in tile */ if (v->IsInDepot()) { gp.x = v->x_pos; gp.y = v->y_pos; } else { /* Not inside depot */ r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y); if (HasBit(r, VETS_CANNOT_ENTER)) goto reverse_direction; /* A leave station order only needs one tick to get processed, so we can * always skip ahead. */ if (v->current_order.IsType(OT_LEAVESTATION)) { v->current_order.Free(); SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH); } else if (v->dest_tile != 0) { /* We have a target, let's see if we reached it... */ if (v->current_order.IsType(OT_GOTO_WAYPOINT) && DistanceManhattan(v->dest_tile, gp.new_tile) <= 3) { /* We got within 3 tiles of our target buoy, so let's skip to our * next order */ UpdateVehicleTimetable(v, true); v->IncrementOrderIndex(); v->current_order.MakeDummy(); } else { /* Non-buoy orders really need to reach the tile */ if (v->dest_tile == gp.new_tile) { if (v->current_order.IsType(OT_GOTO_DEPOT)) { if ((gp.x & 0xF) == 8 && (gp.y & 0xF) == 8) { VehicleEnterDepot(v); return; } } else if (v->current_order.IsType(OT_GOTO_STATION)) { v->last_station_visited = v->current_order.GetDestination(); /* Process station in the orderlist. */ Station *st = Station::Get(v->current_order.GetDestination()); if (st->facilities & FACIL_DOCK) { // ugly, ugly workaround for problem with ships able to drop off cargo at wrong stations ShipArrivesAt(v, st); v->BeginLoading(); } else { // leave stations without docks right aways v->current_order.MakeLeaveStation(); v->IncrementOrderIndex(); } } } } } } } else { DiagDirection diagdir; /* New tile */ if (TileX(gp.new_tile) >= MapMaxX() || TileY(gp.new_tile) >= MapMaxY()) { goto reverse_direction; } dir = ShipGetNewDirectionFromTiles(gp.new_tile, gp.old_tile); assert(dir == DIR_NE || dir == DIR_SE || dir == DIR_SW || dir == DIR_NW); diagdir = DirToDiagDir(dir); tracks = GetAvailShipTracks(gp.new_tile, diagdir); if (tracks == TRACK_BIT_NONE) goto reverse_direction; /* Choose a direction, and continue if we find one */ track = ChooseShipTrack(v, gp.new_tile, diagdir, tracks); if (track == INVALID_TRACK) goto reverse_direction; b = _ship_subcoord[diagdir][track]; gp.x = (gp.x & ~0xF) | b[0]; gp.y = (gp.y & ~0xF) | b[1]; /* Call the landscape function and tell it that the vehicle entered the tile */ r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y); if (HasBit(r, VETS_CANNOT_ENTER)) goto reverse_direction; if (!HasBit(r, VETS_ENTERED_WORMHOLE)) { v->tile = gp.new_tile; v->state = TrackToTrackBits(track); } v->direction = (Direction)b[2]; } } else { /* On a bridge */ if (!IsTileType(gp.new_tile, MP_TUNNELBRIDGE) || !HasBit(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) { v->x_pos = gp.x; v->y_pos = gp.y; VehicleMove(v, !(v->vehstatus & VS_HIDDEN)); return; } } /* update image of ship, as well as delta XY */ dir = ShipGetNewDirection(v, gp.x, gp.y); v->x_pos = gp.x; v->y_pos = gp.y; v->z_pos = GetSlopeZ(gp.x, gp.y); getout: v->UpdateViewport(true, true); return; reverse_direction: dir = ReverseDir(v->direction); v->direction = dir; goto getout; }
bool Tools::Astar(Node start, Node destination, bool **pathingMap, std::vector<Node>& path) { //initialisation des structure necessaire bool solution = false; std::vector<Node> openNodes; std::vector<Node> closedNodes; std::map<Node,Node> parents; //initialisation du cout du premier node a 0 start.SetG(0); start.SetH(0); //ajout au vecteur ouvert openNodes.push_back(start); Node current; int currentIndex; while (solution == false) { //Si le vecteur ouvert est vide il n'y a pas de solution if(openNodes.empty()) { return false; } //index pour faciliter le retrer de current au vecteur ouvert int index = 0; //choisi le meilleur noeud dans le vecteur ouvert current = BestNodeInVector(openNodes, index); //ajout dans le vecteur fermer closedNodes.push_back(current); currentIndex = closedNodes.size() - 1; //on suprime le node choisi du vecteur ouvert openNodes.erase(openNodes.begin()+index); //verification si on est a destination alors on quitte la boucle if (current.GetX() == destination.GetX() && current.GetY() == destination.GetY()) { solution = true; break; } //Verification de la case en bas a gauche if(CheckInBound(current.GetBottomLeftNode()) && Passable(current.GetBottomLeftNode(),pathingMap) && !VectorContainsNode(current.GetBottomLeftNode(),closedNodes)) { if(!VectorContainsNode(current.GetBottomLeftNode(),openNodes)) { Node nodeToAdd = current.GetBottomLeftNode(); nodeToAdd.SetG(current.GetG()+14); nodeToAdd.SetH(DistanceManhattan(nodeToAdd,destination)*10); nodeToAdd.SetParent(&closedNodes[currentIndex]); parents[nodeToAdd] = closedNodes[currentIndex]; openNodes.push_back(nodeToAdd); } else { UpdateNodeScoreInVector(&closedNodes[currentIndex],current.GetBottomLeftNode(),openNodes, 14,parents); } } //Verification de la case en bas if(CheckInBound(current.GetBottomNode()) && Passable(current.GetBottomNode(),pathingMap) && !VectorContainsNode(current.GetBottomNode(),closedNodes)) { if(!VectorContainsNode(current.GetBottomNode(),openNodes)) { Node nodeToAdd = current.GetBottomNode(); nodeToAdd.SetG(current.GetG()+10); nodeToAdd.SetH(DistanceManhattan(nodeToAdd,destination)*10); nodeToAdd.SetParent(&closedNodes[currentIndex]); parents[nodeToAdd] = closedNodes[currentIndex]; openNodes.push_back(nodeToAdd); } else { UpdateNodeScoreInVector(&closedNodes[currentIndex],current.GetBottomNode(),openNodes, 10,parents); } } //Verification de la case a gauche if(CheckInBound(current.GetLeftNode()) && Passable(current.GetLeftNode(),pathingMap) && !VectorContainsNode(current.GetLeftNode(),closedNodes)) { if(!VectorContainsNode(current.GetLeftNode(),openNodes)) { Node nodeToAdd = current.GetLeftNode(); nodeToAdd.SetG(current.GetG()+10); nodeToAdd.SetH(DistanceManhattan(nodeToAdd,destination)*10); nodeToAdd.SetParent(&closedNodes[currentIndex]); parents[nodeToAdd] = closedNodes[currentIndex]; openNodes.push_back(nodeToAdd); } else { UpdateNodeScoreInVector(&closedNodes[currentIndex],current.GetLeftNode(),openNodes, 10,parents); } } // Verification de la case en haut a gauche if(CheckInBound(current.GetTopLeftNode()) && Passable(current.GetTopLeftNode(),pathingMap) && !VectorContainsNode(current.GetTopLeftNode(),closedNodes)) { if(!VectorContainsNode(current.GetTopLeftNode(),openNodes)) { Node nodeToAdd = current.GetTopLeftNode(); nodeToAdd.SetG(current.GetG()+14); nodeToAdd.SetH(DistanceManhattan(nodeToAdd,destination)*10); nodeToAdd.SetParent(&closedNodes[currentIndex]); parents[nodeToAdd] = closedNodes[currentIndex]; openNodes.push_back(nodeToAdd); } else { UpdateNodeScoreInVector(&closedNodes[currentIndex],current.GetTopLeftNode(),openNodes, 14,parents); } } //Verification de la case en haut if(CheckInBound(current.GetTopNode()) && Passable(current.GetTopNode(),pathingMap) && !VectorContainsNode(current.GetTopNode(),closedNodes)) { if(!VectorContainsNode(current.GetTopNode(),openNodes)) { Node nodeToAdd = current.GetTopNode(); nodeToAdd.SetG(current.GetG()+10); nodeToAdd.SetH(DistanceManhattan(nodeToAdd,destination)*10); nodeToAdd.SetParent(&closedNodes[currentIndex]); parents[nodeToAdd] = closedNodes[currentIndex]; openNodes.push_back(nodeToAdd); } else { UpdateNodeScoreInVector(&closedNodes[currentIndex],current.GetTopNode(),openNodes, 10,parents); } } // Verification de la case en haut a droite if(CheckInBound(current.GetTopRightNode()) && Passable(current.GetTopRightNode(),pathingMap) && !VectorContainsNode(current.GetTopRightNode(),closedNodes)) { if(!VectorContainsNode(current.GetTopRightNode(),openNodes)) { Node nodeToAdd = current.GetTopRightNode(); nodeToAdd.SetG(current.GetG()+14); nodeToAdd.SetH(DistanceManhattan(nodeToAdd,destination)*10); nodeToAdd.SetParent(&closedNodes[currentIndex]); parents[nodeToAdd] = closedNodes[currentIndex]; openNodes.push_back(nodeToAdd); } else { UpdateNodeScoreInVector(&closedNodes[currentIndex],current.GetTopRightNode(),openNodes, 14,parents); } } //Verification de la case a droite if(CheckInBound(current.GetRightNode()) && Passable(current.GetRightNode(),pathingMap) && !VectorContainsNode(current.GetRightNode(),closedNodes)) { if(!VectorContainsNode(current.GetRightNode(),openNodes)) { Node nodeToAdd = current.GetRightNode(); nodeToAdd.SetG(current.GetG()+10); nodeToAdd.SetH(DistanceManhattan(nodeToAdd,destination)*10); nodeToAdd.SetParent(&closedNodes[currentIndex]); parents[nodeToAdd] = closedNodes[currentIndex]; openNodes.push_back(nodeToAdd); } else { UpdateNodeScoreInVector(&closedNodes[currentIndex],current.GetRightNode(),openNodes, 10,parents); } } // Verification de la case en bas a droite if(CheckInBound(current.GetBottomRightNode()) && Passable(current.GetBottomRightNode(),pathingMap) && !VectorContainsNode(current.GetBottomRightNode(),closedNodes)) { if(!VectorContainsNode(current.GetBottomRightNode(),openNodes)) { Node nodeToAdd = current.GetBottomRightNode(); nodeToAdd.SetG(current.GetG()+14); nodeToAdd.SetH(DistanceManhattan(nodeToAdd,destination)*10); nodeToAdd.SetParent(&closedNodes[currentIndex]); parents[nodeToAdd] = closedNodes[currentIndex]; openNodes.push_back(nodeToAdd); } else { UpdateNodeScoreInVector(&closedNodes[currentIndex],current.GetBottomRightNode(),openNodes, 14,parents); } } } //Si on trouve une solution alors on Backtrack jusqu'au noeux d'origine if(solution == true) { // Implementation avec les pointeur parent directement dans les Node // Node *currentBactrack = &closedNodes[currentIndex]; // path.push_back(*currentBactrack); // while (currentBactrack->HasParent()){ // std::cout << "solution x : " << currentBactrack->GetX()<<" solution y : " << currentBactrack->GetY() << "\n"; // std::cout << "trackback : "<< path.size() << "\n"; // currentBactrack = currentBactrack->GetParent(); // std::cout << "test"; // path.push_back(*currentBactrack); // std::cout << " solution x : " << currentBactrack->GetX()<<" solution y : " << currentBactrack->GetY() << "\n"; // // } //Implementation en utilisant une map entre les Nodes et leur parents Node currentBactrack = closedNodes[currentIndex]; path.push_back(currentBactrack); std::map<Node,Node>::iterator it = parents.find(currentBactrack); while(it != parents.end()) { currentBactrack = it->second; //std::cout << "solution x : " << currentBactrack.GetX()<<" solution y : " << currentBactrack.GetY() << "\n"; //std::cout << "trackback : "<< path.size() << "\n"; path.push_back(currentBactrack); it = parents.find(currentBactrack); } } return true; }