WEB-INF/classes/com/caucho/games/sudoku/SudokuGame.java

package com.caucho.games.sudoku;

import java.util.*;
import java.util.logging.*;
import java.io.Serializable;
import com.caucho.bam.*;
import com.caucho.hemp.broker.*;
import javax.webbeans.*;

/**
 * An individual sudoku game.  Holds the board state and sends events to
 * players.
 **/
public class SudokuGame extends GenericService {
  private static final Logger log
    = Logger.getLogger(SudokuGame.class.getName());

  @In
  private SudokuMatcher _matcher;

  private final SudokuBoard _board;

  private ArrayList<SudokuPlayer> _players = new ArrayList<SudokuPlayer>(2);

  public SudokuGame(SudokuBoard board)
  {
    _board = board;
  }

  /**
   * Adds a player to this game, if the player is acceptable.  Called 
   * when the player sends a GameStartRequest.  Returns the result value for
   * the query.  If the player is not accepted to the game, returns null.
   * When all players have joined the game, this method will send start
   * messages to all waiting players.
   **/
  public boolean addPlayer(SudokuPlayer player)
  {
    if (_players.size() >= 2)
      return false;

    if (player.getDifficulty() != _board.getDifficulty())
      return false;

    _players.add(player);

    return true;
  }

  /**
   * Returns the list of players playing this game.
   **/
  public List<SudokuPlayer> getPlayers()
  {
    return Collections.unmodifiableList(_players);
  }

  /**
   * Returns the board associated with this game.
   **/
  public SudokuBoard getBoard()
  {
    return _board;
  }

  /**
   * Attempts to make a move in this game.
   **/
  @Override 
  public boolean querySet(long id, String to, String from, Serializable value)
  {
    if (value instanceof MoveQuery) {
      MoveQuery query = (MoveQuery) value;
      SudokuPlayer player = getPlayer(from);

      if (player == null) {
        getBrokerStream().queryError(id, from, to, query,
                                         new BamError(BamError.TYPE_CANCEL,
                                                      BamError.BAD_REQUEST));
        return true;
      }

      boolean success = false;
      
      try {
        success = _board.setEntry(query.getX(), query.getY(), 
                                  query.getValue(), player.getId());
      }
      catch (InvalidMoveException e) {
        getBrokerStream().queryError(id, from, to, query,
                                         new BamError(BamError.TYPE_CANCEL,
                                                      BamError.NOT_ALLOWED,
                                                      e.getMessage()));
        return true;
      }

      if (success)
        player.incrementScore();
      else
        player.decrementScore();

      MoveResult result = 
        new MoveResult(query, player.getId(), success, player.getScore());

      getBrokerStream().queryResult(id, from, to, result);

      for (int i = 0; i < _players.size(); i++) {
        String otherJid = _players.get(i).getJid();

        if (! otherJid.equals(player.getJid()))
          getBrokerStream().message(otherJid, getJid(), result);
      }

      if (success && _board.isSolved())
        gameOver();

      return true;
    }
    
    return false;
  }

  void gameOver()
  {
    finish("Game Over");
  }

  void finish(String reason)
  {
    SudokuPlayer player1 = _players.get(0);
    SudokuPlayer player2 = _players.get(1);
    GameFinishMessage finish = null;

    finish = new GameFinishMessage(reason, _players);
    getBrokerStream().message(player1.getJid(), getJid(), finish);

    finish = new GameFinishMessage(reason, _players);
    getBrokerStream().message(player2.getJid(), getJid(), finish);

    _matcher.finishGame(this);
  }

  private SudokuPlayer getPlayer(String jid)
  {
    for (int i = 0; i < _players.size(); i++) {
      if (jid.equals(_players.get(i).getJid()))
        return _players.get(i);
    }

    return null;
  }
}