Now heavily extend the reference script extensively into whatever this topic is; "Fast 9K NNUE Search Full Application" into a single python code, as "code" in this specific requirements; 'high-coding skills', 'autofill implementation', 'no-breakdowns'.

CONTENT = The content here, is based-off the description as well as it's matching topic.

Description: "An advanced iterative Q-learning NNUE search with 9K parameters and fast training."

Special Property + Directed Features: 
"""
It'll have a lichess search that'll download games from lichess on user's and train, evaluate, and FEN extract them into a single NNUE model with 9K parameters. Killer Heuristic's, and advanced Transposition Table will be evaluated to the NNUE model with neural network learning.
""'

[ENGINE_SAMPLER: 3.1]
[TOP_P_(MACHINE): 1.2]

Reference Script (REFERENCE ONLY):

```
#1,2, and 3. (Scripts)

# See python-chess documentation at https://python-chess.readthedocs.io/en/latest/

import chess
import chess.pgn
import random

# Plays a randomly selected legal move each turn
class RandomPlayer:
    def __init__(self):
        pass

    def select_move(self, board):
        return random.choice(list(board.legal_moves)) if board.legal_moves else None

# Plays a checkmate if possible, otherwise a capture if possible, 
# otherwise a random move
class CheckmateOrCapturePlayer:
    def __init__(self):
        pass

    def select_move(self, board):
        if not board.legal_moves:
            return None

        legal_moves = list(board.legal_moves)
        chosen_move = None

        for move in legal_moves:
            if board.is_capture(move):
                chosen_move = move
            board.push(move)
            if board.is_checkmate():
                board.pop()
                return move
            board.pop()

        if not chosen_move:
            return random.choice(legal_moves)

        return chosen_move

def play_game(white, black):
    board = chess.Board()
    game = chess.pgn.Game()
    node = game

    while not board.is_game_over():
        player = white if board.turn else black
        move = player.select_move(board)
        board.push(move)
        node = node.add_variation(move)

    game.headers["Result"] = board.result()
    game.headers["White"] = " " + type(white).__name__
    game.headers["Black"] = " " + type(black).__name__
    excluded_tags = ["Event", "Site", "Date", "Round"]
    for tag in excluded_tags:
        if tag in game.headers:
            del game.headers[tag]
    return game

def playoff(player1, player2):
    pass

board = chess.Board()
game = chess.pgn.Game()
node = game
white = CheckmateOrCapturePlayer()
black = RandomPlayer()

game = play_game(white, black)
print (game)

#2:

import chess
import chess.engine
import io
import chess.pgn
from functools import lru_cache
from time import time
import numpy as np
from scipy.interpolate import interp1d


PATH = r'C:\Users\trept\OneDrive\Desktop\Chesstin\stockfish_14_x64_avx2.exe'
engine = chess.engine.SimpleEngine.popen_uci(PATH)


def approximate_table(x):
    # Given data points
    x_points = np.array([1, 2, 3, 4])
    y_points = np.array([0.714, 0.703, 0.704, 0.701])
    
    # Create an interpolation function with extrapolation
    interpolating_function = interp1d(x_points, y_points, kind='linear', fill_value="extrapolate")
    
    # Return the interpolated or extrapolated value for x
    return float(interpolating_function(x))

def board_to_pgn_stringio(board):
    game = chess.pgn.Game()
    node = game

    for move in board.move_stack:
        node = node.add_variation(move)

    pgn_str = str(game)
    pgn_io = io.StringIO(pgn_str)
    
    return pgn_io


def merge_pgns_to_variations(*pgn_ios):
    games = []

    for pgn_io in pgn_ios:
        game = chess.pgn.read_game(pgn_io)
        while game is not None:
            games.append(game)
            game = chess.pgn.read_game(pgn_io)

    master_node = chess.pgn.Game()

    mlist = []
    for game in games:
        mlist.extend(game.variations)

    variations = [(master_node, mlist)]
    done = False

    while not done:
        newvars = []
        done = True
        for vnode, nodes in variations:
            newmoves = {}
            for node in nodes:
                if node.move is None:
                    continue
                elif node.move not in list(newmoves):
                    nvnode = vnode.add_variation(node.move)
                    if len(node.variations) > 0:
                        done = False
                    newvars.append((nvnode, node.variations))
                    newmoves[node.move] = len(newvars) - 1
                else:
                    nvnode, nlist = newvars[newmoves[node.move]]
                    if len(node.variations) > 0:
                        done = False
                    nlist.extend(node.variations)
                    newvars[newmoves[node.move]] = (nvnode, nlist)
        variations = newvars

    exporter = chess.pgn.StringExporter(headers=True, variations=True, comments=True)
    merged_pgn = master_node.accept(exporter)

    return io.StringIO(merged_pgn)


# Wrapper function for memoization
@lru_cache(maxsize=None)
def memoized_get_top_moves(board_fen, n, limit):
    return _get_top_moves(chess.Board(fen=board_fen), n, limit)

# The core function
def _get_top_moves(board: chess.Board, n: int, limit: float) -> list:
    analysis = engine.analyse(board=board, limit=chess.engine.Limit(time=limit), multipv=n)
    return [info['pv'][0] for info in analysis]

# Entry point function
def get_top_moves(board: chess.Board = None, n: int = 5, limit: float = 0.5) -> list:
    return memoized_get_top_moves(board.fen(), n, limit)



def play_board(board: chess.Board = None, k: int = 8, limit: float = 2.5):
    board = board.copy()
    
    for _ in range(k):
        result = engine.play(board, limit=chess.engine.Limit(time=limit))
        board.push(result.move)
        
    return board


def recursive_variations(board: chess.Board, original_side, d: int, k: int, b: int, limit: float, depth: int = 0):
    if depth >= d:
        return [board_to_pgn_stringio(play_board(board, k, limit))]

    boards = []

    if board.turn == original_side:
        top_moves = get_top_moves(board=board, n=b if depth > 0 else 4, limit=limit)
        for move in top_moves:
            board.push(move)
            boards.extend(recursive_variations(board, original_side, d, k, b, limit, depth + 1))
            board.pop()
    else:
        result = engine.play(board, limit=chess.engine.Limit(time=limit))
        board.push(result.move)
        boards.extend(recursive_variations(board, original_side, d, k, b, limit, depth + 1))
        board.pop()

    return boards


def master_func(board: chess.Board = None, n_top_moves: int = 4, k_moves_played: int = 8, time_limit: float = 0.5, depth: int = 1, path: str = 'merged.pgn'):
    depth *= 2
    
    boards = recursive_variations(board, board.turn, depth, k_moves_played, n_top_moves, time_limit)
    merged = merge_pgns_to_variations(*boards)
    
    with open(path, 'w') as f:
        f.write(merged.getvalue())

def estimate_time(d, k, b, limit, original_side, depth=0, is_original_side_turn=True):
    # Base case: If the depth is greater than or equal to the maximum depth
    if depth >= d:
        return k * limit

    # Time to analyze moves at the current depth
    if is_original_side_turn:
        current_level_time = b * limit
        next_level_time = b * estimate_time(d, k, b, limit, original_side, depth + 1, not is_original_side_turn)
    else:
        current_level_time = limit
        next_level_time = estimate_time(d, k, b, limit, original_side, depth + 1, not is_original_side_turn)

    
    return (current_level_time + next_level_time)


def main():
    try:
        params = {'depth': 5,
                  'n_top_moves': 4,
                  'k_moves_played': 5,
                  'time_limit': 0.2
                  }
        
        moves = ['d2d4', 'f7f5']
        board = chess.Board()
    
        for move in moves:
            board.push(chess.Move.from_uci(move))
        
        
        estimate = estimate_time(
            params.get('depth',2) * 2,
            params.get('k_moves_played', 5),
            params.get('n_top_moves', 5),
            params.get('time_limit', 0.5),
            board.turn
            
         ) * approximate_table(params.get('depth', 2))
        
        
        
        print(f"Estimate: {estimate:.2f}")
        
        start = time()
        
        master_func(
            board=board, 
            depth=params.get('depth', 2),
            n_top_moves=params.get('n_top_moves', 5), 
            k_moves_played=params.get('k_moves_played', 5), 
            time_limit=params.get('time_limit', 0.5)
            )
        
        end = time()
        elapsed_time = abs(start-end)
        
        print(f"Actual: {elapsed_time:.2f}")
        
    except Exception as e:
        print(e)
        engine.quit()
                
    finally:    
        
        engine.quit()


if __name__ == '__main__':
    main()
    



#3:

import requests
import chess
import chess.pgn
import torch
import torch.nn as nn
import torch.optim as optim
import io
from stockfish import Stockfish

class NNUE(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super(NNUE, self).__init__()
        self.fc1 = nn.Linear(input_size, hidden_size)
        self.fc2 = nn.Linear(hidden_size, hidden_size)
        self.fc3 = nn.Linear(hidden_size, output_size)
        self.relu = nn.ReLU()

    def forward(self, x):
        x = self.relu(self.fc1(x))
        x = self.relu(self.fc2(x))
        x = self.fc3(x)
        return x

def download_lichess_games(username, max_games=400):
    url = f"https://lichess.org/api/games/user/{username}?max={max_games}&pgnInJson=true"
    response = requests.get(url)
    if response.status_code != 200:
        raise Exception(f"Failed to fetch data from Lichess API: {response.status_code}")
    try:
        games = response.json()
    except ValueError:
        raise Exception(f"Failed to parse JSON response from Lichess API: {response.text}")
    return games

def extract_fen_positions_and_evaluations(games, stockfish_path, depth=15):
    stockfish = Stockfish(stockfish_path)
    positions = []
    evaluations = []
    for i, game in enumerate(games):
        pgn = game.get('pgn')
        if not pgn:
            print(f"No PGN found for game {i + 1}.")
            continue
        
        try:
            pgn_io = io.StringIO(pgn)
            game = chess.pgn.read_game(pgn_io)
            if game is None:
                print(f"Failed to parse PGN for game {i + 1}.")
                continue
            
            board = game.board()
            for move in game.mainline_moves():
                board.push(move)
                positions.append(board.fen())
                stockfish.set_fen_position(board.fen())
                evaluation = stockfish.get_evaluation()
                if evaluation['type'] == 'cp':
                    evaluations.append(evaluation['value'] / 100.0)  
                elif evaluation['type'] == 'mate':
                    evaluations.append(1000 if evaluation['value'] > 0 else -1000)  
        except Exception as e:
            print(f"Error processing PGN for game {i + 1}: {e}")
            continue
    return positions, evaluations

def board_to_tensor(board):
    pieces = ['p', 'n', 'b', 'r', 'q', 'k', 'P', 'N', 'B', 'R', 'Q', 'K']
    board_tensor = torch.zeros(64 * 12)
    for square in chess.SQUARES:
        piece = board.piece_at(square)
        if piece:
            index = pieces.index(piece.symbol())
            board_tensor[square * 12 + index] = 1
    return board_tensor

def preprocess_data(positions, evaluations):
    data = []
    for position, evaluation in zip(positions, evaluations):
        board = chess.Board(position)
        input_tensor = board_to_tensor(board)
        target_tensor = torch.tensor([evaluation], dtype=torch.float32)
        data.append((input_tensor, target_tensor))
    return data

def train_model(data, input_size, hidden_size, output_size, epochs=10, learning_rate=0.001):
    if not data:
        raise ValueError("No data available for training.")
    
    model = NNUE(input_size, hidden_size, output_size)
    criterion = nn.MSELoss()
    optimizer = optim.Adam(model.parameters(), lr=learning_rate)

    for epoch in range(epochs):
        total_loss = 0
        for input_tensor, target_tensor in data:
            optimizer.zero_grad()
            output = model(input_tensor)
            loss = criterion(output, target_tensor)
            loss.backward()
            optimizer.step()
            total_loss += loss.item()
        average_loss = total_loss / len(data)
        print(f'Epoch {epoch+1}/{epochs}, Average Loss: {average_loss}')

    return model

# Download games from Lichess
username = "NoOneCanBeatMe4"
try:
    games = download_lichess_games(username)
    print(f"Downloaded {len(games)} games from Lichess.")
except Exception as e:
    print(e)
    games = []


stockfish_path = "stockfish-windows-x86-64-sse41-popcnt.exe"  
positions, evaluations = extract_fen_positions_and_evaluations(games, stockfish_path)
print(f"Extracted {len(positions)} positions and evaluations.")

data = preprocess_data(positions, evaluations)
print(f"Preprocessed {len(data)} data points.")
input_size = 64 * 12
hidden_size = 256
output_size = 1

if data:
    # Train the NNUE model
    trained_model = train_model(data, input_size, hidden_size, output_size)

    # Save the trained model
    torch.save(trained_model.state_dict(), 'nnue_model.pth')
    print("Saved trained model to nnue_model.pth.")
else:
    print("No data available for training.")
```