All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.barrybecker4.game.twoplayer.gomoku.analysis.Line Maven / Gradle / Ivy

/** Copyright by Barry G. Becker, 2000-2011. Licensed under MIT License: http://www.opensource.org/licenses/MIT  */
package com.barrybecker4.game.twoplayer.gomoku.analysis;

import com.barrybecker4.game.common.GameContext;
import com.barrybecker4.game.common.board.BoardPosition;
import com.barrybecker4.game.common.board.GamePiece;
import com.barrybecker4.game.twoplayer.gomoku.pattern.Patterns;

/**
 * Represents a run of symbols to be evaluated on the board.
 * All the symbols in the line should be of the same side.
 * @author Barry Becker
 */
public class Line {

    /** contains the symbols in the line (run) */
    protected StringBuilder line;
    private LineEvaluator evaluator;

    /**
     * Constructor
     * @param evaluator used to evaluate the score for the line.
     */
    public Line(LineEvaluator evaluator) {
        this.evaluator = evaluator;
        line = new StringBuilder();
    }

    /**
     * Extend the line by an additional position.
     * @param pos the position to extend ourselves by.
     */
    public void append(BoardPosition pos) {
        assert (pos != null): "Cannot append at null board position.";
        if ( pos.getPiece() == null )  {
            line.append( Patterns.UNOCCUPIED );
        }
        else {
            char symb = pos.getPiece().getSymbol();
            line.append( symb );
        }
    }

    /**
     * We return the difference in value between how the board looked before the
     * move was played (from both points of view) to after the move was played
     * (from both points of view. It's important that we look at it from both
     * sides because creating a near win is noticed from the moving players point of view
     * while blocks are noted from the opposing viewpoint.
     *
     * @param position position in the string to compute value difference for.
     * @return the difference in worth after making a move compared with before.
     *
     */
    public int computeValueDifference(int position) {

        char symb = line.charAt( position );
        if (symb == Patterns.UNOCCUPIED) {
            throw new IllegalStateException(
                    "The piece just played at position "+ position + " in line "+ line +" must be a symbol.");
        }
        boolean player1Perspective = (symb == GamePiece.P1_SYMB);

        int len = line.length();
        if ( len < evaluator.getMinInterestingLength() ) {
            return 0; // not an interesting pattern.
        }

        line.setCharAt( position, Patterns.UNOCCUPIED );
        int maxpos = len - 1;

        int oldScore = evaluator.evaluate(line, player1Perspective, position, 0, maxpos);
        oldScore += evaluator.evaluate(line, !player1Perspective, position, 0, maxpos);

        line.setCharAt( position, symb );
        int newScore = evaluator.evaluate(line, player1Perspective, position, 0, maxpos);
        newScore += evaluator.evaluate(line, !player1Perspective, position, 0, maxpos);

        return (newScore - oldScore);
    }

    /**
     * debugging aid
     */
    public void worthDebug( String dir, int pos, int diff ) {
        GameContext.log( 0,  dir + " "  + line + "  Pos: " + pos + "  difference:" + diff );
    }

    /** provide access to the evaluator for unit tests. */
    LineEvaluator getLineEvaluator() {
        return evaluator;
    }

    @Override
    public String toString() {
        return line.toString();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy