/// <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)))); }
/// <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))); }
/// <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))); }
/// <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; }
/// <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; }
/// <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))); }
/// <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))]; }