|
1 | 1 | import { useMemo } from 'react' |
2 | 2 | import { Chess } from 'chess.ts' |
3 | | -import { MAIA_MODELS } from 'src/constants/common' |
| 3 | +import { MAIA_MODELS, MAIA_RATINGS } from 'src/constants/common' |
4 | 4 | import { GameNode, MaiaEvaluation, StockfishEvaluation } from 'src/types' |
5 | 5 | import { sortStockfishMoves } from './utils' |
6 | 6 |
|
@@ -105,15 +105,27 @@ export const useMoveRecommendations = ( |
105 | 105 | } |
106 | 106 | } |
107 | 107 |
|
| 108 | + // Maia is only evaluated at multiples of 200 Elo (MAIA_MODELS). The graph is |
| 109 | + // drawn at a finer 100-Elo resolution: evaluated levels use their real policy |
| 110 | + // and the intermediate levels (200n + 100) are linearly interpolated from |
| 111 | + // their two neighbours. |
| 112 | + const probabilityAt = (rating: number, move: string): number => |
| 113 | + (maia[`maia_kdd_${rating}`]?.policy?.[move] || 0) * 100 |
| 114 | + |
| 115 | + const minRating = MAIA_RATINGS[0] |
| 116 | + const maxRating = MAIA_RATINGS[MAIA_RATINGS.length - 1] |
| 117 | + |
108 | 118 | const data = [] |
109 | | - for (const rating of MAIA_MODELS) { |
110 | | - const entry: { [key: string]: number } = { |
111 | | - rating: parseInt(rating.replace('maia_kdd_', '')), |
112 | | - } |
| 119 | + for (let rating = minRating; rating <= maxRating; rating += 100) { |
| 120 | + const entry: { [key: string]: number } = { rating } |
| 121 | + const isEvaluated = rating % 200 === 0 |
113 | 122 |
|
114 | 123 | for (const move of candidates) { |
115 | | - const probability = (maia[rating]?.policy?.[move[0]] || 0) * 100 |
116 | | - entry[move[1]] = probability |
| 124 | + entry[move[1]] = isEvaluated |
| 125 | + ? probabilityAt(rating, move[0]) |
| 126 | + : (probabilityAt(rating - 100, move[0]) + |
| 127 | + probabilityAt(rating + 100, move[0])) / |
| 128 | + 2 |
117 | 129 | } |
118 | 130 |
|
119 | 131 | data.push(entry) |
|
0 commit comments