diff --git a/src/game/gameFlow.ts b/src/game/gameFlow.ts index 40eb57b..ccfeff3 100644 --- a/src/game/gameFlow.ts +++ b/src/game/gameFlow.ts @@ -1,4 +1,5 @@ import GameState, { PHASE_ENUM } from './gameState'; +import { MessageService, MessageFileName } from '../utils/MessageService' class GameFlow { gameState: GameState; @@ -59,21 +60,10 @@ class GameFlow { // Weapons Purchase Subphase if (!userInput) { // Send instructions to the user for the current subphase - responseMessage = ` -🔫 **Choose Your Weapon for the Journey** 🔫 - -Please select from the following options by replying with **!!Oregon [choice]**: - -1. **Frontiersman's Sharpshooter Rifle** - $200 (Best accuracy and range) -2. **Pioneer's Long Rifle** - $150 (Improved accuracy and range) -3. **Settler's Carbine** - $100 (Good balance of cost and performance) -4. **Homesteader's Musket** - $75 (Reliable but not as accurate) -5. **Grandpa's Rusty Shotgun** - Free (Least accurate but no cost) - -**Note:** Your choice of weapon can greatly affect your hunting success and defense against threats on the trail. Choose wisely! - -Reply with the choice number, for example: **!!Oregon 3** to select the Settler's Carbine. -`; + responseMessage = `${MessageService.getRandomMessage( + MessageFileName.Oregon_WeaponPurchase, + {} + )}`; // The lack of userInput argument triggers a request for input. } else { // Process user input here and decide whether to advance subphase or send an error message @@ -81,6 +71,7 @@ Reply with the choice number, for example: **!!Oregon 3** to select the Settler' if (purchaseResult.success) { // If the purchase was successful, advance to the next subphase and recursively call handleSetupPhase without userInput to get the next set of instructions this.gameState.subPhase++; + //TODO next we will need to add a wrapper methood that will dump the game object and the message back to the player return this.handleSetupPhase(); } else { // If there was an error, include the error message in responseMessage @@ -91,18 +82,93 @@ Reply with the choice number, for example: **!!Oregon 3** to select the Settler' break; case 1: //OXEN TEAM Purchase + if (!userInput) { + responseMessage = `${MessageService.getRandomMessage( + MessageFileName.Oregon_OxenPurchase, + {} + )}`; + } else { + const purchaseResult = this.handleGenericPurchase(PurchaseOption.OXEN, userInput, 200, 300); + if (purchaseResult.success) { + this.gameState.subPhase++; + //TODO next we will need to add a wrapper methood that will dump the game object and the message back to the player + return this.handleSetupPhase(); // Call setup phase again for next subphase + } else { + responseMessage = purchaseResult.errorMessage || ''; + } + } break; case 2: //FOOD Purchase + if (!userInput) { + responseMessage = `${MessageService.getRandomMessage( + MessageFileName.Oregon_FoodPurchase, + {} + )}`; + } else { + const purchaseResult = this.handleGenericPurchase(PurchaseOption.FOOD, userInput); + if (purchaseResult.success) { + this.gameState.subPhase++; + //TODO next we will need to add a wrapper methood that will dump the game object and the message back to the player + return this.handleSetupPhase(); // Call setup phase again for next subphase + } else { + responseMessage = purchaseResult.errorMessage || ''; + } + } break; case 3: //AMMUNITION Purchase + if (!userInput) { + responseMessage = `${MessageService.getRandomMessage( + MessageFileName.Oregon_AmmoPurchase, + {} + )}`; + } else { + const purchaseResult = this.handleGenericPurchase(PurchaseOption.AMMO, userInput); + if (purchaseResult.success) { + this.gameState.subPhase++; + //TODO next we will need to add a wrapper methood that will dump the game object and the message back to the player + return this.handleSetupPhase(); // Call setup phase again for next subphase + } else { + responseMessage = purchaseResult.errorMessage || ''; + } + } break; case 4: //CLOTHING Purchase + if (!userInput) { + responseMessage = `${MessageService.getRandomMessage( + MessageFileName.Oregon_ClothingPurchase, + {} + )}`; + } else { + const purchaseResult = this.handleGenericPurchase(PurchaseOption.CLOTHING, userInput); + if (purchaseResult.success) { + this.gameState.subPhase++; + //TODO next we will need to add a wrapper methood that will dump the game object and the message back to the player + return this.handleSetupPhase(); // Call setup phase again for next subphase + } else { + responseMessage = purchaseResult.errorMessage || ''; + } + } break; case 5: //MISCELLANEOUS SUPPLIES Purchase + if (!userInput) { + responseMessage = `${MessageService.getRandomMessage( + MessageFileName.Oregon_MiscSuppliesPurchase, + {} + )}`; + } else { + const purchaseResult = this.handleGenericPurchase(PurchaseOption.MISC, userInput); + if (purchaseResult.success) { + this.gameState.subPhase++; + //TODO next we will need to add a wrapper methood that will dump the game object and the message back to the player + return this.handleSetupPhase(); // Call setup phase again for next subphase + } else { + responseMessage = purchaseResult.errorMessage || ''; + } + } break; default: //Advance Phase @@ -142,6 +208,59 @@ Reply with the choice number, for example: **!!Oregon 3** to select the Settler' }; } + handleGenericPurchase(itemType: PurchaseOption, userInput: string, minAmount?: number, maxAmount?: number): { success: boolean; errorMessage?: string; responseMessage?: string } { + const amount = parseInt(userInput); + if (isNaN(amount) || amount < 0) { + return { + success: false, + errorMessage: "⚠️ Invalid input. Please enter a positive number." + }; + } + + if ((maxAmount && amount > maxAmount) || (minAmount && amount < minAmount)) { + return { + success: false, + errorMessage: `⚠️ Invalid input. Please enter a number between ${minAmount} and ${maxAmount}.` + }; + } + + const totalCost = amount + if (this.gameState.cashLeftAfterInitialPurchases < totalCost) { + return { + success: false, + errorMessage: `⚠️ You do not have enough money to purchase ${amount} units of ${itemType}. You have $${this.gameState.cashLeftAfterInitialPurchases} remaining.` + }; + } + + // Update gameState based on itemType + switch (itemType) { + case PurchaseOption.OXEN: + this.gameState.amountSpentOnAnimals += totalCost; + break; + case PurchaseOption.FOOD: + this.gameState.amountSpentOnFood += totalCost; + break; + case PurchaseOption.AMMO: + this.gameState.amountSpentOnAmmunition += totalCost * 50; + break; + case PurchaseOption.CLOTHING: + this.gameState.amountSpentOnClothing += totalCost; + break; + case PurchaseOption.MISC: + this.gameState.amountSpentOnMiscellaneousSupplies += totalCost; + break; + // Add cases for other item types + } + + this.gameState.cashLeftAfterInitialPurchases -= totalCost; + + // Optionally, return a success message + return { + success: true + }; + } + + private async handleRidersAttack(userInput?: string | number): Promise { // Logic for handling a riders attack, may involve checking userInput for response to attack @@ -191,4 +310,12 @@ const weaponOptions: Record = { "3": { name: "Settler's Carbine", cost: 100 }, "4": { name: "Homesteader's Musket", cost: 75 }, "5": { name: "Grandpa's Rusty Shotgun", cost: 0 } -}; \ No newline at end of file +}; + +enum PurchaseOption { + OXEN = 'oxen', + FOOD = 'food', + AMMO = 'ammo', + CLOTHING = 'clothing', + MISC = 'misc', +};