archive by month
Skip to content

Steamhammer 1.4.4 change list

Steamhammer bugfix version 1.4.4 is uploaded to SSCAIT. It has only been a week since the last version was uploaded, so the changes are not many. The bug fixes probably mean slightly less inexplicable erratic behavior. Zerg is slightly smarter because of a few small tweaks, but it may not be easy to tell.

After rechecking the CIG publication dates, the next public release may not be until October, after AIIDE submission closes. We’ll see; there is plenty of time before then for me to change my mind.

the Bruce bugs

The bugs found by Bruce Nielsen (Locutus) and related fixes.

BuildingManager::validateWorkersAndBuildings() copied building objects unnecessarily.

BuildingManager::cancelQueuedBuildings() and BuildingManager::cancelBuildingType() unsafely deleted buildings from the _buildings vector while looping through it.

Squad::releaseWorkers() had a similar deletion bug.

MapTools::nextExpansion() had a typo that caused it to do a check with the wrong coordinates.

other code changes

UnitUtil::GetAttackRange() and UnitUtil::GetAttackRangeAssumingUpgrades() mistakenly returned the weapons range of a reaver or a carrier as 8 pixels, rather than 8 tiles (8 * 32 pixels). “We’re perfectly safe at this distance, folks!”

• I am reworking DistanceMap as the foundation of a range of classes that keep a number for each tile of the map. A new base class Grid provides the basic data structure, initialization to a constant value, and lookup. DistanceMap is renamed to GridDistances. I wrote a new class GridAttacks as a start on a kind of influence map; some code is there, but it is not yet tested or used, so exercise care.

• Removed the unused BuildingData class, and the unused method MicroManager::calcCenter().

• Removed more unnecessary includes.

zerg

• If an expansion hatchery fails to build, the building manager turns it into a macro hatchery instead. It prevents Steamhammer from sending drone after drone to expand and losing them all. It’s a low-level trick instead of the high-level tactical safety analysis that should be done, but it’s simple and it works moderately well.

• Versus protoss, count only corsairs, scouts, and carriers as reason to make devourers. Steamhammer played a game in which it made devourers to combat the enemy’s large number of observers. “I know how to beat that plan!”

• On 2 player maps, increase the chance of playing rush-safe ZvZ openings. Also rejiggered fast pool chances (suggestion by Antiga). A number of other probabilities are adjusted, mostly to make more diverse choices so that learning has data to work with.

new Steamhammer plan: win

In AIST S1, Steamhammer got to play only 5 games and lost 4 of them. It was a sad showing, though the field was strong. CIG is coming soon, and Steamhammer is registered. Then AIIDE is after that. Also, as I have mentioned, Steamhammer is unbalanced in its play skills, much stronger in strategy and macro than in tactics and micro. Looking at results in the past few months, I’ve concluded recently that it is so unbalanced that improving strategy no longer helps at all. When I fix a strategy weakness, even one which demonstrably loses games, the benefit is so small that there is no detectable change in skill, either objectively in elo or subjectively in my judgment. The imbalance is so extreme that nearly all losses, even in games affected by strategy problems, are due to mistakes in tactics and micro.

That means that if I work on the opponent model and opening selection as I planned, I won’t be able to tell if am doing a good job. No matter what I try, it will hardly affect results. It also means Steamhammer is at risk of getting whomped in CIG and AIIDE.

I have made a bunch of bug fixes recently (thanks Bruce!), so here’s my new plan. I’ll release 1.4.4 shortly with source, and to save time I’ll skip releasing the source of 1.4.3. (It takes more effort than you might imagine.) 1.4.4 includes bug fixes (one of which hasn’t been mentioned here), plus a start on an influence map for tactics, plus a zerg strategy fix that may save 1 game in 200 and a zerg tactics change that is more likely to save 1 game in 15 or 20. I think it’s all stuff that people should have.

Then the next public release will be after the CIG deadline next month (CIG releases source itself), and the following one may be after the AIIDE submission deadline in October. I will buckle down and make the changes that improve play the most in that time.

PurpleSwarm vs human show match

Two short posts today.

The human-machine show match from AIST S1 was streamed today, showing PurpleSwarm against a protoss.

On Sparkle, PurpleSwarm was able to take the crystal gas, unlike Steamhammer. Except for that, the two bots seemed to have similar skills and play styles on the map. One extra gas is a big difference, though.

2 games were on Third World. PurpleSwarm showed no sign that it knew how to mineral walk through the gates on the map. Steamhammer doesn’t know either. From past comments, it sounds like McRave is ignorant too, but Tscmoo has the skill. Does anyone know about MadMix? Just curious.

Hao Pan’s bunker rush

Hao Pan has started to play a cheese opening: Barracks in the center of the map at 6 supply, followed by a bunker at the enemy base, usually near the entrance. Many bots seem unready for the trick and react poorly. Krasi0 has been losing games. Bereaver stopped the bunker with skillful probe micro, but then forgot to make gateway units and suffered for it.

If the bunker fails, then Hao Pan’s marines will scatter and try to lure the enemy units all over the map like the Pied Piper. Most bots fall for it, including Steamhammer and forks. The game Hao Pan-Antiga is entertaining to the end.

LetaBot used to play a similar opening, though not with the strong basics of an Iron fork. There are still new cheeses to try, and old ones to improve on, and every time somebody does it, they catch unsuspecting victims. I have some cheesy ideas in mind; maybe I’ll get one ready in time for AIIDE.

new bot UITtest

New protoss UITtest is from Vietnam. The name “UIT” suggests that it may be from the University of Information Technology at Vietnam National University, Ho Chi Min City. UITtest plays a fixed opening, 1 gateway gas with exactly 4 zealots before the first dragoons. It seems like a fine bot opening. UITtest and its sibling UITtest2 both have a win rate around 50%.

UITtest is a fork of UAlbertaBot. The .dll is larger by 2K out of about 1900K, which means it was recompiled and probably has minor changes. In a quick look through the binary, I see a change in StrategyManager. UITtest2 is similar, with a .dll only 1K larger than UAlbertaBot and a different configuration. In watching games, except for the opening line I wasn’t able to see any changes from UAlbertaBot’s play.

AIST S1 results announced early

The AIST S1 results are out far ahead of schedule. I called the favorites as #1 McRave and #2 Tscmoo protoss. The winners turned out to be #1 PurpleSwarm and #2 McRave. Go zerg! But Steamhammer, the other zerg competitor, was the first to be eliminated.

AIST S1 bracket with results

We don’t get to see the games themselves until later. We do know the match results and the map order, so we can infer some of the specific game results.

The rules said that maps would be chosen randomly. I assumed that meant that the map order for each match would be chosen randomly, and games would cycle through the maps. But no, it was literal: For each game, a map was chosen at random. Some matches had repeated maps. For example, in the match McRave 2-0 Tscmoo, both games were played on Third World.

5 is an awkward number for an elimination tournament, as I said before. I expected 1 bye in the first round and 1 in the second, giving an advantage to the bye players. The bracket software instead gave 3 byes, so that the first winners round consisted of only 1 match, MadMix versus Steamhammer. These 2 players started at a disadvantage; if one of them was to come out on top of the winners bracket, it would have to win 1 more match than the 3 bye players. With 1 player in the losers bracket after 1 round, and 3 after 2 rounds, the losers bracket also needed to be split into 2 rounds, disadvantaging another player. MadMix could not be given another disadvantage, so Tscmoo got it.

The rules call for random seeding, so at least it’s fair on average—nobody has an advantage before seeding (only after). But there is no fair way to pair an elimination tournament with 5 players. Some competitors will always have an easier path than others. It’s hard to know when the byes make a difference in practice, but I notice that the 2 winners were the 2 players who were given no disadvantages.

Steamhammer bug fixes

Yesterday was a productive day for fixing bugs, thanks to info from Bruce Nielsen, author of Locutus. See comments to Steamhammer 1.4.3 change list. Because tournaments are coming up, it may be a while before I release another public version of Steamhammer, but bugfixes are important for everyone with a fork, short of the devil.

After fixing these bugs, I can no longer reproduce the “wrong reserves” error messages that the building manager used to kick out several times per game. Other mysterious misbehavior is probably fixed too, though I’m not sure what.

BuildingManager shouldn’t copy buildings

The methods BuildingManager::validateWorkersAndBuildings() and BuildingManager::checkForCompletedBuildings() loop through the vector of Building data structures and delete those that are no longer needed. To avoid deleting from the vector of Building objects while in the midst of looping through it, it stashes the buildings to delete in another vector toRemove and passes toRemove to a deletion method.

    std::vector<Building> toRemove;

Well, it’s copying the building data. I haven’t uncovered any bug that this causes, but it is wasteful at best and at worst an invitation to errors. If code updates the copies, or updates the real buildings before the copies are sent in for deletion, no real building or the wrong real building might be deleted because of how equality is defined in the Building class. undoBuildings() has to undo data structure dependencies and could easily make such a mistake.

There are several steps to the fix, but the idea is to keep a vector of references instead of a vector of copies. To keep references in a Standard Template Library container, we have to uglify the type signature with a wrapper.

    std::vector< std::reference_wrapper<Building> > toRemove;

The rest of the code doesn’t change, only the declaration. Then we also have to update the declarations of the deletion routines that undo data structure dependencies and perform the deletion.

    void undoBuildings(const std::vector< std::reference_wrapper<Building> > & toRemove);
    void removeBuildings(const std::vector< std::reference_wrapper<Building> > & toRemove);

canceling buildings is incorrect

BuildingManager::cancelQueuedBuildings() and BuildingManager::cancelBuildingType() also delete unwanted buildings, and do it while looping through the vector of buildings. It is unsafe and can cause errors. It’s my fault, I wrote these. I rewrote them like this:

// It's an emergency. Cancel all buildings which are not yet started.
void BuildingManager::cancelQueuedBuildings()
{
	std::vector< std::reference_wrapper<Building> > toCancel;

	for (Building & b : _buildings)
	{
		if (b.status == BuildingStatus::Unassigned || b.status == BuildingStatus::Assigned)
		{
			toCancel.push_back(b);
		}
	}

	for (Building & b : toCancel)
	{
		cancelBuilding(b);
	}
}

and

// It's an emergency. Cancel all buildings of a given type.
void BuildingManager::cancelBuildingType(BWAPI::UnitType t)
{
	std::vector< std::reference_wrapper<Building> > toCancel;

	for (Building & b : _buildings)
	{
		if (b.type == t)
		{
			toCancel.push_back(b);
		}
	}

	for (Building & b : toCancel)
	{
		cancelBuilding(b);
	}
}

releasing workers from a squad

I realized I was not sensitive enough to this category of bug, and surveyed the codebase to see whether there were any more. Almost all risky loops were correct, whether written by Dave Churchill or by me, but I found 2 more. One was inconsequential because it was in the BuildingData class, which is unused (so I deleted it). The other was in Squad::releaseWorkers() and should be fixed.

// Remove all workers from the squad, releasing them back to WorkerManager.
void Squad::releaseWorkers()
{
	for (auto it = _units.begin(); it != _units.end(); )
	{
		if (_combatSquad && (*it)->getType().isWorker())
		{
			WorkerManager::Instance().finishedWithWorker(*it);
			it = _units.erase(it);
		}
		else
		{
			++it;
		}
	}
}

finding the next expansion to take

Bruce also pointed out an unrelated typo in MapTools::nextExpansion(). It's a serious bug. Here is the Locutus commit fixing it.

Change this:

        for (int x = 0; x < player->getRace().getCenter().tileWidth(); ++x)
        {
			for (int y = 0; y < player->getRace().getCenter().tileHeight(); ++y)
            {
				if (BuildingPlacer::Instance().isReserved(x,y))
				{
					// This happens if we were already planning to expand here. Try somewhere else.
					buildingInTheWay = true;
					break;
				}

To this:

        for (int x = 0; x < player->getRace().getCenter().tileWidth(); ++x)
        {
			for (int y = 0; y < player->getRace().getCenter().tileHeight(); ++y)
            {
				if (BuildingPlacer::Instance().isReserved(tile.x + x, tile.y + y))
				{
					// This happens if we were already planning to expand here. Try somewhere else.
					buildingInTheWay = true;
					break;
				}

x and y were treated as absolute map coordinates instead of relative to the building location, so the check gave completely wrong results. The next check, immediately below, is correct; the bug is a typo. But the social status of the bug does not matter. What matters is that it broke stuff.

Proxy updated; Locutus vs. Krasi0

updated Proxy

New bot Proxy is—I can almost add “of course”—updated already. The obvious change is a zergling build if the opponent is zerg; the hydralisk build was too slow for ZvZ. The zergling build is successful, and Proxy’s elo has climbed over 2000. It is now an average bot, maybe better than average. That is excellent for a newcomer.

Locutus and minimum tank range

When Locutus runs dragoons by Krasi0’s bunker, Krasi0 (in games I’ve seen by the current version) has 1 siege tank available as its main interior defense. Terran sieges the tank and Locutus loses its dragoons, doing less damage than it should.

dragoons keeping their distance

In a broad sense, this is why I haven’t implemented runby in Steamhammer. Running by fixed defenses is easy, but playing well after you have run by is not so easy. The runby units become desperadoes, expecting to die and seeking to deal as much destruction and distraction as possible until then. Steamhammer’s units normally retreat from too much danger; desperadoes may be able to retreat, but can’t count on it. They have to make different decisions about what to shoot at, when to run away, and where to run to.

In this case, the important thing to shoot at is the tank, which limits the dragoons’ freedom too much. The dragoons should rush inside the sieged tank’s minimum range. They’ll win the fight and live to cause more trouble. Dragoons that wander too far off or take potshots at SCVs are not contributing as much as they could.

I think it’s complicated to handle all the defenses terran might try. I guess it’s a matter of taking one step at a time.

the ordeal of Sparkle

Mark Twain advised writers that every time you want to write “very” you should put “damn” instead: “Supporting Sparkle is damn hard.” Your editor, he said, would remove the word “damn” and your writing would be as it should. Well, I don’t have an editor. Supporting Sparkle is damn hard, and my writing is as it should be.

When I first looked at the AIST competition, I posted “I will have to spend time surviving tricky map features and won’t have much for thriving with the important play features like mineral-walking drones into the third world, or linking up island bases with nydus canals.” I was right. Steamhammer can survive on Sparkle and Third World, but it doesn’t have the skills to play the maps as they were meant to be played. I did not have the time to implement them. That’s the theme of this post: Not enough time.

the Require: feature

Since Sparkle requires specialized openings, I wanted to implement at least Require: { “map” : “Sparkle” } for openings in the configuration file. See yesterday for the many ways in which my plan was flawed. I invested too much time before I realized that it would not pay off, and I had to put in a hack and move on to other stuff. It was not fun. I’ll rethink this completely for the next version.

the opponent model

You can’t get 5 pooled on an island. You don’t have to do anything special if the enemy makes a fast factory—you expect that on an island map. The plans that Steamhammer knows how to recognize don’t matter on island maps, and I had neither time nor test opponents to work on recognizing island plans, much less to counter the plans. It made more sense to short-circuit the plan recognizer, or you might say, to correctly recognize that none of the known plans mattered.

Still, Steamhammer does know 3 Sparkle openings, and it would have been nice to rely on the opponent model’s opening selection to pick the ones that worked better. But that was problematic too, because of how the opponent model tries to generalize across maps. Most maps you can generalize across: If this opening worked well against this opponent on Circuit Breaker, it has a good chance to work on Roadrunner too. But island maps, and concept maps in general, call for specialized choices; you can’t generalize from a concept map to any other map, or vice versa. I’ll remember that when I work on opening statistics, one of the next planned features. I learned that Steamhammer should be able to measure how much a map is like other maps, and generalize appropriately.

island transport

When I surveyed the AIST S1 map pool, I thought: Hmm, Sparkle is an island map and Third World is a kind of semi-island map where workers can pass between the map halves by mineral walking. The important skills are mineral walking, drop, and placing nydus canals. What combination of skills should I aim for first? Drop is the most flexible and the most useful overall, but it will take a ton of work to implement in Steamhammer because the existing infrastructure is weak. Also drop is slow and awkward for moving units around. Mineral walking drones is comparatively easy, and it is useful on a modest variety of maps. Also mineral walking doesn’t require research; when you can use it at all, you can use it from the start of the game. Nydus canals are the best way to move units between islands in the late game, they’re useful on almost all maps, and they’re related to pathfinding which I want to work on, so now is a good time to work on nydus. Plus Sparkle provides neutral zerg buildings on islands, so zerg can create nydus connections without needing drop. Mineral walking and nydus were my choice; drop is not required for zerg to play either map.

As it turned out, I didn’t have time to implement either feature. Steamhammer is restricted to its starting island and cannot move land units to another island. Zerg will win with air power, or it will not win. On Third World, Steamhammer is restricted to the starting half of the map, which has only 5 bases including the enemy main and natural. It’s disappointing.

island strategy

Ideally, I wanted to provide an air strategy with an optional switch into a late game ground strategy of securing islands with hydralisks by nydus. As the deadline approached, I foresaw that I would not have time for nydus, so I spent a few days getting the air strategy tuned up. I optimized the 3 Sparkle openings (1 hatchery muta, 2 hatchery muta, and 3 hatchery muta) until improvements became small. Once I realized that I could not finish the Require: feature and that the opponent model had to be more or less turned off, I simply set each opening to be played 1/3 of the time. It’s as good a guess as I can make.

At first, the mutalisks were uselessly weak. To get anywhere, I had to make changes to the strategy boss to give it some understanding of island maps. First, correct the unit mix so Steamhammer sticks with air and doesn’t decide to switch to lurkers or ultralisks, which without drop or nydus have no offensive value. Even after that, Steamhammer often lost against the weak built-in AI. I continued: Reduce ground upgrades and eliminate unnecessary research to save gas for mutalisks, and get air armor upgrades. Now Steamhammer can defeat weak or unprepared opponents. Improving mutalisk and scourge micro would help more, but that would have taken way too long.

In Candide’s best of all possible worlds, meaning several versions from now, Steamhammer should support drop and have the option of following a ground strategy on an island map. Ideally.

ground units

Steamhammer still tends to make many zerglings with its leftover minerals, which it accumulates because it has too many drones for what it is doing, which is because it doesn’t understand that it is stuck on one island. Well, its economy control skills are lacking overall; it only wants to make drones up to a limit depending on the number of mineral patches and geysers it has. The zerglings are at least useful for keeping an eye on the island and stopping drop attempts.

At first, the zerglings tried to reach the enemy base, piling up at the island edge. I expected that; it is part of what MapPartitions is for. I updated the tactical analyzer (primitive as it is) to only send ground squads to places they can reach. Now the zerglings understand that they can’t get to any enemy base, so they “explore the map,” running back and forth between corners of the starting island to keep an eye on things. Incursions should be spotted right away.

There is a bug with assigning air units to a ground squad. Despite a fix in the previous version, it still happens sometimes; it must be a second bug. I’ve seen guardians assigned to the ground squad when they should not be, which on Sparkle causes this weird behavior: The squad is sent as usual to explore the map, but because it includes air units it knows it can explore the entire map. The zerglings again gather at the edge of the island, while the guardians slowly drift from empty point to empty point. The bug doesn’t cause much trouble on land maps, but on islands it’s serious.

Steamhammer still makes defensive sunkens as usual when it sees a scary enemy ground army. It doesn’t know whether the army might appear at its base.

At some point in the 1.5.x series I will make squads more dynamic. I plan to make it illegal for a squad to have ground units in more than one map partition; if a ground unit moves from one partition to another, it will be put into a different squad which belongs to that partition. Ground units in transports will belong to a different squad yet. Squads won’t have to worry about their units being stuck in separate places, and should have an easier time making decisions.

island scouting

Steamhammer’s original Recon squad is a small ground squad that scours the map for enemy bases, and when it finds one, may attack if the base is poorly defended. On Sparkle, Steamhammer only found a new enemy island base when it happened to stumble across it while doing something else. I changed the squad assignment so that on an island map, the Recon squad consists of 1 overlord. Before overlord speed finishes, the overlord moves so slowly that its recon target often times out before it gets there, switching the overlord to a new destination, but the overlord still crisscrosses the map and sees stuff that wouldn’t otherwise be seen. Once speed is done, the overlord scouts nicely. Steamhammer has no overlord survival skills, so the overlord will happily fly over turrets and generally has no fear. I’m hoping that the scouting info makes up for the vulnerability. But in test games, Steamhammer loses overlords at a high rate.

destructible blocking buildings

The low ground natural base on each starting island has a psi disruptor building on top of the geyser. Every race can build a refinery building under the psi disruptor, but none can mine the gas until the psi disruptor is destroyed. I found by experience that building an extractor before destroying the psi disruptor was a poor idea. First, the extractor apparently sticks out beyond the edges of the psi disruptor at some points, so that zerglings attacking the psi disruptor have to choose their target carefully and it takes longer to finish off the neutral building. Second, when the psi disruptor is destroyed, usually—though not always—the extractor is destroyed at the same time. I’m not sure how that happens, but it explains why I’ve always seen pros destroy the building first and take the gas after.

Yesterday I described Steamhammer’s new multi-part system to destroy the psi disruptor, and how the openings are adjusted to get the right number of zerglings at the right time to take the gas when needed. It’s complicated and it is needed only on occasional concept maps like Sparkle.

the geyser with a crystal on it

The high ground natural has a geyser with a big crystal on it. Only zerg can mine from that geyser. Steamhammer does not believe that it can take this gas, and never tries. I have a theory about why, but I haven’t looked into it; I chose to deal with the destructible buildings first, and ran out of time. It may have been the wrong decision. Maybe I should have skipped the destructible psi disruptor and figured out how to take the crystal gas.

As zerg, Steamhammer should be able to mine 3 geysers on its starting island. It is only smart enough to get 2.

taking the high ground natural

BWTA believes that the high ground natural base does not exist; it does not locate a base there for any race. Maybe it understands that the neutral zerg lair spreads creep which blocks the base placement. If so, it is a mistake: Zerg can build on the creep and mine the gas, and terran and protoss can either destroy the neutral lair and wait for the creep to dissipate, or (since they can’t mine the gas) locate a base on the opposite side of the minerals. Pros commonly take the opposite side of the minerals. To figure all this out needs a sophisticated understanding of the situation.

Steamhammer’s map analysis doesn’t understand the base either. It doesn’t realize that the neutral lair spreads creep, and tells all races they can build a base in the normal spot. Or, in some starting positions, near the normal spot; it sometimes displaces the base (maybe there’s an off-by-one bug). Since Steamhammer will be playing zerg in AIST and no other map has the weird features, it was good enough and I left it alone.

Steamhammer recognizes the neutral lair as a “blocker” that should be destroyed, but does not destroy it. I think the bug happens because of a use of BWTA that I didn’t remove. It does no harm in practice, so I left this one alone too.

I decided to do all this stuff and I’m not convinced that it was worth it. I could have concentrated on Third World instead. I would now have the mineral walking feature at a minimum, and it could share some pathfinding code with nydus canals. On the downside, I would have done less to improve Steamhammer’s play in AIST, because moving Sparkle from can’t-win to can-win is a bigger jump than moving Third World from can-win to plays-nicely. On the upside, I would have had a feature that is more widely useful. I feel some regret. I could have chosen to play somewhat better on a variety of maps, and instead chose to play substantially better on one map, Sparkle, that may never matter again. And that substantially better play is still painfully weak.

Steamhammer 1.4.3 uploaded to SSCAIT

Steamhammer 1.4.3 is uploaded. I cleared its learning data, so it is starting from zero and has to figure out on its own how each opponent plays. This is the AIST version. As I have mentioned, the changes affect play on SSCAIT so little that it will be hard to notice any difference.

Note: Because this is the same file I submitted to AIST, debug drawing is turned off. The stream will not show Steamhammer’s familiar game info and production displays.

Steamhammer 1.4.3 change list

AIST S1 submission is closed, so here is the change list for the new Steamhammer 1.4.3 which I submitted. I’ll upload this to SSCAIT tomorrow when I have energy again; I had an exhausting weekend. The SSCAIT upload will be the same file I submitted to AIST, and this would also be a good opportunity to clear Steamhammer’s learned data and start the blank slate test that I mentioned in this post.

Most of the work for this version was preparation to compete in AIST with its demanding maps. Play on other maps is barely different. This post is about what I did, and tomorrow I’ll go into the overall plan and what I didn’t do.

map support

• MapPartitions provides information about walkability and ground connectivity per walk tile. It is used in various places, mainly for figuring out what places a worker or a ground squad can reach, as is needed to support island (Sparkle) and semi-island (Third World) maps. It also helps on land maps that have islands or plateaus, which are common. squad.mapPartition() tells which map partition a squad is on (a squad might have units in more than one partition—it picks any one unit arbitrarily and goes with that unit’s partition). On the map Third World, the narrow ramps from the main bases seem impassible to Steamhammer at build tile resolution (32x32 pixels), but MapPartitions at walk tile resolution (8x8 pixels) understands that units can pass through. It fixes the inability to expand on Third World.

• A bug in map analysis caused a crash on Transistor. Fixed.

• On the map Third World, BWTA doesn’t provide a region for the enemy base. Steamhammer uses BWTA regions for directing the worker scout to and around the perimeter of the enemy base. The missing region caused an endless stream of exceptions and left the scouting worker idle. At some point I will have to provide another way to direct the worker scout (Locutus shows one idea), but for now I worked around it by releasing the scout if there is no region when there should be. Third World is a 2 player map, so it is relatively less harmful to skip worker scouting.

• I wrote 3 openings for Sparkle, a map which requires specialized openings—seriously specialized openings for this map only. Zerg has to make the right number of zerglings at the right time, as dictated by the map design, to get the next gas geyser its strategy calls for.

• I wanted to provide the Require: feature to configure openings appropriate to given map features, but my design was crummy. First, as described it cannot work, it’s not correct for all cases; second, because of how opening selection is implemented, it seems to require a substantial rewrite; and third, it interacts with opponent model opening selection in ways that I didn’t account for. Major ouch. For now, I hardcoded “if the map is Sparkle, select from the Sparkle strategy mix” of the 3 Sparkle openings. Hold your nose, it’s a disgusting hack.

• Sparkle places a psi disruptor on top of the geyser at each starting island’s low ground natural base. You have to destroy the psi disruptor to mine the gas. To support Sparkle (and a small number of other maps, such as Arkanoid), I assembled a complex feature that destroys neutral buildings which obstruct the operation of bases. Actually I kept it simple: The feature destroys neutral buildings which are very close to bases; good enough. Each base, during the bot’s initialization when its data structure is created, finds any neutral buildings that it thinks are in the way and remembers them as blockers. The tactical analyzer, choosing targets for squads to attack, looks to see if any of our bases have blockers, and may assign a squad to destroy the blockers. That involved adding a new squad order DestroyNeutrals and new code in the squad to implement the order (this part at least can be reused when I get around to destroying neutral buildings that block paths). When a blocker is destroyed, InformationManager (responsible for unit tracking) notices and informs Bases, which keeps a reverse index for efficiency and tells the affected base that its blocker is gone. Whew. Not simple, but necessary to play an acceptable game on Sparkle. The feature usually works but fails occasionally, apparently because InformationManager prematurely decides that a blocker has been destroyed; I’m not sure how that happens.

• Island support: Steamhammer normally sends an overlord scout, unless the opponent is known to be terran. It has zero overlord survival skills, so it doesn’t send an overlord to look at a terran base. On island maps, it can’t scout by ground, so I changed it to send the overlord anyway (and lose it to marines) if Steamhammer starts on an island.

• Island support: The Recon squad was designed to perform reconnaissance in force with a small ground squad. On an island map, instead it assigns 1 overlord to be the Recon squad. Obviously that’s no longer reconnaissance in force. It works adequately, but the lone overlord is vulnerable and easily lost.

• Island support: Zerg strategy is adapted to islands. Mainly, zerg goes air only until nydus canals are established. Since zerg doesn’t know how to establish nydus canals, that’s the entire game. It does make plenty of zerglings with its excess minerals, which scout around the island they are on and pounce on any drops.

• Island support: Zerg delays ground upgrades to save gas for its air strategy. It turned out to be a necessary adaptation. Steamhammer is normally aggressive about getting evo chamber upgrades, and it ate up so much gas that the mutalisk fleet was stunted.

• Zerg gets air upgrades when appropriate. Well, it gets air armor up to +2 before greater spire. Steamhammer hasn’t had that feature since early days; I finally restored it. This isn’t technically an island support feature, since it could happen in any game, but it is especially important with the island air strategy.

• Island support: The plan recognizer and plan predictor do not try to recognize or predict island plans; the enemy plan is always Unknown. For one thing, I would need to add new and different island plans; the existing plans don’t fit. For another, Steamhammer doesn’t understand that island and non-island maps are fundamentally different, and that what it learns about an opponent on an island map is probably wrong on a land map, and vice versa. To handle this right, the map adaptation in the opponent model needs more smarts. Anyway, the upshot is that the opponent model is effectively turned off on an island map.

•  I removed more uses of BWTA from various places in the code. There are still a lot more to go; I mainly removed the uses that got in the way for AIST.

buildings

• Fixed a nonfatal exception: A fresh Building object was initialized wrong in one case, so that canceling an expansion which could not be placed might throw. An expansion can almost always be placed (that is, can almost always have its final location set), so it was rare.

• Only print the “reserves wrong” debug message if the DrawBuildingInfo debug option is turned on. The “reserves wrong” message was supposed to shame me into fixing the underlying bugs, but it failed; the bugs are still there.

• In removing BWTA from the code which chooses where to place the next expansion, I removed a feature: Steamhammer will now happily expand to a base in a region where the enemy has buildings. I didn’t want to do extra work to keep using the BWTA region when I intend to drop BWTA. I may have to add the feature back if it causes problems.

tactics

• Squad status strings are a little more informative. Turn on DrawSquadInfo to see them. I should rewrite the squad display, because it’s tough to understand and messages from different squads can overlap on the screen.

• Tactical targeting: A lifted building will be assigned to a squad that can attack air. Clever, no? Oops, but a squad with zerglings and scourge qualifies... well, one step at a time.

• Micr0 targeting: A higher priority for air units to hit tanks. Picking off tanks can be critical, but Steamhammer didn’t think so.

• Micr0 targeting: Scourge are slightly more eager to hit carriers, as opposed to other targets.

code changes

• Changed instances of BWAPI::Position(0,0) to BWAPI::Positions::Origin.

• In the configuration file, I moved the debug log location from the Debug section to the IO section. Keeping the file stuff together seemed more important than keeping the debug stuff together, since the other debug options are unrelated to the debug log.

• Added the missing manual commands /set drawscoutinfo (forgotten long ago) and /set drawqueuefixinfo (forgotten recently).

• Formerly, if you asked for the center point of a squad with no units, you got (0,0) and (if it was turned on) a message on the screen. Not so useful. Now you get the location of the starting base—the spot where future squad members are most likely to appear—and no message.

openings

• The Sparkle openings are Sparkle 1HatchMuta, Sparkle 2HatchMuta, and Sparkle 3HatchMuta. Simple. The 1 hatchery opening starts with 9 gas 9 pool to get mutalisks as fast as possible, and the others start with 12 hatchery. The followups are different from the land-based parent openings, though: They have few zerglings at specific timings, more drones, and earlier hatcheries and second gas. Details matter—it’s not so simple after all.

• New anti-factory variations to offer choices in defeating terran vulture-first play: AntiFact_13Pool and AntiFact_2Hatch.

zerg fixes

• Fixed a problem that could make drones way over the limit. It was rare—except on island maps. I had been puzzling over this one for months.

• Fixed a typo in calculating gas reserves after ordering a carapace upgrade. It was a bug, but the effect is barely noticeable even if you know what to look for—it might delay a few gas units from this production round to the next round seconds later.

Next: The ordeal of supporting Sparkle.

AIST S1 prospects

AIST S1 registration has closed, and the participant list has been announced. In alphabetical order:

protossMadMix
protossMcRave
zerg PurpleSwarm
zergSteamhammer
protossTscmoo

I expected McRave and PurpleWave, because their authors said they’d play. Instead of protoss PurpleWave we got zerg PurpleSwarm. I wonder why? Is it because of Sparkle? Is it because Purple Dan foresaw the protoss overload we would have gotten? Tscmoo has always been an ambitious bot, so it is not a surprise to see it. I was surprised by MadMix, and maybe I shouldn’t have been. These are bots that implement, or in Steamhammer’s case at least aspire to implement, a large number of skills for different situations. MadMix has been of that mold since its beginning. The challenging AIST maps demand those skills.

There are no terrans. That’s unfortunate.

The tournament format is double elimination, so we get a #1 and #2 finisher. I think the favorites are McRave for #1 and Tscmoo for #2. But if we knew the outcome ahead of time, we wouldn’t have to play the tournament.

5 participants is an awkward number for an elimination tournament. With an odd number in the first round, 1 player will get a bye and move on to the second round of the winner’s bracket without having to play a game. 2 players will drop to the loser’s bracket, and the second winner’s bracket round will again have an odd number of players. It’s no good to give the same player a bye twice, so this time one of the winners in the first round will get a bye to the third round of the winner’s bracket. With only 5 participants, the players that get byes have a significant advantage. The rules call for random seeding, so the choice should be purely the luck of the draw.

Nothing is perfect, but so far AIST seems to be thoughtfully and skillfully run. Decisions make sense and events are happening on time—not a given, organizing a tournament is no walk in the park. Keep up the good work!

Next: Expect the Steamhammer 1.4.3 change list on Monday, followed by posts about how I approached the tournament.

new bot Proxy

Zerg bot Proxy (which is not a proxy bot but a dll) is a nice start on a new bot. It plays only one strategy and has no outstanding skills, but its strategy is dangerous against many opponents. Most impressively, it holds a score of 2-0 against Tscmoo terran. It is currently rated not far below 1900, a decent performance for a new bot apparently made from scratch. (It does say that it uses BWEM and FAP.)

Proxy describes its strategy as “eco cheese into mass hydra.” “Eco cheese” means make lots of drones, which says that Proxy is vulnerable to almost any early attack. A lot of bots play rushes, so Proxy will never be a top scorer with this strategy. Once the mass hydras arrive, though, with that big economy behind them they seem endless and relentless. It mixes in zerglings as needed to balance minerals and gas; that may be its greatest skill. This game against Marine Hell is boring to watch, with no variety, but it shows what I mean about relentlessness. Proxy slowly battered its way up a ramp by sheer persistence.

Like any new bot, Proxy doesn’t have many skills yet. It takes 2 bases and never expands again. It cannot replace lost buildings. It is poor at scouting. It often makes weak tactical decisions. These things need time to implement. Considering how little it knows, I think it is performing well.

Good start!

Steamhammer and AIST S1

Steamhammer is registered for AIST S1. It is almost done; I am working on final testing and fixes. After submission closes, I’ll release the new version as 1.4.3 and upload it on SSCAIT. Features that I formerly planned for 1.4.3 will be pushed to 1.4.4, and so on down the line. Expect the usual change list et cetera, plus discussions of the map features and how I chose to cope with them.

On SSCAIT, it will probably be hard to notice a difference from version 1.4.2, because most of the changes are to support the difficult maps of AIST. There are about 7 bug fixes and improvements that affect play on all maps, but in such subtle ways that neither stream viewers nor Steamhammer’s elo should see a change. Even so, there are a lot of changes, including entirely new features like MapPartitions. Judging the change bars by eye, I’d say I touched about 15% of the lines of StrategyBossZerg. There are also changes to tactics, micro, map exploration, the Recon squad, and scouting.

Steamhammer is not remotely ready for the tournament. The impossible is impossible. I took shortcuts to get as far as I did. But it can play games on the AIST maps without looking like a moth flying into a windowpane (“I see the light, it’s that way.” Wham! “Oh... I see the light again, it’s that way.” Wham!), and it can defeat some opponents. It’s a huge step up from crashing, or throwing endless exceptions, or playing a mass zergling opening on an island map. And I’ve made more progress toward removing BWTA, though it’s haphazard—I removed the parts that were in the way.

Next: The new bot Proxy.