A complete implementation of the Kalah (Mancala) board game in Swift for macOS command line, featuring modern Swift practices and Apple's ArgumentParser framework.
Kalah is a two-player strategy game where players take turns sowing seeds from their houses into adjacent pits and stores. The goal is to capture more seeds than your opponent through strategic moves and captures.
This implementation provides a complete, playable version with:
- Full game logic including sowing, capturing, and extra turns
- Configurable board sizes (5x4 or 7x5)
- Flexible sowing directions (clockwise or anti-clockwise)
- Modern Swift architecture with clean separation of concerns
- ArgumentParser integration for professional command-line interface
- Swift Package Manager for easy building and distribution
- โ Complete Kalah rules implementation
- โ Seed sowing mechanics with proper direction handling
- โ Capture mechanics when landing in empty houses
- โ Extra turns when landing in player's store
- โ Game over detection and final scoring
- โ ASCII board display with clear visualization
- โ Swift 5.0+ with modern language features
- โ Apple's ArgumentParser for command-line arguments
- โ Swift Package Manager for dependency management
- โ Clean architecture with MVC pattern
- โ Comprehensive input validation
- โ Error handling and user-friendly messages
- โ Cross-platform macOS compatibility
- macOS 10.15 (Catalina) or later
- Swift 5.0 or later
- Xcode Command Line Tools (for building)
-
Clone the repository
git clone https://github.com/banghuazhao/Kalah.git cd Kalah -
Build the project
swift build -c release
-
Run the game
.build/release/Kalah --help
git clone https://github.com/banghuazhao/Kalah.git
cd Kalah
swift run Kalah --help# Start a standard game (5 houses, 4 seeds, anti-clockwise)
swift run Kalah
# or if built: .build/release/Kalah# 7 houses per player with 5 seeds each
swift run Kalah --seven-five
# Use clockwise sowing direction
swift run Kalah --clockwise
# Combine both options
swift run Kalah --seven-five --clockwise
# Show help
swift run Kalah --help- House numbers: Enter 1-5 (or 1-7 with
--seven-five) to select a house - Quit: Type
qto exit the game - Invalid moves: The game will prompt for valid input
- Setup: Each player has 5 (or 7) houses with 4 (or 5) seeds each
- Turns: Players take turns selecting one of their houses
- Sowing: Seeds are distributed one by one into subsequent houses/stores
- Captures: Landing in an empty house on your side captures opposite seeds
- Extra Turns: Landing in your store grants an extra turn
- Game End: When a player has no seeds in their houses
- Seeds in your store count as points
- Captured seeds are added to your store
- Remaining seeds are collected at game end
- Player with most seeds wins
- When you select a house, all seeds from that house are picked up
- Seeds are distributed one by one in the chosen direction (clockwise or counter-clockwise)
- Distribution continues through your houses, your store, opponent's houses, and back to your houses
- Your opponent's store is skipped during sowing
- If your last seed lands in an empty house on your side
- AND the opposite house (on opponent's side) has seeds
- You capture both the last seed and all seeds from the opposite house
- Captured seeds go directly to your store
- If your last seed lands in your own store, you get an extra turn
- This can lead to multiple consecutive moves
- The game ends when the current player has no seeds in their houses
- Remaining seeds from both sides are collected into respective stores
- Final scores are compared to determine the winner
Here's a complete example of a Kalah game session:
Welcome to Kalah!
+----+-------+-------+-------+-------+-------+----+
| P2 | 5[ 4] | 4[ 4] | 3[ 4] | 2[ 4] | 1[ 4] | 0 |
| |-------+-------+-------+-------+-------| |
| 0 | 1[ 4] | 2[ 4] | 3[ 4] | 4[ 4] | 5[ 4] | P1 |
+----+-------+-------+-------+-------+-------+----+
Player P1's turn - Specify house number or 'q' to quit: 1
+----+-------+-------+-------+-------+-------+----+
| P2 | 5[ 4] | 4[ 4] | 3[ 4] | 2[ 4] | 1[ 4] | 0 |
| |-------+-------+-------+-------+-------| |
| 0 | 1[ 0] | 2[ 5] | 3[ 5] | 4[ 5] | 5[ 4] | P1 |
+----+-------+-------+-------+-------+-------+----+
Player P2's turn - Specify house number or 'q' to quit: 3
+----+-------+-------+-------+-------+-------+----+
| P2 | 5[ 4] | 4[ 4] | 3[ 0] | 2[ 4] | 1[ 4] | 0 |
| |-------+-------+-------+-------+-------| |
| 0 | 1[ 0] | 2[ 5] | 3[ 5] | 4[ 5] | 5[ 4] | P1 |
+----+-------+-------+-------+-------+-------+----+
Player P1's turn - Specify house number or 'q' to quit: 5
+----+-------+-------+-------+-------+-------+----+
| P2 | 5[ 4] | 4[ 4] | 3[ 0] | 2[ 4] | 1[ 4] | 0 |
| |-------+-------+-------+-------+-------| |
| 1 | 1[ 0] | 2[ 5] | 3[ 5] | 4[ 5] | 5[ 0] | P1 |
+----+-------+-------+-------+-------+-------+----+
Player P2's turn - Specify house number or 'q' to quit: q
Game over
+----+-------+-------+-------+-------+-------+----+
| P2 | 5[ 4] | 4[ 4] | 3[ 0] | 2[ 4] | 1[ 4] | 0 |
| |-------+-------+-------+-------+-------| |
| 1 | 1[ 0] | 2[ 5] | 3[ 5] | 4[ 5] | 5[ 0] | P1 |
+----+-------+-------+-------+-------+-------+----+
The ASCII board shows:
- Top row: Player 2's houses (5, 4, 3, 2, 1) and store
- Bottom row: Player 1's houses (1, 2, 3, 4, 5) and store
- Numbers in brackets: Seed count in each house
- Store values: Total seeds captured by each player
Player selects house 1 (4 seeds):
Before: 1[ 4] 2[ 4] 3[ 4] 4[ 4] 5[ 4]
After: 1[ 0] 2[ 5] 3[ 5] 4[ 5] 5[ 4]
Player lands in empty house 1, opposite house has seeds:
Capture: 1[ 0] + opposite house seeds โ Player's store
Player's last seed lands in their store:
Result: Player gets another turn immediately
The project follows a clean, modular architecture using Swift Package Manager:
Kalah/
โโโ Sources/
โ โโโ Kalah/
โ โโโ Models/ # Core data structures
โ โ โโโ House.swift # Individual house representation
โ โ โโโ Store.swift # Player scoring areas
โ โ โโโ Player.swift # Player information
โ โ โโโ Board.swift # Game board state management
โ โโโ Game/ # Game logic engine
โ โ โโโ GameEngine.swift # Main game coordinator
โ โ โโโ SowingEngine.swift # Seed distribution logic
โ โ โโโ PlayerManager.swift # Turn management
โ โ โโโ GameStateManager.swift # Game state operations
โ โโโ UI/ # User interface
โ โ โโโ BoardDisplay.swift # ASCII board rendering
โ โ โโโ InputHandler.swift # User input processing
โ โโโ Configuration/ # Game configuration
โ โ โโโ GameConfig.swift # Game settings
โ โโโ Kalah.swift # Main game class
โ โโโ main.swift # Entry point with ArgumentParser
โโโ Tests/
โ โโโ KalahTests/
โ โโโ KalahTests.swift # Unit tests
โโโ Package.swift # Swift Package Manager configuration
โโโ README.md # This file
Kalah: Main game class that coordinates all componentsGameEngine: Manages the game loop and state transitionsSowingEngine: Handles the core sowing mechanics and capture logicBoardDisplay: Renders the game board in ASCII formatInputHandler: Processes and validates user inputArgumentParser: Provides professional command-line argument parsing
The project includes a comprehensive test suite with 50 unit tests covering all aspects of the game to ensure reliability, correctness, and maintainability.
- โ HouseTests: House mechanics, seed management, emptiness checks
- โ StoreTests: Store functionality, seed addition, initialization
- โ PlayerTests: Player management, initialization, identification
- โ GameConfigTests: Game configuration options (5x4, 7x5, directions)
- โ BoardTests: Board setup, seed distribution, capture mechanics
- โ SowingEngineTests: Core sowing logic, store landing, capture scenarios
- โ GameEngineTests: Game flow, move validation, turn management
- โ IntegrationTests: Complete game scenarios, capture mechanics, extra turns
- โ EdgeCaseTests: Boundary conditions, minimum configurations
- โ DebugTests: Troubleshooting and debugging scenarios
- Total Tests: 50
- Test Suites: 9
- Coverage: All major components and game scenarios
- Status: All tests passing โ
# Run all tests
swift test
# Run tests with verbose output
swift test --verbose
# Run specific test suite
swift test --filter HouseTests
swift test --filter GameEngineTests
swift test --filter IntegrationTests
# Run specific test
swift test --filter GameEngineTests/testMoveWithEmptyHouse
swift test --filter SowingEngineTests/testSowingWithCaptureTests/
โโโ KalahTests/
โโโ KalahTests.swift # All unit tests organized by component
- House Operations: Initialization, seed addition/removal, emptiness checks
- Store Operations: Seed collection, scoring, initialization
- Player Management: Turn switching, player identification
- Board Setup: Default and custom configurations, seed distribution
- Sowing Mechanics: Simple sowing, store landing, board traversal
- Capture Logic: Empty house detection, opposite house capture
- Turn Management: Valid/invalid moves, turn switching, extra turns
- Game State: Game over detection, final scoring, game ending
- Complete Game Flow: Multi-move sequences, player interactions
- Capture Scenarios: Complex capture mechanics, multiple captures
- Extra Turn Logic: Store landing, consecutive moves
- Configuration Variations: Different board sizes and sowing directions
- Invalid Moves: Empty house selection, out-of-bounds input
- Boundary Conditions: Minimum configurations, maximum scenarios
- Game End Conditions: No valid moves, forced game termination
- Input Validation: Error handling, user input processing
- Descriptive Names: Clear test names explaining what is being tested
- Independent Tests: Each test can run in isolation
- Comprehensive Assertions: Multiple checks per test for thorough validation
- Real Game Scenarios: Tests based on actual gameplay situations
- Debug Support: Specialized tests for troubleshooting complex issues
The test suite is designed to work seamlessly with CI/CD pipelines:
- Fast execution (< 1 second for all tests)
- No external dependencies
- Clear pass/fail reporting
- Comprehensive coverage reporting
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
# Build the project
swift build
# Run tests
swift test
# Run the game
swift run Kalah
# Clean build artifacts
swift package cleanThis project is licensed under the MIT License - see the LICENSE file for details.
- Based on the traditional Kalah/Mancala board game
- Uses Apple's ArgumentParser framework
- Built with modern Swift best practices and Swift Package Manager
If you encounter any issues or have questions:
- Open an issue on GitHub
- Check the existing issues for solutions
Enjoy playing Kalah! ๐ฎ