Ejemplo n.º 1
0
cost QuickBucket::GetPath(xyLoc & s, xyLoc & g, std::vector<xyLoc> & path)
{
	search++;
	theHeap.clear();
	bucketsInUse = 0;	
	
	#ifdef BUCKET_STATISTICS
		int openSize = 1;
	#endif
		
	// Succesor buckets
	int id[6];	// 0: 0, 1: 2C-D, 2: 2D-2C, 3: 
	
	id[0] = GetBucketId(abCost(0,0));	// Get the bucket for the start state
	GenerateBucket(id[0]);
	buckets[id[0]].contents.push_back(bucketElement(s, 8));	// Insert the start state to the bucket, mark its parent as 8 = no parent
	
	buckets[id[0]].open = true;
	AddToOpen(abCost(0,0));					// Insert the bucket into the open list
	
	theMap[s.x][s.y].open = true;	// Set the start state as open
	theMap[s.x][s.y].generated = search;
	
	theMap[g.x][g.y].open = true;	// Also, set the goal state as open, but do not put it in the buckets yet	
	theMap[g.x][g.y].generated = search;
	
	abCost currCost;
	
	while (theMap[g.x][g.y].open && !theHeap.empty())
	{	
		// Select a bucket to expand
		currCost = theHeap[0];
		PopMin();
	
		#ifdef BUCKET_STATISTICS
			bucketExpansions++;			
		#endif 
		
		// Get the bucket and its successor buckets	
		id[0] = GetBucketId(currCost);
		buckets[id[0]].open = false;
	
		for (int i = 1; i < 6; i++)
		{
			id[i] = GetBucketId(abCost(currCost.a + A[i], currCost.b + B[i]));
		}
		GenerateBucket(id[5]+4);	// make sure we generate all the buckets with just one call
				
		// Expand all the contents of the bucket
		while (!buckets[id[0]].contents.empty())
		{
			bucketElement elem = buckets[id[0]].contents.back();
			buckets[id[0]].contents.pop_back();
			#ifdef BUCKET_STATISTICS			
				openSize--;
			#endif									
			if (theMap[elem.loc.x][elem.loc.y].open)
			{
				#ifdef BUCKET_STATISTICS
					elementExpansions++;
				#endif
				
				theMap[elem.loc.x][elem.loc.y].open = false;
				theMap[elem.loc.x][elem.loc.y].parent = elem.parent;
				
				//unsigned char neighbors = theMap[elem.loc.x][elem.loc.y].neighbors;
				unsigned char neighbors = theMap[elem.loc.x][elem.loc.y].neighbors & parentMask[elem.parent];
				
				unsigned char currNeighbor = 1;
				int baseCase = GetBaseCase(elem.loc, g);
						
				for (int d = 0; d < 8; d++)	// look at 8 directions
				{
					if (currNeighbor & neighbors)	// if there is a potential successor in a direction
					{
						xyLoc succ = xyLoc(elem.loc.x + X[d], elem.loc.y + Y[d]);
						
						// generate it if necessary
						if (theMap[succ.x][succ.y].generated != search)
						{
							theMap[succ.x][succ.y].generated = search;
							theMap[succ.x][succ.y].open = true;
						}
						
						// if it was not already expanded
						if (theMap[succ.x][succ.y].open)
						{
							buckets[id[cases[baseCase]]].contents.push_back(bucketElement(succ, (d+4)&7));
							#ifdef BUCKET_STATISTICS
								openSize++;
								if (openSize > maxOpenSize)
									maxOpenSize = openSize;
							#endif
						}
					}
					baseCase++;
					currNeighbor = (currNeighbor << 1);
				}
			}
			#ifdef BUCKET_STATISTICS
				else
					alreadyExpanded++;
			#endif
		}
		
		// Bucket expanded, try to add new buckets to the open list
		for (int i = 1; i < 6; i++)
		{
			if (!buckets[id[i]].open && !buckets[id[i]].contents.empty())	// if it is not already open and it contains at least one element
			{
				buckets[id[i]].open = true;
				AddToOpen(abCost(currCost.a + A[i], currCost.b + B[i]));
			}
		}
		
		#ifdef BUCKET_MEMORY_OPTIMIZATION
			std::vector<bucketElement>().swap(buckets[id[0]].contents);	// Free the memory for that bucket
			buckets[id[0]].contents.reserve(DEFAULT_BUCKET_SIZE);	// Allow it to have 256 elements so that we don't reallocate too often
		#endif
	}

	if (!theMap[g.x][g.y].open)
	{
		path.clear();
		xyLoc loc = g;
		while (loc.x != s.x || loc.y != s.y)
		{
			path.push_back(loc);
			int parent = theMap[loc.x][loc.y].parent;
			loc.x += X[parent];
			loc.y += Y[parent];
		}
		path.push_back(loc);
		std::reverse(path.begin(), path.end());
		return HCost(s,g) + currCost.GetCost();
	}
	
	return 0;//HCost(s,g);
}
Ejemplo n.º 2
0
/** Heuristic value between node and the stored goal. Asserts that the
 goal is stored **/
double RubiksCube::HCost(const RubiksState &node)
{
	return HCost(node, node);
}