BWEM.NET 0.1.7

dotnet add package BWEM.NET --version 0.1.7                
NuGet\Install-Package BWEM.NET -Version 0.1.7                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="BWEM.NET" Version="0.1.7" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add BWEM.NET --version 0.1.7                
#r "nuget: BWEM.NET, 0.1.7"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install BWEM.NET as a Cake Addin
#addin nuget:?package=BWEM.NET&version=0.1.7

// Install BWEM.NET as a Cake Tool
#tool nuget:?package=BWEM.NET&version=0.1.7                

BWEM.NET

A pure .NET BWEM 1.4 implementation. It's ported from the BWEM library.

Brood War Easy Map for .NET library that analyses Brood War's maps and provides relevant information such as areas, choke points and base locations.

It is built on top of the BWAPI.NET library.

It first aims at simplifying the development of bots for Brood War, but can be used for any task requiring high level map information. It can be used as a replacement for the BWTA2 add-on, as it performs faster and shows better robustness while providing similar information.

Capabilities

  • To access general information on the Map.
  • To access the Tiles (32x32) and the MiniTiles (8x8) information.
  • To access the Areas information.
  • To access the Starting Locations information.
  • To access the Minerals, the Geysers and the Static Buildings information.
  • To parametrize the analysis process.
  • Provides some useful tools such as Paths between Choke Points and generic algorithms like Breadth First Search.

Quick Start

  1. Installation
    • Install .NET SDK
    • Install StarCraft: Brood War
    • Update StarCraft: Brood War to 1.16.1
    • Install BWAPI
  2. Create a bot project
    • Run dotnet new console -o MyBot
    • Run cd MyBot to change directy into MyBot folder
    • Run dotnet add MyBot.csproj package BWAPI.NET to add the reference to the BWAPI.NET nuget package
    • Run dotnet add MyBot.csproj package BWEM.NET to add the reference to the BWEM.NET nuget package
    • Copy and paste example bot below into Program.cs or develop your own bot
    • Run dotnet run (At this point you should see "Game table mapping not found." printed each second)
  3. Run StarCraft through Chaoslauncher
    • Run Chaoslauncher.exe as administrator
      • Chaoslauncher is found in Chaoslauncher directory of BWAPI install directory
    • Check the BWAPI Injector x.x.x [RELEASE]
    • Click Start
      • Make sure the version is set to Starcraft 1.16.1, not ICCup 1.16.1
  4. Run a game against Blizzard's AI
    • Go to Single PlayerExpansion
    • Select any user and click OK
    • Click Play Custom, select a map, and start a game
  5. Run a game against yourself
    • Run Chaoslauncher - MultiInstance.exe as administrator
    • Start
      • Go to MultiplayerExpansionLocal PC
      • Select any user and click OK
      • Click Create Game, select a map, and click OK
    • Start – Uncheck BWAPI Injector x.x.x [RELEASE] to let a human play, leave alone to make AI play itself
      • Go to MultiplayerExpansionLocal PC
      • Select any user and click OK
      • Join the existing game created by the other client

Bot Example

using BWAPI.NET;
using BWEM.NET;

namespace ExampleBot
{
    public class ExampleBot : DefaultBWListener
    {
        private BWClient _bwClient;
        private Game _game;
        private Player _self;

        public void Run()
        {
            _bwClient = new BWClient(this);
            _bwClient.StartGame();
        }

        public override void OnStart()
        {
            _game = _bwClient.Game;
            _self = _game.Self();

            Map.Instance.Initialize(_game);
        }

        public override void OnFrame()
        {
            var workers = new List<Unit>();
            var marines = new List<Unit>();
            Unit barrack = null;
            Unit commandCenter = null;

            var buildingSupply = false;

            // iterate through my units and collect relevant information
            foreach (var myUnit in _self.GetUnits())
            {
                var unitType = myUnit.GetUnitType();
                if (unitType == UnitType.Terran_SCV)
                {
                    workers.Add(myUnit);
                }
                else if (unitType == UnitType.Terran_Command_Center)
                {
                    commandCenter = myUnit;
                }
                else if (unitType == UnitType.Terran_Barracks)
                {
                    if (!myUnit.IsBeingConstructed())
                    {
                        barrack = myUnit;
                    }
                }
                else if (unitType == UnitType.Terran_Marine)
                {
                    marines.Add(myUnit);
                }
                else if (unitType == UnitType.Terran_Supply_Depot)
                {
                    if (myUnit.IsBeingConstructed())
                    {
                        buildingSupply = true;
                    }
                }
            }

            // if it's a worker and it's idle, send it to the closest mineral patch
            foreach (var myUnit in workers)
            {
                if (myUnit.GetUnitType().IsWorker() && myUnit.IsIdle())
                {
                    Unit closestMineral = null;

                    // find the closest mineral
                    foreach (var neutralUnit in _game.Neutral().GetUnits())
                    {
                        if (neutralUnit.GetUnitType().IsMineralField())
                        {
                            if (closestMineral == null || myUnit.GetDistance(neutralUnit) < myUnit.GetDistance(closestMineral))
                            {
                                closestMineral = neutralUnit;
                            }
                        }
                    }

                    // if a mineral patch was found, send the worker to gather it
                    if (closestMineral != null)
                    {
                        myUnit.Gather(closestMineral, false);
                    }
                }
            }

            // build SCV if we can
            if (commandCenter != null && commandCenter.GetTrainingQueue().Count == 0 && workers.Count < 12 && _self.Minerals() >= 50)
            {
                commandCenter.Build(UnitType.Terran_SCV);
            }

            var i = 1;
            foreach (var worker in workers)
            {
                if (worker.IsGatheringMinerals())
                {
                    // check if we can build a barrack and build it
                    if (_self.Minerals() >= 150 * i && barrack == null)
                    {
                        var buildTile = BuildingPlacer.GetBuildLocation(UnitType.Terran_Barracks, _self.GetStartLocation(), 40, false, _game);
                        if (buildTile != TilePosition.Invalid)
                        {
                            worker.Build(UnitType.Terran_Barracks, buildTile);
                        }
                    }

                    // check if we can and need to build a supply depot and build it
                    if (_self.Minerals() >= i * 100 && _self.SupplyUsed() + (_self.SupplyUsed() / 3) >= _self.SupplyTotal() && _self.SupplyTotal() < 400 && !buildingSupply)
                    {
                        var buildTile = BuildingPlacer.GetBuildLocation(UnitType.Terran_Supply_Depot, _self.GetStartLocation(), 40, false, _game);
                        if (buildTile != TilePosition.Invalid)
                        {
                            worker.Build(UnitType.Terran_Supply_Depot, buildTile);
                            buildingSupply = true;
                        }
                    }
                }

                i++;
            }

            // build a marine if we can
            if (barrack != null && !barrack.IsBeingConstructed() && barrack.GetTrainingQueue().Count == 0)
            {
                barrack.Build(UnitType.Terran_Marine);
            }

            // move the marines to the nearest chokepoint in the map
            foreach (var marine in marines)
            {
                if (!marine.IsMoving())
                {
                    var marinePosition = marine.GetPosition();
                    var nearestChokePoint = Map.Instance.ChokePoints.MinBy(x => x.Center.ToPosition().GetDistance(marinePosition));
                    var nearestChokePointPosition = nearestChokePoint.Center.ToPosition();
                    marine.Move(nearestChokePointPosition, false);
                }
            }
        }
    }
}

Limitations

BWEM doesn't provide any geometric description (polygon) of the computed areas.

Starcraft and Starcraft: Broodwar are trademarks of Blizzard Entertainment. BWAPI.NET through BWAPI is a third party "hack" that violates the End User License Agreement (EULA). It is strongly recommended to purchase a legitimate copy of Starcraft: Broodwar from Blizzard Entertainment before using BWAPI.NET and/or BWAPI.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
0.1.7 314 1/28/2023
0.1.5 300 1/21/2023