Making a weaker but natural bot
The two current bots are turning out to be similar in strength, and there are many players who have played them over 30 times without a single win. It’s therefore time to make a weaker bot. The goals:
- Be fun.
- Be understandable and consistent. Not alternating great play with blunders to even it out.
- Be simple. No complex fights, and at the beginner level, every fight is complex, so rather avoid fighting altogether.
- Be beatable.
- and for me: Be little effort.

To begin, let’s down or disable the rules that contribute to attacking moves. Those are:
- reduce opponent liberties
- cut opponent groups
- do a Monkey Jump / slide
- play Vital Points
- InfluenceDelta - play there where the influence swing is largest
At first I thought to just remove the first one. But without the incentive to reduce opponent liberties, the play becomes very contactless, which is unnatural. Example is playing F8 below (left).
At the same time, cuts still happen (right image, the playtester (my gf) plays black, bot is white), so it’ll start a complex fight nonetheless. Along multiple games my gf remarked she didn’t think this bot was any easier than the other ones, and definitely not the calm game she was promised.
–
So lets turn rule 1 back on, and disable 2. More natural contact-play was back, and cuts occur but not often. Monkey Jumps make the bot suprisingly sharp and intimidating, so that was disabled as well. After that we get a bot that’s pretty docile, playing a wall-builder type of game. My playtester remarked she had fun and didn’t feel pressured.
An example is below, the bot is white. There’s no cut in the game, just some calm area claiming.
>>
A bug occured..
However, at some point the bot played B9 instead of D9…This is a "stupid blunder"™. The “Seal Own Territory”-rule prefered this point over anything else, and it this bug had to be fixed.
Details of the issue and fix
The issue: The “Seal own territory” rule is basic to keep cpu cost down. It has some checks to detect a hole in a wall or near to it. Then from there it casts rays in all directions, and sums how much of “own territory” it sees. The more it sees, the bigger the area it seals off, and the more the move is rewarded. The rays stop when they meet the edge of the lake, which is either a neutral point or an opponent.
The problem here is how the rays are cast from D9:
-
to the left, it sees C9. C9 is still more or less a neutral point, as it is in white area, but black E9 casts influence on it as well. And therefore, D9 doesn’t ‘see’ the area on the left, the ray stops there.
-
to below, there are stones, they don’t count as territory.
-
to diagonally left down (in multiple angles), where they do see some territory, but much less than B9 and C9 stones hit more territory with their rays, and thus they are prefered.
The fix: the code is adjusted that IF there is a candidate territory-edge point (D9), then also check if neighbouring stones (B9 and C9) see a larger lake. Then take the largest of those. Basically: also ray-cast from a little side-stepped position.
This seems to work. B9, C9 and D9 see the same area, and D9 wins because it is closest to friendly stones (the wall).
This is computationally cheaper than floodfilling, which is more accurate at determining a territory size. And floodfilling can still fall into the same trap of neutral points counting as an edge.
Note: a different fix would to be to only consider holes in a wall, but this function also works to claim edges of a territory that are not almost completed walls.
Next steps
I can now say that this version of the bot is calm. But I can’t claim that it is easy. The issue I run into is that I can’t play as the intended audience. Humble brag, I know
, but it’s hard to get into the mindset and skill of a true beginner.
And I won’t always bother my gf to playtest, nor is she representative of all other players. So I’ll tweak some more, and once I think this bot is docile and without stupid play, then I’ll deploy it. Based on how people react to it, I can tweak from there.