/// <summary>Moves all seeds into the respective Kalahs.</summary> public Move CollectFinalSeeds(Player firstPlayer, Player secondPlayer) { Move move = new Move(); Player currentPlayer = firstPlayer; for (int playerIndex = 0; playerIndex < 2; ++playerIndex) { Pit currentPlayersKalah = GetKalahOfPlayer(currentPlayer); int internalIndexOfKalah = GetInternalIndexOfKalah(currentPlayer); for (int pitIndex = 0; pitIndex < _numHousesPerPlayer; ++pitIndex) { Pit currentPit = GetPitOfPlayer(currentPlayer, pitIndex); if (currentPit.GetNumberofSeeds() > 0) { int currentPitsInternalIndex = GetInternalPitIndex(currentPlayer, pitIndex); move.AddSeedMovement(new SeedMovement(currentPitsInternalIndex, internalIndexOfKalah, currentPit.GetNumberofSeeds())); currentPlayersKalah.AddSeeds(currentPit.GetNumberofSeeds()); currentPit.RemoveAllSeeds(); } } currentPlayer = secondPlayer; } return move; }
/// <summary> /// Returns the next undo move to be taken together with the player whose turn it is after that move. /// The undo move is removed from the internal list of the UndoManager. /// </summary> /// <param name="undoMove">The move to undo the last move that one of the two players made.</param> /// <param name="nextPlayer">The player whose turn it is after the undoMove</param> public void GetNextUndoMove(ref Move undoMove, ref Player nextPlayer) { if (_moveList.Count == 0) { throw new PSTException("UndoManager.GetNextUndoMove: No move left."); } // Store the respective first elements of the internal lists in the reference parameters: undoMove = _moveList[0]; nextPlayer = _playerList[0]; // Remove both entries from the lists: _moveList.RemoveAt(0); _playerList.RemoveAt(0); }
/// <summary>Selects the given house and distributes the seeds of that house among /// the following pits, one seed per pit. Takes into account the direction of sowing, depending on the rules.</summary> /// <param name="player">The player whose pit is to be moved</param> /// <param name="houseIndexToBeMoved">The index of the house to be moved</param> /// <param name="lastSeedFellInOwnKalah">A reference parameter which gets the information whether the /// <param name="lastSeedFellIntoEmptyOwnHouse">A reference parameter which gets the information whether the /// last seed fell into empty pit that is owned by the player.</param> /// <param name="lastSeedsHouse">If "lastSeedFellIntoEmptyOwnHouse" is true, then this reference parameter /// gets the index of the house that the last seed fell into. Otherwise "lastSeedsHouse" gets the value -1 (for "undefined"). /// <exception cref="KalahaException">Index out of range</exception> public Move MoveHouse(Player player, int houseIndexToBeMoved, ref bool lastSeedFellIntoOwnKalah, ref bool lastSeedFellIntoEmptyOwnHouse, ref int lastSeedsHouse, bool returnMove) { if ((houseIndexToBeMoved < 0) || (houseIndexToBeMoved >= _numHousesPerPlayer)) { throw new PSTException("MovePit: houseIndex out of range: " + houseIndexToBeMoved); } lastSeedFellIntoOwnKalah = false; lastSeedFellIntoEmptyOwnHouse = false; lastSeedsHouse = -1; // Create a move object if this is requested by the caller of the method: Move move = null; if (returnMove) { move = new Move(); } // Calculate the array index of the house from which we take the seeds out: int internalHouseIndex = houseIndexToBeMoved + (player.GetId() * (_numHousesPerPlayer + 1)); // Keep the number of seeds to be distributed in mind: int numOfSeeds = _pit[internalHouseIndex].GetNumberofSeeds(); // The distribution of seeds is done in a fast way, using the internal array structure. // Find out about the sowing direction: It is clockwise if the rule is simply defined that way or if the rule // is set to "Cross-Kalah" and the number of seeds is odd: bool sowingDirectionIsClockwise = ((Rules.I.GetDirectionOfSowing() == Rules.DirectionOfSowing.Clockwise) || ((Rules.I.GetDirectionOfSowing() == Rules.DirectionOfSowing.CrossKalah) && ((numOfSeeds % 2) == 1))); // Empty the pit we start from: _pit[internalHouseIndex].RemoveAllSeeds(); // Distribute the seeds: int maybeOneMore = 0; Pit kalahOfOpponent = GetKalahOfOpponent(player); int loopIndex = 0; for (; loopIndex < numOfSeeds+maybeOneMore; ++loopIndex) { // Depending on the sowing direction, we set the index of the pit that gets a seed accordingly: int pitIndex = -1; if (sowingDirectionIsClockwise) { pitIndex = (internalHouseIndex + 10*_numPitsInTotal - loopIndex - 1) % _numPitsInTotal; } else { pitIndex = (internalHouseIndex + 1 + loopIndex) % _numPitsInTotal; } if (_pit[pitIndex] != kalahOfOpponent) { // This is not the Kalah of the opponent --> Add a seed: _pit[pitIndex].AddASeed(); if (returnMove) { // Store this step in the move: move.AddSeedMovement(new SeedMovement(internalHouseIndex, pitIndex, 1)); } } else { // This is the opponent's Kalah --> Do not add a seed but instead increase the loop by 1: ++maybeOneMore; } } // Calculate which pit the last seed fell into, depending on the sowing direction: int pitOfLastSeed = -1; if (sowingDirectionIsClockwise) { pitOfLastSeed = (internalHouseIndex + 10*_numPitsInTotal - loopIndex) % _numPitsInTotal; } else { pitOfLastSeed = (internalHouseIndex + loopIndex) % _numPitsInTotal; } lastSeedFellIntoOwnKalah = (_pit[pitOfLastSeed] == GetKalahOfPlayer(player)); if (!lastSeedFellIntoOwnKalah) { // Check whether the last seed fell into an empty own pit: if ((_pit[pitOfLastSeed].GetNumberofSeeds() == 1) && IsPlayersOwnPit(player, pitOfLastSeed)) { // Yes, it did. lastSeedFellIntoEmptyOwnHouse = true; // We have to calculate the player's pit from the internal pit: lastSeedsHouse = pitOfLastSeed % (_numHousesPerPlayer + 1); } } return move; }
/// <param name="player">The player whose Kalah coordinates are requested</param> /// <returns>The center coordinate on the "1000-page" of the given player</returns> public Point GetTopLeftCornerOfKalah(Player player) { // Take over the numer of pits in order not to call the method each time: int numPits = _gameBoard.GetNumOfHousesPerPlayer(); // Set the internal index of the first pit in the row: int internalStartIndex = ((player.GetPosition() == Player.Position.South) ? 0 : (numPits + 1)); return (_pit[internalStartIndex + numPits].GetTopLeftCorner()); }
/// <summary>Logs the board contents for debug purposes.</summary> public void LogBoard(Player firstPlayer, Player secondPlayer, Logging.LogLevel logLevel) { if ((Logging.I.GetLogLevel() & logLevel) == Logging.LogLevel.Off) { // Small optimization to leave as soon as possible if logging is not active anyway. return; } if (firstPlayer == secondPlayer) { Logging.I.LogMessage("LogBoard: first and second player are the same: " + firstPlayer + ".\n"); return; } // We find out who of the players is south and who is north; Player south = null; Player north = null; if (firstPlayer.GetPosition() == Player.Position.South) { south = firstPlayer; north = secondPlayer; } else { south = secondPlayer; north = firstPlayer; } // Now we start building up the log string: string logString = ("Game board:\n "); for (int pitIndex = _numHousesPerPlayer - 1; pitIndex >= 0; --pitIndex) { int numberOfSeeds = GetPitOfPlayer(north, pitIndex).GetNumberofSeeds(); if (numberOfSeeds < 10) { logString += " "; } logString += numberOfSeeds + " "; } logString += "\n " + GetKalahOfPlayer(north).GetNumberofSeeds(); for (int index = 0; index < ((3*_numHousesPerPlayer)+3); ++index) { logString += " "; } logString += (GetKalahOfPlayer(south).GetNumberofSeeds() + "\n "); for (int pitIndex = 0; pitIndex < _numHousesPerPlayer; ++pitIndex) { int numberOfSeeds = GetPitOfPlayer(south, pitIndex).GetNumberofSeeds(); if (numberOfSeeds < 10) { logString += " "; } logString += numberOfSeeds + " "; } Logging.I.LogMessage(logString + "\n", logLevel); }
/// <returns>The pit with the given number of the given player</returns> /// <param name="player">The player whose pit is asked for</param> /// <param name="pitIndex">The index of the pit whose internal index is to be returned</param> private int GetInternalPitIndex(Player player, int pitIndex) { if ((pitIndex < 0) || (pitIndex >= _numHousesPerPlayer)) { throw new PSTException("GameBoard.GetInternalPitIndex: pitIndex out of range: " + pitIndex); } return (pitIndex + (player.GetId() * (_numHousesPerPlayer + 1))); }
/// <summary> /// Sets the pit with the given index to state "selected" by making visible the according image. /// Sets all other pits unselected. Sets all pits unhighlighted. /// </summary> /// <param name="pitIndexSelected"></param> public void SetSelected(int pitIndexSelected, Player currentPlayer) { int numHouses = GetNumOfHousesPerPlayer(); if (currentPlayer.GetPosition() == Player.Position.North) { pitIndexSelected += numHouses + 1; } for (int pitIndex = 0; pitIndex < numHouses*2+1; ++pitIndex) { if (pitIndex == numHouses) { // Skip the Kalah: continue; } // Unhighlight the pits in any case: UnHighlight(pitIndex); if (pitIndex == pitIndexSelected) { _pit[pitIndex].SetSelected(); } else { _pit[pitIndex].SetUnSelected(); } } }
/// <summary> /// The given player wins his own pit (given by "ownPitIndex") and the opposite pit. Both pit's contents move into /// the player's Kalah.</summary> /// <param name="player">The player who wins the pit's contents</param> /// <param name="ownPitIndex">The index of the player's pit</param> /// <param name="captureOpponentsHouse">A flag whether the seeds in the opponent's house may be captured, too</param> /// <param name="returnMove">A flag whether or not to return the move in detail</param> /// <returns>The details of this move</returns> public Move PlayerWinsHouses(Player player, int ownPitIndex, bool captureOpponentsHouse, bool returnMove) { Pit ownPit = GetPitOfPlayer(player, ownPitIndex); Pit kalahToBeFilled = GetKalahOfPlayer(player); int internalKalahIndex = -1; // Only used when generating a Move Move move = null; if (returnMove) { move = new Move(); internalKalahIndex = GetInternalIndexOfKalah(player); } if (captureOpponentsHouse) { // Also the opponent's house shall be captured. Pit opponentsPit = GetOppositeHouse(player, ownPitIndex); if (returnMove) { // Move the opponent's seeds to the player's Kalah: move.AddSeedMovement(new SeedMovement(GetInternalIndexOfOppositeHouse(player, ownPitIndex), internalKalahIndex, opponentsPit.GetNumberofSeeds())); } kalahToBeFilled.AddSeeds(opponentsPit.GetNumberofSeeds()); opponentsPit.RemoveAllSeeds(); } if (returnMove) { // Move the one seed from the own house into the player's Kalah: move.AddSeedMovement(new SeedMovement(GetInternalPitIndex(player, ownPitIndex), internalKalahIndex, 1)); } // Fill the own Kalah with the own seed and remove the own seed from the house: kalahToBeFilled.AddSeeds(1); ownPit.RemoveAllSeeds(); return move; }
/// <returns>The internal index of the Kalah for the given player</returns> /// <param name="player">The player whose Kalah's internal index is asked for</param> private int GetInternalIndexOfKalah(Player player) { return (_numHousesPerPlayer + (player.GetId() * (_numHousesPerPlayer + 1))); }
/// <summary> /// Restores the stuff that is stored for the players. /// If no saved data can be found or an exception occurs, nothing is done and the current settings of the players are kept unchanged. /// </summary> private void RestorePlayersValues(ref Player southPlayer, ref Player northPlayer) { // Retrieve the settings from the ApplicationData.Current.RoamingGameStorage: ApplicationDataCompositeValue playersGroup_GameStorage = (ApplicationDataCompositeValue)_roamingSettings.Values[_playersStorageName]; if (playersGroup_GameStorage != null) { try { // We found some settings! //DEBUG Logging.I.LogMessage("GameStorage.RestorePlayersValues: Found saved data.\n"); // Restore the human player's names: southPlayer.SetName((string)playersGroup_GameStorage[_playersKey_humanNameSouth]); northPlayer.SetName((string)playersGroup_GameStorage[_playersKey_humanNameNorth]); // Restore the species and the computer's strength: southPlayer.SetSpecies((Player.Species)playersGroup_GameStorage[_playersKey_speciesSouth], (Player.ComputerStrength)playersGroup_GameStorage[_playersKey_computerStrengthSouth]); northPlayer.SetSpecies((Player.Species)playersGroup_GameStorage[_playersKey_speciesNorth], (Player.ComputerStrength)playersGroup_GameStorage[_playersKey_computerStrengthNorth]); } catch (Exception ex) { // In the case of not reading the player settings correctly we do nothing: Logging.I.LogMessage("GameStorage.RestorePlayersValues: Exception: " + ex.Message + "\n", Logging.LogLevel.Error); } } else { //DEBUG Logging.I.LogMessage("GameStorage.RestorePlayersValues: No saved data found.\n"); } }
/// <summary> /// Saves the stuff that is stored in the players' settings. /// </summary> private void SavePlayersValues(Player southPlayer, Player northPlayer) { ApplicationDataCompositeValue playersGroup_GameStorage = new ApplicationDataCompositeValue(); // Save the human player's names: playersGroup_GameStorage[_playersKey_humanNameSouth] = southPlayer.GetHumansName(); playersGroup_GameStorage[_playersKey_humanNameNorth] = northPlayer.GetHumansName(); // Save the currently set species: playersGroup_GameStorage[_playersKey_speciesSouth] = (int)southPlayer.GetSpecies(); playersGroup_GameStorage[_playersKey_speciesNorth] = (int)northPlayer.GetSpecies(); // Save the currently set computer's strength: playersGroup_GameStorage[_playersKey_computerStrengthSouth] = (int)southPlayer.GetComputerStrength(); playersGroup_GameStorage[_playersKey_computerStrengthNorth] = (int)northPlayer.GetComputerStrength(); // Save all stuff at once now: _roamingSettings.Values[_playersStorageName] = playersGroup_GameStorage; }
/// <summary> /// Restores previously saved values in the respective objects. If no saved values could be found, the defaults are set. /// </summary> public void RestoreSavedValues(ref Player southPlayer, ref Player northPlayer, ref string themeName) { RestoreThemesValues(ref themeName); RestoreSettingsValues(); RestorePlayersValues(ref southPlayer, ref northPlayer); RestoreRulesValues(); }
/// <summary> /// Saves all settings. /// </summary> public void Save(Player southPlayer, Player northPlayer, string currentThemeName) { SaveThemesValues(currentThemeName); SaveSettingsValues(); SavePlayersValues(southPlayer, northPlayer); SaveRulesValues(); }
/// <summary> /// Switches the indicator to the player whose turn it is. /// </summary> /// <param name="currentPlayer">The player whose turn it is</param> public void SwitchVisualIndicators(Player currentPlayer) { if (currentPlayer.GetPosition() == Player.Position.South) { _visualIndicatorSouth.SwitchOn(); _visualIndicatorNorth.SwitchOff(); PlayerNameFieldSouth.Foreground = Application.Current.Resources["GamePageTextOn"] as SolidColorBrush; PlayerNameFieldNorth.Foreground = Application.Current.Resources["GamePageTextOff"] as SolidColorBrush; } else { _visualIndicatorSouth.SwitchOff(); _visualIndicatorNorth.SwitchOn(); PlayerNameFieldSouth.Foreground = Application.Current.Resources["GamePageTextOff"] as SolidColorBrush; PlayerNameFieldNorth.Foreground = Application.Current.Resources["GamePageTextOn"] as SolidColorBrush; } }
/// <summary> /// Prints a message to the screen at the center position, using a globalized string taken from the corresponding resource file. /// This message does not vanish. /// </summary> /// <param name="messageKey">The resource key to be used</param> /// <param name="relevantPlayer">The player whose turn it is currently</param> /// <param name="args">0 or more parameters for the resource key</param> public void PrintFixedMsg(String messageKey, Player relevantPlayer, params object[] args) { string message = KalahaResources.I.GetMsg(messageKey, args); FixedMessageFieldCenter.Text = message; if ((relevantPlayer.GetPosition() == Player.Position.North) && Presenter.I.TabletModeIsActive()) { // Put the words upside down in order for the current player to be easily readable: // Define the angle of the visual indicator: FixedMessageFieldCenter.RenderTransformOrigin = new Point(0.5, 0.5); // Rotate around the center RotateTransform myRotateTransform = new RotateTransform(); // Put the name upside down if we are told to do so: myRotateTransform.Angle = 180; FixedMessageFieldCenter.RenderTransform = myRotateTransform; } }
/// <summary> /// Prints a message to the screen at the center position, using a globalized string taken from the corresponding resource file. /// This message automatically vanishes after a few seconds. /// </summary> /// <param name="messageKey">The resource key to be used</param> /// <param name="relevantPlayer">The player whose turn it is currently</param> /// <param name="args">0 or more parameters for the resource key</param> public async void PrintFadingMsg(String messageKey, Player relevantPlayer, params object[] args) { string message = KalahaResources.I.GetMsg(messageKey, args); MessageFieldCenter.Text = message; // Define the angle of the visual indicator: MessageFieldCenter.RenderTransformOrigin = new Point(0.5, 0.5); // Rotate around the center RotateTransform myRotateTransform = new RotateTransform(); if ((relevantPlayer.GetPosition() == Player.Position.North) && Presenter.I.TabletModeIsActive()) { // Put the name upside down if we are told to do so: myRotateTransform.Angle = 180; } else { // Leave the name in the "usual" angle: myRotateTransform.Angle = 0; } MessageFieldCenter.RenderTransform = myRotateTransform; // Print the actual message to the screen by fading in: await MessageFieldCenter.FadeIn(TimeSpan.FromMilliseconds(1500)); // The parameter defines the time that the message is visible // ... and out: await MessageFieldCenter.FadeOut(TimeSpan.FromMilliseconds(200)); }
/// <returns>True if the given player has no only empty houses left</returns> /// <param name="player">The player whose houses are to be checked</param> public bool PlayerOnlyHasEmptyHouses(Player player) { return (!PlayerStillHasFullHouses(player)); }
/// <returns>The Kalah of the given player's opponent</returns> /// <param name="player">The player whose opponent's Kalah is asked for.</param> public Pit GetKalahOfOpponent(Player player) { return _pit[_numHousesPerPlayer + (((player.GetId()+1)%2) * (_numHousesPerPlayer + 1))]; }
/// <returns>True if the given player has at least one house that still contains seeds</returns> /// <param name="player">The player whose houses are to be checked</param> public bool PlayerStillHasFullHouses(Player player) { int playersId = player.GetId(); for (int pitIndex = 0; pitIndex < _numHousesPerPlayer; ++pitIndex) { if (_pit[pitIndex + (playersId * (_numHousesPerPlayer + 1))].GetNumberofSeeds() > 0) { return true; } } // We walked through all pits and found no filled one: return false; }
/// <returns>The Kalah of the given player</returns> /// <param name="player">The player whose Kalah is asked for.</param> public Pit GetKalahOfPlayer(Player player) { return _pit[GetInternalIndexOfKalah(player)]; }
/// <param name="player"></param> /// <returns>The sum of all seeds that the given player currently has in their pits</returns> public int SumOfAllSeedsOfPlayer(Player player) { int sum = 0; for (int pitIndex = 0; pitIndex < _numHousesPerPlayer; ++pitIndex) { Pit currentPit = GetPitOfPlayer(player, pitIndex); sum += currentPit.GetNumberofSeeds(); } return sum; }
/// <summary> /// Remembers the given move as a "normal" by the given player. /// </summary> /// <param name="move">The move to remember</param> /// <param name="currentPlayer">The player who made the move</param> public void RememberNormalNove(Move move, Player currentPlayer) { // A "normal" move is quite easy to remember: We store a new list entry with the move's "backward move". // Get the move's backward move: Move backMove = move.GetBackwardMove(); // Add the backward move and the current player at the beginnings of the respecive lists: _moveList.Insert(0, backMove); _playerList.Insert(0, currentPlayer); }
/// <returns>The pit that lies on the opposite side of the given pit number and the given player</returns> /// <param name="player">The player whose pit is asked for</param> /// <param name="houseIndex">The index of the house whose opposite house index is to be returned</param> private int GetInternalIndexOfOppositeHouse(Player player, int houseIndex) { if ((houseIndex < 0) || (houseIndex >= _numHousesPerPlayer)) { throw new PSTException("GameBoard.GetInternalIndexOfOppositePit: houseIndex out of range: " + houseIndex); } return (2 * _numHousesPerPlayer - (houseIndex + (player.GetId() * (_numHousesPerPlayer + 1)))); }
/// <summary> /// Remembers the given move as a move that has to be added to the last "normal" move of the same player. /// This is supposed to be used for capture moves or "final" moves. /// </summary> /// <param name="move">The move to remember</param> /// <param name="currentPlayer">The player who made the move</param> public void RememberFollowUpMove(Move move, Player currentPlayer) { // We need an existing player list: if (_playerList.Count == 0) { throw new PSTException("UndoManager.RememberFollowUpMove: player list is empty."); } // We need an existing move list: if (_moveList.Count == 0) { throw new PSTException("UndoManager.RememberFollowUpMove: move list is empty."); } // We can only add a follow-up move for the same player as exists as the first entry in the list of players: if (_playerList[0] != currentPlayer) { throw new PSTException("UndoManager.RememberFollowUpMove: Unexpected player: " + currentPlayer + ". Expected " + _playerList[0] + "."); } // Get the move's backward move: Move backMove = move.GetBackwardMove(); // Integrate the backward move into the move that is the first in the already existing list of "undo moves": _moveList[0].IntegrateMove(backMove); }
/// <returns>The house which is located to the opposite of the given pit</returns> /// <param name="player">The player whose house is given</param> /// <param name="houseIndex">The index of the house whose opposite house is to be returned</param> /// <exception cref="PSTException">Index out of range</exception> public Pit GetOppositeHouse(Player player, int houseIndex) { return _pit[GetInternalIndexOfOppositeHouse(player, houseIndex)]; }
/// <param name="player">The player whose pit coordinates are requested</param> /// <param name="pitIndex">The index of the pit. May be between 0 and the number of pits-1.</param> /// <returns>The center coordinate on the "1000-page" of the given pit</returns> public Point GetTopLeftCornerOfPit(Player player, int pitIndex) { // Take over the numer of pits in order not to call the method each time: int numPits = GetNumOfHousesPerPlayer(); if (pitIndex >= numPits) { throw new PSTException("GetCenterOfPit: Unknown pitIndex: " + pitIndex); } // Set the internal index of the first pit in the row: int internalStartIndex = ((player.GetPosition() == Player.Position.South) ? 0 : (numPits + 1)); return (_pit[internalStartIndex + pitIndex].GetTopLeftCorner()); }
/// <returns>The pit with the given number of the given player</returns> /// <param name="player">The player whose pit is asked for</param> /// <param name="pitIndex">The index of the pit to be returned</param> /// <exception cref="PSTException">Index out of range</exception> public Pit GetPitOfPlayer(Player player, int pitIndex) { return _pit[GetInternalPitIndex(player, pitIndex)]; }
/// <returns>True if the given pit is one of the player's pits</returns> /// <param name="player">The player whose pit is to be checked</param> /// <param name="pitIndex">The pit's index which can have a range from 0 to _numPitsInTotal-1, i.e. the complete array</param> public bool IsPlayersOwnPit(Player player, int pitIndex) { if ((pitIndex < 0) || (pitIndex >= _numPitsInTotal)) { throw new PSTException("PlayerOwnsPit: pitIndex out of range: " + pitIndex); } return ((pitIndex >= (player.GetId() * (_numHousesPerPlayer + 1))) && (pitIndex < ((player.GetId() * (_numHousesPerPlayer + 1)) + _numHousesPerPlayer))); }
/// <summary> /// Returns the recursion depth for the calculation of a move, depending on the computer's strength and the number of houses /// </summary> /// <param name="compStrength">The computer's strength</param> /// <param name="numOfHouses">The number of houses per player (may have values 3 through 7)</param> /// <returns></returns> public int GetRecursionDepth(Player.ComputerStrength compStrength, int numOfHouses) { if ((numOfHouses < 3) || (numOfHouses > 7)) { throw new PSTException("Settings.RecursionDepth: Unexpected numOfHouses: " + numOfHouses); } return _recursionDepth[(int)compStrength, numOfHouses]; }
/// <summary>Enables the non-empty houses of the given player and disables all of his opponent.</summary> /// <param name="player">The player whose turn it is</param> public void EnableHousesOfPlayer(Player player) { int numPits = GetNumOfHousesPerPlayer(); int startIndexOfPlayer = ((player.GetPosition() == Player.Position.South) ? 0 : numPits + 1); int startIndexOfOpponent = ((player.GetPosition() == Player.Position.South) ? numPits + 1 : 0); for (int pitIndex = 0; pitIndex < numPits; ++pitIndex) { if (_pit[pitIndex + startIndexOfPlayer].GetNumberOfSeeds() > 0) { _pit[pitIndex + startIndexOfPlayer].EnableTouchField(); } else { _pit[pitIndex + startIndexOfPlayer].DisableTouchField(); } _pit[pitIndex + startIndexOfOpponent].DisableTouchField(); } }