Recent from talks
Nothing was collected or created yet.
Evaluation function
View on Wikipedia| This article is part of the series on |
| Chess programming |
|---|
An evaluation function, also known as a heuristic evaluation function or static evaluation function, is a function used by game-playing computer programs to estimate the value or goodness of a position (usually at a leaf or terminal node) in a game tree.[1] Most of the time, the value is either a real number or a quantized integer, often in nths of the value of a playing piece such as a stone in go or a pawn in chess, where n may be tenths, hundredths or other convenient fraction, but sometimes, the value is an array of three values in the unit interval, representing the win, draw, and loss percentages of the position.
There do not exist analytical or theoretical models for evaluation functions for unsolved games, nor are such functions entirely ad-hoc. The composition of evaluation functions is determined empirically by inserting a candidate function into an automaton and evaluating its subsequent performance. A significant body of evidence now exists for several games like chess, shogi and go as to the general composition of evaluation functions for them.
Games in which game playing computer programs employ evaluation functions include chess,[2] go,[2] shogi (Japanese chess),[2] othello, hex, backgammon,[3] and checkers.[4][5] In addition, with the advent of programs such as MuZero, computer programs also use evaluation functions to play video games, such as those from the Atari 2600.[6] Some games like tic-tac-toe are strongly solved, and do not require search or evaluation because a discrete solution tree is available.
Relation to search
[edit]A tree of such evaluations is usually part of a search algorithm, such as Monte Carlo tree search or a minimax algorithm like alpha–beta search. The value is presumed to represent the relative probability of winning if the game tree were expanded from that node to the end of the game. The function looks only at the current position (i.e. what spaces the pieces are on and their relationship to each other) and does not take into account the history of the position or explore possible moves forward of the node (therefore static). This implies that for dynamic positions where tactical threats exist, the evaluation function will not be an accurate assessment of the position. These positions are termed non-quiescent; they require at least a limited kind of search extension called quiescence search to resolve threats before evaluation. Some values returned by evaluation functions are absolute rather than heuristic, if a win, loss or draw occurs at the node.
There is an intricate relationship between search and knowledge in the evaluation function. Deeper search favors less near-term tactical factors and more subtle long-horizon positional motifs in the evaluation. There is also a trade-off between efficacy of encoded knowledge and computational complexity: computing detailed knowledge may take so much time that performance decreases, so approximations to exact knowledge are often better. Because the evaluation function depends on the nominal depth of search as well as the extensions and reductions employed in the search, there is no generic or stand-alone formulation for an evaluation function. An evaluation function which works well in one application will usually need to be substantially re-tuned or re-trained to work effectively in another application.[citation needed]
In chess
[edit]In computer chess, larger evaluations indicate a material imbalance or positional advantage or that a win of material is usually imminent. Very large evaluations may indicate that checkmate is imminent. An evaluation function also implicitly encodes the value of the right to move, which can vary from a small fraction of a pawn to win or loss.
Handcrafted evaluation functions
[edit]The output of a handcrafted evaluation function is typically an integer whose units are typically referred to as pawns. The term 'pawn' refers to the value when the player has one more pawn than the opponent in a position, as explained in Chess piece relative value. The integer 1 usually represents some fraction of a pawn, and commonly used in computer chess are centipawns, which are a hundredth of a pawn.
Historically in computer chess, the terms of an evaluation function are constructed (i.e. handcrafted) by the engine developer, as opposed to discovered through training neural networks. The general approach for constructing handcrafted evaluation functions is as a linear combination of various weighted terms determined to influence the value of a position. However, not all terms in a handcrafted evaluation function are linear, such as king safety and pawn structure. Each term may be considered to be composed of first order factors (those that depend only on the space and any piece on it), second order factors (the space in relation to other spaces), and nth-order factors (dependencies on history of the position).
A handcrafted evaluation function typically has a material balance term that usually dominates the evaluation. The conventional values used for material are Queen=9, Rook=5; Knight or Bishop=3; Pawn=1; the king is assigned an arbitrarily large value, usually larger than the total value of all the other pieces.[1] In addition, it typically has a set of positional terms usually totaling no more than the value of a pawn, though in some positions the positional terms can get much larger, such as when checkmate is imminent. Handcrafted evaluation functions typically contain dozens to hundreds of individual terms.
In practice, effective handcrafted evaluation functions are not created by expanding the list of evaluated parameters, but by careful tuning or training of the weights relative to each other, of a modest set of parameters such as those described above. Toward this end, positions from various databases are employed, such as from master games, engine games, Lichess games, or even from self-play, as in reinforcement learning.
Example
[edit]An example handcrafted evaluation function for chess might look like the following:
- c1 * material + c2 * mobility + c3 * king safety + c4 * center control + c5 * pawn structure + c6 * king tropism + ...
Each of the terms is a weight multiplied by a difference factor: the value of white's material or positional terms minus black's.
- The material term is obtained by assigning a value in pawn-units to each of the pieces.
- Mobility is the number of legal moves available to a player, or alternately the sum of the number of spaces attacked or defended by each piece, including spaces occupied by friendly or opposing pieces. Effective mobility, or the number of "safe" spaces a piece may move to, may also be taken into account.
- King safety is a set of bonuses and penalties assessed for the location of the king and the configuration of pawns and pieces adjacent to or in front of the king, and opposing pieces bearing on spaces around the king.
- Center control is derived from how many pawns and pieces occupy or bear on the four center spaces and sometimes the 12 spaces of the extended center.
- Pawn structure is a set of penalties and bonuses for various strengths and weaknesses in pawn structure, such as penalties for doubled and isolated pawns.
- King tropism is a bonus for closeness (or penalty for distance) of certain pieces, especially queens and knights, to the opposing king.
Piece-square tables
[edit]An important technique in evaluation since at least the early 1990s is the piece-square table (also called piece-value table).[7][8] Each table is a set of 64 values corresponding to the squares of the chessboard. The most basic implementation of piece-square table consists of separate tables for each type of piece per player, which in chess results in 12 piece-square tables in total. The values in the tables are bonuses/penalties for the location of each piece on each space, and encode a composite of many subtle factors difficult to quantify analytically. In handcrafted evaluation functions, there are sometimes two sets of tables: one for the opening/middlegame, and one for the endgame; positions of the middle game are interpolated between the two.[9]
Neural networks
[edit]While neural networks have been used in the evaluation functions of chess engines since the late 1980s,[10][11] they did not become popular in computer chess until the late 2010s, as the hardware needed to train neural networks was not strong enough at the time, and fast training algorithms and network topology and architectures had not been developed yet. Neural network based evaluation functions generally consist of a neural network trained using reinforcement learning or supervised learning to accept a board state as input and output a real or integer value.
Deep neural networks have been used, albeit infrequently, in computer chess after Matthew Lai's Giraffe[12] in 2015 and Deepmind's AlphaZero in 2017 demonstrated the feasibility of deep neural networks in evaluation functions. The distributed computing project Leela Chess Zero was started shortly after to attempt to replicate the results of Deepmind's AlphaZero paper. Apart from the size of the networks, the neural networks used in AlphaZero and Leela Chess Zero also differ from those used in traditional chess engines in that they predict a distribution across subsequent moves (the policy head) in addition to the evaluation (the value head).[13] Since deep neural networks are very large, engines using deep neural networks in their evaluation function usually require a graphics processing unit in order to efficiently calculate the evaluation function.
The evaluation function used by most top engines [citation needed] is the efficiently updatable neural network (NNUE), a sparse and shallow neural network originally proposed for computer shogi in 2018 by Yu Nasu.[14][15][16] In fact, the most basic NNUE architecture is simply the 12 piece-square tables described above, a neural network with only one layer and no activation functions. An efficiently updatable neural network architecture was first ported to chess in a Stockfish derivative called Stockfish NNUE, publicly released on May 30, 2020,[17] and was incorporated into the official Stockfish engine on August 6, 2020.[18][19]
Endgame tablebases
[edit]Chess engines frequently use endgame tablebases to quickly and accurately evaluate endgame positions.
In Go
[edit]Historically, evaluation functions in Computer Go took into account both territory controlled, influence of stones, number of prisoners and life and death of groups on the board. [citation needed] However, modern go playing computer programs largely use deep neural networks in their evaluation functions, such as AlphaGo, Leela Zero, Fine Art, and KataGo, and output a win/draw/loss percentage rather than a value in number of stones.
References
[edit]- ^ a b Shannon, Claude (1950), Programming a Computer for Playing Chess (PDF), Ser. 7, vol. 41, Philosophical Magazine, retrieved 12 December 2021
- ^ a b c Silver, David; Hubert, Thomas; Schrittwieser, Julian; Antonoglou, Ioannis; Lai, Matthew; Guez, Arthur; Lanctot, Marc; Sifre, Laurent; Kumaran, Dharshan; Graepel, Thore; Lillicrap, Timothy; Simonyan, Karen; Hassabis, Demis (7 December 2018). "A general reinforcement learning algorithm that masters chess, shogi, and go through self-play". Science. 362 (6419): 1140–1144. Bibcode:2018Sci...362.1140S. doi:10.1126/science.aar6404. PMID 30523106.
- ^ Tesauro, Gerald (March 1995). "Temporal Difference Learning and TD-Gammon". Communications of the ACM. 38 (3): 58–68. doi:10.1145/203330.203343. S2CID 8763243. Retrieved Nov 1, 2013.
- ^ Schaeffer, J.; Burch, N.; Y. Björnsson; Kishimoto, A.; Müller, M.; Lake, R.; Lu, P.; Sutphen, S. (2007). "Checkers is Solved" (PDF). Science. 317 (5844): 1518–22. Bibcode:2007Sci...317.1518S. doi:10.1126/science.1144079. PMID 17641166. S2CID 10274228.
- ^ Schaeffer, J.; Björnsson, Y.; Burch, N.; Kishimoto, A.; Müller, M.; Lake, R.; Lu, P.; Sutphen, S. "Solving Checkers" (PDF). Proceedings of the 2005 International Joint Conferences on Artificial Intelligence Organization.
- ^ Schrittwieser, Julian; Antonoglou, Ioannis; Hubert, Thomas; Simonyan, Karen; Sifre, Laurent; Schmitt, Simon; Guez, Arthur; Lockhart, Edward; Hassabis, Demis; Graepel, Thore; Lillicrap, Timothy (2020). "Mastering Atari, Go, chess and shogi by planning with a learned model". Nature. 588 (7839): 604–609. arXiv:1911.08265. Bibcode:2020Natur.588..604S. doi:10.1038/s41586-020-03051-4. PMID 33361790. S2CID 208158225.
- ^ Beal, Don; Smith, Martin C., Learning Piece-Square Values using Temporal Differences, vol. 22, ICCA Journal
- ^ Jun Nagashima; Masahumi Taketoshi; Yoichiro Kajihara; Tsuyoshi Hashimoto; Hiroyuki Iida (2002), "An Efficient Use of Piece-Square Tables in Computer Shogi", 情報処理学会研究報告 = IPSJ SIG technical reports, no. 69, Information Processing Society of Japan, pp. 29–36
- ^ Stockfish Evaluation Guide, retrieved 12 December 2021
- ^ Thurn, Sebastian (1995), Learning to Play the Game of Chess (PDF), MIT Press, retrieved 12 December 2021
- ^ Levinson, Robert (1989), A Self-Learning, Pattern-Oriented Chess Program, vol. 12, ICCA Journal
- ^ Lai, Matthew (4 September 2015), Giraffe: Using Deep Reinforcement Learning to Play Chess, arXiv:1509.01549v1
- ^ "Neural network topology". lczero.org. Retrieved 2021-12-12.
- ^ Yu Nasu (April 28, 2018). "Efficiently Updatable Neural-Network-based Evaluation Function for computer Shogi" (PDF) (in Japanese).
- ^ Yu Nasu (April 28, 2018). "Efficiently Updatable Neural-Network-based Evaluation Function for computer Shogi (Unofficial English Translation)" (PDF). GitHub.
- ^ Gary Linscott (April 30, 2021). "NNUE". GitHub. Retrieved December 12, 2020.
- ^ Noda, Hisayori (30 May 2020). "Release stockfish-nnue-2020-05-30". Github. Retrieved 12 December 2021.
- ^ "Introducing NNUE Evaluation". 6 August 2020.
- ^ Joost VandeVondele (July 25, 2020). "official-stockfish / Stockfish, NNUE merge". GitHub.
- Slate, D and Atkin, L., 1983, "Chess 4.5, the Northwestern University Chess Program" in Chess Skill in Man and Machine 2nd Ed., pp. 93–100. Springer-Verlag, New York, NY.
- Ebeling, Carl, 1987, All the Right Moves: A VLSI Architecture for Chess (ACM Distinguished Dissertation), pp. 56–86. MIT Press, Cambridge, MA
External links
[edit]Evaluation function
View on GrokipediaFundamentals
Definition
An evaluation function is a static heuristic function employed in artificial intelligence for game-playing programs to assign a numerical score to a given game state or position, approximating its desirability or strength from the perspective of a specific player.[5] This score serves as an estimate of the expected outcome under optimal play, guiding decision-making when exhaustive search of the game tree is infeasible due to computational limits.[6] In essence, it provides a quick assessment of position quality without simulating all possible future moves, relying on domain-specific features to differentiate between favorable and unfavorable states.[7] Mathematically, an evaluation function can be represented as , where denotes the game state (or position) and is a scalar value indicating the estimated advantage.[5] In zero-sum two-player games, typically ranges from negative infinity (certain loss for the current player) to positive infinity (certain win), with values centered around 0 representing approximate equality, such as a draw or balanced positions.[6] For terminal positions, exactly matches the game's outcome: +∞ or +1 for a win, -∞ or -1 for a loss, and 0 for a draw, aligning with standard game theory utilities.[5] Key assumptions underlying evaluation functions include their heuristic nature, which compensates for incomplete information about future game developments by approximating the minimax value of a position.[6] They are designed to be independent of search depth, providing a consistent static assessment regardless of how deeply the game tree is explored, though their accuracy improves when applied closer to terminal states.[7] This approach presupposes familiarity with basic game theory concepts, such as the ternary outcomes of win, loss, and draw in perfect-information games.[5] The concept of the evaluation function originated in the context of early AI game programs during the 1950s, notably in the work of Herbert Simon, Allen Newell, and J.C. Shaw on chess and checkers programs at RAND Corporation and Carnegie Mellon University.[7] Their 1958 paper described evaluation routines that numerically scored board positions based on material and positional factors, marking a foundational step in using heuristics for complex problem-solving in games.[7] These early efforts integrated evaluation functions with search algorithms like minimax to enable practical gameplay on limited hardware.[5]Role in Adversarial Search
In adversarial search algorithms for two-player zero-sum games, evaluation functions approximate the utility of positions at leaf nodes of the game tree, where exhaustive search to terminal states becomes infeasible owing to the exponential explosion caused by high branching factors—often exceeding 30 in complex games—and the need for depths of 10 or more plies to capture meaningful strategy.[5] This depth-limited approach treats non-terminal positions at the cutoff horizon as pseudo-terminals, applying the evaluation to estimate long-term prospects and avoid the "horizon effect" where important future developments are overlooked.[8] The integration with the minimax algorithm is foundational: the evaluation function provides static estimates for non-terminal cutoff positions, enabling recursive value propagation up the tree. Formally, the minimax value for a state at depth limit is defined as with the optimal move selected as the action maximizing (or minimizing) this backed-up value at the root.[5] This substitution allows minimax to approximate optimal play despite incomplete search, as pioneered in early computational game analyses.[9] Evaluation functions synergize with alpha-beta pruning by supplying scalar scores that tighten the alpha (best max value) and beta (best min value) bounds during search, permitting early cutoff of subtrees proven irrelevant to the root decision—for instance, if a node's value exceeds beta for a minimizer, all remaining siblings can be pruned.[10] This reduces the effective branching factor from to roughly in ordered trees, exponentially accelerating evaluation while preserving minimax optimality.[10] A central design trade-off arises between evaluation accuracy and computational cost: highly accurate functions, incorporating nuanced features like king safety or pawn structure, demand more processing time per leaf, constraining search depth on limited hardware, whereas simpler linear combinations of material and mobility enable deeper plunges—often 2-4 plies more—for superior tactical insight.[11] Empirical studies confirm that modest accuracy gains can yield disproportionate strength improvements when paired with deeper search.[5] The role of evaluation functions has evolved from fixed-depth minimax implementations in 1970s programs, which rigidly halted at a preset horizon and relied heavily on eval for all assessments, to modern iterative deepening frameworks starting in the 1980s. These incrementally deepen searches (e.g., 1 ply, then 2, up to time allowance), reusing shallower results to refine move ordering and principal lines while applying evaluations primarily at the deepest leaves, thus mitigating time overruns and enhancing reliability.[12] Beyond games, evaluation functions generalize to heuristic guidance in non-adversarial optimization, estimating solution quality to steer local search toward global optima in domains like scheduling or circuit design, though their primary impact remains in competitive, zero-sum settings.[13]Construction Methods
Handcrafted Functions
Handcrafted evaluation functions rely on domain expertise to manually define and weight key features of a game position, forming a heuristic approximation of its value. Experts identify informative attributes, such as material balance (the relative value of captured and remaining pieces) and positional advantages (like control of the board center), then combine them linearly to produce a score that guides search algorithms toward promising moves. This approach typically employs a formula of the form where represents the game state, are normalized feature values (often ranging from -1 to 1 or scaled to piece units), and are expert-assigned weights reflecting each feature's strategic importance.[14] Early implementations, such as the 1967 Greenblatt chess program (also known as MacHack VI), exemplified this simplicity by primarily using material counts—assigning fixed values like 1 for pawns and 9 for queens—augmented with basic positional bonuses for piece development and king safety.[15] The design process begins with feature selection, where developers choose a set of measurable properties based on game theory and expert analysis, followed by weighting to balance their contributions. Weights are refined iteratively through empirical testing: positions from game databases are evaluated against known outcomes (e.g., wins, losses, or draws), and adjustments are made manually or via optimization techniques like linear regression to minimize prediction errors. For instance, in chess, developers might test thousands of grandmaster games to tune penalties for weaknesses like isolated pawns. Common features include king safety (assessing exposure to attacks), pawn structure (evaluating chains or passed pawns for advancement potential), and mobility (counting legal moves for pieces to quantify activity). This manual process ensures the function captures strategic nuances but requires deep game knowledge.[14][16] These functions offer key advantages in interpretability—experts can inspect and justify individual terms—and computational speed, as they avoid the overhead of data-driven models, enabling real-time evaluation in resource-constrained environments. However, they are inherently limited by human expertise, potentially overlooking subtle patterns or struggling with novel positions outside the designer's experience, making them brittle to evolving strategies. In modern AI, handcrafted functions have been surpassed in strength by learned alternatives, such as those in AlphaZero, which achieved superhuman performance without manual feature engineering, though they persist as baselines or in hybrid systems for their transparency and efficiency.[17]Learned Functions
Learned evaluation functions in game AI employ machine learning techniques, primarily neural networks, to approximate the value of game states by learning patterns from large datasets of positions and outcomes. These functions are typically trained using supervised learning, where positions are labeled with win/loss/draw outcomes or estimated values from expert play or simulations, or through reinforcement learning methods that update estimates based on temporal differences in rewards. Common architectures include feedforward neural networks for simpler board representations and convolutional neural networks (CNNs) for spatial games like Go, which capture local patterns such as piece interactions and board control.[18] Training paradigms for these functions often involve self-play, where agents generate their own data by simulating games against themselves, producing policy-value networks that simultaneously learn move probabilities and state values. Alternatively, imitation learning from expert human games provides initial supervision, with loss functions combining mean squared error for value prediction and cross-entropy for policy matching, often augmented by regularization terms like L2 penalties to prevent overfitting. In reinforcement learning setups, temporal difference (TD) methods bootstrap value estimates from subsequent states, enabling incremental learning without full game rollouts.[19] Key advancements trace back to the 1990s with TD-Gammon, which used TD(λ) learning on a feedforward network to master backgammon through self-play, achieving expert-level performance without human knowledge. Post-2010s developments shifted to deep learning, with CNN-based evaluators demonstrating superior pattern recognition in complex games, as seen in early Go applications predicting expert moves at human dan levels. Efficiency improvements came via quantized networks and specialized architectures like efficiently updatable neural networks (NNUE), which enable rapid incremental updates during search by representing inputs as sparse half-keypoint features, reducing computational overhead on CPUs.[19][18][20] These learned functions excel at modeling non-linear interactions among game elements, such as subtle positional trade-offs that handcrafted rules might overlook, leading to more accurate evaluations in high-branching-factor games. However, their black-box nature complicates interpretability and debugging, and training requires substantial computational resources, often involving millions of simulated games on GPU clusters. To mitigate these issues, hybrid approaches integrate learned components with handcrafted features, such as material counts or mobility scores, blending data-driven insights with domain-specific priors for enhanced robustness and faster convergence.[21][22] By 2025, learned evaluation functions have achieved widespread adoption in commercial and open-source game engines, powering top-performing systems in chess and shogi through NNUE integrations that rival or exceed traditional methods in strength while maintaining real-time efficiency. Ongoing research explores multimodal inputs, incorporating not just current board states but also move histories or auxiliary data like time controls, to further refine evaluations in dynamic environments.[22][23]Exact Evaluation via Tablebases
Exact evaluation via tablebases refers to the use of precomputed databases that provide perfect assessments of win, loss, or draw outcomes for endgame positions in games like chess, limited to configurations with a specific maximum number of pieces on the board. These tablebases are constructed through retrograde analysis, a backward induction technique that exhaustively enumerates all reachable positions from terminal states, determining the optimal result and distance to it for each. For instance, in chess, 7-piece tablebases cover all positions involving up to seven pieces (including kings), storing outcomes such as distance-to-mate (DTM) or distance-to-zeroing (DTZ) metrics.[24][25] The construction process employs dynamic programming, originating from Richard Bellman's foundational work on dynamic programming in the 1950s, which applies backward induction to solve subgames iteratively. Starting from terminal positions (e.g., checkmates or stalemates), the algorithm generates predecessor positions via "un-move" generation and classifies them based on the results of their successors, propagating values until all positions up to the piece limit are resolved. Storage is achieved through efficient indexing, such as bijective mappings to Gödel numbers or Zobrist hashing, combined with compression techniques like bit-packing to manage the enormous state space; for example, the Lomonosov 7-piece tablebases, computed in 2012, encompass over 500 trillion positions in approximately 140 TB after compression.[26][24][25] In practice, tablebases are integrated into game engines for lookup during adversarial search, replacing approximate evaluation at leaf nodes with precise values when a position falls within the database's scope, often probed via transposition tables to avoid redundant computations and ensure efficient access even in real-time play. This probing enhances search accuracy without additional computational overhead beyond the initial storage cost.[24] Scalability is constrained by the combinatorial explosion of positions, making tablebases feasible primarily for endgames where the reduced material limits the state space compared to midgame or opening phases; the full 7-piece chess tablebases were completed in 2012 using the Lomonosov supercomputer at Moscow State University. Advantages include zero evaluation error for covered positions, enabling perfect play and theoretical insights, while disadvantages encompass massive storage requirements and applicability only to shallow depths, beyond which approximate methods must supplement.[27][25] Extensions involve real-time probing in modern engines, such as Stockfish or Leela Chess Zero, which access remote or local tablebases during analysis. Ongoing research leverages distributed computing for larger bases; as of 2025, partial 8-piece tablebases have been generated for specific configurations, with efforts like those by Marc Bourzutschky resolving significant subsets to uncover new endgame records; as of August 2025, progress includes the identification of a 400-move winning line in pawnless 8-piece endgames, though a complete set remains computationally prohibitive at estimated petabyte scales.[28][29][29]Applications in Games
In Chess
In chess, evaluation functions assess the relative strength of a position by quantifying advantages in material, positional elements, and strategic factors tailored to the game's tactical and piece-based nature. Standard material values assign 1 point to a pawn, 3 points each to a knight and bishop, 5 points to a rook, and 9 points to a queen, forming the core of most evaluations since these reflect average exchange equivalences derived from extensive game analysis.[30] Beyond material, chess-specific features include penalties for pawn structure weaknesses, such as -0.3 to -0.5 points for isolated or doubled pawns that limit mobility and create vulnerabilities, and king safety metrics like tropism, which penalize positions where enemy pieces exert pressure near the king (e.g., -0.2 points per unprotected square in the king's vicinity). Piece mobility contributes positively, often adding 0.1 points per legal move to reward active development and control.[31] Piece-square tables enhance positional evaluation by using 2D arrays—one for each piece type and color—to assign bonuses or penalties based on board location, reflecting strategic ideals like central control or edge avoidance. For instance, a knight on c3 might receive +0.5 points for its central influence in the midgame, while the same knight on a1 incurs a -0.4 penalty for poor activity; these values are scaled in centipawns (1/100 of a pawn unit) for precision. Modern implementations, such as those in early Stockfish versions, employ tapered tables with separate midgame and endgame variants, interpolating between them based on remaining material (e.g., full midgame weighting at 40+ pieces, shifting to endgame at under 20) to adapt to phase-specific priorities like pawn promotion potential.[32] Handcrafted evaluation functions in chess engines like pre-NNUE Stockfish combined these features into a linear formula summing material balance, piece-square table scores, and adjustments for structure and safety, tuned via automated testing on millions of positions. A basic pseudocode representation of such an evaluation might look like:double evaluate(Board board) {
double score = 0.0;
// [Material](/page/Material) balance
score += (board.white_pawns - board.black_pawns) * 100;
score += (board.white_knights - board.black_knights) * 300;
// ... similar for other pieces
// Piece-square tables
for each piece in board {
score += pst[piece.type][piece.square] * (piece.color == WHITE ? 1 : -1);
}
// [Pawn structure](/page/Pawn_structure) penalties
score -= isolated_pawn_penalty(board.white_pawns) - isolated_pawn_penalty(board.black_pawns);
// King safety and mobility
score += king_safety(board.white_king) - king_safety(board.black_king);
score += mobility(board.white_pieces) - mobility(board.black_pieces);
return score / 100.0; // Convert to pawn units
}
double evaluate(Board board) {
double score = 0.0;
// [Material](/page/Material) balance
score += (board.white_pawns - board.black_pawns) * 100;
score += (board.white_knights - board.black_knights) * 300;
// ... similar for other pieces
// Piece-square tables
for each piece in board {
score += pst[piece.type][piece.square] * (piece.color == WHITE ? 1 : -1);
}
// [Pawn structure](/page/Pawn_structure) penalties
score -= isolated_pawn_penalty(board.white_pawns) - isolated_pawn_penalty(board.black_pawns);
// King safety and mobility
score += king_safety(board.white_king) - king_safety(board.black_king);
score += mobility(board.white_pieces) - mobility(board.black_pieces);
return score / 100.0; // Convert to pawn units
}