// Decompiled by Jad v1.5.7f. Copyright 2000 Pavel Kouznetsov.
// Jad home page: http://www.geocities.com/SiliconValley/Bridge/8617/jad.html
// Decompiler options: packimports(3) 
// Source File Name:   ComputerPlayer.java

package Scrabble;

import KennethTam.Debug;
import java.io.*;
import java.util.BitSet;
import java.util.Date;

// Referenced classes of package Scrabble:
//            BoardSquare, BoardState, CrossInfo, DAWG, 
//            Edge, ServerRackState, Tile

public class ComputerPlayer
{

    public ComputerPlayer(BoardState boardstate, ServerRackState serverrackstate, DAWG dawg, int i, Integer integer)
    {
        _bs = boardstate;
        _rs = serverrackstate;
        _DAWG = dawg;
        _aryCI = new CrossInfo[15][15];
        for(int j = 0; j < 15; j++)
        {
            for(int k = 0; k < 15; k++)
                _aryCI[j][k] = null;

        }

        _bestMove = null;
        _bestScore = 0;
        _bestMoveRow = -1;
        _bestMoveCol = -1;
        _bestMoveDir = 0;
        try
        {
            _logFile = new RandomAccessFile("cp" + integer.intValue() + "-" + i + ".log", "rw");
            _logFile.seek(_logFile.length());
            _logStream = new PrintStream(new FileOutputStream(_logFile.getFD()));
            _logStream.println("Computer Player #" + i + " : Initiated @ " + new Date());
            return;
        }
        catch(Exception exception)
        {
            System.out.println(exception);
        }
        _logStream = System.out;
    }

    public int generateMove(int i, PrintStream printstream)
    {
        _logStream.println("Turn number: " + i);
        printstream.println("Turn " + i + ": ComputerPlayer");
        computeCrosses();
        _bestMove = null;
        _bestScore = 0;
        _bestMoveRow = -1;
        _bestMoveCol = -1;
        _bestMoveDir = 0;
        if(i == 0)
        {
            Debug.assert(_aryCI[7][7] == null, "Center shouldn't have crossinfo at this point");
            _aryCI[7][7] = new CrossInfo();
            for(int j = 0; j < 26; j++)
            {
                _aryCI[7][7]._dxs.set(j);
                _aryCI[7][7]._axs.set(j);
            }

        } else
        {
            Debug.assert(_aryCI[7][7] == null, "Center shouldn't have crossinfo at this point");
        }
        StringBuffer stringbuffer = new StringBuffer();
        for(int k = 0; k < 15; k++)
        {
            for(int j1 = 0; j1 < 15; j1++)
            {
                if(_aryCI[k][j1] == null)
                    continue;
                Debug.assert(_bs.letterAt(k, j1) == 100, "Anchor square shouldn't have a tile!");
                int i3 = 0;
                for(int i2 = j1 - 1; i2 >= 0 && _aryCI[k][i2] == null && _bs.letterAt(k, i2) == 100; i2--)
                    i3++;

                _logStream.println(" Anchor @ (" + k + "," + j1 + ") : " + i3 + " to L.");
                if(i3 == 0)
                {
                    int j2 = j1 - 1;
                    stringbuffer.setLength(0);
                    int k3;
                    for(; j2 >= 0 && (k3 = _bs.letterAt(k, j2)) != 100; j2--)
                    {
                        char c = (char)(k3 + 65);
                        stringbuffer.insert(0, c);
                    }

                    if(stringbuffer.length() > 0)
                    {
                        if(_DAWG.recognizes_e(stringbuffer.toString()) == -1)
                        {
                            printstream.println("\tERROR: left part " + stringbuffer.toString() + " on the board, but we don't recognize it!  Anchor @ " + k + "," + j1);
                            break;
                        }
                        int ai[] = new int[1];
                        ai[0] = 1;
                        int k4 = computeLeftPartScore(stringbuffer.toString(), k, j1 - stringbuffer.length(), ai, false);
                        extendRight(stringbuffer.toString(), _DAWG.recognizes_e(stringbuffer.toString()), k, j1, false, k4, ai, 0, 0);
                    } else
                    {
                        leftPart("", _DAWG.getStartIndex(), 0, k, j1);
                    }
                } else
                {
                    leftPart("", _DAWG.getStartIndex(), i3, k, j1);
                }
            }

        }

        StringBuffer stringbuffer1 = new StringBuffer();
        for(int l = 0; l < 15; l++)
        {
            for(int k1 = 0; k1 < 15; k1++)
                if(_aryCI[l][k1] != null)
                {
                    Debug.assert(_bs.letterAt(l, k1) == 100, "Anchor square shouldn't have a tile!");
                    int j3 = 0;
                    for(int k2 = l - 1; k2 >= 0 && _aryCI[k2][k1] == null && _bs.letterAt(k2, k1) == 100; k2--)
                        j3++;

                    _logStream.println(" D Anchor @ (" + l + "," + k1 + ") : " + j3 + " up.");
                    if(j3 == 0)
                    {
                        int l2 = l - 1;
                        stringbuffer1.setLength(0);
                        int l3;
                        for(; l2 >= 0 && (l3 = _bs.letterAt(l2, k1)) != 100; l2--)
                        {
                            char c1 = (char)(l3 + 65);
                            stringbuffer1.insert(0, c1);
                        }

                        if(stringbuffer1.length() > 0)
                        {
                            int ai1[] = new int[1];
                            ai1[0] = 1;
                            int l4 = computeTopPartScore(stringbuffer1.toString(), l - stringbuffer1.length(), k1, ai1, false);
                            extendDown(stringbuffer1.toString(), _DAWG.recognizes_e(stringbuffer1.toString()), l, k1, false, l4, ai1, 0, 0);
                        } else
                        {
                            topPart("", _DAWG.getStartIndex(), 0, l, k1);
                        }
                    } else
                    {
                        topPart("", _DAWG.getStartIndex(), j3, l, k1);
                    }
                }

        }

        if(_bestScore == 0)
        {
            _logStream.println("Can't find a move!  Exchanging tiles.");
            printstream.println(" Can't find a move!  Exchanging tiles.");
            if(_bestMove != null)
                printstream.println("  ERROR: No move, but bestword = " + _bestMove.toString());
        } else
        {
            _logStream.println(" Playing " + _bestMove + " @ (" + _bestMoveRow + "," + _bestMoveCol + ") for " + _bestScore + " points.");
            printstream.println(" Playing " + _bestMove + " @ (" + _bestMoveRow + "," + _bestMoveCol + ") for " + _bestScore + " points.");
        }
        int i1 = _bestMoveRow;
        int l1 = _bestMoveCol;
        if(_bestMoveDir == 1)
        {
            for(int i4 = 0; i4 < _bestMove.length(); i4++)
                if(_bs.letterAt(i1, l1 + i4) == 100)
                {
                    Tile tile = _rs.playTile(_bestMove.charAt(i4) - 65);
                    Debug.assert(tile != null, "Must have this letter!");
                    _bs.putTileAt(i1, l1 + i4, tile);
                }

        } else
        if(_bestMoveDir == -1)
        {
            for(int j4 = 0; j4 < _bestMove.length(); j4++)
                if(_bs.letterAt(i1 + j4, l1) == 100)
                {
                    Tile tile1 = _rs.playTile(_bestMove.charAt(j4) - 65);
                    Debug.assert(tile1 != null, "Must have this letter!");
                    _bs.putTileAt(i1 + j4, l1, tile1);
                }

        }
        return _bestScore;
    }

    private void computeCrosses()
    {
        for(int i = 0; i < 15; i++)
        {
            for(int j = 0; j < 15; j++)
                _aryCI[i][j] = computeCrossInfo(i, j);

        }

    }

    private CrossInfo computeCrossInfo(int i, int j)
    {
        if(_bs.letterAt(i, j) != 100 || !_bs.hasAdjacentTiles(i, j))
            return null;
        CrossInfo crossinfo = new CrossInfo();
        StringBuffer stringbuffer = new StringBuffer();
        StringBuffer stringbuffer1 = new StringBuffer();
        int k1 = 0;
        int k = i;
        stringbuffer.setLength(0);
        for(; _bs.letterAt(k - 1, j) != 100; k--);
        int j1;
        if(k != i)
            while((j1 = _bs.letterAt(k, j)) != 100) 
            {
                j1 += 65;
                stringbuffer.append((char)j1);
                k1 += _bs.baseScoreAt(k, j);
                k++;
            }
        Debug.assert(k == i, "Should be true at this point");
        k++;
        stringbuffer1.setLength(0);
        while((j1 = _bs.letterAt(k, j)) != 100) 
        {
            j1 += 65;
            stringbuffer1.append((char)j1);
            k1 += _bs.baseScoreAt(k, j);
            k++;
        }
        for(int l = 0; l < 26; l++)
            if(_DAWG.recognizes(stringbuffer.toString() + (char)(l + 65) + stringbuffer1.toString()))
                crossinfo._dxs.set(l);

        crossinfo._dsum = k1;
        k1 = 0;
        k = j;
        stringbuffer.setLength(0);
        for(; _bs.letterAt(i, k - 1) != 100; k--);
        if(k != j)
            while((j1 = _bs.letterAt(i, k)) != 100) 
            {
                j1 += 65;
                stringbuffer.append((char)j1);
                k1 += _bs.baseScoreAt(i, k);
                k++;
            }
        Debug.assert(k == j, "Should be true at this point");
        k++;
        stringbuffer1.setLength(0);
        while((j1 = _bs.letterAt(i, k)) != 100) 
        {
            j1 += 65;
            stringbuffer1.append((char)j1);
            k1 += _bs.baseScoreAt(i, k);
            k++;
        }
        for(int i1 = 0; i1 < 26; i1++)
            if(_DAWG.recognizes(stringbuffer.toString() + (char)(i1 + 65) + stringbuffer1.toString()))
                crossinfo._axs.set(i1);

        crossinfo._asum = k1;
        return crossinfo;
    }

    private void leftPart(String s, int i, int j, int k, int l)
    {
        int ai[] = new int[1];
        ai[0] = 1;
        int i1 = computeLeftPartScore(s, k, l - s.length(), ai, true);
        extendRight(s, i, k, l, false, i1, ai, 0, s.length());
        if(j > 6)
            j = 6;
        if(j > 0)
            do
            {
                Edge edge = _DAWG.getEdge(i);
                if(edge._d == i)
                    break;
                Tile tile = _rs.playTile(edge._l);
                if(tile != null)
                {
                    Debug.assert(edge._l == tile.letter(), "Bad tile label?");
                    leftPart(s + tile.letterAsChar(), edge._d, j - 1, k, l);
                    _rs.returnTile(tile);
                }
                if(edge._e)
                    break;
                i++;
            } while(true);
    }

    private void extendRight(String s, int i, int j, int k, boolean flag, int l, int ai[], 
            int i1, int j1)
    {
        int k1 = _bs.letterAt(j, k);
        if(k1 == 100)
        {
            Edge edge = _DAWG.getEdge(i);
            if(edge._t && flag)
            {
                int j2 = l * ai[0] + i1;
                Debug.assert(j1 <= 7, "Can't play more than 7 tiles!");
                if(j1 == 7)
                    j2 += 50;
                legalMove(s, j2, j, k - s.length(), 1);
            }
            if(k < 15)
            {
                do
                {
                    Edge edge1 = _DAWG.getEdge(i);
                    if(edge1._d == i)
                        break;
                    Tile tile = _rs.playTile(edge1._l);
                    if(tile != null)
                    {
                        if(_aryCI[j][k] == null || _aryCI[j][k]._dxs.get(edge1._l))
                        {
                            int l1 = 0;
                            if(_aryCI[j][k] != null && _aryCI[j][k]._dsum != 0)
                                l1 = (_aryCI[j][k]._dsum + tile.score() * _bs.letterModifierAt(j, k)) * _bs.wordModifierAt(j, k);
                            int i2 = tile.score() * _bs.letterModifierAt(j, k);
                            ai[0] *= _bs.wordModifierAt(j, k);
                            extendRight(s + tile.letterAsChar(), edge1._d, j, k + 1, true, l + i2, ai, i1 + l1, j1 + 1);
                            ai[0] /= _bs.wordModifierAt(j, k);
                        }
                        _rs.returnTile(tile);
                    }
                    if(edge1._e)
                        break;
                    i++;
                } while(true);
                return;
            }
        } else
        {
            k1 += 65;
            int k2;
            if((k2 = _DAWG.matchChar((byte)k1, i)) != -1 && k2 != i)
                extendRight(s + (char)k1, k2, j, k + 1, true, l + Tile.scoreOf((char)k1), ai, i1, j1);
        }
    }

    private void topPart(String s, int i, int j, int k, int l)
    {
        int ai[] = new int[1];
        ai[0] = 1;
        int i1 = computeTopPartScore(s, k - s.length(), l, ai, true);
        extendDown(s, i, k, l, false, i1, ai, 0, s.length());
        if(j > 6)
            j = 6;
        if(j > 0)
            do
            {
                Edge edge = _DAWG.getEdge(i);
                if(edge._d == i)
                    break;
                Tile tile = _rs.playTile(edge._l);
                if(tile != null)
                {
                    Debug.assert(edge._l == tile.letter(), "Bad tile label?");
                    topPart(s + tile.letterAsChar(), edge._d, j - 1, k, l);
                    _rs.returnTile(tile);
                }
                if(edge._e)
                    break;
                i++;
            } while(true);
    }

    private void extendDown(String s, int i, int j, int k, boolean flag, int l, int ai[], 
            int i1, int j1)
    {
        int k1 = _bs.letterAt(j, k);
        if(k1 == 100)
        {
            Edge edge = _DAWG.getEdge(i);
            if(edge._t && flag)
            {
                int j2 = l * ai[0] + i1;
                Debug.assert(j1 <= 7, "Can't play more than 7 tiles!");
                if(j1 == 7)
                    j2 += 50;
                legalMove(s, j2, j - s.length(), k, -1);
            }
            if(j < 15)
            {
                do
                {
                    Edge edge1 = _DAWG.getEdge(i);
                    if(edge1._d == i)
                        break;
                    Tile tile = _rs.playTile(edge1._l);
                    if(tile != null)
                    {
                        if(_aryCI[j][k] == null || _aryCI[j][k]._axs.get(edge1._l))
                        {
                            int l1 = 0;
                            if(_aryCI[j][k] != null && _aryCI[j][k]._asum != 0)
                                l1 = (_aryCI[j][k]._asum + tile.score() * _bs.letterModifierAt(j, k)) * _bs.wordModifierAt(j, k);
                            int i2 = tile.score() * _bs.letterModifierAt(j, k);
                            ai[0] *= _bs.wordModifierAt(j, k);
                            extendDown(s + tile.letterAsChar(), edge1._d, j + 1, k, true, l + i2, ai, i1 + l1, j1 + 1);
                            ai[0] /= _bs.wordModifierAt(j, k);
                        }
                        _rs.returnTile(tile);
                    }
                    if(edge1._e)
                        break;
                    i++;
                } while(true);
                return;
            }
        } else
        {
            k1 += 65;
            int k2;
            if((k2 = _DAWG.matchChar((byte)k1, i)) != -1 && k2 != i)
                extendDown(s + (char)k1, k2, j + 1, k, true, l + Tile.scoreOf((char)k1), ai, i1, j1);
        }
    }

    private void legalMove(String s, int i, int j, int k, int l)
    {
        _logStream.println("  " + s + "\t\t: " + i);
        if(!_DAWG.recognizes(s))
            _logStream.println("   ^ BAD WORD");
        if(i > _bestScore)
        {
            _bestMove = s;
            _bestScore = i;
            _bestMoveRow = j;
            _bestMoveCol = k;
            _bestMoveDir = l;
        }
    }

    private int computeLeftPartScore(String s, int i, int j, int ai[], boolean flag)
    {
        Debug.assert(i >= 0 && j >= 0 && i < 15 && j < 15, "Left part starts out of bounds!");
        int k = s.length();
        Debug.assert((j + k) - 1 < 15, "Left part ends out of bounds!");
        int i1 = 0;
        boolean flag1 = false;
        for(int l = 0; l < k; l++)
        {
            int j1 = Tile.scoreOf(s.charAt(l));
            if(flag)
            {
                j1 *= _bs.letterModifierAt(i, j + l);
                ai[0] *= _bs.wordModifierAt(i, j + l);
            }
            i1 += j1;
        }

        return i1;
    }

    private int computeTopPartScore(String s, int i, int j, int ai[], boolean flag)
    {
        Debug.assert(i >= 0 && j >= 0 && i < 15 && j < 15, "Top part starts out of bounds!");
        int k = s.length();
        Debug.assert((i + k) - 1 < 15, "top part ends out of bounds!");
        int i1 = 0;
        boolean flag1 = false;
        for(int l = 0; l < k; l++)
        {
            int j1 = Tile.scoreOf(s.charAt(l));
            if(flag)
            {
                j1 *= _bs.letterModifierAt(i + l, j);
                ai[0] *= _bs.wordModifierAt(i + l, j);
            }
            i1 += j1;
        }

        return i1;
    }

    private static final int NUMSQR = 15;
    private BoardState _bs;
    public ServerRackState _rs;
    private DAWG _DAWG;
    private CrossInfo _aryCI[][];
    private String _bestMove;
    private int _bestScore;
    private int _bestMoveRow;
    private int _bestMoveCol;
    private int _bestMoveDir;
    private RandomAccessFile _logFile;
    private PrintStream _logStream;
}
