Example #1
0
File: DM.cpp Project: tiftof/skia
static void push_sink(const char* tag, Sink* s) {
    SkAutoTDelete<Sink> sink(s);
    if (!FLAGS_config.contains(tag)) {
        return;
    }
    // Try a simple Src as a canary.  If it fails, skip this sink.
    struct : public Src {
        Error draw(SkCanvas* c) const override {
            c->drawRect(SkRect::MakeWH(1,1), SkPaint());
            return "";
        }
        SkISize size() const override { return SkISize::Make(16, 16); }
        Name name() const override { return "justOneRect"; }
    } justOneRect;

    SkBitmap bitmap;
    SkDynamicMemoryWStream stream;
    SkString log;
    Error err = sink->draw(justOneRect, &bitmap, &stream, &log);
    if (err.isFatal()) {
        SkDebugf("Could not run %s: %s\n", tag, err.c_str());
        exit(1);
    }

    TaggedSink& ts = gSinks.push_back();
    ts.reset(sink.detach());
    ts.tag = tag;
}
Example #2
0
static void push_sink(const SkCommandLineConfig& config, Sink* s) {
    SkAutoTDelete<Sink> sink(s);

    // Try a simple Src as a canary.  If it fails, skip this sink.
    struct : public Src {
        Error draw(SkCanvas* c) const override {
            c->drawRect(SkRect::MakeWH(1,1), SkPaint());
            return "";
        }
        SkISize size() const override { return SkISize::Make(16, 16); }
        Name name() const override { return "justOneRect"; }
    } justOneRect;

    SkBitmap bitmap;
    SkDynamicMemoryWStream stream;
    SkString log;
    Error err = sink->draw(justOneRect, &bitmap, &stream, &log);
    if (err.isFatal()) {
        info("Could not run %s: %s\n", config.getTag().c_str(), err.c_str());
        exit(1);
    }

    TaggedSink& ts = gSinks.push_back();
    ts.reset(sink.release());
    ts.tag = config.getTag();
}
Example #3
0
File: DM.cpp Project: tiftof/skia
    static void Run(Task* task) {
        SkString name = task->src->name();

        // We'll skip drawing this Src/Sink pair if:
        //   - the Src vetoes the Sink;
        //   - this Src / Sink combination is on the blacklist;
        //   - it's a dry run.
        SkString note(task->src->veto(task->sink->flags()) ? " (veto)" : "");
        SkString whyBlacklisted = is_blacklisted(task->sink.tag, task->src.tag,
                                                 task->src.options, name.c_str());
        if (!whyBlacklisted.isEmpty()) {
            note.appendf(" (--blacklist %s)", whyBlacklisted.c_str());
        }

        SkString log;
        WallTimer timer;
        timer.start();
        if (!FLAGS_dryRun && note.isEmpty()) {
            SkBitmap bitmap;
            SkDynamicMemoryWStream stream;
            if (FLAGS_pre_log) {
                SkDebugf("\nRunning %s->%s", name.c_str(), task->sink.tag);
            }
            start(task->sink.tag, task->src.tag, task->src.options, name.c_str());
            Error err = task->sink->draw(*task->src, &bitmap, &stream, &log);
            if (!err.isEmpty()) {
                timer.end();
                if (err.isFatal()) {
                    fail(SkStringPrintf("%s %s %s %s: %s",
                                        task->sink.tag,
                                        task->src.tag,
                                        task->src.options,
                                        name.c_str(),
                                        err.c_str()));
                } else {
                    note.appendf(" (skipped: %s)", err.c_str());
                }
                done(timer.fWall, task->sink.tag, task->src.tag, task->src.options,
                     name, note, log);
                return;
            }
            SkAutoTDelete<SkStreamAsset> data(stream.detachAsStream());

            SkString md5;
            if (!FLAGS_writePath.isEmpty() || !FLAGS_readPath.isEmpty()) {
                SkMD5 hash;
                if (data->getLength()) {
                    hash.writeStream(data, data->getLength());
                    data->rewind();
                } else {
                    // If we're BGRA (Linux, Windows), swizzle over to RGBA (Mac, Android).
                    // This helps eliminate multiple 0-pixel-diff hashes on gold.skia.org.
                    // (Android's general slow speed breaks the tie arbitrarily in RGBA's favor.)
                    // We might consider promoting 565 to RGBA too.
                    if (bitmap.colorType() == kBGRA_8888_SkColorType) {
                        SkBitmap swizzle;
                        SkAssertResult(bitmap.copyTo(&swizzle, kRGBA_8888_SkColorType));
                        hash.write(swizzle.getPixels(), swizzle.getSize());
                    } else {
                        hash.write(bitmap.getPixels(), bitmap.getSize());
                    }
                }
                SkMD5::Digest digest;
                hash.finish(digest);
                for (int i = 0; i < 16; i++) {
                    md5.appendf("%02x", digest.data[i]);
                }
            }

            if (!FLAGS_readPath.isEmpty() &&
                !gGold.contains(Gold(task->sink.tag, task->src.tag,
                                     task->src.options, name, md5))) {
                fail(SkStringPrintf("%s not found for %s %s %s %s in %s",
                                    md5.c_str(),
                                    task->sink.tag,
                                    task->src.tag,
                                    task->src.options,
                                    name.c_str(),
                                    FLAGS_readPath[0]));
            }

            if (!FLAGS_writePath.isEmpty()) {
                const char* ext = task->sink->fileExtension();
                if (data->getLength()) {
                    WriteToDisk(*task, md5, ext, data, data->getLength(), nullptr);
                    SkASSERT(bitmap.drawsNothing());
                } else if (!bitmap.drawsNothing()) {
                    WriteToDisk(*task, md5, ext, nullptr, 0, &bitmap);
                }
            }
        }
        timer.end();
        done(timer.fWall, task->sink.tag, task->src.tag, task->src.options, name, note, log);
    }
Example #4
0
void ExampleAIModule::onFrame()
{
  // Called once every game frame

  // Display the game frame rate as text in the upper left area of the screen
  Broodwar->drawTextScreen(200, 0,  "FPS: %d", Broodwar->getFPS() );
  Broodwar->drawTextScreen(200, 20, "Average FPS: %f", Broodwar->getAverageFPS() );

  // Return if the game is a replay or is paused
  if ( Broodwar->isReplay() || Broodwar->isPaused() || !Broodwar->self() )
    return;

  // Prevent spamming by only running our onFrame once every number of latency frames.
  // Latency frames are the number of frames before commands are processed.
  if ( Broodwar->getFrameCount() % Broodwar->getLatencyFrames() != 0 )
    return;

  // Iterate through all the units that we own
  Unitset myUnits = Broodwar->self()->getUnits();
  for ( Unitset::iterator u = myUnits.begin(); u != myUnits.end(); ++u )
  {
    // Ignore the unit if it no longer exists
    // Make sure to include this block when handling any Unit pointer!
    if ( !u->exists() )
      continue;

    // Ignore the unit if it has one of the following status ailments
    if ( u->isLockedDown() || u->isMaelstrommed() || u->isStasised() )
      continue;

    // Ignore the unit if it is in one of the following states
    if ( u->isLoaded() || !u->isPowered() || u->isStuck() )
      continue;

    // Ignore the unit if it is incomplete or busy constructing
    if ( !u->isCompleted() || u->isConstructing() )
      continue;


    // Finally make the unit do some stuff!


    // If the unit is a worker unit
    if ( u->getType().isWorker() )
    {
      // if our worker is idle
      if ( u->isIdle() )
      {
        // Order workers carrying a resource to return them to the center,
        // otherwise find a mineral patch to harvest.
        if ( u->isCarryingGas() || u->isCarryingMinerals() )
        {
          u->returnCargo();
        }
        else if ( !u->getPowerUp() )  // The worker cannot harvest anything if it
        {                             // is carrying a powerup such as a flag
          // Harvest from the nearest mineral patch or gas refinery
          if ( !u->gather( u->getClosestUnit( IsMineralField || IsRefinery )) )
          {
            // If the call fails, then print the last error message
            Broodwar << Broodwar->getLastError() << std::endl;
          }

        } // closure: has no powerup
      } // closure: if idle

    }
    else if ( u->getType().isResourceDepot() ) // A resource depot is a Command Center, Nexus, or Hatchery
    {

      // Order the depot to construct more workers! But only when it is idle.
      if ( u->isIdle() && !u->train(u->getType().getRace().getWorker()) )
      {
        // If that fails, draw the error at the location so that you can visibly see what went wrong!
        // However, drawing the error once will only appear for a single frame
        // so create an event that keeps it on the screen for some frames
        Position pos = u->getPosition();
        Error lastErr = Broodwar->getLastError();
        Broodwar->registerEvent([pos,lastErr](Game*){ Broodwar->drawTextMap(pos, "%c%s", Text::White, lastErr.c_str()); },   // action
                                nullptr,    // condition
                                Broodwar->getLatencyFrames());  // frames to run

        // Retrieve the supply provider type in the case that we have run out of supplies
        UnitType supplyProviderType = u->getType().getRace().getSupplyProvider();
        static int lastChecked = 0;

        // If we are supply blocked and haven't tried constructing more recently
        if (  lastErr == Errors::Insufficient_Supply &&
              lastChecked + 400 < Broodwar->getFrameCount() &&
              Broodwar->self()->incompleteUnitCount(supplyProviderType) == 0 )
        {
          lastChecked = Broodwar->getFrameCount();

          // Retrieve a unit that is capable of constructing the supply needed
          Unit supplyBuilder = u->getClosestUnit(  GetType == supplyProviderType.whatBuilds().first &&
                                                    (IsIdle || IsGatheringMinerals) &&
                                                    IsOwned);
          // If a unit was found
          if ( supplyBuilder )
          {
            if ( supplyProviderType.isBuilding() )
            {
			
              TilePosition targetBuildLocation = Broodwar->getBuildLocation(supplyProviderType, supplyBuilder->getTilePosition());
              if ( targetBuildLocation )
              {

                // Register an event that draws the target build location
                Broodwar->registerEvent([targetBuildLocation,supplyProviderType](Game*)
                                        {
                                          Broodwar->drawBoxMap( Position(targetBuildLocation),
                                                                Position(targetBuildLocation + supplyProviderType.tileSize()),
                                                                Colors::Blue);
                                        },
                                        nullptr,  // condition
                                        supplyProviderType.buildTime() + 100 );  // frames to run

                // Order the builder to construct the supply structure
                supplyBuilder->build( supplyProviderType, targetBuildLocation );
              }
            }
            else
            {
              // Train the supply provider (Overlord) if the provider is not a structure
              supplyBuilder->train( supplyProviderType );
            }
          } // closure: supplyBuilder is valid
        } // closure: insufficient supply
      } // closure: failed to train idle unit

    }
   

  } // closure: unit iterator
}
Example #5
0
    static void Run(const Task& task) {
        SkString name = task.src->name();

        SkString log;
        if (!FLAGS_dryRun) {
            SkBitmap bitmap;
            SkDynamicMemoryWStream stream;
            start(task.sink.tag.c_str(), task.src.tag.c_str(),
                  task.src.options.c_str(), name.c_str());
            Error err = task.sink->draw(*task.src, &bitmap, &stream, &log);
            if (!log.isEmpty()) {
                info("%s %s %s %s:\n%s\n", task.sink.tag.c_str()
                                         , task.src.tag.c_str()
                                         , task.src.options.c_str()
                                         , name.c_str()
                                         , log.c_str());
            }
            if (!err.isEmpty()) {
                if (err.isFatal()) {
                    fail(SkStringPrintf("%s %s %s %s: %s",
                                        task.sink.tag.c_str(),
                                        task.src.tag.c_str(),
                                        task.src.options.c_str(),
                                        name.c_str(),
                                        err.c_str()));
                } else {
                    done(task.sink.tag.c_str(), task.src.tag.c_str(),
                         task.src.options.c_str(), name.c_str());
                    return;
                }
            }

            // We're likely switching threads here, so we must capture by value, [=] or [foo,bar].
            SkStreamAsset* data = stream.detachAsStream();
            gDefinitelyThreadSafeWork.add([task,name,bitmap,data]{
                SkAutoTDelete<SkStreamAsset> ownedData(data);

                // Why doesn't the copy constructor do this when we have pre-locked pixels?
                bitmap.lockPixels();

                SkString md5;
                if (!FLAGS_writePath.isEmpty() || !FLAGS_readPath.isEmpty()) {
                    SkMD5 hash;
                    if (data->getLength()) {
                        hash.writeStream(data, data->getLength());
                        data->rewind();
                    } else {
                        // If we're BGRA (Linux, Windows), swizzle over to RGBA (Mac, Android).
                        // This helps eliminate multiple 0-pixel-diff hashes on gold.skia.org.
                        // (Android's general slow speed breaks the tie arbitrarily in RGBA's favor.)
                        // We might consider promoting 565 to RGBA too.
                        if (bitmap.colorType() == kBGRA_8888_SkColorType) {
                            SkBitmap swizzle;
                            SkAssertResult(bitmap.copyTo(&swizzle, kRGBA_8888_SkColorType));
                            hash.write(swizzle.getPixels(), swizzle.getSize());
                        } else {
                            hash.write(bitmap.getPixels(), bitmap.getSize());
                        }
                    }
                    SkMD5::Digest digest;
                    hash.finish(digest);
                    for (int i = 0; i < 16; i++) {
                        md5.appendf("%02x", digest.data[i]);
                    }
                }

                if (!FLAGS_readPath.isEmpty() &&
                    !gGold.contains(Gold(task.sink.tag, task.src.tag,
                                         task.src.options, name, md5))) {
                    fail(SkStringPrintf("%s not found for %s %s %s %s in %s",
                                        md5.c_str(),
                                        task.sink.tag.c_str(),
                                        task.src.tag.c_str(),
                                        task.src.options.c_str(),
                                        name.c_str(),
                                        FLAGS_readPath[0]));
                }

                if (!FLAGS_writePath.isEmpty()) {
                    const char* ext = task.sink->fileExtension();
                    if (data->getLength()) {
                        WriteToDisk(task, md5, ext, data, data->getLength(), nullptr);
                        SkASSERT(bitmap.drawsNothing());
                    } else if (!bitmap.drawsNothing()) {
                        WriteToDisk(task, md5, ext, nullptr, 0, &bitmap);
                    }
                }
            });
        }
        done(task.sink.tag.c_str(), task.src.tag.c_str(), task.src.options.c_str(), name.c_str());
    }
Example #6
0
bool Camera_FirewireClass::Capture(int duration, usImage& img, int options, const wxRect& subframe)
{
    int xsize, ysize, i;
    unsigned short *dataptr;
    unsigned char *imgptr;
    Error err;
    bool retval;
    static int programmed_dur = 200;

    xsize = FullSize.GetWidth();
    ysize = FullSize.GetHeight();

    if (img.Init(FullSize))
    {
        pFrame->Alert(_("Memory allocation error"));
        return true;
    }
    dataptr = img.ImageData;

    if ((duration != programmed_dur) && (m_pExposureAbs != 0)) {
        m_pExposureAbs->setValue(duration / 1000.0);
        programmed_dur = duration;
    }

    retval = m_pGrabber->startLive(false);
    if (!retval) {
        pFrame->Alert(_("Could not start video stream"));
        return true;
    }

    // Flush


    // grab the next frame

    err = pSink->snapImages( 1,15000 );
    if (err.getVal() ==  eTIMEOUT_PREMATURLY_ELAPSED) {
        wxMilliSleep(200);
        err = pSink->snapImages( 1,15000 );
    }
    if (err.getVal() ==  eTIMEOUT_PREMATURLY_ELAPSED) {
        wxMilliSleep(200);
        err = pSink->snapImages( 1,15000 );
    }

    if (err.isError())
    {
        DisconnectWithAlert(wxString::Format(_("Error capturing image: %d (%d) %s"), (int) err.getVal(), (int) eTIMEOUT_PREMATURLY_ELAPSED, wxString(err.c_str())));
        return true;
    }
    imgptr = (unsigned char *) pSink->getLastAcqMemBuffer()->getPtr();

    for (i=0; i<img.NPixels; i++, dataptr++, imgptr++)
        *dataptr = (unsigned short) *imgptr;

/*  if (dc1394_capture_dequeue(camera, DC1394_CAPTURE_POLICY_WAIT, &vframe)!=DC1394_SUCCESS) {
        DisconnectWithAlert(_("Cannot get a frame from the queue"));
        return true;
    }
    imgptr = vpFrame->image;
    for (i=0; i<img.NPixels; i++, dataptr++, imgptr++)
        *dataptr = (unsigned short) *imgptr;
    dc1394_capture_enqueue(camera, vframe);  // release this frame
    */

    m_pGrabber->suspendLive();

    if (options & CAPTURE_SUBTRACT_DARK) SubtractDark(img);

    return false;
}
Example #7
0
    static void Run(Task* task) {
        SkString name = task->src->name();
        SkString note;
        SkString whyBlacklisted = is_blacklisted(task->sink.tag, task->src.tag,
                                                 task->src.options, name.c_str());
        if (!whyBlacklisted.isEmpty()) {
            note.appendf(" (--blacklist %s)", whyBlacklisted.c_str());
        }
        SkString log;
        WallTimer timer;
        timer.start();
        if (!FLAGS_dryRun && whyBlacklisted.isEmpty()) {
            SkBitmap bitmap;
            SkDynamicMemoryWStream stream;
            start(task->sink.tag, task->src.tag, task->src.options, name.c_str());
            Error err = task->sink->draw(*task->src, &bitmap, &stream, &log);
            if (!err.isEmpty()) {
                timer.end();
                if (err.isFatal()) {
                    fail(SkStringPrintf("%s %s %s %s: %s",
                                        task->sink.tag,
                                        task->src.tag,
                                        task->src.options,
                                        name.c_str(),
                                        err.c_str()));
                } else {
                    note.appendf(" (skipped: %s)", err.c_str());
                }
                done(timer.fWall, task->sink.tag, task->src.tag, task->src.options,
                     name, note, log);
                return;
            }
            SkAutoTDelete<SkStreamAsset> data(stream.detachAsStream());

            SkString md5;
            if (!FLAGS_writePath.isEmpty() || !FLAGS_readPath.isEmpty()) {
                SkMD5 hash;
                if (data->getLength()) {
                    hash.writeStream(data, data->getLength());
                    data->rewind();
                } else {
                    hash.write(bitmap.getPixels(), bitmap.getSize());
                }
                SkMD5::Digest digest;
                hash.finish(digest);
                for (int i = 0; i < 16; i++) {
                    md5.appendf("%02x", digest.data[i]);
                }
            }

            if (!FLAGS_readPath.isEmpty() &&
                !gGold.contains(Gold(task->sink.tag, task->src.tag,
                                     task->src.options, name, md5))) {
                fail(SkStringPrintf("%s not found for %s %s %s %s in %s",
                                    md5.c_str(),
                                    task->sink.tag,
                                    task->src.tag,
                                    task->src.options,
                                    name.c_str(),
                                    FLAGS_readPath[0]));
            }

            if (!FLAGS_writePath.isEmpty()) {
                const char* ext = task->sink->fileExtension();
                if (data->getLength()) {
                    WriteToDisk(*task, md5, ext, data, data->getLength(), NULL);
                    SkASSERT(bitmap.drawsNothing());
                } else if (!bitmap.drawsNothing()) {
                    WriteToDisk(*task, md5, ext, NULL, 0, &bitmap);
                }
            }
        }
        timer.end();
        done(timer.fWall, task->sink.tag, task->src.tag, task->src.options, name, note, log);
    }
Example #8
0
void BwapiGame::DebugDrawMapLastGameError(_In_ TID unitId) const
{
    Error lastErr = Broodwar->getLastError();
    BWAPI::Position unitPos = Broodwar->getUnit(unitId)->getPosition();

    Broodwar->registerEvent([unitPos, lastErr](Game*){ Broodwar->drawTextMap(unitPos, "%c%s", Text::Red, lastErr.c_str()); },   // action
        nullptr,    // condition
        100);  // frames to run
}
Example #9
0
void TurkAnalyzer::onFrame()
{
	// Called once every game frame

	// Display the game frame rate as text in the upper left area of the screen
	Broodwar->drawTextScreen(200, 0, "FPS: %d", Broodwar->getFPS());
	// Broodwar->drawTextScreen(200, 20, "Average FPS: %f", Broodwar->getAverageFPS() );

	//Broodwar->drawTextScreen(200, 20, "Number of Units: %d", BWAPI::Broodwar->self()->supplyUsed() / 2 );
	//Broodwar->drawTextScreen(200, 40, "Number of Units: %d", BWAPI::Broodwar->self()->supplyTotal() / 2 );


	// Return if the game is a replay or is paused
	if (Broodwar->isReplay() || Broodwar->isPaused() || !Broodwar->self())
		return;

	//BWTA draw
	if (analyzed){
		drawTerrainData();
	}


	if (analysis_just_finished)
	{
		Broodwar << "Finished analyzing map." << std::endl;;
		analysis_just_finished = false;
	}


	// Prevent spamming by only running our onFrame once every number of latency frames.
	// Latency frames are the number of frames before commands are processed.
	if (Broodwar->getFrameCount() % Broodwar->getLatencyFrames() != 0)
		return;


	// Iterate through all the units that we own


	// Count the number of probes
	ProbeCount = 0;
	ZealotCount = 0;
	DragoonCount = 0;
	GateWayCount = 0;
	for (auto & unit2 : Broodwar->self()->getUnits())
	{
		if (!unit2->exists())
			continue;

		// Ignore the unit if it is incomplete or busy constructing
		if (!unit2->isCompleted() || unit2->isConstructing())
			continue;

		// If the unit is a worker unit
		if (unit2->getType().isWorker())
		{
			ProbeCount = ProbeCount + 1;
		}
		else if (unit2->getType() == BWAPI::UnitTypes::Protoss_Zealot)
		{
			ZealotCount = ZealotCount + 1;
		}
		else if (unit2->getType() == BWAPI::UnitTypes::Protoss_Dragoon)
		{
			DragoonCount = DragoonCount + 1;
		}
		else if (unit2->getType() == GateWay)
		{
			GateWayCount = GateWayCount + 1;
		}
	}

	Broodwar->drawTextScreen(100, 10, "Number of Zealot: %d", ZealotCount);
	Broodwar->drawTextScreen(100, 30, "Number of Dragoon: %d", DragoonCount);







	// Iterate through all the units that we own
	for (auto &u : Broodwar->self()->getUnits())
	{
		// Ignore the unit if it no longer exists
		// Make sure to include this block when handling any Unit pointer!
		if (!u->exists())
			continue;

		// Ignore the unit if it has one of the following status ailments
		if (u->isLockedDown() || u->isMaelstrommed() || u->isStasised())
			continue;

		// Ignore the unit if it is in one of the following states
		if (u->isLoaded() || !u->isPowered() || u->isStuck())
			continue;

		// Ignore the unit if it is incomplete or busy constructing
		if (!u->isCompleted() || u->isConstructing())
			continue;


		// Finally make the unit do some stuff!




		// Build a gateway or generate a zealot	
		if (u->getType().isBuilding())
		{
			// We found a gateway, and it is not generating a unit
			if (u->isIdle() && u->getType() == GateWay)
			{
				u->rightClick(Enterance);

				//BWAPI::Position Hill = BWTA::getNearestChokepoint(BWAPI::Position(Broodwar->self()->getStartLocation()))->getCenter();
				//u->rightClick(Hill);


				if (FirstCybernetics && ZealotCount >= DragoonCount){
					u->train(BWAPI::UnitTypes::Protoss_Dragoon);
				}
				else{
					u->train(BWAPI::UnitTypes::Protoss_Zealot);
				}

			}

			// We found a gateway, and it is generating a unit.
			else if (!u->isIdle() && u->getType() == GateWay && GateWayCount < MaxGateWayCount && FirstCybernetics)
			{
				static int lastChecked = 0;

				// If we are supply blocked and haven't tried constructing more recently
				if (lastChecked + 400 < Broodwar->getFrameCount() && Broodwar->self()->incompleteUnitCount(GateWay) == 0)
				{
					// Frame Count
					lastChecked = Broodwar->getFrameCount();

					// Retrieve a unit that is capable of constructing the supply needed
					Unit GateBuilder = u->getClosestUnit(GetType == GateWay.whatBuilds().first && (IsIdle || IsGatheringMinerals) && IsOwned);

					// If a unit was found
					if (GateBuilder)
					{
						TilePosition targetBuildLocation = Broodwar->getBuildLocation(GateWay, GateBuilder->getTilePosition());
						if (targetBuildLocation)
						{
							// Order the builder to construct the supply structure				
							GateBuilder->build(GateWay, targetBuildLocation);

						}
					}
				}
			}
		}







		/*
		if (Broodwar->self())
		{
		Unitset myUnits = Broodwar->self()->getUnits();
		for (auto u : myUnits)
		{
		if (u->isIdle() && u->getType().isResourceDepot())
		u->train(u->getType().getRace().getWorker());
		}
		}
		*/




		// If the unit is a worker unit
		if (u->getType().isWorker())
		{
			// if our worker is idle
			if (u->isIdle())
			{
				// Order workers carrying a resource to return them to the center,
				// otherwise find a mineral patch to harvest.
				if (u->isCarryingGas() || u->isCarryingMinerals())
				{
					u->returnCargo();
				}
				else if (!u->getPowerUp())  // The worker cannot harvest anything if it
				{                             // is carrying a powerup such as a flag
					// Harvest from the nearest mineral patch or gas refinery
					if (!u->gather(u->getClosestUnit(IsMineralField))) // IsRefinery
					{
						// If the call fails, then print the last error message
						Broodwar << Broodwar->getLastError() << std::endl;
					}
				} // closure: has no powerup

			} // closure: if idle

		}
		else if (u->getType().isResourceDepot()) // A resource depot is a Command Center, Nexus, or Hatchery
		{

			// Order the depot to construct more workers! But only when it is idle.
			if (u->isIdle() && ProbeCount < 40) // && !u->train(u->getType().getRace().getWorker())
			{
				u->train(u->getType().getRace().getWorker());
				// If that fails, draw the error at the location so that you can visibly see what went wrong!
				// However, drawing the error once will only appear for a single frame
				// so create an event that keeps it on the screen for some frames

				// Position homePosition = Position(Broodwar->self()->getStartLocation());
			}
			Position pos = u->getPosition();
			Error lastErr = Broodwar->getLastError();
			Broodwar->registerEvent([pos, lastErr](Game*){ Broodwar->drawTextMap(pos, "%c%s", Text::White, lastErr.c_str()); },   // action
				nullptr,    // condition
				Broodwar->getLatencyFrames());  // frames to run

			// Retrieve the supply provider type in the case that we have run out of supplies		
			UnitType supplyProviderType = u->getType().getRace().getSupplyProvider();
			static int lastChecked = 0;


			// If we are supply blocked and haven't tried constructing more recently
			if (lastErr == Errors::Insufficient_Supply &&
				lastChecked + 300 < Broodwar->getFrameCount() &&
				Broodwar->self()->incompleteUnitCount(supplyProviderType) <= PylonLimiter)
			{
				lastChecked = Broodwar->getFrameCount();

				// Retrieve a unit that is capable of constructing the supply needed
				Unit supplyBuilder = u->getClosestUnit(GetType == supplyProviderType.whatBuilds().first &&
					(IsIdle || IsGatheringMinerals) &&
					IsOwned);

				// If a unit was found
				if (supplyBuilder)
				{
					if (supplyProviderType.isBuilding())
					{
						TilePosition targetBuildLocation = Broodwar->getBuildLocation(supplyProviderType, supplyBuilder->getTilePosition());
						if (targetBuildLocation)
						{
							// Register an event that draws the target build location
							Broodwar->registerEvent([targetBuildLocation, supplyProviderType](Game*)
							{
								Broodwar->drawBoxMap(Position(targetBuildLocation),
									Position(targetBuildLocation + supplyProviderType.tileSize()),
									Colors::Blue);
							},
								nullptr,  // condition
								supplyProviderType.buildTime() + 100);  // frames to run

							// Order the builder to construct the supply structure				
							supplyBuilder->build(supplyProviderType, targetBuildLocation);

						}
					}
					else
					{
						// Train the supply provider (Overlord) if the provider is not a structure
						supplyBuilder->train(supplyProviderType);
					}
				} // closure: supplyBuilder is valid
			} // closure: insufficient supply     

			// If there is the first pylon,but it there is no gateway, please build a gateway.s
			else if (FirstPylonExist && !FirstGateExist)
			{
				static int lastChecked = 0;

				// If we are supply blocked and haven't tried constructing more recently
				if (lastChecked + 400 < Broodwar->getFrameCount() && Broodwar->self()->incompleteUnitCount(GateWay) == 0)
				{
					// Frame Count
					lastChecked = Broodwar->getFrameCount();

					// Retrieve a unit that is capable of constructing the supply needed
					Unit GateBuilder = u->getClosestUnit(GetType == GateWay.whatBuilds().first && (IsIdle || IsGatheringMinerals) && IsOwned);

					if (GateBuilder)
					{
						TilePosition targetBuildLocation = Broodwar->getBuildLocation(GateWay, GateBuilder->getTilePosition());

						if (targetBuildLocation)
						{
							// Order the builder to construct the supply structure				
							GateBuilder->build(GateWay, targetBuildLocation);
						}
					}
				}
			}
			else if (FirstGateExist && !FirstGasExist)
			{

				BWAPI::TilePosition closestGeyser = BWAPI::TilePositions::None;
				double minGeyserDistanceFromHome = (std::numeric_limits<double>::max)();
				BWAPI::Position homePosition = BWAPI::Position(Broodwar->self()->getStartLocation());

				// for each geyser
				for (auto & geyser : Broodwar->getStaticGeysers())
				{
					if (geyser->getType() != BWAPI::UnitTypes::Resource_Vespene_Geyser)
					{
						continue;
					}

					BWAPI::Position geyserPos = geyser->getInitialPosition();
					BWAPI::TilePosition geyserTilePos = geyser->getInitialTilePosition();

					// check to see if it's next to one of our depots
					bool nearDepot = false;
					for (auto & unit : BWAPI::Broodwar->self()->getUnits())
					{
						if (unit->getType().isResourceDepot() && unit->getDistance(geyserPos) < 300)
						{
							nearDepot = true;
						}
					}

					if (nearDepot)
					{
						double homeDistance = geyser->getDistance(homePosition);

						if (homeDistance < minGeyserDistanceFromHome)
						{
							minGeyserDistanceFromHome = homeDistance;
							closestGeyser = geyser->getInitialTilePosition();
						}
					}


					static int lastChecked = 0;

					// If we are supply blocked and haven't tried constructing more recently
					if (lastChecked + 400 < Broodwar->getFrameCount() && Broodwar->self()->incompleteUnitCount(Assimilator) == 0)
					{
						// Frame Count
						lastChecked = Broodwar->getFrameCount();

						// Retrieve a unit that is capable of constructing the supply needed
						Unit GasBuilder = u->getClosestUnit(GetType == GateWay.whatBuilds().first && (IsIdle || IsGatheringMinerals) && IsOwned);

						if (GasBuilder)
						{
							// Order the builder to construct the supply structure				
							GasBuilder->build(Assimilator, closestGeyser);
						}
					}
				}
			}
		}

	} // closure: unit iterator


	// Build the supply unit
	if (BWAPI::Broodwar->self()->supplyUsed() / 2 + 6 > BWAPI::Broodwar->self()->supplyTotal() / 2){
		for (auto & unit2 : Broodwar->self()->getUnits()){

			if (!unit2->exists())
				continue;

			// Ignore the unit if it is incomplete or busy constructing
			if (!unit2->isCompleted() || unit2->isConstructing())
				continue;

			// If the unit is a worker unit
			if (unit2->getType().isResourceDepot()){
				UnitType supplyProviderType = unit2->getType().getRace().getSupplyProvider();
				static int lastChecked = 0;

				// If we are supply blocked and haven't tried constructing more recently
				if (lastChecked + 300 < Broodwar->getFrameCount() && Broodwar->self()->incompleteUnitCount(supplyProviderType) == 0){
					lastChecked = Broodwar->getFrameCount();

					// Retrieve a unit that is capable of constructing the supply needed
					Unit supplyBuilder = unit2->getClosestUnit(GetType == supplyProviderType.whatBuilds().first && (IsIdle || IsGatheringMinerals) && IsOwned);

					// If a unit was found
					if (supplyBuilder){
						TilePosition targetBuildLocation = Broodwar->getBuildLocation(supplyProviderType, supplyBuilder->getTilePosition());
						if (targetBuildLocation){
							// Order the builder to construct the supply structure				
							supplyBuilder->build(supplyProviderType, targetBuildLocation);
						}
					}
				}
			}
		}
	}








	// Build the Cybernetics Core
	if (FirstGasExist && !FirstCybernetics)
	{
		for (auto & unit2 : Broodwar->self()->getUnits())
		{
			// If the unit is a worker unit
			if (unit2->getType().isWorker())
			{

				static int lastChecked = 0;

				// If we are supply blocked and haven't tried constructing more recently
				if (lastChecked + 400 < Broodwar->getFrameCount() && Broodwar->self()->incompleteUnitCount(Cybernetics) == 0)
				{
					// Frame Count
					lastChecked = Broodwar->getFrameCount();

					// Retrieve a unit that is capable of constructing the supply needed
					Unit GateBuilder = unit2->getClosestUnit(GetType == Cybernetics.whatBuilds().first && (IsIdle || IsGatheringMinerals) && IsOwned);

					if (GateBuilder)
					{
						TilePosition targetBuildLocation = Broodwar->getBuildLocation(Cybernetics, GateBuilder->getTilePosition());

						if (targetBuildLocation)
						{
							// Order the builder to construct the supply structure				
							GateBuilder->build(Cybernetics, targetBuildLocation);

						}
					}
				}
			}
		}
	}


	if (FirstCybernetics && !Singularity){
		for (auto & unit : BWAPI::Broodwar->self()->getUnits())
		{
			if (unit->getType() == Cybernetics && !unit->isUpgrading())
			{
				unit->upgrade(BWAPI::UpgradeTypes::Singularity_Charge);
			}

		}
	}






	// Send workers to the gas refinary
	if (FirstGasExist && GasWorkerCount == 0)
	{
		// for each unit we have
		for (auto & unit : BWAPI::Broodwar->self()->getUnits())
		{
			// if that unit is a refinery
			if (unit->getType().isRefinery() && unit->isCompleted())
			{
				for (auto & unit2 : Broodwar->self()->getUnits())
				{
					if (GasWorkerCount == 3)
					{
						break;
					}

					// If the unit is a worker unit
					if (unit2->getType().isWorker())
					{
						GasWorkerCount = GasWorkerCount + 1;
						unit2->rightClick(unit);
					}
				}
			}
		}
	}



	// Build the Adun 
	if (FirstCybernetics && !FirstAdun && GateWayCount >= 4)
	{
		for (auto & unit2 : Broodwar->self()->getUnits())
		{
			// If the unit is a worker unit
			if (unit2->getType().isWorker())
			{
				static int lastChecked = 0;

				// If we are supply blocked and haven't tried constructing more recently
				if (lastChecked + 400 < Broodwar->getFrameCount() && Broodwar->self()->incompleteUnitCount(CitadelOfAdun) == 0)
				{
					// Frame Count
					lastChecked = Broodwar->getFrameCount();

					// Retrieve a unit that is capable of constructing the supply needed
					Unit GateBuilder = unit2->getClosestUnit(GetType == CitadelOfAdun.whatBuilds().first && (IsIdle || IsGatheringMinerals) && IsOwned);

					if (GateBuilder)
					{
						TilePosition targetBuildLocation = Broodwar->getBuildLocation(CitadelOfAdun, GateBuilder->getTilePosition());

						if (targetBuildLocation)
						{
							// Order the builder to construct the supply structure				
							GateBuilder->build(CitadelOfAdun, targetBuildLocation);
						}
					}
				}
			}
		}
	}



	// Leg Enhancements
	if (FirstAdun && !Leg_Enhancements){
		for (auto & unit : BWAPI::Broodwar->self()->getUnits())
		{
			if (unit->getType() == CitadelOfAdun && !unit->isUpgrading())
			{
				unit->upgrade(BWAPI::UpgradeTypes::Leg_Enhancements);
			}
		}
	}











	BWAPI::Position homePosition = BWAPI::Position(Broodwar->self()->getStartLocation());

	// Build the expansion nexus
	if (GateWayCount >= MaxGateWayCount)
	{
		for (auto & unit2 : Broodwar->self()->getUnits())
		{
			// If the unit is a worker unit
			if (unit2->getType().isWorker())
			{
				static int lastChecked = 0;

				// If we are supply blocked and haven't tried constructing more recently
				if (lastChecked + 400 < Broodwar->getFrameCount() && Broodwar->self()->incompleteUnitCount(Nexus) == 0)
				{
					// Frame Count
					lastChecked = Broodwar->getFrameCount();

					// Retrieve a unit that is capable of constructing the supply needed
					Unit GateBuilder = unit2->getClosestUnit(GetType == Nexus.whatBuilds().first && (IsIdle || IsGatheringMinerals) && IsOwned);

					if (GateBuilder)
					{
						
						double minDistance = 100000;

						BWAPI::TilePosition homeTile = Broodwar->self()->getStartLocation();

						

						if (NexusLocation){
							// Order the builder to construct the supply structure				
							GateBuilder->build(Nexus, NexusLocation);
						}
					}
				}
			}
		}
	}

	// If the number of Nexus is greater or equal to 2, increase the number of gates.
	int NofNexus = 0;
	for (auto & unit2 : Broodwar->self()->getUnits())
	{
		if (unit2->getType().isBuilding() && unit2->getType() == Nexus)
		{
			NofNexus = NofNexus + 1;
		}
		if (NofNexus >= 2){
			MaxGateWayCount = 8;
			break;
		}
	}






}