Week 12: SALT Farewell


The project is over, and that means it’s time to bid farewell to this blog and for now, SALT Bot. This process has been trying in some ways but also worthwhile in others.

I was able to learn a great deal from doing this project. First of all, I mildly congratulate myself on only missing one deadline (which was due to a birthday celebration…). In terms of coding, I learned how to effectively research and make use of an API, as well as how to setup classes and effectively create a large project. However, I was also forced to face the frustrations of bugs and trying to search for minute changes that were devastating the entire bot’s processes.

Meanwhile, I was able to show myself that I had the motivation and willpower necessary to begin a project independently, with very little external motivation, and see it through to the end. There were many times I felt unmotivated to work on the bot and took some days off, but I was ultimately able to stick through to the very end.

In the end, the bot is as expected – it runs, it plays, but it isn’t good enough to win. That’s what I had planned for, and it was unreasonable to expect anything more. As a final treat, here is the a game I played vs the bot. While I did play more games than this, it’s really annoying to record them so here’s everyone’s favorite mirror matchup.

Bot released here: https://sscaitournament.com/index.php?action=botDetails&bot=SALT+Bot

I will be presenting my experience on the evening of May 23 somewhere between 6PM – 8PM at DoubleTree by Hilton Hotel in San Jose. Join me there!

Last of all, thanks to my BASIS Adviser Mrs. Jefferson, external adviser Dr. Michal Certicky, and the entire StarCraft AI community. Separately, thanks to everyone who made this not such a mundane time: Sergey, Chris, William, Alex, etc. (if you’re on the etc you don’t hang out with me enough).



Week 11: Economy and Strategy

Hi folks,

This week was a quiet one that I spent peacefully at home. While I would say it is a welcome change from the chaos of last week, it’s all been very boring to be honest. Anyway, this week I worked on strategy based on army and supply.

Basically I made a system called econScore, which evaluates each player’s economy through a basic method: econScore = 10 * expansions + workerCount.

This is the first I’ve done of matchup differentiation. In all 3 matchups, a simple condition is used: if the enemy has an econScore of 10 greater than mine (that means they have an extra expansion or I’ve taken tons of damage), the bot will attack immediately.

In the below video, the principle is demonstrated. In fact, I was taken aback completely, as this is the first time something has actually been implemented correctly on the first try! The enemy goes Nexus first (very greedy) and my bot quickly puts the enemy to rest.

Since the mirror matchup is so volatile most of the benchmarks of attack and defense are based on econScore, so if the bot is behind it will attack and ahead it will defend.

For Terran and Protoss I had a much harder time figuring out how to do it. This is particularly because of the UNCONVENTIONAL (bad) strategy used by the default AI (but is good against my specific strategy). Mostly the games turned into Macrogames, which means both players have many bases and are constantly building units.

Also my bot only attacks the main base, so at the end I have to control it manually to kill the enemy for good (even though the game is essentially won).

vs Zerg was much easier, since I had sorted out all of the bugs of vs Terran beforehand. The basic strategy vs Zerg is to attack early, defend mid, and attack late.

The default AI wins with 4 pool, which is the MOST MOST MOST MOST MOST MOST dirty and underhanded tactic in the entire game, only used by the most dark of dolphins. Basically the strategy sacrifices any hope of going to mid game or late game and tries to win in the first 5 minutes (if fails, the game is over).

In a more normal game my bot reigns supreme. Though the kill is definitely not graceful or effective, my bot is certainly persistent and wins through constant aggression.

This is likely the final form of my bot beyond some bugfixes that I do next week. Mostly, I’ll be practicing in preparation for the final presentation on May 23 (so far away).

Alex is god.


Week 10: An Introduction to Strategy


This week involved finally beginning the long awaited strategy portion. I was having a very difficult time, since I couldn’t really find how to start such a broad topic. However, some advice from my advisor Mrs. Jefferson gave me some inspiration.

“Maybe you can come up with a way to decide whether you should be on the offensive or defensive?”

Although in retrospect this is pretty obvious, before I was WAY overthinking how to work on this problem, making huge maps with tons of information. Now, I’ve started working on a basic system that will decide whether to attack or defend.

However, this means I must begin to differentiate between the different matchups starting now. Before, I had the same build order regardless of matchup, but now I’ve begun making some cookie-cutter build orders for each matchup. For those of you who want specifics, vs T is a 2 Gate Robo, vs P is a 2 Gate Robo, and vs Z is 2 Gate CorsairDT (unit AI not implemented).

As for attack vs defense, I was mostly spending time fixing up bugs from the past instead of increasing the system’s complexity. For now, the strategy is to attack at different supply counts that I know in my mind as “advantageous” and “disadvantageous” because of how each race functions.

Super basic strategy…. if it can even be called that

For instance, one problem that  came up was in the early game, units have trouble attacking when the enemy base has not been discovered. To fix this I simply gave the attacking units the same AI as the scouting ones, to look for undiscovered bases.

Various units scouting the map

Furthermore, in the early game when there are fewer units, there was an issue in using the group movement function, since units would only attack IF the leader was near an enemy unit. Since the units are generally split up, this no longer works, so I had each unit attack separately in the early game.

Next week I hope to differentiate and advance the strategy by using various categories: tech, economy, and army. By using these three, I hope I will be able to figure out who has the advantage in any given situation.


Week 8: A Better Way to Move


Last week, I was having trouble creating the scouting function in which units would investigate unknown territory. However, the units were not moving, and I was having trouble tackling the issue, as shown by my words:

Unfortunately, this proved to be bugged as the units fail to move anywhere or attempt to scout. I think the problem that I have is

This week, however, I worked on finding a different approach to handling the issue. Instead of creating individual unit movement, I decided to refine group movement. To do this, I created something called “leader based movement,” where units will follow a leader unit instead of moving independently.

Ultimately, this can lead to armies staying much more compact in their movement, as opposed to the default movement, in which armies turn into loooong congo lines of units.

However, this comes at the cost of speed, as the leader based movement leads to stop and go motions of the large clump. Though, since Protoss units are slower than other races on their own, I don’t consider this to be a particularly large problem.

The more important issue, in my opinion, is the possibility of entire large clumps of units getting stuck when the leader is cornered. To combat this, I should use a better method of choosing a leader to purposefully pick one that won’t be trapped (currently it chooses randomly).


Next, I worked on the very simple version of a combat AI : while I don’t think I’m ready to truly calculate the nitty-gritty of a battle, I have have the units simply decide whether to move or attack when a unit approaches. Currently, while attacking units “dive” (move forward after attacking) but while defending “kite” (move backwards after attacking).

In the future, I hope to refine these, but for now I intend to move on to better methods to decide when to have a full out attack vs when to stay back and defend. There’s spring break next week, so see you guys after that!


Week 7: Beginning Strategy

Hey all!

This week I spent some time at school doing PCR (polymerase chain reaction). Unfortunately, it seems the gel electrophoresis failed somewhere along the way so the results are inconclusive.

Meanwhile, work on the bot has been difficult because the of the lack of visible results currently being produced. For now, I’ve sort of been taking steps backwards in order to prepare to advance. I find that this has been hard to test until it is fully implemented.

As for more specifics, I looked online for examples of how to implement strategy. I found one example which uses an InfluenceMap, which keeps a record of the map and calculates which player has “control” of the map. In particular, this bot is called ecgberht, one of the few bots I found also created in Java, as most of them were created in C++ which I haven’t learned. Source code here: https://github.com/Jabbo16/Ecgberht

I tried to create a similar thing, but in a much simpler version. Each point on the map has 4 potential statuses – neutral (nothing is there), SALT Bot controlled, enemy controlled, and contested. Contested is when both players have more than 4 units, but neither player has 1.5x or more of the enemy’s units in the vicinity.

Code excerpt of how SALT Bot determines influence

However, I have not found a way to effectively make use of this information. I started by trying to create an automated scouting function, in which units would search through neutral areas and “gain control” of them. Unfortunately, this proved to be bugged as the units fail to move anywhere or attempt to scout. I think the problem that I have is

As for next week, I look forward to trying to fix the scouting bugs so that units are able to effectively move around unknown areas to look for enemies. Then, I want to focus on creating judgement for the units, to decide whether they should retreat, get backup, or stay and fight. Sorry for the relatively shorter blog post but I’ve been caught up with going to school and dealing with personal matters.



Week 6: Kiting and Observers


This week gets a rating of OK on progress. This definitely wasn’t the most prolific of weeks, but it wasn’t the worst either, as I was generally able to get things done. I was able to have my bot tech to observers and make dragoons vaguely kite.

First of all, making observers was pretty easy. All I had to do was adjust my bot’s build order (which doesn’t change) to include a Robotics Facility and Observatory.

Robotics Facility

Then, I had the Observer AI function similarly to other units : they stand by the most recent expansion until 100 supply, until they move to the enemy base. In the future (next week), I will work on making Observers scout by default and search for enemy units.


The second mechanic I attempted to implement kiting, which is when ranged units move after shooting. By doing this, engagements with melee units become much more favorable. For instance, a Dragoon will lose horribly against a Zealot without kiting, but can survive completely unscathed with kiting.

In order to kite, my bot flees in the opposite direction of the closest enemy. and fires if it is a certain distance away. However, this is not ideal because this can easily lead to the Dragoons being cornered and killed. Here is a video of the bot trying to kite and decent human kiting.

Near the end, the Dragoons in the bot video are cornered and pinned then, then killed. In an ideal world, the AI would account for being cornered and trapped, and avoid these situations. However, this task is likely too complex for me to tackle.

While the kiting is still sub-par, for now it is satisfactory for my purposes.

Now, people may ask, how am I able to fix bugs? Well, I have an abundance of sources I can use for help. Beyond asking my external adviser, there is also both a Facebook group and a Discord server specifically for Starcraft AI, where people respond nearly instantly upon seeing requests for help.

Also, for specific mechanical issues (such as kiting) there are UMS (use map settings) maps that are premade. In the videos, I am using a map that has 2 Dragoons vs 4 Zealots.

Well, that’s all for this week. I highly recommend anyone reading to start watching the ASL (https://www.youtube.com/channel/UCK5eBtuoj_HkdXKHNmBLAXg/videos) since Season 5 is just getting started and has been very interesting.


Week 5: Triumph


This week I have something a bit different for everyone: a sneak peek into the progress of SALT Bot! This entails a full game against the Starcraft default AI (which is considered to be very bad). Here, the game is a Protoss vs Protoss, and I’ll leave some comments below with timestamps so follow along if you don’t know the game.

0:04 The game begins, with 4 Probes and 1 Nexus (units and building). Immediately, the Probes begin mining while the Nexus begins producing another Probe. While it is optimal to have Probes all mine different mineral patches (called splitting), the bot currently searches for the closest patch to mine.

0:20 At 9/9 supply (on the top right), the Probe makes a Pylon using 100 Minerals in order to increase the max supply. Whenever max supply is about to be reached, the bot will automatically make a Pylon.

0:28 A Gateway is created. At the same time, the bot sends a Probe to scout the enemy. The scout will automatically move to each starting location (in each of the 4 corners of the map on the bottom left) until finding the enemy).

0:37 The enemy is found!

0:51 The Gateway has produced a Zealot, which will guard the ramp to the base by default.

1:38 At 400 Minerals the bot makes a Nexus at the nearest base.

1:49 An Assimilator and Cybernetics Core is produced, in order to collect gas and create Dragoons.

1:58 The second Nexus is completed, and the Zealots move to defend the new base.

2:11 Immediately after reaching 100 supply, the bot moves out to attack the enemy.

2:20 The enemy has Photon Cannons, which is a building that fires upon seeing an enemy. They stand no chance against the might of the SALT!

2:57 All of the enemy buildings are destroyed, and the game is won. GG!

Though it was able to defeat the default AI, the bot is far from complete. Next on my list is to expand the tech and the units able to be produced. So far, the bot only makes Dragoons, Zealots, and Probes. Also, I plan to give Dragoons the ability to kite melee units, so they can move after firing instead of standing still.


Week 4: Boring and ASL5

An uneventful week passes, and progress on SALT Bot is slow. A lot of this week was fixing up some bugs that already existed, and I was barely able to get started on scouting.

My first two days were spent just bug fixing expansions, which was quite difficult. I also restructured some of my methods, but that just means the bot does the exact same thing in the game.

On these last three days, I focused on keeping track of the enemy and scouting the enemy base. So far however, the scout is very buggy, and a probe simply walks to another spawn location and stops there.

A Probe standing still.

As for the enemy, the bot is able to keep track of enemy units, buildings, and bases, but does nothing to react to them in any way, unfortunately.

All in all, so far the bot’s state is: follows a pre-set build order (very generic) and pumps tons of Dragoons and Zealots from Gateways while staying on two bases. The units stand outside of the second base and idle. For next week, I hope to have efficient scouting (at least to see the enemy base), be able to attack, and expand past 2 bases.

In other Starcraft related news, next week will be the start of Afreeca StarLeague (ASL) Season 5! I’ve followed ASL since Season 2, and I’m extremely excited for this. In the first two days of the Ro24, personally, I’m cheering for Shine, Stork, and effort, and I’m very very very very very interested to see what kind of strategies and games Sparkle brings about. Here are some more details on ASL: http://liquipedia.net/starcraft/Afreeca_Starleague_Season_5


Week 3: Pylonmania

Yo! After an exciting one-week break full of mystery, luck, and woodwork, the project resumes. This time, it’s been full of ups and downs.

First, I worked to figure out pylon placement and production. After an unfruitful first day of attempts, I managed to get it working at the end of the second. Now, the probes automatically build pylons when needed and they are placed at the perimeter of the base to give vision.

Next, I built gateways, which wasn’t as hard as pylons since there is already a built in building placement method. In terms of selecting when to place a gateway, my Bot follows a build order so it places it when it has the available money. In theory, this means only after developing and excess of minerals will a tech structure be placed.


I made my Zealot and Dragoon AI very simply stand by the choke point of the main base, as attacking and scouting is an issue I will handle next week.

Lastly, I tried to work on expanding, but to little success. Currently, the Bot is unable to decide which base to expand to and can result in shenanigans like this.


Overall, I’ve realized that the creation of SALT is going to be a long and arduous journey. But at the least, no matter how slow it is if I work at it eventually I will reach some form of solution. A brief discussion with a friend of mine made me realize that the output of my bot is proportional to the effort I am willing to put in. For that reason, I will continue to work hard and hope to see you next week with a functioning bot that even you guys can play against.


Week 1: Inception

Hello! I’ve been asked by some people how my bot is going. All I can say is it’s not good, but it’s also not bad. Progress is pretty slow, but definitely not negligible.

Basically, I started my bot and got a hang of how to use the BWAPI. I wrote a short synopsis of each day I was working:

Day 1: A LOT a LOT of troubleshooting. It took a while to get the game and AI to even run without bugging out. My first task was to get the units to work. It failed. At the end of the day, my function that was supposed to make my probes mine didn’t make them mine, and my bot was useless.

Day 2: I figured out the problem (I think). It seems that for whatever reason, calling game.getUnits() doesn’t work outside of the main class. Though I know the problem, the solution still lies ever so far away…

Day 3: Wasn’t able to work much thanks to some college shenanigans.

Day 4: PROBLEM FIXED! Instead of calling a getGame(), I just passed Game and Player as arguments in the onFrame function. I can now have Probes mine and Nexus build until 9 supply.

Day 5: To make Pylons, I need a way to decide where each Pylon will go. To decide where Pylons go, I need to know what my base looks like. To know the layout of my base, I need to do a lot more planning. I structured the layout of my project and got a general sense of what classes I was going to use.

This blog post is kind of short, so I’ll include some background about myself. I first learned of Brood War in 2008, when my older brother got the game. At the time, I was completely oblivious to most of the nuances of the game. I played single player only, and used cheats (show me the money, operation cwal, etc.) against the AI. I soon stopped playing because I got bored of how mundane the game was with cheats.

Flash forward to February 2017, I watched a progame for the first time. After that, I started following the Starcraft: Brood War professional scene. At that time, ASL Season 2 had ended and I watched the VODs of Ro8 to the finals. Since then, I have ardently followed the pro scene and watch every new game of ASL that comes out. My favorite player is Bisu (come back soon) but my favorite matchup to watch is PvT. My favorite game is Stork vs Last ASL4 Ro24 Day 2.