# Malatro ## About `Malatro` is a simplified clone of the game `Balatro`. Its main purpose is to serve as an educational tool, teaching foundational programming concepts. 📢 **Note**: This project is purely educational and will not be used for any commercial purposes. --- ## For Students The remainder of this README is yours to complete. Take this opportunity to describe your contributions, the design decisions you've made, and any other information you deem necessary. # Task 1 - Partial Delivery 1 This project defines the basic entities for a card-based video game using Scala. It includes classes for `Card`, `Rank`, `Suit`, `Joker`, `Hand`, and `Score`, each documented and independently tested. ## Structure - `cards/` → Cards, ranks, and suits - `jokers/` → Jokers with type as a string - `hand/` → A hand containing a set of cards and jokers - `score/` → Score with chips and multiplier ## Task 1 - Partial Delivery 2 This delivery defines the 9 poker combinations as classes implementing the `PokerCombination` trait. Each class includes its name, a `Score`, and a `verify(cards: List[Card])` method to check if a hand matches the combination. All combinations are tested with valid and invalid cases using MUnit. The logic uses explicit loops and avoids higher-order functions, as required. --- ## Task 2 - Partial Delivery 3 This delivery improves encapsulation by adding explicit getters and setters to the main classes. ### Changes: - Marked class fields as `private` where appropriate. - Added `get` and `set` methods in: - `Joker`: `getJokerType`, `setJokerType` - `Hand`: `setCards`, `setJokers` - `Score`: `getChips`, `setChips`, `getMultiplier`, `setMultiplier` - Updated tests to cover the new accessors. --- ## Task 3 - Partial Delivery 4 This delivery focuses on adding **robust rule enforcement** using **custom exceptions**, and introducing the **base scoring logic** influenced by Jokers. ### Changes: - Implemented constraints and exceptions in `Hand`: - A hand cannot have more than 8 cards → `TooManyCardsException` - A hand cannot have more than 2 jokers → `TooManyJokersException` - Cannot remove a card or joker using an invalid index → `InvalidCardIndexException`, `InvalidJokerIndexException` - Cannot play more than 3 times → `TooManyPlaysException` - Cannot discard more than 3 times → `TooManyDiscardsException` - Playing or discarding must involve 1 to 5 cards → `InvalidPlaySizeException` - Index validation now rejects unordered or out-of-range lists - Added `discardCards(indices: List[Int])` method to `Hand` with full validation and tracking - Created custom exception classes under the `exceptions/` package - Added unit tests in `ExceptionTest.scala` to cover: - Each custom exception - Limits and index validation in `Hand` - Introduced scoring logic via `ScoreUtils.applyScore(score, joker, cards)`: - **Greedy Joker**: +3 multiplier per Diamond - **Devious Joker**: +100 chips if cards form a straight - **Even Steven**: +4 multiplier per even-valued card - **Scary Face**: +30 chips per face card (J, Q, K) ---