// 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:   GameTable.java

package server;

import java.util.Random;
import java.util.Vector;

// Referenced classes of package server:
//            Player, _German, SkrabbleServer

public class GameTable
{

    GameTable(SkrabbleServer skrabbleserver, int i)
    {
        joinable = false;
        vacant = true;
        startedGame = false;
        gameOver = false;
        order = new int[4];
        whereIs = new int[4];
        observers = new Vector();
        players = new Player[4];
        names = new String[4];
        notPlaying = new boolean[4];
        pids = new int[4];
        acceptance = new int[4];
        playerBricksValue = new int[4];
        playerBricksCount = new int[4];
        playerPoints = new int[4];
        moveKinds = new int[4][2];
        tableNumber = i;
        serv = skrabbleserver;
    }

    public String _gameMover(int i, int j, int k, int l)
    {
        return Integer.toString(11) + ' ' + i + ' ' + j + ' ' + k + ' ' + l + '\n';
    }

    public String _gameOver(int i, int j)
    {
        return Integer.toString(10) + ' ' + i + ' ' + j + '\n';
    }

    public String _givenBricks(int i, int j, int ai[])
    {
        StringBuffer stringbuffer = new StringBuffer(Integer.toString(18) + ' ' + i + ' ' + j + ' ' + ai.length);
        for(int k = 0; k < ai.length; k++)
            stringbuffer.append(' ').append(ai[k]);

        stringbuffer.append('\n');
        return stringbuffer.toString();
    }

    public String _moveAccepted(int i, int j)
    {
        return Integer.toString(19) + ' ' + i + ' ' + j + '\n';
    }

    public String _moveProp(int i, int j, int ai[])
    {
        StringBuffer stringbuffer = new StringBuffer(Integer.toString(15) + ' ' + i + ' ' + j + ' ' + ai.length);
        for(int k = 0; k < ai.length; k++)
            stringbuffer.append(' ').append(ai[k]);

        stringbuffer.append('\n');
        return stringbuffer.toString();
    }

    public String _moveRejected(int i, int j)
    {
        return Integer.toString(20) + ' ' + i + ' ' + j + '\n';
    }

    public String _newPlayerPoints(int i, int j, int k, int l)
    {
        return Integer.toString(17) + ' ' + i + ' ' + j + ' ' + k + ' ' + l + '\n';
    }

    public String _newTableAllowed()
    {
        return Integer.toString(7) + '\n';
    }

    public String _newTableDisallowed()
    {
        return Integer.toString(8) + '\n';
    }

    public String _newTime(int i, int j, int k)
    {
        return Integer.toString(16) + ' ' + i + ' ' + j + ' ' + k + '\n';
    }

    public String _say(int i, int j, String s)
    {
        return Integer.toString(21) + ' ' + i + ' ' + j + '\n' + s + '\n';
    }

    public String _tableJoin(int i, int j, String s, int k)
    {
        return Integer.toString(27) + ' ' + i + ' ' + j + ' ' + k + '\n' + s + '\n';
    }

    public String _tableLeave(int i, int j, int k)
    {
        return Integer.toString(29) + ' ' + i + ' ' + j + ' ' + k + '\n';
    }

    public String _tableNewHost(int i, int j, int k, String s)
    {
        return Integer.toString(22) + ' ' + i + ' ' + j + ' ' + k + '\n' + s + '\n';
    }

    public String _tableStart(int i, int j, int k, int l, int i1, String as[])
    {
        StringBuffer stringbuffer = new StringBuffer(Integer.toString(23) + ' ' + i + ' ' + j + ' ' + k + ' ' + l + ' ' + i1 + '\n');
        for(int j1 = 0; j1 < i1; j1++)
            stringbuffer.append(as[j1]).append('\n');

        return stringbuffer.toString();
    }

    public String _tableStartGame(int i, int j, int k, String as[], int ai[], int ai1[])
    {
        StringBuffer stringbuffer = new StringBuffer(Integer.toString(26) + ' ' + i + ' ' + j + ' ' + k);
        for(int l = 0; l < k; l++)
            stringbuffer.append(' ').append(ai[l]).append(' ').append(ai1[l]);

        for(int i1 = 0; i1 < k; i1++)
            stringbuffer.append('\n').append(as[i1]);

        stringbuffer.append('\n');
        return stringbuffer.toString();
    }

    public String _tableStop(int i, int j)
    {
        return Integer.toString(24) + ' ' + i + ' ' + j + '\n';
    }

    public synchronized void acceptMove(boolean flag, Player player)
    {
        for(int i = 0; i < nop; i++)
        {
            if(players[i] != player)
                continue;
            accepted++;
            acceptance[i] = flag ? 1 : 0;
            if(!flag)
                rejection++;
            break;
        }

        if(accepted == leftPlaying)
            allAccepted();
    }

    public void allAccepted()
    {
        Player player = players[whereIs[currentPlayer]];
        if(rejection > 0)
        {
            String s = null;
            for(int j = 0; j < nop; j++)
                if(acceptance[j] == 0)
                    if(s == null)
                        s = "[" + names[j];
                    else
                        s = s + "," + names[j];

            say2(_German.TXT_PREFIX + _German.TXT_MOVE_REJECTED, _German.TXT_PREFIX + s + "]");
            broadcast(_moveRejected(tableNumber, gameId));
            int k = whereIs[currentPlayer];
            if(moveKinds[k][0] == 1)
                passes--;
            moveKinds[k][0] = moveKinds[k][1];
            moveKinds[k][1] = 1;
            passes++;
            if(passes == leftPlaying * 2)
                gameOver(0, player);
        } else
        {
            broadcast(_moveAccepted(tableNumber, gameId));
            broadcastBut(player, _newPlayerPoints(tableNumber, gameId, whereIs[currentPlayer], lastMovePoints));
            int i = whereIs[currentPlayer];
            playerPoints[i] = lastMovePoints;
            playerBricksCount[i] -= lastMoveBricksNumber;
            playerBricksValue[i] -= lastMoveBricksValue;
            if(spareBricks.size() > 0)
            {
                giveBricks(currentPlayer, lastMoveBricksNumber);
                if(spareBricks.size() == 0)
                    say(_German.TXT_PREFIX + _German.TXT_ALL_BRICKS_DEALT);
            } else
            if(playerBricksCount[i] == 0)
                gameOver(1, player);
            if(moveKinds[i][0] == 1)
                passes--;
            moveKinds[i][0] = moveKinds[i][1];
            moveKinds[i][1] = 0;
        }
        gameState = 0;
        if(!gameOver)
        {
            currentPlayer = nextPlayer(currentPlayer);
            broadcast(_gameMover(tableNumber, gameId, players[whereIs[currentPlayer]].pid, spareBricks.size()));
        }
    }

    public void broadcast(String s)
    {
        for(int i = 0; i < nop; i++)
            if(players[i] != null)
                players[i].send(s);

    }

    public void broadcastBut(Player player, String s)
    {
        for(int i = 0; i < nop; i++)
            if(players[i] != null && players[i].pid != player.pid)
                players[i].send(s);

    }

    public void gameOver(int i, Player player)
    {
        int j = -1;
        for(int k = 0; k < nop; k++)
        {
            if(players[k] != player)
                continue;
            j = k;
            break;
        }

        serv.broadcastNosync(_gameOver(tableNumber, gameId));
        for(int l = 0; l < nop; l++)
        {
            playerPoints[l] -= playerBricksValue[l];
            if(i == 1)
                playerPoints[j] += playerBricksValue[l];
        }

        for(int i1 = 0; i1 < nop; i1++)
            broadcast(_newPlayerPoints(tableNumber, gameId, whereIs[i1], playerPoints[whereIs[i1]]));

        say2("", _German.TXT_PREFIX + _German.TXT_GAME_OVER);
        if(i == 1)
            say2(_German.TXT_PREFIX + "(" + _German.TXT_ALL_LAID_OUT_PREFIX + player.name + _German.TXT_ALL_LAID_OUT_SUFFIX + ")", "");
        else
        if(i == 0)
            say2(_German.TXT_PREFIX + "(" + _German.TXT_DOUBLE_PASS + ")", "");
        gameOver = true;
    }

    public void giveBricks(int i, int j)
    {
        int k = whereIs[i];
        int l = spareBricks.size();
        if(j > l)
            j = l;
        int ai[] = new int[j * 2];
        for(int i1 = 0; i1 < j; i1++)
        {
            int j1 = rnd.nextInt() % l;
            if(j1 < 0)
                j1 = -j1;
            int k1 = ((Integer)spareBricks.elementAt(j1)).intValue();
            spareBricks.removeElementAt(j1);
            l--;
            ai[i1 * 2] = k1;
            ai[i1 * 2 + 1] = _German.bvalues[k1];
            playerBricksValue[k] += _German.bvalues[k1];
            playerBricksCount[k]++;
        }

        players[k].send(_givenBricks(tableNumber, gameId, ai));
    }

    public void join(Player player)
    {
        player.send(_tableStart(tableNumber, gameId, gameTL, moveTL, nop, names));
        synchronized(this)
        {
            pids[nop] = player.pid;
            players[nop] = player;
            names[nop] = player.name;
            nop++;
            if(nop == 4)
                joinable = false;
        }
        serv.broadcastNosync(_tableJoin(tableNumber, gameId, player.name, player.pid));
        player.addOnTable(this);
    }

    public synchronized void leave(Player player)
    {
        int i = -1;
        for(int j = 0; j < nop; j++)
        {
            if(player.pid != pids[j])
                continue;
            i = j;
            break;
        }

        serv.broadcastNosync(_tableLeave(tableNumber, gameId, i));
        if(startedGame)
        {
            pids[i] = 0;
            players[i] = null;
            if(!notPlaying[i])
            {
                notPlaying[i] = true;
                leftPlaying--;
            }
            names[i] = "** " + names[i];
            left--;
            if(left == 0)
            {
                serv.broadcastNosync(_tableStop(tableNumber, gameId));
                vacant = true;
                startedGame = false;
                gameOver = false;
                nop = 0;
                numberOfVacant++;
                if(numberOfVacant == 1)
                    serv.broadcastNosync(_newTableAllowed());
            } else
            if(!gameOver)
                if(leftPlaying == 0)
                {
                    gameOver(2, player);
                } else
                {
                    if(moveKinds[i][0] == 1)
                        passes--;
                    if(moveKinds[i][1] == 1)
                        passes--;
                    if(gameState == 0)
                    {
                        if(i == whereIs[currentPlayer])
                        {
                            currentPlayer = nextPlayer(currentPlayer);
                            broadcast(_gameMover(tableNumber, gameId, players[whereIs[currentPlayer]].pid, spareBricks.size()));
                        }
                    } else
                    {
                        if(acceptance[i] != -1)
                        {
                            accepted--;
                            if(acceptance[i] == 0)
                                rejection--;
                        }
                        if(i == whereIs[currentPlayer])
                        {
                            gameState = 0;
                            broadcast(_moveRejected(tableNumber, gameId));
                            currentPlayer = nextPlayer(currentPlayer);
                            broadcast(_gameMover(tableNumber, gameId, players[whereIs[currentPlayer]].pid, spareBricks.size()));
                        } else
                        if(accepted == leftPlaying)
                            allAccepted();
                    }
                }
            if(i == 0)
                player.send(_newTableAllowed());
        } else
        {
            for(int k = i; k < nop - 1; k++)
            {
                pids[k] = pids[k + 1];
                players[k] = players[k + 1];
                names[k] = names[k + 1];
            }

            nop--;
            pids[nop] = 0;
            players[nop] = null;
            names[nop] = null;
            if(nop == 0)
            {
                vacant = true;
                joinable = false;
                numberOfVacant++;
                if(numberOfVacant == 1)
                    serv.broadcastNosync(_newTableAllowed());
            } else
            if(nop == 3)
                joinable = true;
            if(i == 0)
            {
                player.send(_newTableAllowed());
                if(nop > 0)
                    broadcast(_tableNewHost(tableNumber, gameId, players[0].pid, players[0].name));
            }
        }
        player.removeOnTable(this);
    }

    public synchronized void moveExchange(Player player, int ai[], int i)
    {
        if(players[whereIs[currentPlayer]] == player && gameState == 0)
        {
            int j = ai.length;
            say(_German.TXT_PREFIX + _German.TXT_EXCHANGE_PREFIX + player.name + _German.TXT_EXCHANGE_SUFFIX + " [" + j + "]");
            broadcastBut(player, _newTime(tableNumber, gameId, i));
            giveBricks(currentPlayer, j);
            int k = whereIs[currentPlayer];
            playerBricksCount[k] -= j;
            for(int l = 0; l < j; l++)
                playerBricksValue[k] -= _German.bvalues[ai[l]];

            int i1 = spareBricks.size() + 1;
            for(int j1 = 0; j1 < j; j1++)
            {
                int k1 = rnd.nextInt() % i1;
                if(k1 < 0)
                    k1 = -k1;
                spareBricks.insertElementAt(new Integer(ai[j1]), k1);
                i1++;
            }

            if(moveKinds[k][0] == 1)
                passes--;
            moveKinds[k][0] = moveKinds[k][1];
            moveKinds[k][1] = 0;
            currentPlayer = nextPlayer(currentPlayer);
            broadcast(_gameMover(tableNumber, gameId, players[whereIs[currentPlayer]].pid, spareBricks.size()));
        }
    }

    public synchronized void moveOK(Player player, int ai[], int i, int j)
    {
        if(players[whereIs[currentPlayer]] == player && gameState == 0)
        {
            lastMovePoints = j;
            lastMoveBricksNumber = ai.length / 4;
            lastMoveBricksValue = 0;
            for(int k = 2; k < ai.length; k += 4)
                lastMoveBricksValue += _German.bvalues[ai[k]];

            for(int l = 0; l < nop; l++)
                acceptance[l] = -1;

            accepted = 0;
            rejection = 0;
            broadcastBut(player, _newTime(tableNumber, gameId, i));
            broadcastBut(player, _moveProp(tableNumber, gameId, ai));
            gameState = 1;
            for(int i1 = 0; i1 < nop; i1++)
            {
                if(players[i1] != player)
                    continue;
                accepted++;
                acceptance[i1] = 1;
                break;
            }

            if(accepted == leftPlaying)
                allAccepted();
        }
    }

    public synchronized void movePass(Player player, int i)
    {
        if(players[whereIs[currentPlayer]] == player && gameState == 0)
        {
            say(_German.TXT_PREFIX + _German.TXT_PASS_PREFIX + player.name + _German.TXT_PASS_SUFFIX);
            broadcastBut(player, _newTime(tableNumber, gameId, i));
            int j = whereIs[currentPlayer];
            if(moveKinds[j][0] == 1)
                passes--;
            moveKinds[j][0] = moveKinds[j][1];
            moveKinds[j][1] = 1;
            passes++;
            if(passes == leftPlaying * 2)
            {
                gameOver(0, player);
            } else
            {
                currentPlayer = nextPlayer(currentPlayer);
                broadcast(_gameMover(tableNumber, gameId, players[whereIs[currentPlayer]].pid, spareBricks.size()));
            }
        }
    }

    public int nextPlayer(int i)
    {
        int j = i + 1;
        for(int k = 0; k < nop; k++)
        {
            int l = j % nop;
            if(!notPlaying[whereIs[l]])
                return l;
            j++;
        }

        return -1;
    }

    public synchronized void say(String s)
    {
        broadcast(_say(tableNumber, gameId, s));
    }

    public synchronized void say2(String s, String s1)
    {
        broadcast(_say(tableNumber, gameId, s) + _say(tableNumber, gameId, s1));
    }

    public synchronized void startGame()
    {
        if(startedGame)
            return;
        startedGame = true;
        gameOver = false;
        joinable = false;
        left = nop;
        leftPlaying = nop;
        passes = 0;
        for(int i = 0; i < nop; i++)
        {
            moveKinds[i][0] = -1;
            moveKinds[i][1] = -1;
            playerBricksCount[i] = 0;
            playerBricksValue[i] = 0;
            playerPoints[i] = 0;
            notPlaying[i] = false;
        }

        say2("", _German.TXT_PREFIX + _German.TXT_ORDER_DRAWING);
        for(int j = 0; j < nop; j++)
            order[j] = j;

        for(int k = nop - 1; k > 0; k--)
        {
            int j1 = Math.abs(rnd.nextInt() % (k + 1));
            if(k != j1)
            {
                int i2 = order[k];
                order[k] = order[j1];
                order[j1] = i2;
            }
        }

        for(int l = 0; l < nop; l++)
            whereIs[order[l]] = l;

        serv.broadcastNosync(_tableStartGame(tableNumber, gameId, nop, names, pids, order));
        say2(_German.TXT_PREFIX + _German.TXT_STARTED, "");
        spareBricks = new Vector();
        int i1 = 1;
        for(int k1 = 0; k1 < _German.bnumbers.length; k1++)
        {
            for(int j2 = 0; j2 < _German.bnumbers[k1]; j2++)
            {
                int k2 = rnd.nextInt() % i1;
                if(k2 < 0)
                    k2 = -k2;
                spareBricks.insertElementAt(new Integer(k1), k2);
                i1++;
            }

        }

        for(int l1 = 0; l1 < nop; l1++)
            giveBricks(l1, 7);

        currentPlayer = 0;
        broadcast(_gameMover(tableNumber, gameId, players[whereIs[0]].pid, spareBricks.size()));
        gameState = 0;
    }

    public void startUp(Player player, int i, int j)
    {
        synchronized(this)
        {
            pids[0] = player.pid;
            players[0] = player;
            names[0] = player.name;
            nop = 1;
        }
        gameTL = i;
        moveTL = j;
        gameId = nextGameId++;
        joinable = true;
        vacant = false;
        startedGame = false;
        numberOfVacant--;
        for(int k = 0; k < 4; k++)
            playerBricksCount[k] = 0;

        player.send(_tableStart(tableNumber, gameId, i, j, 0, null));
        serv.broadcastNosync(_tableJoin(tableNumber, gameId, player.name, player.pid));
        if(numberOfVacant == 0)
            serv.broadcastNosync(_newTableDisallowed());
        player.addOnTable(this);
    }

    public synchronized void tilesNumbers(Player player)
    {
        if(startedGame && !gameOver)
        {
            player.send(_say(tableNumber, gameId, _German.TXT_PREFIX + _German.TXT_TILES_OWNED));
            for(int i = 0; i < nop; i++)
            {
                int j = whereIs[i];
                if(players[j] != null)
                    player.send(_say(tableNumber, gameId, _German.TXT_PREFIX + "# " + players[j].name + " - " + playerBricksCount[j]));
            }

            player.send(_say(tableNumber, gameId, _German.TXT_PREFIX + _German.TXT_TILES_LEFT + spareBricks.size()));
        }
    }

    public synchronized void timeoutGame(Player player, int i)
    {
        if(players[whereIs[currentPlayer]] == player && gameState == 0)
        {
            say(_German.TXT_PREFIX + _German.TXT_GAME_TIMEOUT_PREFIX + player.name + _German.TXT_GAME_TIMEOUT_SUFFIX);
            broadcastBut(player, _newTime(tableNumber, gameId, i));
            notPlaying[whereIs[currentPlayer]] = true;
            leftPlaying--;
            int j = whereIs[currentPlayer];
            if(moveKinds[j][0] == 1)
                passes--;
            if(moveKinds[j][1] == 1)
                passes--;
            if(leftPlaying == 0)
            {
                gameOver(2, player);
            } else
            {
                currentPlayer = nextPlayer(currentPlayer);
                broadcast(_gameMover(tableNumber, gameId, players[whereIs[currentPlayer]].pid, spareBricks.size()));
            }
        }
    }

    public synchronized void timeoutMove(Player player, int i)
    {
        if(players[whereIs[currentPlayer]] == player && gameState == 0)
        {
            say(_German.TXT_PREFIX + _German.TXT_MOVE_TIMEOUT_PREFIX + player.name + _German.TXT_MOVE_TIMEOUT_SUFFIX);
            broadcastBut(player, _newTime(tableNumber, gameId, i));
            int j = whereIs[currentPlayer];
            if(moveKinds[j][0] == 1)
                passes--;
            moveKinds[j][0] = moveKinds[j][1];
            moveKinds[j][1] = 1;
            passes++;
            if(passes == leftPlaying * 2)
            {
                gameOver(0, player);
            } else
            {
                currentPlayer = nextPlayer(currentPlayer);
                broadcast(_gameMover(tableNumber, gameId, players[whereIs[currentPlayer]].pid, spareBricks.size()));
            }
        }
    }

    static int nextGameId = 1;
    static int numberOfVacant;
    static Random rnd = new Random();
    SkrabbleServer serv;
    boolean joinable;
    boolean vacant;
    boolean startedGame;
    boolean gameOver;
    int tableNumber;
    int gameId;
    int currentPlayer;
    int gameState;
    int lastMovePoints;
    int lastMoveBricksNumber;
    int lastMoveBricksValue;
    int order[];
    int whereIs[];
    int nop;
    int left;
    int leftPlaying;
    int accepted;
    int rejection;
    Vector observers;
    Player players[];
    String names[];
    boolean notPlaying[];
    int pids[];
    int acceptance[];
    int playerBricksValue[];
    int playerBricksCount[];
    int playerPoints[];
    int gameTL;
    int moveTL;
    int moveKinds[][];
    int passes;
    Vector spareBricks;

}
