<commit_before>package com.diusrex.tictactoe.ai;

import java.util.ArrayList;
import java.util.List;

import com.diusrex.tictactoe.ai.AIPlayer;
import com.diusrex.tictactoe.ai.scoring_calculations.Scorer;
import com.diusrex.tictactoe.ai.scoring_calculations.ScoringValues;
import com.diusrex.tictactoe.data_structures.BoardStatus;
import com.diusrex.tictactoe.data_structures.BoxPosition;
import com.diusrex.tictactoe.data_structures.Move;
import com.diusrex.tictactoe.data_structures.Player;
import com.diusrex.tictactoe.data_structures.SectionPosition;
import com.diusrex.tictactoe.logic.GeneralTicTacToeLogic;
import com.diusrex.tictactoe.logic.GridLists;

/*
 *  Is actually a negamax alpha beta player, due to it being easier to code.
 */
public abstract class BaseAlphaBetaPlayer extends AIPlayer {
    private final int WIN_SCORE = 10000000;
    private final Scorer scorer;

    public BaseAlphaBetaPlayer(ScoringValues scoringInfo) {
        this.scorer = new Scorer(scoringInfo);
    }

    @Override
    protected Move choosePosition(BoardStatus board) {
        // Is actually possible to get a larger score than WIN_SCORE, due to multiplying it by the depth left
        return getBestMoveAndItsScore(board, getMaxDepth(board), -Integer.MAX_VALUE, Integer.MAX_VALUE).move;
    }

    protected abstract int getMaxDepth(BoardStatus board);

    private MoveScore getBestMoveAndItsScore(BoardStatus board, int depth, int alpha, int beta) {
        if (board.getWinner() != Player.Unowned) {
            // The previous player won, but this scoring is for the current
            // player
            // Multiplies by depth to prefer (mostly) winning sooner
            // Adds one to ensure that the score wouldn't be 0 if depth is 0
            return new MoveScore(null, -1 * WIN_SCORE * (depth + 1));
        } else if (GeneralTicTacToeLogic.boardIsFull(board)) {
            return new MoveScore(null, scorer.getTieScore());
        } else if (depth == 0) {
            return new MoveScore(null, scorer.calculateScore(board.getNextPlayer(), board));
        }
        
        List<Move> allMoves = generateMoves(board);

        MoveScore bestMove = null;
        
        for (Move move : allMoves) {
            board.applyMoveIfValid(move);
            int score = - getBestMoveAndItsScore(board, depth - 1, -beta, -alpha).score;
            board.undoLastMove();
            
            if (bestMove == null || score > bestMove.score)
                bestMove = new MoveScore(move, score);
            
            alpha = Math.max(alpha, score);
            
            // bestMove will not be null, so it is fine
            if (alpha >= beta) {
                break;
            }
        }

        return bestMove;
    }
<commit_msg>Improved BaseAlphaBetaPlayer code<commit_after>package com.diusrex.tictactoe.ai;

import com.diusrex.tictactoe.ai.scoring_calculations.Scorer;
import com.diusrex.tictactoe.ai.scoring_calculations.ScoringValues;
import com.diusrex.tictactoe.data_structures.*;
import com.diusrex.tictactoe.logic.GeneralTicTacToeLogic;
import com.diusrex.tictactoe.logic.GridLists;

import java.util.ArrayList;
import java.util.List;

/*
 *  Is actually a negamax alpha beta player, due to it being easier to code.
 */
public abstract class BaseAlphaBetaPlayer extends AIPlayer {
    private final int WIN_SCORE = 10000000;
    private final Scorer scorer;

    public BaseAlphaBetaPlayer(ScoringValues scoringInfo) {
        this.scorer = new Scorer(scoringInfo);
    }

    @Override
    protected Move choosePosition(BoardStatus board) {
        // Is actually possible to get a larger score than WIN_SCORE, due to multiplying it by the depth left
        return getBestMoveAndItsScore(board, getMaxDepth(board), -Integer.MAX_VALUE, Integer.MAX_VALUE).move;
    }

    protected abstract int getMaxDepth(BoardStatus board);

    private MoveScore getBestMoveAndItsScore(BoardStatus board, int depthLeft, int alpha, int beta) {
        if (board.getWinner() != Player.Unowned) {
            // The previous player won, but this scoring is for the current player
            // Multiplies by depth to prefer winning sooner, and also causes it to lose later
            // Adds one to ensure that the score wouldn't be 0 if depth is 0
            return new MoveScore(null, -1 * WIN_SCORE * (depthLeft + 1));
        } else if (GeneralTicTacToeLogic.boardIsFull(board)) {
            return new MoveScore(null, scorer.getTieScore());
        } else if (depthLeft == 0) {
            return new MoveScore(null, scorer.calculateScore(board.getNextPlayer(), board));
        }

        List<Move> allMoves = generateMoves(board);

        MoveScore bestMove = null;

        for (Move move : allMoves) {
            board.applyMoveIfValid(move);
            int score = - getBestMoveAndItsScore(board, depthLeft - 1, -beta, -alpha).score;
            board.undoLastMove();

            if (bestMove == null || score > bestMove.score)
                bestMove = new MoveScore(move, score);

            alpha = Math.max(alpha, score);

            // bestMove will not be null, so it is fine
            if (alpha >= beta) {
                break;
            }
        }

        return bestMove;
    }

{'fraction_non_alphanumeric': 0.08676582761250953, 'fraction_numerical': 0.005339435545385202, 'mean_word_length': 2.6781206171107996, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6889579', 'n_tokens_mistral': 1605, 'n_tokens_neox': 1523, 'n_words': 418}