Android Open Source - GhostStories Ghost Stories Game Manager






From Project

Back to project page GhostStories.

License

The source code is released under:

GNU General Public License

If you think the Android project GhostStories listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package games.ghoststories.data;
//w  w  w  .  j  a v a 2 s.c  om
import games.ghoststories.R;
import games.ghoststories.data.interfaces.IGamePhaseListener;
import games.ghoststories.data.interfaces.IGameTokenListener;
import games.ghoststories.data.interfaces.IGhostDeckListener;
import games.ghoststories.data.village.VillageTileData;
import games.ghoststories.enums.EBoardLocation;
import games.ghoststories.enums.EColor;
import games.ghoststories.enums.EDifficulty;
import games.ghoststories.enums.EGamePhase;
import games.ghoststories.enums.ETileLocation;
import games.ghoststories.enums.EVillageTile;
import games.ghoststories.utils.XmlUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

import android.content.Context;
import android.util.Log;

/**
 * Game manager responsible for managing and maintaining all necessary game
 * state. This state includes:
 * <li>Ghost Card Deck
 * <li>Exorcised Ghosts
 * <li>Player Data
 * <li>Game Board Information
 * <li>Token Supply
 * <br>
 *
 * The function {@link #initializeGame()} must be called at the start of the
 * game to setup all necessary game data.
 */
public class GhostStoriesGameManager {
   /**
    * Holds the static instance of the game manager
    */
   private static class INSTANCE_HOLDER {
      public static final GhostStoriesGameManager sInstance =
            new GhostStoriesGameManager();
   }

   /**
    * @return The static instance of the {@link GhostStoriesGameManager}
    */
   public static GhostStoriesGameManager getInstance() {
      return INSTANCE_HOLDER.sInstance;
   }

   /**
    * Add a listener to receive notifications when the number of tokens
    * in the token repository changes.
    * @param pListener
    */
   public void addGameTokenListener(IGameTokenListener pListener) {
      mGameTokenListeners.add(pListener);
   }

   /**
    * Add a listener to receive notifications when the game phase is updated
    * @param pListener
    */
   public void addGamePhaseListener(IGamePhaseListener pListener) {
      mGamePhaseListeners.add(pListener);
   }

   /**
    * Add a listener to receive notifications when the ghost deck is updated
    * @param pListener
    */
   public void addGhostDeckListener(IGhostDeckListener pListener) {
      mGhostDeckListeners.add(pListener);
   }

   /**
    * Increases the amount of available dice by 1
    */
   public void addDice() {
      mNumDice++;
   }

   /**
    * Advances the game to the next game phase. Will update to the next player's
    * turn if currently at the last phase.
    */
   public void advanceGamePhase() {
      //Save the state before advancing the game phase
      saveGame(false);

      boolean notify = true;
      PlayerData currentPlayer = getCurrentPlayerData();
      GameBoardData currentBoard = getCurrentPlayerBoard();
      switch(mGamePhase) {
      case TurnStart:
         mGamePhase = EGamePhase.YinPhase1A;
         if(getCurrentPlayerBoard().getNumHaunters() == 0) {
            //If the next player has no haunter to advance then skip to the
            //next phase
            notify = false;
            advanceGamePhase();
         }
         break;
      case YinPhase1A:
         mGamePhase = EGamePhase.YinPhase1B;
         if(currentBoard.getCursedDieRollCount() == 0) {
            //Don't need to roll the cursed die so skip to the next phase
            notify = false;
            advanceGamePhase();
         }
         break;
      case YinPhase1B:
         mGamePhase = EGamePhase.YinPhase2;
         if(!currentBoard.isBoardFilled()) {
            //No board overrun so skip to the next phase
            notify = false;
            advanceGamePhase();
         }
         break;
      case YinPhase2:
         mGamePhase = EGamePhase.YinPhase3;
         if(currentBoard.isBoardFilled()) {
            //There was a board overrun so do not draw a new ghost and
            //skip to the next phase
            notify = false;
            advanceGamePhase();
         }
         break;
      case YinPhase3:
         mGamePhase = EGamePhase.YangPhase1;
         break;
      case YangPhase1:
         mGamePhase = EGamePhase.YangPhase2;
         break;
      case YangPhase2:
         mGamePhase = EGamePhase.TaoistResolution;
         break;
      case TaoistResolution:
         mGamePhase = EGamePhase.YangPhase3;
         if(currentPlayer.getNumBuddhaTokens() == 0) {
            //If the player has no buddhas then skip to the next phase
            notify = false;
            advanceGamePhase();
         }
         break;
      case YangPhase3:
         mGamePhase = EGamePhase.TurnStart;
         updateCurrentPlayer();
         break;
      }

      //Notify listeners that the game phase has changed
      if(notify) {
         for(IGamePhaseListener listener : mGamePhaseListeners) {
            listener.gamePhaseUpdated(mGamePhase);
         }
      }
   }

   /**
    * @return The ghost deck data
    */
   public GhostDeckData getGhostDeckData() {
      return mGhostDeck;
   }

   /**
    * @return The ghost graveyard data
    */
   public GhostGraveyardData getGhostGraveyardData() {
      return mGhostGraveyard;
   }

   /**
    * @return The number of dice available to use. Does not take into account
    * player special abilities.
    */
   public int getNumDice() {
      return mNumDice;
   }

   /**
    * Called to initialize the game. Sets up all necessary game data before
    * returning. It is recommended to call this on a background thread to avoid
    * locking up the UI thread while the game sets itself up.
    * @param pDifficulty The difficulty of the game to initialize
    */
   public void initializeGame(EDifficulty pDifficulty, Context pContext) {
      mDifficulty = pDifficulty;
      mGamePhase = EGamePhase.TurnStart;
      mCurrentPlayerIndex = 0;
      mNumDice = 3;
      try {
         mGhostGraveyard = new GhostGraveyardData();
         List<GhostData> ghosts = XmlUtils.parseGhostXml(pContext, R.xml.ghosts);
         List<GhostData> incarnations = XmlUtils.parseGhostXml(pContext, R.xml.wufeng);

         //Initialize the supply of tokens
         initSupply();

         //Create the deck of ghost cards
         mGhostDeck = new GhostDeckData(mDifficulty, ghosts, incarnations);

         //Initialize the game boards
         initGameBoards(pContext);

         //Initialize the village tiles
         initVillageTiles(pContext);

         //Initialize the players
         initPlayerData();
         setupPlayerOrder();

      } catch (Exception pException) {
         Log.e("GhostStoriesGameManager", "Exception",  pException);
      }
   }

   /**
    * @return The current phase of the game
    */
   public EGamePhase getCurrentGamePhase() {
      return mGamePhase;
   }

   /**
    * Gets the {@link PlayerData} for the player whose turn it currently is
    * @return The {@link PlayerData} for the current player
    */
   public PlayerData getCurrentPlayerData() {
      return mPlayerData.get(mPlayerOrder.get(mCurrentPlayerIndex));
   }

   /**
    * Gets the {@link GameBoardData} for the current player
    * @return The {@link GameBoardData} for the current player
    */
   public GameBoardData getCurrentPlayerBoard() {
      return mGameBoards.get(getCurrentPlayerData().getColor());
   }

   /**
    * Gets the game board data for the passed in {@link EColor}
    * @param pColor The color to get the game board for
    * @return The {@link GameBoardData} for the specified color
    */
   public GameBoardData getGameBoard(EColor pColor) {
      return mGameBoards.get(pColor);
   }

   /**
    * Gets the game board at the specified {@link EBoardLocation}
    * @param pLocation The location to get the game board for
    * @return The {@link GameBoardData} at the specified location
    */
   public GameBoardData getGameBoard(EBoardLocation pLocation) {
      GameBoardData data = null;
      for(GameBoardData d : mGameBoards.values()) {
         if(d.getLocation() == pLocation) {
            data = d;
            break;
         }
      }
      return data;
   }

   /**
    * @return The map of game boards for the current game
    */
   public Map<EColor, GameBoardData> getGameBoards() {
      return Collections.unmodifiableMap(mGameBoards);
   }

   /**
    * Gets the player data for the specified {@link EColor}
    * @param pColor the color of the player data to get
    * @return The player data of the requested color
    */
   public PlayerData getPlayerData(EColor pColor) {
      return mPlayerData.get(pColor);
   }

   /**
    * Gets the players that are located on the specified tile
    * @param pTile The tile to get the players on
    * @return A list of players on the specified tile
    */
   public List<PlayerData> getPlayersOnTile(ETileLocation pTile) {
      List<PlayerData> players = new ArrayList<PlayerData>();
      for(PlayerData pd : mPlayerData.values()) {
         if(pd.getLocation() == pTile) {
            players.add(pd);
         }
      }
      return players;
   }

   /**
    * @return An unmodifiable list of player colors in the order that they take
    * turns.
    */
   public List<EColor> getPlayerOrder() {
      return Collections.unmodifiableList(mPlayerOrder);
   }

   /**
    * @return The token supply containing the remaining Tao Tokens and Qi Tokens
    * available to the players.
    */
   public TokenSupplyData getTokenSupply() {
      return mTokenSupply;
   }

   /**
    * Gets the village tile where the passed in player is currently at.
    * @param pColor The color of the player to get the tile for
    * @return The tile where the player is at
    */
   public VillageTileData getVillageTile(EColor pColor) {
      return mVillageTiles.get(mPlayerData.get(pColor).getLocation());
   }


   /**
    * Gets the village tile at the passed in {@link ETileLocation}
    * @param pLocation The location to get the tile for
    * @return The tile at the requested location
    */
   public VillageTileData getVillageTile(ETileLocation pLocation) {
      return mVillageTiles.get(pLocation);
   }

   /**
    * Gets the specified village tile.
    * @param pVillageTile The village tile to get
    */
   public VillageTileData getVillageTile(EVillageTile pVillageTile) {
      VillageTileData vtd = null;
      for(VillageTileData v : mVillageTiles.values()) {
         if(v.getType() == pVillageTile) {
            vtd = v;
            break;
         }
      }
      return vtd;
   }

   /**
    * @return The map of village tiles
    */
   public Map<ETileLocation, VillageTileData> getVillageTiles() {
      return Collections.unmodifiableMap(mVillageTiles);
   }

   /**
    * Decreases the amount of available dice by 1
    */
   public void removeDice() {
      mNumDice = Math.max(0, mNumDice - 1);
   }

   /**
    * Saves the current state of the game
    * @param pClearData Whether or not to clear the game data after saving
    */
   public void saveGame(boolean pClearData) {
      //TODO Figure out how to save the state

      if(pClearData) {
         mGhostDeck.dispose();
         mGhostGraveyard.dispose();
         for(GameBoardData gbd : mGameBoards.values()) {
            gbd.dispose();
         }
         mGameBoards.clear();
         for(PlayerData pd : mPlayerData.values()) {
            pd.dispose();
         }
         mPlayerData.clear();
         for(VillageTileData vtd : mVillageTiles.values()) {
            vtd.dipose();
         }
         mVillageTiles.clear();
         mGamePhaseListeners.clear();
         mGameTokenListeners.clear();
         mGhostDeckListeners.clear();
         mPlayerOrder.clear();
         mTokenSupply.dispose();
      }
   }

   /**
    * Initialize the game boards by parsing the xml of game boards and then
    * randomly choosing a single game board for each player color.
    * @param pContext The context used to initialize the game boards
    */
   private void initGameBoards(Context pContext) throws IOException {
      //Initialize the game boards
      Map<EColor, List<GameBoardData>> boards =
            XmlUtils.parseGameBoardXml(pContext, R.xml.gameboards);

      //Randomly choose a game board for each color
      List<GameBoardData> redBoards = boards.get(EColor.RED);
      List<GameBoardData> blueBoards = boards.get(EColor.BLUE);
      List<GameBoardData> greenBoards = boards.get(EColor.GREEN);
      List<GameBoardData> yellowBoards = boards.get(EColor.YELLOW);

      if(!redBoards.isEmpty() && !blueBoards.isEmpty() &&
            !greenBoards.isEmpty() && !yellowBoards.isEmpty()) {
         Random r = GhostStoriesConstants.sRandom;
         mGameBoards.put(EColor.RED, redBoards.get(r.nextInt(redBoards.size())));
         mGameBoards.put(EColor.BLUE, blueBoards.get(r.nextInt(blueBoards.size())));
         mGameBoards.put(EColor.GREEN, greenBoards.get(r.nextInt(greenBoards.size())));
         mGameBoards.put(EColor.YELLOW, yellowBoards.get(r.nextInt(yellowBoards.size())));
      }

      //Randomize the locations of the game boards
      List<EBoardLocation> locs = Arrays.asList(EBoardLocation.values());
      Collections.shuffle(locs);
      mGameBoards.get(EColor.RED).setLocation(locs.get(0));
      mGameBoards.get(EColor.BLUE).setLocation(locs.get(1));
      mGameBoards.get(EColor.GREEN).setLocation(locs.get(2));
      mGameBoards.get(EColor.YELLOW).setLocation(locs.get(3));
   }

   /**
    * Initializes the player data
    */
   private void initPlayerData() {
      mPlayerData.put(EColor.RED, createPlayerData("Red Player", EColor.RED));
      mPlayerData.put(EColor.BLUE, createPlayerData("Blue Player", EColor.BLUE));
      mPlayerData.put(EColor.YELLOW, createPlayerData("Yellow Player", EColor.YELLOW));
      mPlayerData.put(EColor.GREEN, createPlayerData("Green Player", EColor.GREEN));
   }

   /**
    * Initialize the supply of tokens
    */
   private void initSupply() {
      mTokenSupply = new TokenSupplyData();
      //There are 5 tokens of each color and 20 Qi tokens in the initial supply
      mTokenSupply.setNumQi(20);
      for(EColor color : EColor.values()) {
         mTokenSupply.setNumTaoTokens(color, 4);
      }
   }

   /**
    * Initialize the village tiles
    * @param pContext The context used to initialize the village tiles
    */
   private void initVillageTiles(Context pContext) {
      //Initialize the village tiles
      List<VillageTileData> tiles =
            XmlUtils.parseVillageXml(pContext, R.xml.village);
      //Randomly order the tiles
      Collections.shuffle(tiles);

      //TODO Error check this
      ETileLocation tileLocs[] = ETileLocation.values();
      for(int i = 0; i < tileLocs.length; ++i) {
         ETileLocation loc = tileLocs[i];
         VillageTileData villageTile = tiles.get(i);
         villageTile.setLocation(loc);
         mVillageTiles.put(loc, villageTile);
      }
   }

   /**
    * Creates a {@link PlayerData} using the given color and name and based on
    * the currently set difficulty level.
    * @param pName The name of the player to create
    * @param pColor The color of the player
    * @return The created player data
    */
   private PlayerData createPlayerData(String pName, EColor pColor) {
      PlayerData pd = new PlayerData(pName, pColor, mGameBoards.get(pColor));

      //Initialize the player data based on the current difficulty
      switch(mDifficulty) {
      case INITIATE:
         pd.setNumQi(4);
         mTokenSupply.removeQi(4);
         pd.setNumTaoTokens(EColor.BLACK, 1);
         mTokenSupply.removeTaoToken(EColor.BLACK);
         pd.setNumTaoTokens(pColor, 1);
         mTokenSupply.removeTaoToken(pColor);
         break;
      case NORMAL:
      case NIGHTMARE:
         pd.setNumQi(3);
         mTokenSupply.removeQi(3);
         pd.setNumTaoTokens(pColor, 1);
         mTokenSupply.removeTaoToken(pColor);
         break;
      case HELL:
         pd.setNumQi(3);
         mTokenSupply.removeQi(3);
         pd.setNumTaoTokens(pColor, 1);
         mTokenSupply.removeTaoToken(pColor);
         pd.setYinYangAvailable(false);
         break;
      }

      return pd;
   }

   /**
    * Sets up the order of the player's turns
    */
   private void setupPlayerOrder() {
      mPlayerOrder.add(getGameBoard(EBoardLocation.BOTTOM).getColor());
      mPlayerOrder.add(getGameBoard(EBoardLocation.LEFT).getColor());
      mPlayerOrder.add(getGameBoard(EBoardLocation.TOP).getColor());
      mPlayerOrder.add(getGameBoard(EBoardLocation.RIGHT).getColor());
   }

   /**
    * Updates the current player to the next one
    */
   private void updateCurrentPlayer() {
      mCurrentPlayerIndex++;
      if(mCurrentPlayerIndex >= mPlayerOrder.size()) {
         mCurrentPlayerIndex = 0;
      }
   }

   /**
    * Constructor
    */
   private GhostStoriesGameManager() {
   }

   /** The current difficulty level **/
   private EDifficulty mDifficulty;
   /** The deck of ghost cards **/
   private GhostDeckData mGhostDeck;
   /** The ghosts in the ghost graveyard **/
   private GhostGraveyardData mGhostGraveyard;
   /** The player game boards **/
   private final Map<EColor, GameBoardData> mGameBoards =
         new EnumMap<EColor, GameBoardData>(EColor.class);
   /** The player data **/
   private final Map<EColor, PlayerData> mPlayerData =
         new EnumMap<EColor, PlayerData>(EColor.class);
   /** The village tiles **/
   private final Map<ETileLocation, VillageTileData> mVillageTiles =
      new EnumMap<ETileLocation, VillageTileData>(ETileLocation.class);

   /** The current game phase **/
   private EGamePhase mGamePhase;
   /** Listeners for game phase updates **/
   private final Set<IGamePhaseListener> mGamePhaseListeners =
         new CopyOnWriteArraySet<IGamePhaseListener>();
   /** Listeners for game token updates **/
   private final Set<IGameTokenListener> mGameTokenListeners =
         new CopyOnWriteArraySet<IGameTokenListener>();
   /** Listeners for ghost deck updates **/
   private final Set<IGhostDeckListener> mGhostDeckListeners =
         new CopyOnWriteArraySet<IGhostDeckListener>();
   /** The index of the current player **/
   private int mCurrentPlayerIndex = 0;
   /** The order of player turns **/
   private final List<EColor> mPlayerOrder = new ArrayList<EColor>();

   /** The number of dice available to the player **/
   private int mNumDice = 3;

   /** The token supply **/
   private TokenSupplyData mTokenSupply;
}




Java Source Code List

com.drawable.shapes.GradientRectangle.java
com.interfaces.IDraggable.java
com.utils.AndroidUtils.java
com.utils.AnimationUtils2.java
com.utils.ImageLoadingTask.java
com.utils.ImageRotationTask.java
com.utils.ImageViewUtils.java
com.views.NumberedImageView.java
com.views.ToggledImageView.java
com.views.layouts.ScaledLinearLayout.java
com.views.layouts.ScaledRelativeLayout.java
com.views.layouts.SquareGridLayout.java
com.views.layouts.SquareLinearLayout.java
com.views.layouts.SquareTableLayout.java
com.views.layouts.ZoomableRelativeLayout.java
com.views.listeners.DragTouchListener.java
games.ghoststories.activities.GameLoadingActivity.java
games.ghoststories.activities.GameScreenActivity.java
games.ghoststories.activities.TitleActivity.java
games.ghoststories.controllers.GhostDeckController.java
games.ghoststories.controllers.HaunterController.java
games.ghoststories.controllers.PlayerBoardCardController.java
games.ghoststories.controllers.VillageTileController.java
games.ghoststories.controllers.combat.CombatAreaController.java
games.ghoststories.controllers.combat.DiceDragListener.java
games.ghoststories.controllers.combat.GhostDragListener.java
games.ghoststories.controllers.combat.TaoTokenDragListener.java
games.ghoststories.data.DragData.java
games.ghoststories.data.GameBoardData.java
games.ghoststories.data.GhostData.java
games.ghoststories.data.GhostDeckData.java
games.ghoststories.data.GhostGraveyardData.java
games.ghoststories.data.GhostStoriesBitmaps.java
games.ghoststories.data.GhostStoriesConstants.java
games.ghoststories.data.GhostStoriesGameManager.java
games.ghoststories.data.PlayerData.java
games.ghoststories.data.TokenSupplyData.java
games.ghoststories.data.interfaces.IGameBoardListener.java
games.ghoststories.data.interfaces.IGamePhaseListener.java
games.ghoststories.data.interfaces.IGameTokenListener.java
games.ghoststories.data.interfaces.IGhostDeckListener.java
games.ghoststories.data.interfaces.IGhostListener.java
games.ghoststories.data.interfaces.ITokenListener.java
games.ghoststories.data.interfaces.IVillageTileListener.java
games.ghoststories.data.village.BuddhistTempleTileData.java
games.ghoststories.data.village.CircleOfPrayerTileData.java
games.ghoststories.data.village.VillageTileDataFactory.java
games.ghoststories.data.village.VillageTileData.java
games.ghoststories.enums.EBoardLocation.java
games.ghoststories.enums.ECardLocation.java
games.ghoststories.enums.EColor.java
games.ghoststories.enums.ECombatPhase.java
games.ghoststories.enums.EDiceSide.java
games.ghoststories.enums.EDice.java
games.ghoststories.enums.EDifficulty.java
games.ghoststories.enums.EDragItem.java
games.ghoststories.enums.EGamePhase.java
games.ghoststories.enums.EGhostAbility.java
games.ghoststories.enums.EHaunterLocation.java
games.ghoststories.enums.EPlayerAbility.java
games.ghoststories.enums.ETileLocation.java
games.ghoststories.enums.EVillageTile.java
games.ghoststories.fragments.AuxAreaFragment.java
games.ghoststories.fragments.GameboardFragment.java
games.ghoststories.utils.BitmapUtils.java
games.ghoststories.utils.GameUtils.java
games.ghoststories.utils.XmlUtils.java
games.ghoststories.views.GameScreen.java
games.ghoststories.views.aux_area.CardInfoView.java
games.ghoststories.views.aux_area.GamePhaseDetailsView.java
games.ghoststories.views.aux_area.GamePhaseView.java
games.ghoststories.views.aux_area.GhostDeckView.java
games.ghoststories.views.aux_area.GhostGraveyardCardView.java
games.ghoststories.views.aux_area.PlayerInfoView.java
games.ghoststories.views.combat.CombatDamageView.java
games.ghoststories.views.combat.CombatDiceAreaView.java
games.ghoststories.views.combat.CombatDiceView.java
games.ghoststories.views.combat.CombatGhostView.java
games.ghoststories.views.combat.CombatInstructionsView.java
games.ghoststories.views.combat.CombatRollView.java
games.ghoststories.views.combat.CombatView.java
games.ghoststories.views.combat.ExtraCombatDiceView.java
games.ghoststories.views.combat.GhostHealthView.java
games.ghoststories.views.common.AbstractNumberedTokenView.java
games.ghoststories.views.common.BuddhaTokenView.java
games.ghoststories.views.common.QiTokenView.java
games.ghoststories.views.common.TaoTokenView.java
games.ghoststories.views.common.YinYangTokenView.java
games.ghoststories.views.gameboard.PlayerAreaView.java
games.ghoststories.views.gameboard.PlayerBoardCardView.java
games.ghoststories.views.gameboard.PlayerBoardView.java
games.ghoststories.views.gameboard.PlayerTokenAreaView.java
games.ghoststories.views.gameboard.VillageTileView.java
games.ghoststories.views.graveyard.GraveyardScrollView.java
games.ghoststories.views.graveyard.GraveyardView.java
games.ghoststories.views.title.TitleButton.java
games.ghoststories.views.title.TitleScreen.java
games.ghoststories.views.village.CircleOfPrayerView.java