📄 boardmediator.java
字号:
// Copyright (c) 2005 Sony Ericsson Mobile Communications AB
//
// This software is provided "AS IS," without a warranty of any kind.
// ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
// INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
//
// THIS SOFTWARE IS COMPLEMENTARY OF JAYWAY AB (www.jayway.se)
package bluegammon.logic;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import bluegammon.Audio;
import bluegammon.Device;
import bluegammon.Bluegammon;
import bluegammon.Resources;
import bluegammon.RmsFacade;
import bluegammon.gui.BoardCanvas;
import bluegammon.gui.popup.Popup;
/**
* <p>
* The <code>BoardMediator</code> class is active during a backgammon game. It takes care
* of coordination between <code>BoardState</code> and <code>BoardCanvas</code> i.e.
* between the gui and the logic. <code>BoardCanvas</code> is detached from any
* backgammon-logic - this connection is made by this class by implementing
* <code>BoardStateListener</code> to receive events upon board state changes. The
* <code>BoardMediator</code> then calls the <code>BoardCanvas</code> to update the gui
* when state changes.
* </p><p>
* In order to save the game at any time, but still have animations, the
* <code>BoardState</code> differs from the <code>BoardCanvas</code>: when the state
* is changed (e.g. a move is made), the <code>BoardState</code> is updated
* directly. The <code>BoardCanvas</code> has intermittent states; e.g. during an animation
* of a piece movement, one piece is "missing" from <code>BoardCanvas</code> board until
* the piece is put down.
* </p><p>
* This class is a simple coordinater, thus it does not have any state. The
* <code>BoardMediator</code> is accessed statically.
* <p>
*
* @see bluegammon.gui.BoardCanvas
* @see bluegammon.logic.BoardState
* @author Peter Andersson
*/
public class BoardMediator implements BoardStateListener
{
/**
* Starts the BoardMediator.
*/
public static void startup()
{
BoardState.getInstance().setGameListener(new BoardMediator());
}
/**
* Initiates a new or resumed game with specified players.
* @param p1 Player 1.
* @param p2 Player 2.
* @param resumed True if resumed, false if new game.
*/
public static void init(Player p1, Player p2, boolean resumed)
{
BoardState state = BoardState.getInstance();
BoardCanvas canvas = BoardCanvas.getInstance();
state.setPlayers(p1,p2);
state.setGameFinished(false);
if (!resumed)
{
int whiteDice = newDiceValue();
int blackDice = newDiceValue();
if (whiteDice == blackDice)
{
if (whiteDice > 3)
{
whiteDice--;
}
else
{
whiteDice++;
}
}
boolean whiteTurn = whiteDice > blackDice;
state.setStartPositions();
canvas.setStartPositions();
canvas.invalidate();
canvas.selectTurns(whiteDice, blackDice);
}
}
/**
* Shuts the BoardMediator down.
*/
public static void shutdown()
{
BoardCanvas.getInstance().shutdown();
}
// Actions
/**
* Called from interaction, moves a player piece.
* @param possibleMoveIndex How to move according to current BoardState
*/
public static void makePlayerMove(int possibleMoveIndex)
{
BoardState state = BoardState.getInstance();
int[][] moves = getPossibleMoves();
state.makeMove(
moves[possibleMoveIndex][BoardState.PM_SOUR],
moves[possibleMoveIndex][BoardState.PM_DEST],
isCurrentPlayerWhite());
int diceValIndex = moves[possibleMoveIndex][BoardState.PM_DICE];
int diceValue = state.getDiceValue(diceValIndex);
BoardCanvas.getInstance().consumeDiceValue(diceValue);
state.consumeDice(diceValIndex);
state.commitMove(isCurrentPlayerWhite(), diceValue);
}
/**
* Called from interaction, undoes the last move.
* Does nothing if there are no moves to undo.
*/
public static void undoLastMove()
{
BoardCanvas canvas = BoardCanvas.getInstance();
int oldSourceIdx = BoardState.getInstance().undoLastMove(isCurrentPlayerWhite());
canvas.setQueryCommit(false);
canvas.cursorNearestIndex(oldSourceIdx, 0);
canvas.updateUndoCommand();
canvas.updateCursor();
}
/**
* Called from interaction, commits players' moves.
*/
public static void commitTurn()
{
newTurn(!BoardMediator.isCurrentPlayerWhite());
BoardCanvas.getInstance().setQueryCommit(false);
}
/**
* Called from interaction and logic, changes turn.
*
* @param whiteTurn true if turn changes to white player, false otherwise.
*/
public static void newTurn(boolean whiteTurn)
{
if (!BoardState.getInstance().isGameFinished())
{
BoardState.getInstance().setTurn(whiteTurn);
Player p = BoardState.getInstance().getCurrentPlayer();
if (p instanceof LocalPlayer)
{
BoardCanvas.getInstance().setCurrentLocalPlayer((LocalPlayer)p);
}
else
{
BoardCanvas.getInstance().setCurrentLocalPlayer(null);
}
BoardState.getInstance().newDiceValues(
newDiceValue(), newDiceValue());
BoardCanvas.getInstance().throwDices(whiteTurn);
if (Bluegammon.getGameType() != Bluegammon.GAME_TYPE_LOCAL &&
!isRemoteTurn())
{
Device.vibrate(100,0,1);
}
}
}
/**
* Called from interaction, exits current game.
*
* @param reason An integer denoting the reason for quitting,
* one of <code>PlayerListener.LOCAL_QUIT</code>,
* <code>PlayerListener.REMOTE_QUIT,</code>
* <code>PlayerListener.LOCAL_GIVE_UP,</code>
* <code>PlayerListener.REMOTE_GIVE_UP</code>
*/
public synchronized static void exitGame(int reason)
{
if (reason == PlayerListener.LOCAL_GIVE_UP ||
reason == PlayerListener.REMOTE_GIVE_UP)
{
boolean localLoser = reason == PlayerListener.LOCAL_GIVE_UP;
boolean whiteWinner = !BoardMediator.getLocalPlayer().isWhite();
if (reason == PlayerListener.REMOTE_GIVE_UP)
{
whiteWinner = !whiteWinner;
Bluegammon.showPopup(Resources.getChars(Resources.TXT_REMOTE_GAVE_UP),
Popup.ALT_OK, 10, 0, 0, null);
}
int piecesLeft = BoardState.getInstance().calculatePiecesLeft(!whiteWinner);
int points = BoardState.getInstance().calculatePoints(!whiteWinner);
// Only show animation to the winning player, the player who gives up
// probably just want to quit
BoardMediator.finishGame(whiteWinner, piecesLeft, points, !localLoser);
if (localLoser)
{
Bluegammon.exitGame();
}
}
else if (reason == PlayerListener.REMOTE_QUIT)
{
if (!isGameFinished())
{
Bluegammon.showPopup(Resources.getChars(Resources.TXT_BT_REMOTE_QUIT),
Popup.ALT_OK, 0, 0, 0, null);
Bluegammon.exitGame();
}
}
else
{
if (Bluegammon.isShowingPopup())
{
Bluegammon.getCurrentPopup().dispose();
}
Bluegammon.exitGame();
}
}
/**
* Called from IO framework remote connection is lost in a
* remote game.
* @param e The exception that was
* the reason of losing connection.
*/
public synchronized static void lostRemoteConnection(IOException e)
{
if (!isGameFinished())
{
System.err.println("Lost remote connection!");
e.printStackTrace();
Audio.playSound(Audio.CONN_FAIL);
Bluegammon.showPopup(Resources.getChars(Resources.TXT_BT_CONN_LOST),
Popup.ALT_OK, 0, 0, 0, null);
Bluegammon.exitGame();
}
}
/**
* Called when remote player sent a message
* @param mess the message.
*/
public static void showMessage(char[] mess)
{
Device.vibrate(100,50,3);
Audio.playSound(Audio.MESSAGE);
mess =
(new String(getOpponentPlayer().getName()) + ":\n\n" + new String(mess)).toCharArray();
Bluegammon.showPopup(mess, null, 60, 0, 0, null);
}
/**
* Returns the player whos holding the turn, i.e. can make moves.
* This method returns null if current player has not yet been chosen,
* meaning that the first dice roll is still ongoing.
* @return The current player or null.
*/
public static Player getCurrentPlayer()
{
return BoardState.getInstance().getCurrentPlayer();
}
/**
* Returns opponent player. In case of local game, this method returns
* the player currently waiting for his or her turn. In a remote game,
* it returns the remote player.
*
* @return The opponent.
*/
public static Player getOpponentPlayer()
{
Player p1 = BoardState.getInstance().getCurrentPlayer();
Player p2 = BoardState.getInstance().getWaitingPlayer();
if (Bluegammon.getGameType() == Bluegammon.GAME_TYPE_LOCAL)
{
return p2;
}
else
{
return (p1 instanceof LocalPlayer) ? p2 : p1;
}
}
/**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -