How to dumb down/weaken/humanize an engine algorithmically?

Discussion of chess software programming and technical issues.

Moderators: hgm, Dann Corbit, Harvey Williamson

Forum rules
This textbox is used to restore diagrams posted with the [d] tag before the upgrade.
dkl
Posts: 20
Joined: Wed Jan 14, 2015 4:55 pm

How to dumb down/weaken/humanize an engine algorithmically?

Post by dkl » Sun Jan 18, 2015 10:07 pm

I'd be interested to hear if there is any published material on how to make an engine play weaker, especially in such a way that it'll be a good opponent. I haven't found any published material or algorithm descriptions on that.

I know that several engines nowadays allow to weaken their strength. I am aware of
a) Stockfish, which has an uci engine option for engine skill
b) Shredder, which allows to set the elo
c) a more general approach used by the Fritz GUI ("handicap mode", seems to work with any uci-engine).

Stockfish seems to just limit the search depth, consider via multipv several lines, and dependent on the strength level, add some kind of penalty for each line, and then chooses some weaker move.

see
http://sourcecodebrowser.com/stockfish/ ... ource.html

Fritz GUI seems to do similar things.

I have no clue about shredder, but there seems to be an additional pattern matching, that looks for dangerous positions etc.

None of these seem to adjust w.r.t. engine parameters. To mimick human play, for example, I'd presume that humans crush under pressure, i.e. have difficulties to precisely defend when the king is under attack etc.

I did note however subjectively these things:
a) Fritz results quite often in very tactical positions, i.e. after playing a game, I often see a lot of missed opportunities on my side (overlooked tactics).
b) shredder games are quite often very boring

All engines do make very stupid moves. Fritz for example once sacked his queen for nothing, Shredder "forgot" a piece that was attacked by a pawn... all moves, that even a 1200 player would never do. Nevertheless Fritz GUI's implementation seems to create the most interesting games.

I am wondering:
a) what ideas are out there to create engines that make better opponents for humans?
b) in particular, how does fritz gui inner mechanis works. For example, if you set the handicap to 200, how is a move selected? Choosing a move that is around (best_move - 2.00)? That would lead to a very stupid game, and almost immediately loss? When is a better move chosen? etc. etc.

I heard that Chess System Tal created often "interesting" games. Any knowledge on the inner workings?

bob
Posts: 20925
Joined: Mon Feb 27, 2006 6:30 pm
Location: Birmingham, AL

Re: How to dumb down/weaken/humanize an engine algorithmical

Post by bob » Mon Jan 19, 2015 12:05 am

dkl wrote:I'd be interested to hear if there is any published material on how to make an engine play weaker, especially in such a way that it'll be a good opponent. I haven't found any published material or algorithm descriptions on that.

I know that several engines nowadays allow to weaken their strength. I am aware of
a) Stockfish, which has an uci engine option for engine skill
b) Shredder, which allows to set the elo
c) a more general approach used by the Fritz GUI ("handicap mode", seems to work with any uci-engine).

Stockfish seems to just limit the search depth, consider via multipv several lines, and dependent on the strength level, add some kind of penalty for each line, and then chooses some weaker move.

see
http://sourcecodebrowser.com/stockfish/ ... ource.html

Fritz GUI seems to do similar things.

I have no clue about shredder, but there seems to be an additional pattern matching, that looks for dangerous positions etc.

None of these seem to adjust w.r.t. engine parameters. To mimick human play, for example, I'd presume that humans crush under pressure, i.e. have difficulties to precisely defend when the king is under attack etc.

I did note however subjectively these things:
a) Fritz results quite often in very tactical positions, i.e. after playing a game, I often see a lot of missed opportunities on my side (overlooked tactics).
b) shredder games are quite often very boring

All engines do make very stupid moves. Fritz for example once sacked his queen for nothing, Shredder "forgot" a piece that was attacked by a pawn... all moves, that even a 1200 player would never do. Nevertheless Fritz GUI's implementation seems to create the most interesting games.

I am wondering:
a) what ideas are out there to create engines that make better opponents for humans?
b) in particular, how does fritz gui inner mechanis works. For example, if you set the handicap to 200, how is a move selected? Choosing a move that is around (best_move - 2.00)? That would lead to a very stupid game, and almost immediately loss? When is a better move chosen? etc. etc.

I heard that Chess System Tal created often "interesting" games. Any knowledge on the inner workings?
I've tried a BUNCH of things. I do not like just randomly choosing moves, as it doesn't feel right. Here's what I do in Crafty:

(1) slow the program down, which weakens it tactically. Note that I said "slow it down" and not "speed it up or make it move faster." This keeps the "flow of the game" feel reasonable.

(2) back off of the pruning stuff that tends to help tactically, and become more "brute-forceish"..

(3) interpolate the eval between a purely random number and the actual eval. For example, with the "skill" command, if you use "skill 50" it (a) runs much slower; (2) doesn't extend or reduce; and (3) the eval is made of of 50% random, 50% actual eval. As you back off on the skill level, the strength of the program has a reasonably linear drop, giving you a good chance of finding a setting that is right in line with your playing skill.

jdart
Posts: 4162
Joined: Fri Mar 10, 2006 4:23 am
Location: http://www.arasanchess.org

Re: How to dumb down/weaken/humanize an engine algorithmical

Post by jdart » Mon Jan 19, 2015 2:41 am

In my engine I slow the speed (thus cutting depth) and randomize the eval. In addition I raise the minimum move frequency for the opening book, so as it gets weaker it will play very common lines but not know about less common ones (it also comes out of book earlier).

However, I am not really happy with the results. At low settings the randomness overwhelms the eval, so that it seems to lack even rudimentary chess knowledge. For example, it will walk the King out to the 3rd or 4th rank in the opening.

I'd like to have a "basic" and "advanced" eval and somehow keep the basic chess knowledge, like development and rudimentary king safety, while progressively reducing the more advanced stuff. That way at low levels it would play a bit more like a beginner who's had a few lessons but lacks sophisticated positional knowledge.

--Jon

User avatar
emadsen
Posts: 316
Joined: Wed Apr 25, 2012 11:51 pm
Location: Oak Park, IL, USA
Full name: Erik Madsen
Contact:

Re: How to dumb down/weaken/humanize an engine algorithmical

Post by emadsen » Mon Jan 19, 2015 2:50 am

A while ago, I wrote a detailed description of how my engine reduces playing strength.

http://www.madchess.net/page/The-MadChe ... -Algorithm
My C# chess engine: https://www.madchess.net

kinderchocolate
Posts: 454
Joined: Mon Nov 01, 2010 5:55 am
Full name: Ted Wong
Contact:

Re: How to dumb down/weaken/humanize an engine algorithmical

Post by kinderchocolate » Mon Jan 19, 2015 3:29 am

There're infinite ways to dumb down an engine. Your idea is only limited by your imagination. Please note that making an engine play like a human such as cracking under pressures is something only the programmer wants but not the users. Everybody wants to win, an engine that loses a game pseudo-randomly is more interesting practically. This answers your first question, the best engine that makes better opponents is the one that loses reasonably, but not like dropping your queen randomly. Virtually all users prefer something that they can kick ass or one in which they get ass kicked (like Stockfish). Very very very few like equal chances with the engine.

Depends on the skill level, I prefer to divide the skills algorithm by 0-1200, 1200-2000, over 2000. In the medium range, run some number of multi-pvs. Collect the scores and moves, then add a small stochastic factor to the non-optimal moves. Select the best move once the random factor added. This way, there is no need to explicitly slow down the engine. The magnitude of the random factor and the number of lines can be interpolated by the skill level.

Players prefer 2000 prefer stronger challenge. They will get small internal parameter random fluctuation such as pawn evaluation (like double-pawn). They will get up to two multi-pv.

Players in the lowest range are assumed be clueless, the engine will get shut down completely and instead the move generator will randomly pick a move. If the move generator finds a material that it can capture for free statically, it'll play it otherwise a random move. This is done to allow absolute beginners to win a game. They're always happy to win despite not knowing how to castle.

bob
Posts: 20925
Joined: Mon Feb 27, 2006 6:30 pm
Location: Birmingham, AL

Re: How to dumb down/weaken/humanize an engine algorithmical

Post by bob » Mon Jan 19, 2015 4:54 am

jdart wrote:In my engine I slow the speed (thus cutting depth) and randomize the eval. In addition I raise the minimum move frequency for the opening book, so as it gets weaker it will play very common lines but not know about less common ones (it also comes out of book earlier).

However, I am not really happy with the results. At low settings the randomness overwhelms the eval, so that it seems to lack even rudimentary chess knowledge. For example, it will walk the King out to the 3rd or 4th rank in the opening.

I'd like to have a "basic" and "advanced" eval and somehow keep the basic chess knowledge, like development and rudimentary king safety, while progressively reducing the more advanced stuff. That way at low levels it would play a bit more like a beginner who's had a few lessons but lacks sophisticated positional knowledge.

--Jon
I have generally gotten complaints that what I do is "not enough" although since the last adjustments I have not heard any complaints. But I discovered that the "Beal effect" can be deadly and that a pure random eval + a normal search can EASILY play at 1700 or so. I had to greatly slow things down so that the random eval did not have enough search behind it to excite the Beal effect.

Last time I tested this, the eval steadily dropped, which is what I wanted. It seemed possible to drive the Elo to sub-1200 levels, which is really "down there". It is hard to measure Elo down at that level since there are few programs that play that badly..

Ferdy
Posts: 4681
Joined: Sun Aug 10, 2008 1:15 pm
Location: Philippines

Re: How to dumb down/weaken/humanize an engine algorithmical

Post by Ferdy » Mon Jan 19, 2015 6:57 am

dkl wrote:I'd be interested to hear if there is any published material on how to make an engine play weaker, especially in such a way that it'll be a good opponent. I haven't found any published material or algorithm descriptions on that.

I know that several engines nowadays allow to weaken their strength. I am aware of
a) Stockfish, which has an uci engine option for engine skill
b) Shredder, which allows to set the elo
c) a more general approach used by the Fritz GUI ("handicap mode", seems to work with any uci-engine).

Stockfish seems to just limit the search depth, consider via multipv several lines, and dependent on the strength level, add some kind of penalty for each line, and then chooses some weaker move.

see
http://sourcecodebrowser.com/stockfish/ ... ource.html

Fritz GUI seems to do similar things.

I have no clue about shredder, but there seems to be an additional pattern matching, that looks for dangerous positions etc.
None of these seem to adjust w.r.t. engine parameters. To mimick human play, for example, I'd presume that humans crush under pressure, i.e. have difficulties to precisely defend when the king is under attack etc.
Nice idea to implement "under pressure". I could just increase the multipv value say 1 or 2 depending on the current score for example. If the score is close to losing add 2 here.
I did note however subjectively these things:
a) Fritz results quite often in very tactical positions, i.e. after playing a game, I often see a lot of missed opportunities on my side (overlooked tactics).
b) shredder games are quite often very boring
All engines do make very stupid moves. Fritz for example once sacked his queen for nothing, Shredder "forgot" a piece that was attacked by a pawn... all moves, that even a 1200 player would never do. Nevertheless Fritz GUI's implementation seems to create the most interesting games.
Try Deuterium it will lose sensibly :)
I am wondering:
a) what ideas are out there to create engines that make better opponents for humans?
Deuterium has the following.
1. When engine is low on time say 1 minute or less apply time pressure by increasing the multipv
2. Adjust opening book selection
3. Don't move quickly when playing book moves
4. Initially multipv is using the formula,
use_multipv = 2800/(30*set_elo/100)
if engine is set to play elo 1200, the initial multipv will be 7. The engine will play normally no search adjustments and no eval adjustments, but will search at a given multipv value. The engine will play the 7th move or the worst move. But there is restriction here. If the 7th move score is very bad compared to the 1st move score, say 7th move is -1000cp, and 1st move has score of 1cp, the engine will not play this this is too obvious for a 1200 elo player. So it will check the 6th move, if the score of 6th move is say -120 cp, then this will be played by the engine. This score threshold is adjusted automatically by the engine depending on set_elo. If the set_elo is say 2700, this threshold is smaller say -50 cp, if set_elo is say 1200 threshold can be -180.
5. There is also a tracked counter of how many times the worst move in a multipv is selected, so sometimes the the 1st or 2nd or 3rd move in multipv is selected, again depending on the set_elo. High set elo will have higher chance that it will play the top 3 moves.
b) in particular, how does fritz gui inner mechanis works. For example, if you set the handicap to 200, how is a move selected? Choosing a move that is around (best_move - 2.00)? That would lead to a very stupid game, and almost immediately loss? When is a better move chosen? etc. etc.
I tried Deuterium with log on. In F13, using handicap default. It is sending multipv 64 and to search only at depth 2.

Code: Select all

<< Open log-135316Mon19Jan2015.txt for logging
<< string received&#58; setoption name MultiPV value 64
>> setoption name MultiPV value 64
<< string received&#58; position startpos moves d2d4 c7c6 c2c4 d7d5 b1c3 e7e6 c1d2
>> position startpos moves d2d4 c7c6 c2c4 d7d5 b1c3 e7e6 c1d2
<< This is a new game
<< There is no fen
<< Initialize board
<< string received&#58; go depth 2
>> go depth 2
<< Make the legal move in internal board
<< bestmove d8g5
Using handicap careless.

Code: Select all

<< Open log-135920Mon19Jan2015.txt for logging
<< string received&#58; setoption name MultiPV value 64
>> setoption name MultiPV value 64
<< string received&#58; position startpos moves b1c3
>> position startpos moves b1c3
<< This is a new game
<< There is no fen
<< Initialize board
<< string received&#58; go depth 3
>> go depth 3
<< Make the legal move in internal board
<< bestmove b7b5
Use Deuterium in Fritz gui enable the log and try to experiment.
I heard that Chess System Tal created often "interesting" games. Any knowledge on the inner workings?
Try MadChess and Ufim, I played those, they are good.

User avatar
hgm
Posts: 26530
Joined: Fri Mar 10, 2006 9:06 am
Location: Amsterdam
Full name: H G Muller
Contact:

Re: How to dumb down/weaken/humanize an engine algorithmical

Post by hgm » Mon Jan 19, 2015 8:06 am

I proposed an algorithm for this here on several occasions. It was based on consistently overlooking some moves throughout the tree, depending on the ply level the move first appears in the tree. I.e. keep a table of all possible legal moves, clear it before any search, and when the search then encounters a move not yet in the table, decide with a configurable probability that grows with the root iteration number whether this move will be pruned. And if you decide to prune it, mark it as such in the table so that it will also be pruned in all future nodes of that search. You could make the pruning chance also dependent on if the moving piece was already present on that same square in the root.

This should be applied in combination with pseudo-legal move generation: i.e. the search should be allowed to expose its King to capture, to give that capture an opportunity to be pruned. Otherwise it would not be possible for the engine to overlook that a piece was pinned, which actually is a common human mistake.

Henk
Posts: 6996
Joined: Mon May 27, 2013 8:31 am

Re: How to dumb down/weaken/humanize an engine algorithmical

Post by Henk » Mon Jan 19, 2015 10:17 am

I would say disable optimizing features until it plays good enough.
Actually I don't have this problem because Skipper already plays bad enough for me.

User avatar
stegemma
Posts: 859
Joined: Mon Aug 10, 2009 8:05 pm
Location: Italy
Full name: Stefano Gemma
Contact:

Re: How to dumb down/weaken/humanize an engine algorithmical

Post by stegemma » Mon Jan 19, 2015 10:33 am

Maybe you should analyze why and when humans make some mistake. Sometime is under pressure, sometime is because of limited depth. Humans can leave piece under attack and do any kind of mistake. A grand master of the past has lose a queen only because a piece was hiding another piece, and he doesn't see it. Sometime a human make a mistake because he/she doesn't consider that a piece gets pinned (or gets un-pinned). Sometime during human evaluation some piece can appears as doubled... or desappears in the brain image memory. Often we don't see all the possible moves of a Knight. Sometime we see only moves of pieces in the interesting part of the chessboad: we are attacking the king and we ignore what happen in the opposite site. More often, we simply choose the wrong plan, we attack in the border instead of centre, we exchange the good bishop with a bad one, we keep Knight instead of bishop in open positions... and we cannot mate with KQ vs K! ;)

Post Reply