working version with json analysis engine
This commit is contained in:
1 parent
ff1db55a97
commit
da5d99194b
9 files changed
+72
-707
No files matched your search
@@ -1,305 +0,0 @@
|
|||||||
# Example config for C++ (non-python) gtp bot
|
|
||||||
|
|
||||||
# RUNNING ON AN ONLINE SERVER OR IN A REAL TOURNAMENT OR MATCH:
|
|
||||||
# If you plan to do so, you may want to read through the "Rules" section
|
|
||||||
# below carefully for proper handling of komi and handicap games and end-of-game cleanup
|
|
||||||
# and various other details.
|
|
||||||
|
|
||||||
# NOTES ABOUT PERFORMANCE AND MEMORY USAGE:
|
|
||||||
# You will likely want to tune one or more the following:
|
|
||||||
#
|
|
||||||
# numSearchThreads:
|
|
||||||
# The number of CPU threads to use. If your GPU is powerful, it can actually be much higher than
|
|
||||||
# the number of cores on your processor because you will need many threads to feed large enough
|
|
||||||
# batches to make good use of the GPU.
|
|
||||||
#
|
|
||||||
# The "./katago benchmark" command can help you tune this parameter, as well as to test out the effect
|
|
||||||
# of changes to any of the other parameters below!
|
|
||||||
#
|
|
||||||
# nnMaxBatchSize:
|
|
||||||
# The maximum GPU batch size. Should often be at least as large as numSearchThreads.
|
|
||||||
# Larger won't do anything, but also won't hurt except use a little bit more GPU memory.
|
|
||||||
# Smaller can be fine if you have more than one GPU, since the GPUs will be sharing the work
|
|
||||||
# of servicing the CPU threads.
|
|
||||||
#
|
|
||||||
# cudaUseFP16 and cudaUseNHWC:
|
|
||||||
# These have a good chance of improving peformance at larger threads/batch sizes if
|
|
||||||
# you are using the CUDA implementation with an NVIDIA GPU with FP16 tensor cores.
|
|
||||||
#
|
|
||||||
# nnCacheSizePowerOfTwo:
|
|
||||||
# This controls the NN Cache size, which is the primary RAM/memory use.
|
|
||||||
# Increase this if you don't mind the memory use and want better performance for searches with
|
|
||||||
# tens of thousands of visits or more. Decrease this if you want to limit memory usage.
|
|
||||||
#
|
|
||||||
# If you're someone who is happy to do a bit of math - each neural net entry takes very
|
|
||||||
# approximately 1.5KB, except when using whole-board ownership/territory visualizations, each
|
|
||||||
# entry will take very approximately 3KB. The number of entries is (2 ** nnCacheSizePowerOfTwo),
|
|
||||||
# for example 2 ** 18 = 262144.
|
|
||||||
#
|
|
||||||
# OTHER NOTES:
|
|
||||||
# If you have more than one GPU, take a look at "OpenCL GPU settings" or "CUDA GPU settings" below.
|
|
||||||
#
|
|
||||||
# If using OpenCL, you will want to verify that KataGo is picking up the correct device!
|
|
||||||
# (e.g. some systems may have both an Intel CPU OpenCL and GPU OpenCL, if KataGo appears to pick
|
|
||||||
# the wrong one, you correct this by specifying "openclGpuToUse" below).
|
|
||||||
#
|
|
||||||
# You may also want to adjust "maxVisits", "ponderingEnabled", "resignThreshold", and possibly
|
|
||||||
# other parameters depending on your intended usage.
|
|
||||||
|
|
||||||
|
|
||||||
# Logs------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
# Where to output log?
|
|
||||||
logFile = gtp.log
|
|
||||||
# Logging options
|
|
||||||
logAllGTPCommunication = true
|
|
||||||
logSearchInfo = true
|
|
||||||
logToStderr = false
|
|
||||||
|
|
||||||
# KataGo will display some info to stderr on GTP startup
|
|
||||||
# Uncomment this to suppress that and remain silent
|
|
||||||
# startupPrintMessageToStderr = false
|
|
||||||
|
|
||||||
# Chat some stuff to stderr, for use in things like malkovich chat to OGS.
|
|
||||||
# ogsChatToStderr = true
|
|
||||||
|
|
||||||
# Configure the maximum length of analysis printed out by lz-analyze and other places.
|
|
||||||
# Controls the number of moves after the first move in a variation.
|
|
||||||
# analysisPVLen = 9
|
|
||||||
|
|
||||||
# Report winrates for chat and analysis as (BLACK|WHITE|SIDETOMOVE).
|
|
||||||
# Default is SIDETOMOVE, which is what tools that use LZ probably also expect
|
|
||||||
# reportAnalysisWinratesAs = SIDETOMOVE
|
|
||||||
|
|
||||||
# Default rules------------------------------------------------------------------------------------
|
|
||||||
# See https://lightvector.github.io/KataGo/rules.html for a description of the rules.
|
|
||||||
# These rules are defaults and can be changed mid-run by several custom GTP commands.
|
|
||||||
# See https://github.com/lightvector/KataGo/blob/master/docs/GTP_Extensions.md for those commands.
|
|
||||||
|
|
||||||
# koRule = SIMPLE # Simple ko rules (triple ko = no result)
|
|
||||||
koRule = POSITIONAL # Positional superko
|
|
||||||
# koRule = SITUATIONAL # Situational superko
|
|
||||||
|
|
||||||
scoringRule = AREA # Area scoring
|
|
||||||
# scoringRule = TERRITORY # Territory scoring (uses a sort of special computer-friendly territory ruleset)
|
|
||||||
|
|
||||||
taxRule = NONE # All surrounded empty points are scored
|
|
||||||
# taxRule = SEKI # Eyes in seki do NOT count as points
|
|
||||||
# taxRule = ALL # All groups are taxed up to 2 points for the two eyes needed to live
|
|
||||||
|
|
||||||
multiStoneSuicideLegal = true #Is multiple-stone suicide legal? (Single-stone suicide is always illegal).
|
|
||||||
|
|
||||||
hasButton = false # Set to true when area scoring to award 0.5 points to the first pass.
|
|
||||||
|
|
||||||
whiteHandicapBonus = 0 # In handicap games, give white no compensation for black's handicap stones (Tromp-taylor, NZ, JP)
|
|
||||||
# whiteHandicapBonus = N-1 # In handicap games, give white N-1 points for black's handicap stones (AGA)
|
|
||||||
# whiteHandicapBonus = N # In handicap games, give white N points for black's handicap stones (Chinese)
|
|
||||||
|
|
||||||
# Bot behavior---------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
# Resignation -------------
|
|
||||||
|
|
||||||
# Resignation occurs if for at least resignConsecTurns in a row,
|
|
||||||
# the winLossUtility (which is on a [-1,1] scale) is below resignThreshold.
|
|
||||||
allowResignation = true
|
|
||||||
resignThreshold = -0.98
|
|
||||||
resignConsecTurns = 3
|
|
||||||
|
|
||||||
# Handicap -------------
|
|
||||||
|
|
||||||
# Assume that if black makes many moves in a row right at the start of the game, then the game is a handicap game.
|
|
||||||
# This is necessary on some servers and for some GUIs and also when initializing from many SGF files, which may
|
|
||||||
# set up a handicap games using repeated GTP "play" commands for black rather than GTP "place_free_handicap" commands.
|
|
||||||
# However, it may also lead to incorrect understanding of komi if whiteHandicapBonus is used and a server does NOT
|
|
||||||
# have such a practice.
|
|
||||||
# Defaults to true! Uncomment and set to false to disable this behavior.
|
|
||||||
# assumeMultipleStartingBlackMovesAreHandicap = true
|
|
||||||
|
|
||||||
# Makes katago dynamically adjust to play more aggressively in handicap games based on the handicap and the current state of the game.
|
|
||||||
# Comment to disable this and make KataGo play the same always.
|
|
||||||
dynamicPlayoutDoublingAdvantageCapPerOppLead = 0.04
|
|
||||||
# Instead of setting dynamicPlayoutDoublingAdvantageCapPerOppLead, you can uncomment these and set this to a value from -2.0 to 2.0
|
|
||||||
# to set KataGo's aggression to a FIXED level.
|
|
||||||
# Negative makes KataGo behave as if it is much weaker than the opponent, preferring to play defensively
|
|
||||||
# Positive makes KataGo behave as if it is much stronger than the opponent, prefering to play aggressively or even overplay slightly.
|
|
||||||
# playoutDoublingAdvantage = 0.0
|
|
||||||
|
|
||||||
# Controls which side dynamicPlayoutDoublingAdvantageCapPerOppLead or playoutDoublingAdvantage applies to.
|
|
||||||
playoutDoublingAdvantagePla = WHITE
|
|
||||||
|
|
||||||
# Passing and cleanup -------------
|
|
||||||
|
|
||||||
# Make the bot never assume that its pass will end the game, even if passing would end and "win" under Tromp-Taylor rules.
|
|
||||||
# Usually this is a good idea when using it for analysis or playing on servers where scoring may be implemented non-tromp-taylorly.
|
|
||||||
# Defaults to true! Uncomment and set to false to disable this.
|
|
||||||
# conservativePass = true
|
|
||||||
|
|
||||||
# When playing under territory scoring, encourage the bot to fill dame before passing.
|
|
||||||
# This is NOT absolutely guaranteed to work, and possibly in some rare pathological situations will make the bot
|
|
||||||
# play a bad move, losing points. However, it also acts as a safeguard against things like a situation when the opponent must
|
|
||||||
# eventually make a protective move and lose 1 point, where the bot might otherwise assume that the score would be counted as such,
|
|
||||||
# yet without filling the dame to force the opponent to actually make the move.
|
|
||||||
# Defaults to true! Uncomment and set to false to disable this.
|
|
||||||
# fillDameBeforePass = true
|
|
||||||
|
|
||||||
# When using territory scoring, self-play games continue beyond two passes with special cleanup
|
|
||||||
# rules that may be confusing for human players. This option prevents the special cleanup phases from being
|
|
||||||
# reachable when using the bot for GTP play.
|
|
||||||
# Defaults to true! Uncomment and set to false if you want KataGo to be able to enter special cleanup.
|
|
||||||
# For example, if you are testing it against itself, or against another bot that has precisely implemented the rules
|
|
||||||
# documented at https://lightvector.github.io/KataGo/rules.html
|
|
||||||
# preventCleanupPhase = true
|
|
||||||
|
|
||||||
|
|
||||||
# Search limits-----------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
# If provided, limit maximum number of root visits per search to this much. (With tree reuse, visits do count earlier search)
|
|
||||||
maxVisits = 500
|
|
||||||
# If provided, limit maximum number of new playouts per search to this much. (With tree reuse, playouts do not count earlier search)
|
|
||||||
# maxPlayouts = 300
|
|
||||||
# If provided, cap search time at this many seconds (search will still try to follow GTP time controls)
|
|
||||||
# maxTime = 60
|
|
||||||
|
|
||||||
# Ponder on the opponent's turn?
|
|
||||||
ponderingEnabled = false
|
|
||||||
|
|
||||||
# Same limits but for ponder searches if pondering is enabled
|
|
||||||
# maxVisitsPondering = 1000
|
|
||||||
# maxPlayoutsPondering = 1000
|
|
||||||
# maxTimePondering = 60
|
|
||||||
|
|
||||||
# Number of seconds to buffer for lag for GTP time controls
|
|
||||||
lagBuffer = 1.0
|
|
||||||
|
|
||||||
# Number of threads to use in search
|
|
||||||
numSearchThreads = 1
|
|
||||||
|
|
||||||
# Play a little faster if the opponent is passing, for friendliness
|
|
||||||
searchFactorAfterOnePass = 0.50
|
|
||||||
searchFactorAfterTwoPass = 0.25
|
|
||||||
# Play a little faster if super-winning, for friendliess
|
|
||||||
searchFactorWhenWinning = 0.40
|
|
||||||
searchFactorWhenWinningThreshold = 0.95
|
|
||||||
|
|
||||||
# GPU Settings-------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
# Maximum number of positions to send to GPU at once. Note that you will also need to increase numSearchThreads
|
|
||||||
# to make use of this, as every thread in KataGo is synchronous, so with 1 thread max batch will only be 1 anyways.
|
|
||||||
nnMaxBatchSize = 16
|
|
||||||
# Cache up to 2 ** this many neural net evaluations in case of transpositions in the tree.
|
|
||||||
nnCacheSizePowerOfTwo = 19
|
|
||||||
# Size of mutex pool for nnCache is 2 ** this
|
|
||||||
nnMutexPoolSizePowerOfTwo = 15
|
|
||||||
# Randomize board orientation when running neural net evals?
|
|
||||||
nnRandomize = true
|
|
||||||
# If provided, force usage of a specific seed for nnRandomize instead of randomizing
|
|
||||||
# nnRandSeed = abcdefg
|
|
||||||
|
|
||||||
# How many threads should there be to feed positions to the neural net?
|
|
||||||
# Server threads are indexed 0,1,...(n-1) for the purposes of the below GPU settings arguments
|
|
||||||
# that specify which threads should use which GPUs.
|
|
||||||
# NOTE: This parameter is probably ONLY useful if you have multiple GPUs, since each GPU will need a thread.
|
|
||||||
# If you're tuning single-GPU performance, use numSearchThreads instead.
|
|
||||||
numNNServerThreadsPerModel = 1
|
|
||||||
|
|
||||||
# CUDA GPU settings--------------------------------------
|
|
||||||
# These only apply when using CUDA as the backend for inference.
|
|
||||||
# (For GTP, we only ever have one model, when playing matches, we might have more than one, see match_example.cfg)
|
|
||||||
|
|
||||||
# Default behavior tries to guess the 'best' GPU or device
|
|
||||||
# You will want to uncomment and adjust one or more of these lines to take advantage of a multi-gpu machine
|
|
||||||
# cudaDeviceToUse = 0 #use device 0 for all server threads (numNNServerThreadsPerModel) unless otherwise specified per-model or per-thread-per-model
|
|
||||||
# cudaDeviceToUseModel0 = 3 #use device 3 for model 0 for all threads unless otherwise specified per-thread for this model
|
|
||||||
# cudaDeviceToUseModel1 = 2 #use device 2 for model 1 for all threads unless otherwise specified per-thread for this model
|
|
||||||
# cudaDeviceToUseModel0Thread0 = 3 #use device 3 for model 0, server thread 0
|
|
||||||
# cudaDeviceToUseModel0Thread1 = 2 #use device 2 for model 0, server thread 1
|
|
||||||
|
|
||||||
# Uncomment these on NVIDIA devices with FP16 tensor cores for probably a speedup, at the cost of introducing some precision loss in the nn calculation.
|
|
||||||
# cudaUseFP16 = true
|
|
||||||
# cudaUseNHWC = true
|
|
||||||
|
|
||||||
# OpenCL GPU settings--------------------------------------
|
|
||||||
# These only apply when using OpenCL as the backend for inference.
|
|
||||||
# (For GTP, we only ever have one model, when playing matches, we might have more than one, see match_example.cfg)
|
|
||||||
|
|
||||||
# Default behavior tries to guess the 'best' GPU or device
|
|
||||||
# You will want to uncomment and adjust one or more of these lines to take advantage of a multi-gpu machine
|
|
||||||
# openclDeviceToUse = 0 #use device 0 for all server threads (numNNServerThreadsPerModel) unless otherwise specified per-model or per-thread-per-model
|
|
||||||
# openclDeviceToUseModel0 = 3 #use device 3 for model 0 for all threads unless otherwise specified per-thread for this model
|
|
||||||
# openclDeviceToUseModel1 = 2 #use device 2 for model 1 for all threads unless otherwise specified per-thread for this model
|
|
||||||
# openclDeviceToUseModel0Thread0 = 3 #use device 3 for model 0, server thread 0
|
|
||||||
# openclDeviceToUseModel0Thread1 = 2 #use device 2 for model 0, server thread 1
|
|
||||||
|
|
||||||
# Uncomment to tune OpenCL for every board size separately, rather than only the largest possible size
|
|
||||||
# openclReTunePerBoardSize = true
|
|
||||||
|
|
||||||
# Root move selection and biases------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
# If provided, force usage of a specific seed for various things in the search instead of randomizing
|
|
||||||
# searchRandSeed = hijklmn
|
|
||||||
|
|
||||||
# Temperature for the early game, randomize between chosen moves with this temperature
|
|
||||||
chosenMoveTemperatureEarly = 0.5
|
|
||||||
# Decay temperature for the early game by 0.5 every this many moves, scaled with board size.
|
|
||||||
chosenMoveTemperatureHalflife = 19
|
|
||||||
# At the end of search after the early game, randomize between chosen moves with this temperature
|
|
||||||
chosenMoveTemperature = 0.10
|
|
||||||
# Subtract this many visits from each move prior to applying chosenMoveTemperature
|
|
||||||
# (unless all moves have too few visits) to downweight unlikely moves
|
|
||||||
chosenMoveSubtract = 0
|
|
||||||
# The same as chosenMoveSubtract but only prunes moves that fall below the threshold, does not affect moves above
|
|
||||||
chosenMovePrune = 1
|
|
||||||
|
|
||||||
# Use dirichlet noise for the root node policy?
|
|
||||||
rootNoiseEnabled = false
|
|
||||||
# Dirichlet noise alpha is set to this divided by number of legal moves. 10.83 produces an alpha of 0.03 on an empty 19x19 board.
|
|
||||||
rootDirichletNoiseTotalConcentration = 10.83
|
|
||||||
# Proportion of root policy that is noise
|
|
||||||
rootDirichletNoiseWeight = 0.25
|
|
||||||
|
|
||||||
# Number of symmetries to sample (WITH replacement) and average at the root
|
|
||||||
rootNumSymmetriesToSample = 1
|
|
||||||
|
|
||||||
# Using LCB for move selection?
|
|
||||||
useLcbForSelection = true
|
|
||||||
# How many stdevs a move needs to be better than another for LCB selection
|
|
||||||
lcbStdevs = 5.0
|
|
||||||
# Only use LCB override when a move has this proportion of visits as the top move
|
|
||||||
minVisitPropForLCB = 0.15
|
|
||||||
|
|
||||||
# Internal params------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
# Scales the utility of winning/losing
|
|
||||||
winLossUtilityFactor = 1.0
|
|
||||||
# Scales the utility for trying to maximize score
|
|
||||||
staticScoreUtilityFactor = 0.10
|
|
||||||
dynamicScoreUtilityFactor = 0.30
|
|
||||||
# Adjust dynamic score center this proportion of the way towards zero, capped at a reasonable amount.
|
|
||||||
dynamicScoreCenterZeroWeight = 0.20
|
|
||||||
dynamicScoreCenterScale = 0.75
|
|
||||||
# The utility of getting a "no result" due to triple ko or other long cycle in non-superko rulesets (-1 to 1)
|
|
||||||
noResultUtilityForWhite = 0.0
|
|
||||||
# The number of wins that a draw counts as, for white. (0 to 1)
|
|
||||||
drawEquivalentWinsForWhite = 0.5
|
|
||||||
|
|
||||||
# Exploration constant for mcts
|
|
||||||
cpuctExploration = 0.9
|
|
||||||
cpuctExplorationLog = 0.6
|
|
||||||
# FPU reduction constant for mcts
|
|
||||||
fpuReductionMax = 0.2
|
|
||||||
rootFpuReductionMax = 0.1
|
|
||||||
# Use parent average value for fpu base point instead of point value net estimate
|
|
||||||
fpuUseParentAverage = true
|
|
||||||
# Amount to apply a downweighting of children with very bad values relative to good ones
|
|
||||||
valueWeightExponent = 0.5
|
|
||||||
# Slight incentive for the bot to behave human-like with regard to passing at the end, filling the dame,
|
|
||||||
# not wasting time playing in its own territory, etc, and not play moves that are equivalent in terms of
|
|
||||||
# points but a bit more unfriendly to humans.
|
|
||||||
rootEndingBonusPoints = 0.5
|
|
||||||
# Make the bot prune useless moves that are just prolonging the game to avoid losing yet
|
|
||||||
rootPruneUselessMoves = true
|
|
||||||
|
|
||||||
# How big to make the mutex pool for search synchronization
|
|
||||||
mutexPoolSize = 8192
|
|
||||||
# How many virtual losses to add when a thread descends through a node
|
|
||||||
numVirtualLossesPerThread = 1
|
|
||||||
@@ -1,305 +0,0 @@
|
|||||||
# Example config for C++ (non-python) gtp bot
|
|
||||||
|
|
||||||
# RUNNING ON AN ONLINE SERVER OR IN A REAL TOURNAMENT OR MATCH:
|
|
||||||
# If you plan to do so, you may want to read through the "Rules" section
|
|
||||||
# below carefully for proper handling of komi and handicap games and end-of-game cleanup
|
|
||||||
# and various other details.
|
|
||||||
|
|
||||||
# NOTES ABOUT PERFORMANCE AND MEMORY USAGE:
|
|
||||||
# You will likely want to tune one or more the following:
|
|
||||||
#
|
|
||||||
# numSearchThreads:
|
|
||||||
# The number of CPU threads to use. If your GPU is powerful, it can actually be much higher than
|
|
||||||
# the number of cores on your processor because you will need many threads to feed large enough
|
|
||||||
# batches to make good use of the GPU.
|
|
||||||
#
|
|
||||||
# The "./katago benchmark" command can help you tune this parameter, as well as to test out the effect
|
|
||||||
# of changes to any of the other parameters below!
|
|
||||||
#
|
|
||||||
# nnMaxBatchSize:
|
|
||||||
# The maximum GPU batch size. Should often be at least as large as numSearchThreads.
|
|
||||||
# Larger won't do anything, but also won't hurt except use a little bit more GPU memory.
|
|
||||||
# Smaller can be fine if you have more than one GPU, since the GPUs will be sharing the work
|
|
||||||
# of servicing the CPU threads.
|
|
||||||
#
|
|
||||||
# cudaUseFP16 and cudaUseNHWC:
|
|
||||||
# These have a good chance of improving peformance at larger threads/batch sizes if
|
|
||||||
# you are using the CUDA implementation with an NVIDIA GPU with FP16 tensor cores.
|
|
||||||
#
|
|
||||||
# nnCacheSizePowerOfTwo:
|
|
||||||
# This controls the NN Cache size, which is the primary RAM/memory use.
|
|
||||||
# Increase this if you don't mind the memory use and want better performance for searches with
|
|
||||||
# tens of thousands of visits or more. Decrease this if you want to limit memory usage.
|
|
||||||
#
|
|
||||||
# If you're someone who is happy to do a bit of math - each neural net entry takes very
|
|
||||||
# approximately 1.5KB, except when using whole-board ownership/territory visualizations, each
|
|
||||||
# entry will take very approximately 3KB. The number of entries is (2 ** nnCacheSizePowerOfTwo),
|
|
||||||
# for example 2 ** 18 = 262144.
|
|
||||||
#
|
|
||||||
# OTHER NOTES:
|
|
||||||
# If you have more than one GPU, take a look at "OpenCL GPU settings" or "CUDA GPU settings" below.
|
|
||||||
#
|
|
||||||
# If using OpenCL, you will want to verify that KataGo is picking up the correct device!
|
|
||||||
# (e.g. some systems may have both an Intel CPU OpenCL and GPU OpenCL, if KataGo appears to pick
|
|
||||||
# the wrong one, you correct this by specifying "openclGpuToUse" below).
|
|
||||||
#
|
|
||||||
# You may also want to adjust "maxVisits", "ponderingEnabled", "resignThreshold", and possibly
|
|
||||||
# other parameters depending on your intended usage.
|
|
||||||
|
|
||||||
|
|
||||||
# Logs------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
# Where to output log?
|
|
||||||
logFile = gtp.log
|
|
||||||
# Logging options
|
|
||||||
logAllGTPCommunication = true
|
|
||||||
logSearchInfo = true
|
|
||||||
logToStderr = false
|
|
||||||
|
|
||||||
# KataGo will display some info to stderr on GTP startup
|
|
||||||
# Uncomment this to suppress that and remain silent
|
|
||||||
# startupPrintMessageToStderr = false
|
|
||||||
|
|
||||||
# Chat some stuff to stderr, for use in things like malkovich chat to OGS.
|
|
||||||
# ogsChatToStderr = true
|
|
||||||
|
|
||||||
# Configure the maximum length of analysis printed out by lz-analyze and other places.
|
|
||||||
# Controls the number of moves after the first move in a variation.
|
|
||||||
# analysisPVLen = 9
|
|
||||||
|
|
||||||
# Report winrates for chat and analysis as (BLACK|WHITE|SIDETOMOVE).
|
|
||||||
# Default is SIDETOMOVE, which is what tools that use LZ probably also expect
|
|
||||||
# reportAnalysisWinratesAs = SIDETOMOVE
|
|
||||||
|
|
||||||
# Default rules------------------------------------------------------------------------------------
|
|
||||||
# See https://lightvector.github.io/KataGo/rules.html for a description of the rules.
|
|
||||||
# These rules are defaults and can be changed mid-run by several custom GTP commands.
|
|
||||||
# See https://github.com/lightvector/KataGo/blob/master/docs/GTP_Extensions.md for those commands.
|
|
||||||
|
|
||||||
koRule = SIMPLE # Simple ko rules (triple ko = no result)
|
|
||||||
# koRule = POSITIONAL # Positional superko
|
|
||||||
# koRule = SITUATIONAL # Situational superko
|
|
||||||
|
|
||||||
# scoringRule = AREA # Area scoring
|
|
||||||
scoringRule = TERRITORY # Territory scoring (uses a sort of special computer-friendly territory ruleset)
|
|
||||||
|
|
||||||
# taxRule = NONE # All surrounded empty points are scored
|
|
||||||
taxRule = SEKI # Eyes in seki do NOT count as points
|
|
||||||
# taxRule = ALL # All groups are taxed up to 2 points for the two eyes needed to live
|
|
||||||
|
|
||||||
multiStoneSuicideLegal = false #Is multiple-stone suicide legal? (Single-stone suicide is always illegal).
|
|
||||||
|
|
||||||
hasButton = false # Set to true when area scoring to award 0.5 points to the first pass.
|
|
||||||
|
|
||||||
whiteHandicapBonus = 0 # In handicap games, give white no compensation for black's handicap stones (Tromp-taylor, NZ, JP)
|
|
||||||
# whiteHandicapBonus = N-1 # In handicap games, give white N-1 points for black's handicap stones (AGA)
|
|
||||||
# whiteHandicapBonus = N # In handicap games, give white N points for black's handicap stones (Chinese)
|
|
||||||
|
|
||||||
# Bot behavior---------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
# Resignation -------------
|
|
||||||
|
|
||||||
# Resignation occurs if for at least resignConsecTurns in a row,
|
|
||||||
# the winLossUtility (which is on a [-1,1] scale) is below resignThreshold.
|
|
||||||
allowResignation = true
|
|
||||||
resignThreshold = -0.999
|
|
||||||
resignConsecTurns = 3
|
|
||||||
|
|
||||||
# Handicap -------------
|
|
||||||
|
|
||||||
# Assume that if black makes many moves in a row right at the start of the game, then the game is a handicap game.
|
|
||||||
# This is necessary on some servers and for some GUIs and also when initializing from many SGF files, which may
|
|
||||||
# set up a handicap games using repeated GTP "play" commands for black rather than GTP "place_free_handicap" commands.
|
|
||||||
# However, it may also lead to incorrect understanding of komi if whiteHandicapBonus is used and a server does NOT
|
|
||||||
# have such a practice.
|
|
||||||
# Defaults to true! Uncomment and set to false to disable this behavior.
|
|
||||||
# assumeMultipleStartingBlackMovesAreHandicap = true
|
|
||||||
|
|
||||||
# Makes katago dynamically adjust to play more aggressively in handicap games based on the handicap and the current state of the game.
|
|
||||||
# Comment to disable this and make KataGo play the same always.
|
|
||||||
dynamicPlayoutDoublingAdvantageCapPerOppLead = 0.04
|
|
||||||
# Instead of setting dynamicPlayoutDoublingAdvantageCapPerOppLead, you can uncomment these and set this to a value from -2.0 to 2.0
|
|
||||||
# to set KataGo's aggression to a FIXED level.
|
|
||||||
# Negative makes KataGo behave as if it is much weaker than the opponent, preferring to play defensively
|
|
||||||
# Positive makes KataGo behave as if it is much stronger than the opponent, prefering to play aggressively or even overplay slightly.
|
|
||||||
# playoutDoublingAdvantage = 0.0
|
|
||||||
|
|
||||||
# Controls which side dynamicPlayoutDoublingAdvantageCapPerOppLead or playoutDoublingAdvantage applies to.
|
|
||||||
playoutDoublingAdvantagePla = WHITE
|
|
||||||
|
|
||||||
# Passing and cleanup -------------
|
|
||||||
|
|
||||||
# Make the bot never assume that its pass will end the game, even if passing would end and "win" under Tromp-Taylor rules.
|
|
||||||
# Usually this is a good idea when using it for analysis or playing on servers where scoring may be implemented non-tromp-taylorly.
|
|
||||||
# Defaults to true! Uncomment and set to false to disable this.
|
|
||||||
conservativePass = true
|
|
||||||
|
|
||||||
# When playing under territory scoring, encourage the bot to fill dame before passing.
|
|
||||||
# This is NOT absolutely guaranteed to work, and possibly in some rare pathological situations will make the bot
|
|
||||||
# play a bad move, losing points. However, it also acts as a safeguard against things like a situation when the opponent must
|
|
||||||
# eventually make a protective move and lose 1 point, where the bot might otherwise assume that the score would be counted as such,
|
|
||||||
# yet without filling the dame to force the opponent to actually make the move.
|
|
||||||
# Defaults to true! Uncomment and set to false to disable this.
|
|
||||||
# fillDameBeforePass = true
|
|
||||||
|
|
||||||
# When using territory scoring, self-play games continue beyond two passes with special cleanup
|
|
||||||
# rules that may be confusing for human players. This option prevents the special cleanup phases from being
|
|
||||||
# reachable when using the bot for GTP play.
|
|
||||||
# Defaults to true! Uncomment and set to false if you want KataGo to be able to enter special cleanup.
|
|
||||||
# For example, if you are testing it against itself, or against another bot that has precisely implemented the rules
|
|
||||||
# documented at https://lightvector.github.io/KataGo/rules.html
|
|
||||||
# preventCleanupPhase = true
|
|
||||||
|
|
||||||
|
|
||||||
# Search limits-----------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
# If provided, limit maximum number of root visits per search to this much. (With tree reuse, visits do count earlier search)
|
|
||||||
maxVisits = 2500
|
|
||||||
# If provided, limit maximum number of new playouts per search to this much. (With tree reuse, playouts do not count earlier search)
|
|
||||||
# maxPlayouts = 300
|
|
||||||
# If provided, cap search time at this many seconds (search will still try to follow GTP time controls)
|
|
||||||
# maxTime = 60
|
|
||||||
|
|
||||||
# Ponder on the opponent's turn?
|
|
||||||
ponderingEnabled = false
|
|
||||||
|
|
||||||
# Same limits but for ponder searches if pondering is enabled
|
|
||||||
# maxVisitsPondering = 1000
|
|
||||||
# maxPlayoutsPondering = 1000
|
|
||||||
# maxTimePondering = 60
|
|
||||||
|
|
||||||
# Number of seconds to buffer for lag for GTP time controls
|
|
||||||
lagBuffer = 1.0
|
|
||||||
|
|
||||||
# Number of threads to use in search
|
|
||||||
numSearchThreads = 4
|
|
||||||
|
|
||||||
# Play a little faster if the opponent is passing, for friendliness
|
|
||||||
searchFactorAfterOnePass = 0.50
|
|
||||||
searchFactorAfterTwoPass = 0.25
|
|
||||||
# Play a little faster if super-winning, for friendliess
|
|
||||||
searchFactorWhenWinning = 0.40
|
|
||||||
searchFactorWhenWinningThreshold = 0.95
|
|
||||||
|
|
||||||
# GPU Settings-------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
# Maximum number of positions to send to GPU at once. Note that you will also need to increase numSearchThreads
|
|
||||||
# to make use of this, as every thread in KataGo is synchronous, so with 1 thread max batch will only be 1 anyways.
|
|
||||||
nnMaxBatchSize = 16
|
|
||||||
# Cache up to 2 ** this many neural net evaluations in case of transpositions in the tree.
|
|
||||||
nnCacheSizePowerOfTwo = 20
|
|
||||||
# Size of mutex pool for nnCache is 2 ** this
|
|
||||||
nnMutexPoolSizePowerOfTwo = 16
|
|
||||||
# Randomize board orientation when running neural net evals?
|
|
||||||
nnRandomize = true
|
|
||||||
# If provided, force usage of a specific seed for nnRandomize instead of randomizing
|
|
||||||
# nnRandSeed = abcdefg
|
|
||||||
|
|
||||||
# How many threads should there be to feed positions to the neural net?
|
|
||||||
# Server threads are indexed 0,1,...(n-1) for the purposes of the below GPU settings arguments
|
|
||||||
# that specify which threads should use which GPUs.
|
|
||||||
# NOTE: This parameter is probably ONLY useful if you have multiple GPUs, since each GPU will need a thread.
|
|
||||||
# If you're tuning single-GPU performance, use numSearchThreads instead.
|
|
||||||
numNNServerThreadsPerModel = 1
|
|
||||||
|
|
||||||
# CUDA GPU settings--------------------------------------
|
|
||||||
# These only apply when using CUDA as the backend for inference.
|
|
||||||
# (For GTP, we only ever have one model, when playing matches, we might have more than one, see match_example.cfg)
|
|
||||||
|
|
||||||
# Default behavior tries to guess the 'best' GPU or device
|
|
||||||
# You will want to uncomment and adjust one or more of these lines to take advantage of a multi-gpu machine
|
|
||||||
# cudaDeviceToUse = 0 #use device 0 for all server threads (numNNServerThreadsPerModel) unless otherwise specified per-model or per-thread-per-model
|
|
||||||
# cudaDeviceToUseModel0 = 3 #use device 3 for model 0 for all threads unless otherwise specified per-thread for this model
|
|
||||||
# cudaDeviceToUseModel1 = 2 #use device 2 for model 1 for all threads unless otherwise specified per-thread for this model
|
|
||||||
# cudaDeviceToUseModel0Thread0 = 3 #use device 3 for model 0, server thread 0
|
|
||||||
# cudaDeviceToUseModel0Thread1 = 2 #use device 2 for model 0, server thread 1
|
|
||||||
|
|
||||||
# Uncomment these on NVIDIA devices with FP16 tensor cores for probably a speedup, at the cost of introducing some precision loss in the nn calculation.
|
|
||||||
# cudaUseFP16 = true
|
|
||||||
# cudaUseNHWC = true
|
|
||||||
|
|
||||||
# OpenCL GPU settings--------------------------------------
|
|
||||||
# These only apply when using OpenCL as the backend for inference.
|
|
||||||
# (For GTP, we only ever have one model, when playing matches, we might have more than one, see match_example.cfg)
|
|
||||||
|
|
||||||
# Default behavior tries to guess the 'best' GPU or device
|
|
||||||
# You will want to uncomment and adjust one or more of these lines to take advantage of a multi-gpu machine
|
|
||||||
# openclDeviceToUse = 0 #use device 0 for all server threads (numNNServerThreadsPerModel) unless otherwise specified per-model or per-thread-per-model
|
|
||||||
# openclDeviceToUseModel0 = 3 #use device 3 for model 0 for all threads unless otherwise specified per-thread for this model
|
|
||||||
# openclDeviceToUseModel1 = 2 #use device 2 for model 1 for all threads unless otherwise specified per-thread for this model
|
|
||||||
# openclDeviceToUseModel0Thread0 = 3 #use device 3 for model 0, server thread 0
|
|
||||||
# openclDeviceToUseModel0Thread1 = 2 #use device 2 for model 0, server thread 1
|
|
||||||
|
|
||||||
# Uncomment to tune OpenCL for every board size separately, rather than only the largest possible size
|
|
||||||
# openclReTunePerBoardSize = true
|
|
||||||
|
|
||||||
# Root move selection and biases------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
# If provided, force usage of a specific seed for various things in the search instead of randomizing
|
|
||||||
# searchRandSeed = hijklmn
|
|
||||||
|
|
||||||
# Temperature for the early game, randomize between chosen moves with this temperature
|
|
||||||
chosenMoveTemperatureEarly = 0.5
|
|
||||||
# Decay temperature for the early game by 0.5 every this many moves, scaled with board size.
|
|
||||||
chosenMoveTemperatureHalflife = 19
|
|
||||||
# At the end of search after the early game, randomize between chosen moves with this temperature
|
|
||||||
chosenMoveTemperature = 0.10
|
|
||||||
# Subtract this many visits from each move prior to applying chosenMoveTemperature
|
|
||||||
# (unless all moves have too few visits) to downweight unlikely moves
|
|
||||||
chosenMoveSubtract = 0
|
|
||||||
# The same as chosenMoveSubtract but only prunes moves that fall below the threshold, does not affect moves above
|
|
||||||
chosenMovePrune = 1
|
|
||||||
|
|
||||||
# Use dirichlet noise for the root node policy?
|
|
||||||
rootNoiseEnabled = false
|
|
||||||
# Dirichlet noise alpha is set to this divided by number of legal moves. 10.83 produces an alpha of 0.03 on an empty 19x19 board.
|
|
||||||
rootDirichletNoiseTotalConcentration = 10.83
|
|
||||||
# Proportion of root policy that is noise
|
|
||||||
rootDirichletNoiseWeight = 0.25
|
|
||||||
|
|
||||||
# Number of symmetries to sample (WITH replacement) and average at the root
|
|
||||||
rootNumSymmetriesToSample = 1
|
|
||||||
|
|
||||||
# Using LCB for move selection?
|
|
||||||
useLcbForSelection = true
|
|
||||||
# How many stdevs a move needs to be better than another for LCB selection
|
|
||||||
lcbStdevs = 5.0
|
|
||||||
# Only use LCB override when a move has this proportion of visits as the top move
|
|
||||||
minVisitPropForLCB = 0.15
|
|
||||||
|
|
||||||
# Internal params------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
# Scales the utility of winning/losing
|
|
||||||
winLossUtilityFactor = 0.4
|
|
||||||
# Scales the utility for trying to maximize score
|
|
||||||
staticScoreUtilityFactor = 0.2
|
|
||||||
dynamicScoreUtilityFactor = 0.4
|
|
||||||
# Adjust dynamic score center this proportion of the way towards zero, capped at a reasonable amount.
|
|
||||||
dynamicScoreCenterZeroWeight = 0.20
|
|
||||||
dynamicScoreCenterScale = 0.75
|
|
||||||
# The utility of getting a "no result" due to triple ko or other long cycle in non-superko rulesets (-1 to 1)
|
|
||||||
noResultUtilityForWhite = 0.0
|
|
||||||
# The number of wins that a draw counts as, for white. (0 to 1)
|
|
||||||
drawEquivalentWinsForWhite = 0.5
|
|
||||||
|
|
||||||
# Exploration constant for mcts
|
|
||||||
cpuctExploration = 2.0
|
|
||||||
cpuctExplorationLog = 0.8
|
|
||||||
# FPU reduction constant for mcts
|
|
||||||
fpuReductionMax = 0.2
|
|
||||||
rootFpuReductionMax = 0.1
|
|
||||||
# Use parent average value for fpu base point instead of point value net estimate
|
|
||||||
fpuUseParentAverage = true
|
|
||||||
# Amount to apply a downweighting of children with very bad values relative to good ones
|
|
||||||
valueWeightExponent = 0.5
|
|
||||||
# Slight incentive for the bot to behave human-like with regard to passing at the end, filling the dame,
|
|
||||||
# not wasting time playing in its own territory, etc, and not play moves that are equivalent in terms of
|
|
||||||
# points but a bit more unfriendly to humans.
|
|
||||||
rootEndingBonusPoints = 0.5
|
|
||||||
# Make the bot prune useless moves that are just prolonging the game to avoid losing yet
|
|
||||||
rootPruneUselessMoves = true
|
|
||||||
|
|
||||||
# How big to make the mutex pool for search synchronization
|
|
||||||
mutexPoolSize = 8192
|
|
||||||
# How many virtual losses to add when a thread descends through a node
|
|
||||||
numVirtualLossesPerThread = 1
|
|
||||||
Binary file not shown.
@@ -4,36 +4,38 @@ Manual
|
|||||||
Installation
|
Installation
|
||||||
------------
|
------------
|
||||||
* pip install kivy
|
* pip install kivy
|
||||||
* change the `engine.command` field in `config.json` to your kata installation (for example, to `path/to/lizzie/katago/katago.exe`)
|
* On linux, change the `engine.command` field in `config.json` to your kata v1.3+ installation.
|
||||||
* start the app by running `python katrain.py` (or `python3` if needed)
|
* start the app by running `python katrain.py`
|
||||||
|
|
||||||
Options
|
Options
|
||||||
-------
|
-------
|
||||||
* Top row options
|
* Check box options
|
||||||
* Eval: show the coloured dots on the moves for this player.
|
* Eval: show the coloured dots on the moves for this player.
|
||||||
* Hints: show suggested moves for this player.
|
* Hints: show suggested moves for this player.
|
||||||
* Undo: automatically undo poor moves for this player and make them try again.
|
* Undo: automatically undo poor moves for this player and make them try again.
|
||||||
|
* AI: let the AI control this player. Check both for self-play.
|
||||||
|
* Show owner: show expected control of territory.
|
||||||
* Lock AI: disallow extra undos, changing hints options, changing auto move, or AI move.
|
* Lock AI: disallow extra undos, changing hints options, changing auto move, or AI move.
|
||||||
* Show owner: show expected control of territory.
|
* Fast: use a lower number of max visits for evaluation/AI move.
|
||||||
|
* Balance score: Deliberately make sub-optimal moves as the AI in an attempt to balance the score towawrds a slight win.
|
||||||
|
|
||||||
* Temperature/Evaluation/Score: Not that these fields can be hidden by clicking on the text.
|
* Temperature/Evaluation/Score: Not that these fields can be hidden by clicking on the text.
|
||||||
* Temperature is the point difference between passing and the best move.
|
* Temperature is the point difference between passing and the best move.
|
||||||
* Evaluation is where on this scale the last move was, from 0% (equivalent to a pass) to 100% (best move).
|
* Evaluation is where on this scale the last move was, from 0% (equivalent to a pass) to 100% (best move).
|
||||||
This can be < 0% in case of suicidal moves, or >100% when Kata did not consider the move before, or further analysis shows it to be better than the best one considered.
|
This can be < 0% in case of suicidal moves, or >100% when Kata did not consider the move before, or further analysis shows it to be better than the best one considered.
|
||||||
* Score: Expected score.
|
* Score: How far one player is ahead.
|
||||||
|
|
||||||
Play
|
Play
|
||||||
----
|
----
|
||||||
|
|
||||||
* Play against the AI
|
* Play against the AI
|
||||||
* Turn on auto move.
|
* Turn on AI for the chosen player.
|
||||||
* Choose whether to turn on `balance score` to make the AI play slack moves.
|
* Choose whether to turn on `balance score` to make the AI play slack moves.
|
||||||
* Choose whether to turn on `undo` for your colour to be prompted to re-try poor moves.
|
* Choose whether to turn on `undo` for your colour to be prompted to re-try poor moves.
|
||||||
* Choose whether or not to turn on `fast` to make the AI play faster but read less deeply (NB: with balance score, faster AI can be a stronger opponent, as there are fewer mediocre moves considered).
|
* Choose whether or not to turn on `fast` to make the AI play faster but read less deeply (NB: with balance score, faster AI can be a stronger opponent, as there are fewer mediocre moves considered).
|
||||||
* Possibly lock AI to prevent yourself from peeking at hints, etc.
|
* Possibly lock AI to prevent yourself from peeking at hints, etc.
|
||||||
* Possibly hide score or temperature.
|
* Possibly hide score or temperature.
|
||||||
* Possibly hide evaluation for the AI player.
|
* If you chose AI to play black, click AI move for the first move.
|
||||||
* Play by playing a move or clicking AI move if you want white.
|
|
||||||
|
|
||||||
* Engine-assisted play
|
* Engine-assisted play
|
||||||
* Turn off auto move.
|
* Turn off auto move.
|
||||||
@@ -43,7 +45,7 @@ Play
|
|||||||
* Play with a friend with instant feedback and/or undos for both, or see how many stones stronger you are with one undo. (But please play unranked and be honest to your opponent on what you're doing)
|
* Play with a friend with instant feedback and/or undos for both, or see how many stones stronger you are with one undo. (But please play unranked and be honest to your opponent on what you're doing)
|
||||||
|
|
||||||
* Analysis
|
* Analysis
|
||||||
* Copy the SGF into the text box
|
* Copy the SGF into the text box. Note that branches are not supported and will lead to strange results.
|
||||||
* Choose whether or not to turn on `fast` to make the AI weaker but analyze faster.
|
* Choose whether or not to turn on `fast` to make the AI weaker but analyze faster.
|
||||||
* Click `Analyze`
|
* Click `Analyze`
|
||||||
|
|
||||||
@@ -61,9 +63,7 @@ The `trainer` block has the following options to tweak:
|
|||||||
* `balance_play_min_eval`: when needing to balance score, the AI will pick a move which is at least this good.
|
* `balance_play_min_eval`: when needing to balance score, the AI will pick a move which is at least this good.
|
||||||
* `balance_play_min_visits`: never pick a move with fewer playouts than this.
|
* `balance_play_min_visits`: never pick a move with fewer playouts than this.
|
||||||
* `undo_eval_threshold`, `undo_point_threshold`: prompt player to undo if move is worse than this in terms of points AND evaluation.
|
* `undo_eval_threshold`, `undo_point_threshold`: prompt player to undo if move is worse than this in terms of points AND evaluation.
|
||||||
* `undo_outdated_eval_threshold`: don't prompt undo if last move's evaluation is >= `undo_eval_threshold` and the NEW evaluation is greater than this. (this decreases frustration when hints are on, or when kata over-estimates the best move).
|
|
||||||
* `num_undo_prompts`: automatically undo bad moves when `undo` is on at most this many times.
|
* `num_undo_prompts`: automatically undo bad moves when `undo` is on at most this many times.
|
||||||
* `show_ai_options`: show which moves the AI considered.
|
|
||||||
|
|
||||||
The cfg file has additional configuration for kata. In particular, it changes the default to being more exploratory and score-based (and therefore nicer as an opponent, but weaker as analysis tool).
|
The cfg file has additional configuration for kata. In particular, it changes the default to being more exploratory and score-based (and therefore nicer as an opponent, but weaker as analysis tool).
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ class Move:
|
|||||||
self.analysis = None
|
self.analysis = None
|
||||||
self.pass_analysis = None
|
self.pass_analysis = None
|
||||||
self.ownership = None
|
self.ownership = None
|
||||||
|
self.x_comment = ""
|
||||||
|
self.auto_undid = False
|
||||||
self.move_number = 0
|
self.move_number = 0
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
@@ -61,11 +63,13 @@ class Move:
|
|||||||
score = score or self.score
|
score = score or self.score
|
||||||
return f"{'B' if score >= 0 else 'W'}+{abs(score):.1f}"
|
return f"{'B' if score >= 0 else 'W'}+{abs(score):.1f}"
|
||||||
|
|
||||||
@property
|
def comment(self,sgf=False, eval=False, hints=False):
|
||||||
def comment(self,sgf=False):
|
|
||||||
if not self.parent: # root
|
if not self.parent: # root
|
||||||
return ""
|
return ""
|
||||||
text = f"Move {self.move_number}: {self.bw_player()} @ {self.gtp()} {'(AI Move)' if self.robot else ''}\n"
|
text = f"Move {self.move_number}: {self.bw_player()} {self.gtp()} {'(AI Move)' if self.robot else ''}\n"
|
||||||
|
text += self.x_comment
|
||||||
|
text += "".join(f"Auto undid move {m.gtp()} ({m.evaluation*100:.1f}% efficient)\n" for m in self.children if m.auto_undid)
|
||||||
|
|
||||||
if self.analysis_ready:
|
if self.analysis_ready:
|
||||||
score, _, temperature = self.temperature_stats
|
score, _, temperature = self.temperature_stats
|
||||||
if sgf:
|
if sgf:
|
||||||
@@ -73,13 +77,14 @@ class Move:
|
|||||||
text += f"Temperature: {temperature:.1f}\n"
|
text += f"Temperature: {temperature:.1f}\n"
|
||||||
if self.parent and self.parent.analysis_ready:
|
if self.parent and self.parent.analysis_ready:
|
||||||
prev_best_score, prev_worst_score, prev_temperature = self.parent.temperature_stats
|
prev_best_score, prev_worst_score, prev_temperature = self.parent.temperature_stats
|
||||||
text += f"Top move was {self.format_score(prev_best_score)} @ {self.parent.analysis[0]['move']}\n"
|
if sgf or hints:
|
||||||
text += f"Pass score was {self.format_score(prev_worst_score)}\n"
|
text += f"Top move was {self.parent.analysis[0]['move']} ({self.format_score(prev_best_score)})\n"
|
||||||
|
text += f"Pass score was {self.format_score(prev_worst_score)}\n"
|
||||||
if prev_temperature < 0.5:
|
if prev_temperature < 0.5:
|
||||||
text += f"Previous temperature ({prev_temperature}) too low for evaluation\n"
|
text += f"Previous temperature ({prev_temperature}) too low for evaluation\n"
|
||||||
else:
|
else:
|
||||||
if eval:
|
if sgf or eval:
|
||||||
text += f"Evaluation: {100*self.evaluation:.1f}%\n"
|
text += f"Evaluation: {100*self.evaluation:.1f}% efficient\n"
|
||||||
outdated_evaluation = self.outdated_evaluation
|
outdated_evaluation = self.outdated_evaluation
|
||||||
if outdated_evaluation and outdated_evaluation > self.evaluation and outdated_evaluation > self.evaluation + 0.01:
|
if outdated_evaluation and outdated_evaluation > self.evaluation and outdated_evaluation > self.evaluation + 0.01:
|
||||||
text += f"(Was considered last move as: {100 * outdated_evaluation :.1f}%)\n"
|
text += f"(Was considered last move as: {100 * outdated_evaluation :.1f}%)\n"
|
||||||
@@ -94,7 +99,7 @@ class Move:
|
|||||||
@property
|
@property
|
||||||
def evaluation_info(self):
|
def evaluation_info(self):
|
||||||
if self.parent and self.parent.analysis_ready and self.analysis_ready:
|
if self.parent and self.parent.analysis_ready and self.analysis_ready:
|
||||||
return self.evaluation,self.parent.temperature_stats[2]
|
return self.evaluation, self.parent.temperature_stats[2]
|
||||||
else:
|
else:
|
||||||
return None,None
|
return None,None
|
||||||
|
|
||||||
@@ -264,7 +269,7 @@ class Board:
|
|||||||
def moves(self) -> list: # flat list of moves to current
|
def moves(self) -> list: # flat list of moves to current
|
||||||
moves = []
|
moves = []
|
||||||
p = self.current_move
|
p = self.current_move
|
||||||
while p != self.root:
|
while p is not self.root: # NB == is wrong here
|
||||||
moves.append(p)
|
moves.append(p)
|
||||||
p = p.parent
|
p = p.parent
|
||||||
return moves[::-1]
|
return moves[::-1]
|
||||||
|
|||||||
+2
-4
@@ -3,12 +3,11 @@
|
|||||||
"pass_visits": 200,
|
"pass_visits": 200,
|
||||||
"pass_visits_fast": 50,
|
"pass_visits_fast": 50,
|
||||||
"visits": 3500,
|
"visits": 3500,
|
||||||
"visits_fast": 1500,
|
"visits_fast": 1500
|
||||||
"nopass_visits": 10
|
|
||||||
},
|
},
|
||||||
"board": {
|
"board": {
|
||||||
"size": 19,
|
"size": 19,
|
||||||
"komi": 7.5
|
"komi": 6.5
|
||||||
},
|
},
|
||||||
"ui": {
|
"ui": {
|
||||||
"size_min": 1,
|
"size_min": 1,
|
||||||
@@ -35,7 +34,6 @@
|
|||||||
"balance_play_min_eval": 0.875,
|
"balance_play_min_eval": 0.875,
|
||||||
"balance_play_min_visits": 20,
|
"balance_play_min_visits": 20,
|
||||||
"undo_eval_threshold": 0.875,
|
"undo_eval_threshold": 0.875,
|
||||||
"undo_outdated_eval_threshold": 0.8,
|
|
||||||
"undo_point_threshold": 1,
|
"undo_point_threshold": 1,
|
||||||
"num_undo_prompts": 1
|
"num_undo_prompts": 1
|
||||||
},
|
},
|
||||||
|
|||||||
+27
-61
@@ -26,7 +26,6 @@ class EngineControls(GridLayout):
|
|||||||
[analysis_settings["pass_visits"], analysis_settings["visits"]],
|
[analysis_settings["pass_visits"], analysis_settings["visits"]],
|
||||||
[analysis_settings["pass_visits_fast"], analysis_settings["visits_fast"]],
|
[analysis_settings["pass_visits_fast"], analysis_settings["visits_fast"]],
|
||||||
]
|
]
|
||||||
self.min_nopass_visits = analysis_settings["nopass_visits"]
|
|
||||||
self.train_settings = Config.get("trainer")
|
self.train_settings = Config.get("trainer")
|
||||||
self.debug = Config.get("debug")["level"]
|
self.debug = Config.get("debug")["level"]
|
||||||
self.board_size = Config.get("board")["size"]
|
self.board_size = Config.get("board")["size"]
|
||||||
@@ -78,13 +77,11 @@ class EngineControls(GridLayout):
|
|||||||
print(str(e))
|
print(str(e))
|
||||||
self.info.text = f"Illegal move: {str(e)}"
|
self.info.text = f"Illegal move: {str(e)}"
|
||||||
return
|
return
|
||||||
print("PLAYED", move, self.board.stones)
|
|
||||||
self._request_analysis(mr)
|
self._request_analysis(mr)
|
||||||
return mr
|
return mr
|
||||||
|
|
||||||
# engine action functions
|
# engine action functions
|
||||||
def _do_play(self, *args):
|
def _do_play(self, *args):
|
||||||
print("CURRENT PLAYER", self.board.current_player)
|
|
||||||
move = Move(player=self.board.current_player, coords=args[0])
|
move = Move(player=self.board.current_player, coords=args[0])
|
||||||
self.play(move)
|
self.play(move)
|
||||||
# mr.waiting_for_analysis
|
# mr.waiting_for_analysis
|
||||||
@@ -93,66 +90,34 @@ class EngineControls(GridLayout):
|
|||||||
def update_evaluation(self):
|
def update_evaluation(self):
|
||||||
current_move = self.board.current_move
|
current_move = self.board.current_move
|
||||||
if self.eval.active(current_move.player):
|
if self.eval.active(current_move.player):
|
||||||
self.info.text = current_move.comment
|
self.info.text = current_move.comment(eval=self.eval.active(current_move.player), hints=self.hints.active(current_move.player))
|
||||||
self.evaluation.text = ''
|
self.evaluation.text = ''
|
||||||
if current_move.analysis_ready:
|
if current_move.analysis_ready and self.eval.active(current_move.player):
|
||||||
self.score.text = current_move.format_score().replace("-", "\u2013")
|
self.score.text = current_move.format_score().replace("-", "\u2013")
|
||||||
self.temperature.text = f"{current_move.temperature_stats[2]:.1f}"
|
self.temperature.text = f"{current_move.temperature_stats[2]:.1f}"
|
||||||
if current_move.parent and current_move.parent.analysis_ready:
|
if current_move.parent and current_move.parent.analysis_ready:
|
||||||
self.evaluation.text = f"{100 * current_move.evaluation:.1f}%"
|
self.evaluation.text = f"{100 * current_move.evaluation:.1f}%"
|
||||||
|
|
||||||
# when to trigger auto undo?
|
if current_move.analysis_ready and current_move.parent and current_move.parent.analysis_ready and not current_move.children:
|
||||||
# self.undo.disabled = True # undo while waiting for this does weird things
|
# handle automatic undo
|
||||||
# undid = False
|
if self.auto_undo.active(current_move.player) and not self.ai_auto.active(current_move.player) and not current_move.auto_undid:
|
||||||
# self.info.text = ""
|
ts = self.train_settings
|
||||||
# if self.auto_undo.active(1 - self.board.current_player):
|
# TODO: is this overly generous wrt low visit outdated evaluations?
|
||||||
# undid = self._auto_undo(move)
|
eval = max(current_move.evaluation, current_move.outdated_evaluation or 0)
|
||||||
# if self.ai_auto.active and not undid:
|
points_lost = (current_move.parent or current_move).temperature_stats[2] * (1 - eval)
|
||||||
# self._do_aimove(move, True)
|
if eval < ts["undo_eval_threshold"] and points_lost >= ts["undo_point_threshold"]:
|
||||||
# self.undo.disabled = False
|
current_move.auto_undid = True
|
||||||
|
|
||||||
def _auto_undo(self, move):
|
|
||||||
ts = self.train_settings
|
|
||||||
self.info.text = "Evaluating..."
|
|
||||||
if (
|
|
||||||
move.evaluation
|
|
||||||
and move.evaluation < ts["undo_eval_threshold"]
|
|
||||||
and move.points_lost >= ts["undo_point_threshold"]
|
|
||||||
and ts["num_undo_prompts"] > 0
|
|
||||||
):
|
|
||||||
if move.outdated_evaluation:
|
|
||||||
outdated_points_lost = (1 - move.outdated_evaluation) * move.points_lost / (1 - move.evaluation)
|
|
||||||
# so if the move was not that far off (>undo_outdated_eval_threshold) and according to last move's analysis it was fine, don't undo.
|
|
||||||
if (
|
|
||||||
move.outdated_evaluation
|
|
||||||
and (
|
|
||||||
move.outdated_evaluation >= ts["undo_eval_threshold"]
|
|
||||||
or outdated_points_lost < ts["undo_point_threshold"]
|
|
||||||
)
|
|
||||||
and (
|
|
||||||
move.evaluation > ts["undo_outdated_eval_threshold"]
|
|
||||||
or outdated_points_lost < ts["undo_point_threshold"]
|
|
||||||
)
|
|
||||||
):
|
|
||||||
self.info.text += f"\nBut according to my previous evaluation it was {move.outdated_evaluation*100:.1f}% effective and lost {outdated_points_lost:.1f} point(s), so let's continue anyway.\n"
|
|
||||||
else:
|
|
||||||
if len(self.board.current_move.parent.children) <= ts["num_undo_prompts"]:
|
|
||||||
self.info.text += f"\nLet's try again.\n"
|
|
||||||
self.board.undo()
|
self.board.undo()
|
||||||
return True
|
if len(current_move.parent.children) >= ts["num_undo_prompts"] + 1:
|
||||||
else:
|
best_move = sorted([m for m in current_move.parent.children], key=lambda m: -(m.evaluation_info[0] or 0) )[0]
|
||||||
evaled_moves = sorted(
|
best_move.x_comment = f"Automatically played as best option after max. {ts['num_undo_prompts']} undo(s).\n"
|
||||||
[m for m in self.board.current_move.parent.children if m.evaluation],
|
self.board.play(best_move)
|
||||||
key=lambda m: -m.evaluation,
|
self.update_evaluation()
|
||||||
)
|
# ai player doesn't technically need parent ready, but don't want to override waiting for undo
|
||||||
if evaled_moves and evaled_moves[0].coords != move.coords:
|
elif self.ai_auto.active(1 - current_move.player) and not current_move.children:
|
||||||
self.board.undo()
|
self._do_aimove()
|
||||||
self.board.play(evaled_moves[0])
|
|
||||||
summary = "\n".join(f"{m.gtp()}: {100*m.evaluation:.1f}% effective" for m in evaled_moves)
|
|
||||||
self.info.text += f"\nYour moves:\n{summary}.\nLet's continue with {evaled_moves[0].gtp()}.\n"
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _do_aimove(self, auto=False):
|
def _do_aimove(self):
|
||||||
ts = self.train_settings
|
ts = self.train_settings
|
||||||
while not self.board.current_move.analysis_ready:
|
while not self.board.current_move.analysis_ready:
|
||||||
self.info.text = "Thinking..."
|
self.info.text = "Thinking..."
|
||||||
@@ -204,9 +169,9 @@ class EngineControls(GridLayout):
|
|||||||
sgfmoves = re.findall(r"([BW])\[([a-z]{2})\]", sgf)
|
sgfmoves = re.findall(r"([BW])\[([a-z]{2})\]", sgf)
|
||||||
moves = [Move(player=Move.PLAYERS.index(p.upper()), sgfcoords=(mv, self.board_size)) for p, mv in sgfmoves]
|
moves = [Move(player=Move.PLAYERS.index(p.upper()), sgfcoords=(mv, self.board_size)) for p, mv in sgfmoves]
|
||||||
for move in moves:
|
for move in moves:
|
||||||
self.board.play(move)
|
self.play(move)
|
||||||
while not all(m.analysis for m in moves):
|
while not all(m.analysis for m in moves):
|
||||||
time.sleep(0.01)
|
time.sleep(0.05)
|
||||||
self.info.text = f"{sum([1 if m.analysis else 0 for m in moves])}/{len(moves)} analyzed"
|
self.info.text = f"{sum([1 if m.analysis else 0 for m in moves])}/{len(moves)} analyzed"
|
||||||
|
|
||||||
# analysis thread
|
# analysis thread
|
||||||
@@ -215,7 +180,8 @@ class EngineControls(GridLayout):
|
|||||||
while self.outstanding_analysis_queries:
|
while self.outstanding_analysis_queries:
|
||||||
self._send_analysis_query(self.outstanding_analysis_queries.pop(0))
|
self._send_analysis_query(self.outstanding_analysis_queries.pop(0))
|
||||||
line = self.kata.stdout.readline()
|
line = self.kata.stdout.readline()
|
||||||
print("KATA ANALYSIS RECEIVED:", line[:50])
|
if self.debug:
|
||||||
|
print("KATA ANALYSIS RECEIVED:", line[:50])
|
||||||
self.board.store_analysis(json.loads(line))
|
self.board.store_analysis(json.loads(line))
|
||||||
self.update_evaluation()
|
self.update_evaluation()
|
||||||
self.redraw(include_board=False)
|
self.redraw(include_board=False)
|
||||||
@@ -242,14 +208,14 @@ class EngineControls(GridLayout):
|
|||||||
"includeOwnership": True,
|
"includeOwnership": True,
|
||||||
"maxVisits": self.visits[fast][1],
|
"maxVisits": self.visits[fast][1],
|
||||||
}
|
}
|
||||||
print("query", query)
|
if self.debug:
|
||||||
|
print("query", query)
|
||||||
self._send_analysis_query(query)
|
self._send_analysis_query(query)
|
||||||
query.update(
|
query.update(
|
||||||
{"id": f"PASS_{move_id}", "maxVisits": self.visits[fast][0], "includeOwnership": False}
|
{"id": f"PASS_{move_id}", "maxVisits": self.visits[fast][0], "includeOwnership": False}
|
||||||
) # TODO: merge?
|
)
|
||||||
query["moves"] += [[move.bw_player(next_move=True), "pass"]]
|
query["moves"] += [[move.bw_player(next_move=True), "pass"]]
|
||||||
query["analyzeTurns"][0] += 1
|
query["analyzeTurns"][0] += 1
|
||||||
print("pass-query", query)
|
|
||||||
self._send_analysis_query(query)
|
self._send_analysis_query(query)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+12
-12
@@ -168,11 +168,11 @@
|
|||||||
id: auto_undo
|
id: auto_undo
|
||||||
text: 'undo'
|
text: 'undo'
|
||||||
on_active: root.parent.board.redraw()
|
on_active: root.parent.board.redraw()
|
||||||
CheckBoxHint:
|
BWCheckBoxHint:
|
||||||
size_hint: 0.2, 0.5
|
size_hint: 0.166, 0.5
|
||||||
text: 'lock\nai'
|
text: 'ai'
|
||||||
id: ai_lock
|
id: ai_auto
|
||||||
on_active: self.checkbox.disabled = hints.black.disabled = hints.white.disabled = ai_move.disabled = auto_undo.black.disabled = auto_undo.white.disabled = ai_auto.checkbox.disabled = True
|
default_active: False
|
||||||
CheckBoxHint:
|
CheckBoxHint:
|
||||||
size_hint: 0.2, 0.5
|
size_hint: 0.2, 0.5
|
||||||
id: ownership
|
id: ownership
|
||||||
@@ -189,19 +189,19 @@
|
|||||||
on_press: root.action("aimove")
|
on_press: root.action("aimove")
|
||||||
CheckBoxHint:
|
CheckBoxHint:
|
||||||
size_hint: 0.166, 0.5
|
size_hint: 0.166, 0.5
|
||||||
text: 'auto\nmove'
|
text: 'fast'
|
||||||
id: ai_auto
|
id: ai_fast
|
||||||
default_active: False
|
default_active: True
|
||||||
CheckBoxHint:
|
CheckBoxHint:
|
||||||
size_hint: 0.166, 0.5
|
size_hint: 0.166, 0.5
|
||||||
text: 'balance\nscore'
|
text: 'balance\nscore'
|
||||||
id: ai_balance
|
id: ai_balance
|
||||||
default_active: False
|
default_active: False
|
||||||
CheckBoxHint:
|
CheckBoxHint:
|
||||||
size_hint: 0.166, 0.5
|
size_hint: 0.2, 0.5
|
||||||
text: 'fast'
|
text: 'lock\nai'
|
||||||
id: ai_fast
|
id: ai_lock
|
||||||
default_active: True
|
on_active: self.checkbox.disabled = hints.black.disabled = hints.white.disabled = ai_move.disabled = auto_undo.black.disabled = auto_undo.white.disabled = ai_auto.checkbox.disabled = True
|
||||||
GridLayout:
|
GridLayout:
|
||||||
cols: 2
|
cols: 2
|
||||||
rows: 1
|
rows: 1
|
||||||
|
|||||||
@@ -47,6 +47,12 @@ class BadukPanWidget(Widget):
|
|||||||
def on_touch_up(self, touch):
|
def on_touch_up(self, touch):
|
||||||
if self.ghost_stone:
|
if self.ghost_stone:
|
||||||
self.engine.action("play", self.ghost_stone)
|
self.engine.action("play", self.ghost_stone)
|
||||||
|
else:
|
||||||
|
xd, xp = self._find_closest(touch.x)
|
||||||
|
yd, yp = self._find_closest(touch.y)
|
||||||
|
stones_here = [m for m in self.engine.board.stones if m.coords == (xp,yp)]
|
||||||
|
if stones_here and max(yd, xd) < self.grid_size / 2: # load old comment
|
||||||
|
self.engine.info.text = stones_here[-1].comment(sgf=True)
|
||||||
self.ghost_stone = None
|
self.ghost_stone = None
|
||||||
self.redraw() # remove ghost
|
self.redraw() # remove ghost
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user