Refactored gameflow to a static method, Updated All code. Refactored existing phases to seperate classes

master
j 2024-05-02 00:48:51 -04:00
parent 399fdfbe38
commit 8b630c45c9
7 changed files with 221 additions and 216 deletions

View File

@ -3,224 +3,88 @@ import { MessageService, MessageFileName } from '../utils/MessageService'
import { CommentPoster } from '../rdrama/services/CommentPoster'; import { CommentPoster } from '../rdrama/services/CommentPoster';
import { RidersPhase } from '../phases/riders'; import { RidersPhase } from '../phases/riders';
import { HuntPhase } from '../phases/hunt'; import { HuntPhase } from '../phases/hunt';
import { HandleSetup } from '../phases/setup'; import { HandleSetup as SetupPhase } from '../phases/setup';
import { travelPhase as TravelPhase } from '../phases/travel';
import { ActionPhase } from '../phases/action';
class GameFlow { class GameFlow {
gameState: GameState;
constructor(gameState: GameState) { static async executeCurrentPhase(gameState: GameState, userInput?: string) {
this.gameState = gameState; GameFlow.cleanupGameState(gameState);
}
async executeCurrentPhase(userInput?: string) { switch (gameState.phase) {
this.cleanupGameState();
switch (this.gameState.phase) {
case PHASE_ENUM.SETUP: case PHASE_ENUM.SETUP:
// Handle the setup phase, e.g., initial purchases // Handle the setup phase, e.g., initial purchases
await HandleSetup.handleSetupPhase(this.gameState, this, userInput); await SetupPhase.handleSetupPhase(gameState, userInput);
break; break;
case PHASE_ENUM.START_TURN: case PHASE_ENUM.START_TURN:
await this.startTurn(); await GameFlow.startTurn(gameState);
break; break;
case PHASE_ENUM.ACTION_CHOICE: case PHASE_ENUM.ACTION_CHOICE:
await this.actionChoice(userInput) await ActionPhase.actionChoice(gameState, userInput)
break; break;
case PHASE_ENUM.TRAVEL: case PHASE_ENUM.TRAVEL:
// Handle travel logic // Handle travel logic
await this.handleTravel(); await TravelPhase.handleTravel(gameState, userInput);
break; break;
case PHASE_ENUM.FORT: case PHASE_ENUM.FORT:
// Handle interactions at the fort // Handle interactions at the fort
await HandleSetup.handleSetupPhase(this.gameState, this, userInput); await SetupPhase.handleSetupPhase(gameState, userInput);
break; break;
case PHASE_ENUM.HUNT: case PHASE_ENUM.HUNT:
// Handle hunting logic // Handle hunting logic
await HuntPhase.handleHunt(this.gameState, this, userInput); await HuntPhase.handleHunt(gameState, userInput);
break; break;
case PHASE_ENUM.RIDERS_ATTACK: case PHASE_ENUM.RIDERS_ATTACK:
// Handle a riders attack phase // Handle a riders attack phase
await RidersPhase.handleRidersAttack(this.gameState, this, userInput); await RidersPhase.handleRidersAttack(gameState, userInput);
break; break;
case PHASE_ENUM.EVENT: case PHASE_ENUM.EVENT:
// Handle random events that can occur // Handle random events that can occur
await this.handleRandomEvent();
break; break;
case PHASE_ENUM.MOUNTAIN: case PHASE_ENUM.MOUNTAIN:
// Handle mountain traversal challenges // Handle mountain traversal challenges
await this.handleMountain();
break; break;
case PHASE_ENUM.DEATH: case PHASE_ENUM.DEATH:
// Check if conditions leading to the player's death have been met // Check if conditions leading to the player's death have been met
break; break;
default: default:
console.error("Unknown game phase:", this.gameState.phase); console.error("Unknown game phase:", gameState.phase);
break; break;
} }
} }
private cleanupGameState(): void { static cleanupGameState(gameState: GameState): void {
// Ensure all expenditures are non-negative // Ensure all expenditures are non-negative
this.gameState.amountSpentOnFood = Math.max(0, this.gameState.amountSpentOnFood); gameState.amountSpentOnFood = Math.max(0, gameState.amountSpentOnFood);
this.gameState.amountSpentOnAmmunition = Math.max(0, this.gameState.amountSpentOnAmmunition); gameState.amountSpentOnAmmunition = Math.max(0, gameState.amountSpentOnAmmunition);
this.gameState.amountSpentOnClothing = Math.max(0, this.gameState.amountSpentOnClothing); gameState.amountSpentOnClothing = Math.max(0, gameState.amountSpentOnClothing);
this.gameState.amountSpentOnMiscellaneousSupplies = Math.max(0, this.gameState.amountSpentOnMiscellaneousSupplies); gameState.amountSpentOnMiscellaneousSupplies = Math.max(0, gameState.amountSpentOnMiscellaneousSupplies);
// Round expenditures and cash to integers // Round expenditures and cash to integers
this.gameState.amountSpentOnFood = Math.floor(this.gameState.amountSpentOnFood); gameState.amountSpentOnFood = Math.floor(gameState.amountSpentOnFood);
this.gameState.amountSpentOnAmmunition = Math.floor(this.gameState.amountSpentOnAmmunition); gameState.amountSpentOnAmmunition = Math.floor(gameState.amountSpentOnAmmunition);
this.gameState.amountSpentOnClothing = Math.floor(this.gameState.amountSpentOnClothing); gameState.amountSpentOnClothing = Math.floor(gameState.amountSpentOnClothing);
this.gameState.amountSpentOnMiscellaneousSupplies = Math.floor(this.gameState.amountSpentOnMiscellaneousSupplies); gameState.amountSpentOnMiscellaneousSupplies = Math.floor(gameState.amountSpentOnMiscellaneousSupplies);
this.gameState.totalMileageWholeTrip = Math.floor(this.gameState.totalMileageWholeTrip); gameState.totalMileageWholeTrip = Math.floor(gameState.totalMileageWholeTrip);
//Round Cash to two digits //Round Cash to two digits
this.gameState.cashLeftAfterInitialPurchases = Math.floor(this.gameState.cashLeftAfterInitialPurchases * 100) / 100; gameState.cashLeftAfterInitialPurchases = Math.floor(gameState.cashLeftAfterInitialPurchases * 100) / 100;
} }
private async startTurn(): Promise<void> { static async startTurn(gameState: GameState): Promise<void> {
// Update total mileage up through the previous turn // Update total mileage up through the previous turn
this.gameState.totalMileageUpThroughPreviousTurn = this.gameState.totalMileageWholeTrip; gameState.totalMileageUpThroughPreviousTurn = gameState.totalMileageWholeTrip;
// Toggle fort option flag // Toggle fort option flag
this.gameState.fortOptionFlag = !this.gameState.fortOptionFlag; gameState.fortOptionFlag = !gameState.fortOptionFlag;
this.gameState.phase = PHASE_ENUM.ACTION_CHOICE; gameState.phase = PHASE_ENUM.ACTION_CHOICE;
await this.gameState.save() await gameState.save()
this.executeCurrentPhase() GameFlow.executeCurrentPhase(gameState)
}
private async actionChoice(userInput?: string): Promise<void> {
let responseMessage = "";
userInput = userInput?.toLowerCase()
console.log("userInput", userInput);
switch (userInput) {
case "1": // Hunt
if (this.gameState.amountSpentOnAmmunition < 40) {
responseMessage = `You do not have enough ammunition to hunt. Purchase more ammunition first.\n\n`;
if (this.gameState.fortOptionFlag) {
responseMessage += `Do you want to:\n2. Continue\n3. Stop at the Next Fort\n\n`
} else {
responseMessage += `Do you want to:\n2. Continue\n\n`
}
await MessageService.statusUpdate(this.gameState, responseMessage)
} else {
this.gameState.phase = PHASE_ENUM.HUNT;
this.gameState.totalMileageWholeTrip -= 45;
await this.gameState.save()
this.executeCurrentPhase()
}
return;
break;
case "2": // Continue
this.gameState.phase = PHASE_ENUM.TRAVEL;
await this.gameState.save()
this.executeCurrentPhase()
return;
break;
case "3": // Stop at the Next Fort (if applicable)
if (this.gameState.fortOptionFlag) {
this.gameState.subPhase = 2
this.gameState.totalMileageWholeTrip -= 45;
this.gameState.phase = PHASE_ENUM.FORT;
await this.gameState.save()
this.executeCurrentPhase()
return;
} else {
responseMessage += "⚠️ There is no fort option available at this time.\n\n"
responseMessage += `Do you want to:\n1. Hunt\n2. Continue\n\n`
await MessageService.statusUpdate(this.gameState, responseMessage)
return;
}
break;
default:
console.log("Starting turn...");
if (userInput !== undefined || userInput === "" || userInput === "start") {
responseMessage += "⚠️ Invalid Selection.\n\n"
}
//check for illness or injury
if (this.gameState.illnessFlag || this.gameState.injuryFlag) {
responseMessage += this.handleDoctor();
if (this.gameState.phase === PHASE_ENUM.DEATH) {
this.executeCurrentPhase()
return;
}
}
// Warn the player if food is low
if (this.gameState.amountSpentOnFood < 13) {
responseMessage += `You only have ${this.gameState.amountSpentOnFood} pounds of food.\n\n YOU'D BETTER DO SOME HUNTING OR BUY FOOD AND SOON!!!!\n\n`;
}
if (this.gameState.fortOptionFlag) {
responseMessage += `Do you want to:\n1. Hunt\n2. Continue\n3. Stop at the Next Fort\n\n`
} else {
responseMessage += `Do you want to:\n1. Hunt\n2. Continue\n\n`
}
await MessageService.statusUpdate(this.gameState, this.gameState.lastPrompt + responseMessage)
this.gameState.lastPrompt = responseMessage;
break;
}
return;
}
private async handleTravel(userInput?: string | number): Promise<void> {
let responseMessage = "";
if (!userInput || userInput?.toString().toLowerCase() === "start") {
responseMessage = "DO YOU WANT TO EAT\n(1) POORLY\n(2) MODERATELY\n(3) WELL: ";
await MessageService.statusUpdate(this.gameState, responseMessage);
return;
}
// Check if userInput is a number or can be converted to a valid number
if (isNaN(Number(userInput))) {
responseMessage = "Invalid input. Please enter a number.\n\n"
responseMessage += "DO YOU WANT TO EAT\n(1) POORLY\n(2) MODERATELY\n(3) WELL: ";
await MessageService.statusUpdate(this.gameState, responseMessage);
return; // Exit if input is not a valid number
}
let eatingChoice: number = parseInt(userInput.toString(), 10);
// Validate eating choice
if (eatingChoice < 1 || eatingChoice > 3) {
responseMessage = "Invalid choice.\n\n"
responseMessage += "DO YOU WANT TO EAT\n(1) POORLY\n(2) MODERATELY\n(3) WELL: ";
await MessageService.statusUpdate(this.gameState, responseMessage);
return;
}
// Calculate potential food consumption without updating the game state yet
let potentialAmountSpentOnFood = this.gameState.amountSpentOnFood - (8 + 5 * eatingChoice);
// Check if the potential amount spent on food is negative
if (potentialAmountSpentOnFood < 0) {
// If it would result in a negative value, inform the user they can't eat that well
responseMessage = "YOU CAN'T EAT THAT WELL\n\n";
responseMessage += "DO YOU WANT TO EAT\n(1) POORLY\n(2) MODERATELY\n(3) WELL: ";
await MessageService.statusUpdate(this.gameState, responseMessage);
return; // Exit the method to prevent further execution
} else {
// If the amount is sufficient, update the game state with the new amount
this.gameState.amountSpentOnFood = potentialAmountSpentOnFood;
}
// Calculate total mileage
this.gameState.totalMileageWholeTrip += 200 + (this.gameState.amountSpentOnAnimals - 220) / 5 + 10 * Math.random();
this.gameState.blizzardFlag = this.gameState.insufficientClothingFlag = false;
this.gameState.phase = PHASE_ENUM.RIDERS_ATTACK;
// Save the game state after making changes
await this.gameState.save();
// Continue with the game flow
this.executeCurrentPhase();
} }
private async handleEncounter(): Promise<void> { private async handleEncounter(): Promise<void> {
@ -236,29 +100,29 @@ class GameFlow {
} }
private handleDoctor(): string { static handleDoctor(gameState: GameState): string {
let responseMessage: string = "" let responseMessage: string = ""
// Handle illness and injury // Handle illness and injury
if (this.gameState.illnessFlag && this.gameState.injuryFlag) { if (gameState.illnessFlag && gameState.injuryFlag) {
responseMessage += `You were sick and and injured ` responseMessage += `You were sick and and injured `
} else if (this.gameState.illnessFlag) { } else if (gameState.illnessFlag) {
responseMessage += `You were sick and ` responseMessage += `You were sick and `
} else { } else {
responseMessage += `You were injured and ` responseMessage += `You were injured and `
} }
this.gameState.cashLeftAfterInitialPurchases -= 20; gameState.cashLeftAfterInitialPurchases -= 20;
if (this.gameState.cashLeftAfterInitialPurchases < 0) { if (gameState.cashLeftAfterInitialPurchases < 0) {
if (this.gameState.illnessFlag) this.gameState.death = DEATH_REASON_ENUM.ILLNESS if (gameState.illnessFlag) gameState.death = DEATH_REASON_ENUM.ILLNESS
if (this.gameState.injuryFlag) this.gameState.death = DEATH_REASON_ENUM.INJURY if (gameState.injuryFlag) gameState.death = DEATH_REASON_ENUM.INJURY
this.gameState.phase = PHASE_ENUM.DEATH gameState.phase = PHASE_ENUM.DEATH
return ""; return "";
} else { } else {
responseMessage += `The Doctors bill was $20\n\n` responseMessage += `The Doctors bill was $20\n\n`
} }
this.gameState.injuryFlag = false; gameState.injuryFlag = false;
this.gameState.illnessFlag = false; gameState.illnessFlag = false;
return responseMessage; return responseMessage;

View File

@ -0,0 +1,81 @@
import GameState, { PHASE_ENUM } from '../game/gameState';
import GameFlow from '../game/gameFlow';
import { MessageService } from '../utils/MessageService';
export class ActionPhase {
static async actionChoice(gameState: GameState, userInput?: string): Promise<void> {
let responseMessage = "";
userInput = userInput?.toLowerCase()
console.log("userInput", userInput);
switch (userInput) {
case "1": // Hunt
if (gameState.amountSpentOnAmmunition < 40) {
responseMessage = `You do not have enough ammunition to hunt. Purchase more ammunition first.\n\n`;
if (gameState.fortOptionFlag) {
responseMessage += `Do you want to:\n2. Continue\n3. Stop at the Next Fort\n\n`
} else {
responseMessage += `Do you want to:\n2. Continue\n\n`
}
await MessageService.statusUpdate(gameState, responseMessage)
} else {
gameState.phase = PHASE_ENUM.HUNT;
gameState.totalMileageWholeTrip -= 45;
await gameState.save()
GameFlow.executeCurrentPhase(gameState)
}
return;
break;
case "2": // Continue
gameState.phase = PHASE_ENUM.TRAVEL;
await gameState.save()
GameFlow.executeCurrentPhase(gameState)
return;
break;
case "3": // Stop at the Next Fort (if applicable)
if (gameState.fortOptionFlag) {
gameState.subPhase = 2
gameState.totalMileageWholeTrip -= 45;
gameState.phase = PHASE_ENUM.FORT;
await gameState.save()
GameFlow.executeCurrentPhase(gameState)
return;
} else {
responseMessage += "⚠️ There is no fort option available at this time.\n\n"
responseMessage += `Do you want to:\n1. Hunt\n2. Continue\n\n`
await MessageService.statusUpdate(gameState, responseMessage)
return;
}
break;
default:
console.log("Starting turn...");
if (userInput !== undefined || userInput === "" || userInput === "start") {
responseMessage += "⚠️ Invalid Selection.\n\n"
}
//check for illness or injury
if (gameState.illnessFlag || gameState.injuryFlag) {
responseMessage += GameFlow.handleDoctor(gameState);
if (gameState.phase === PHASE_ENUM.DEATH) {
GameFlow.executeCurrentPhase(gameState)
return;
}
}
// Warn the player if food is low
if (gameState.amountSpentOnFood < 13) {
responseMessage += `You only have ${gameState.amountSpentOnFood} pounds of food.\n\n YOU'D BETTER DO SOME HUNTING OR BUY FOOD AND SOON!!!!\n\n`;
}
if (gameState.fortOptionFlag) {
responseMessage += `Do you want to:\n1. Hunt\n2. Continue\n3. Stop at the Next Fort\n\n`
} else {
responseMessage += `Do you want to:\n1. Hunt\n2. Continue\n\n`
}
await MessageService.statusUpdate(gameState, gameState.lastPrompt + responseMessage)
gameState.lastPrompt = responseMessage;
break;
}
return;
}
}

View File

@ -4,16 +4,16 @@ import { HandleShooting } from './shooting';
import { MessageService } from '../utils/MessageService'; import { MessageService } from '../utils/MessageService';
export class HuntPhase { export class HuntPhase {
static async handleHunt(gameState: GameState, gameFlow: GameFlow, userInput?: string): Promise<void> { static async handleHunt(gameState: GameState, userInput?: string): Promise<void> {
switch (gameState.subPhase) { switch (gameState.subPhase) {
case 0: // Initial Logic case 0: // Initial Logic
await HuntPhase.initialLogic(gameState, gameFlow); await HuntPhase.initialLogic(gameState);
break; break;
case 1: // Shooting Logic case 1: // Shooting Logic
await HuntPhase.shootingLogic(gameState, gameFlow, userInput); await HuntPhase.shootingLogic(gameState, userInput);
break; break;
case 2: // Outcome Logic case 2: // Outcome Logic
await HuntPhase.outcomeLogic(gameState, gameFlow); await HuntPhase.outcomeLogic(gameState);
break; break;
default: default:
console.error("Unknown subphase in HuntPhase"); console.error("Unknown subphase in HuntPhase");
@ -22,7 +22,7 @@ export class HuntPhase {
} }
static async initialLogic(gameState: GameState, gameFlow: GameFlow,): Promise<void> { static async initialLogic(gameState: GameState): Promise<void> {
let responseMessage = ''; let responseMessage = '';
responseMessage += HandleShooting.handleShooting(gameState); responseMessage += HandleShooting.handleShooting(gameState);
gameState.subPhase = 1; gameState.subPhase = 1;
@ -31,7 +31,7 @@ export class HuntPhase {
await gameState.save(); await gameState.save();
} }
static async shootingLogic(gameState: GameState, gameFlow: GameFlow, userInput?: string): Promise<void> { static async shootingLogic(gameState: GameState, userInput?: string): Promise<void> {
let responseMessage = ''; let responseMessage = '';
if (!userInput) { if (!userInput) {
responseMessage = "Invalid input.\n\n"; responseMessage = "Invalid input.\n\n";
@ -48,11 +48,11 @@ export class HuntPhase {
gameState.lastPrompt = responseMessage; gameState.lastPrompt = responseMessage;
gameState.subPhase = 2; gameState.subPhase = 2;
await gameState.save(); await gameState.save();
await gameFlow.executeCurrentPhase(); await GameFlow.executeCurrentPhase(gameState);
return; return;
} }
static async outcomeLogic(gameState: GameState, gameFlow: GameFlow): Promise<void> { static async outcomeLogic(gameState: GameState): Promise<void> {
let responseMessage = gameState.lastPrompt; let responseMessage = gameState.lastPrompt;
if (gameState.shootResponseTime <= 1) { if (gameState.shootResponseTime <= 1) {
responseMessage += `RIGHT BETWEEN THE EYES---YOU GOT A BIG ONE!!!!\n\n`; responseMessage += `RIGHT BETWEEN THE EYES---YOU GOT A BIG ONE!!!!\n\n`;
@ -71,7 +71,7 @@ export class HuntPhase {
gameState.phase = PHASE_ENUM.ACTION_CHOICE; gameState.phase = PHASE_ENUM.ACTION_CHOICE;
gameState.subPhase = 0; gameState.subPhase = 0;
await gameState.save(); await gameState.save();
await gameFlow.executeCurrentPhase(); await GameFlow.executeCurrentPhase(gameState);
return; return;
} }
} }

View File

@ -4,15 +4,15 @@ import { HandleShooting } from './shooting';
import { MessageService } from '../utils/MessageService'; import { MessageService } from '../utils/MessageService';
export class RidersPhase { export class RidersPhase {
static async handleRidersAttack(gameState: GameState, gameFlow: GameFlow, userInput?: string): Promise<void> { static async handleRidersAttack(gameState: GameState, userInput?: string): Promise<void> {
let responseMessage = ''; let responseMessage = '';
gameState.lastPrompt = responseMessage; gameState.lastPrompt = responseMessage;
switch (gameState.subPhase) { switch (gameState.subPhase) {
case 0: // Initial Logic case 0: // Initial Logic
await RidersPhase.initialLogic(gameState, gameFlow); await RidersPhase.initialLogic(gameState);
break; break;
case 1: // Choice Logic case 1: // Choice Logic
await RidersPhase.choiceLogic(gameState, gameFlow, userInput); await RidersPhase.choiceLogic(gameState, userInput);
break; break;
case 2: //Fight Logic case 2: //Fight Logic
responseMessage = gameState.lastPrompt responseMessage = gameState.lastPrompt
@ -43,7 +43,7 @@ export class RidersPhase {
gameState.phase = PHASE_ENUM.EVENT; gameState.phase = PHASE_ENUM.EVENT;
gameState.subPhase = 0 gameState.subPhase = 0
await gameState.save(); await gameState.save();
await gameFlow.executeCurrentPhase(); await GameFlow.executeCurrentPhase(gameState);
return; return;
case 4: // wagon fight logic case 4: // wagon fight logic
responseMessage = gameState.lastPrompt responseMessage = gameState.lastPrompt
@ -67,12 +67,12 @@ export class RidersPhase {
gameState.phase = PHASE_ENUM.EVENT; gameState.phase = PHASE_ENUM.EVENT;
gameState.subPhase = 0 gameState.subPhase = 0
await gameState.save(); await gameState.save();
await gameFlow.executeCurrentPhase(); await GameFlow.executeCurrentPhase(gameState);
return; return;
} }
} }
static async initialLogic(gameState: GameState, gameFlow: GameFlow): Promise<void> { static async initialLogic(gameState: GameState): Promise<void> {
let responseMessage = ''; let responseMessage = '';
gameState.lastPrompt = responseMessage; gameState.lastPrompt = responseMessage;
// Check for random encounter // Check for random encounter
@ -90,7 +90,7 @@ export class RidersPhase {
gameState.phase = PHASE_ENUM.EVENT; gameState.phase = PHASE_ENUM.EVENT;
gameState.subPhase = 0 gameState.subPhase = 0
gameState.save(); gameState.save();
return gameFlow.executeCurrentPhase(); return GameFlow.executeCurrentPhase(gameState);
} }
// If encounter occurs // If encounter occurs
gameState.hostileRiders = false; gameState.hostileRiders = false;
@ -107,7 +107,7 @@ export class RidersPhase {
await MessageService.statusUpdate(gameState, responseMessage); await MessageService.statusUpdate(gameState, responseMessage);
} }
static async choiceLogic(gameState: GameState, gameFlow: GameFlow, userInput?: string): Promise<void> { static async choiceLogic(gameState: GameState, userInput?: string): Promise<void> {
let responseMessage = ''; let responseMessage = '';
if (!userInput || isNaN(Number(userInput)) || +userInput < 1 && +userInput > 4) { if (!userInput || isNaN(Number(userInput)) || +userInput < 1 && +userInput > 4) {
@ -121,12 +121,12 @@ export class RidersPhase {
// Random chance to flip hostility // Random chance to flip hostility
if (Math.random() > 0.2) gameState.hostileRiders = !gameState.hostileRiders; if (Math.random() > 0.2) gameState.hostileRiders = !gameState.hostileRiders;
if (gameState.hostileRiders) RidersPhase.hostileRidersLogic(gameState, gameFlow) if (gameState.hostileRiders) RidersPhase.hostileRidersLogic(gameState)
else RidersPhase.friendlyRidersLogic(gameState, gameFlow); else RidersPhase.friendlyRidersLogic(gameState);
} }
static async hostileRidersLogic(gameState: GameState, gameFlow: GameFlow): Promise<void> { static async hostileRidersLogic(gameState: GameState): Promise<void> {
gameState.lastPrompt = ""; gameState.lastPrompt = "";
switch (gameState.tacticsChoiceWhenAttacked) { switch (gameState.tacticsChoiceWhenAttacked) {
case 1: // RUN away case 1: // RUN away
@ -139,12 +139,12 @@ export class RidersPhase {
gameState.phase = PHASE_ENUM.EVENT; gameState.phase = PHASE_ENUM.EVENT;
gameState.subPhase = 0; gameState.subPhase = 0;
gameState.save(); gameState.save();
return gameFlow.executeCurrentPhase(); return GameFlow.executeCurrentPhase(gameState);
case 2: // ATTACK case 2: // ATTACK
gameState.lastPrompt = "You decide to attack the hostile riders.\n\n"; gameState.lastPrompt = "You decide to attack the hostile riders.\n\n";
gameState.subPhase = 2; gameState.subPhase = 2;
gameState.save() gameState.save()
return gameFlow.executeCurrentPhase() return GameFlow.executeCurrentPhase(gameState)
case 3: // CONTINUE case 3: // CONTINUE
//Penalize lost initiative if riders are hostile //Penalize lost initiative if riders are hostile
gameState.lastPrompt = "You continue on cautiously, keeping your guard up. THE RIDERS ATTACK!\n\n"; gameState.lastPrompt = "You continue on cautiously, keeping your guard up. THE RIDERS ATTACK!\n\n";
@ -152,12 +152,12 @@ export class RidersPhase {
gameState.amountSpentOnAmmunition -= 100; gameState.amountSpentOnAmmunition -= 100;
gameState.subPhase = 2; gameState.subPhase = 2;
gameState.save() gameState.save()
return gameFlow.executeCurrentPhase() return GameFlow.executeCurrentPhase(gameState)
case 4: // CIRCLE WAGONS case 4: // CIRCLE WAGONS
gameState.subPhase = 4; gameState.subPhase = 4;
gameState.lastPrompt = "You formed a defensive circle with your wagons.THE RIDERS ATTACK!\n\n" gameState.lastPrompt = "You formed a defensive circle with your wagons.THE RIDERS ATTACK!\n\n"
gameState.save() gameState.save()
return gameFlow.executeCurrentPhase() return GameFlow.executeCurrentPhase(gameState)
default: default:
// Handle unexpected input (should be unreachable due to prior validation) // Handle unexpected input (should be unreachable due to prior validation)
console.log("Unexpected tactics choice."); console.log("Unexpected tactics choice.");
@ -165,7 +165,7 @@ export class RidersPhase {
} }
} }
static async friendlyRidersLogic(gameState: GameState, gameFlow: GameFlow): Promise<void> { static async friendlyRidersLogic(gameState: GameState): Promise<void> {
gameState.lastPrompt = ""; gameState.lastPrompt = "";
switch (gameState.tacticsChoiceWhenAttacked) { switch (gameState.tacticsChoiceWhenAttacked) {
case 1: // RUN Away case 1: // RUN Away
@ -178,25 +178,25 @@ export class RidersPhase {
gameState.phase = PHASE_ENUM.EVENT; gameState.phase = PHASE_ENUM.EVENT;
gameState.subPhase = 0; gameState.subPhase = 0;
gameState.save(); gameState.save();
return gameFlow.executeCurrentPhase(); return GameFlow.executeCurrentPhase(gameState);
case 2: // ATTACK case 2: // ATTACK
gameState.lastPrompt = "You decide to attack the friendly riders. They flee in confusion\n\n"; gameState.lastPrompt = "You decide to attack the friendly riders. They flee in confusion\n\n";
gameState.subPhase = 2; gameState.subPhase = 2;
gameState.save() gameState.save()
return gameFlow.executeCurrentPhase() return GameFlow.executeCurrentPhase(gameState)
case 3: // CONTINUE case 3: // CONTINUE
gameState.lastPrompt = "The riders share news from up ahead and wish you safe travels. Your party continues on.\n\n"; gameState.lastPrompt = "The riders share news from up ahead and wish you safe travels. Your party continues on.\n\n";
gameState.phase = PHASE_ENUM.EVENT; gameState.phase = PHASE_ENUM.EVENT;
gameState.subPhase = 0; gameState.subPhase = 0;
gameState.save(); gameState.save();
return gameFlow.executeCurrentPhase(); return GameFlow.executeCurrentPhase(gameState);
case 4: // CIRCLE WAGONS case 4: // CIRCLE WAGONS
gameState.totalMileageWholeTrip -= 20; gameState.totalMileageWholeTrip -= 20;
gameState.lastPrompt = "You formed a defensive circle with your wagons. The riders continue on their way without incident.\n\n"; gameState.lastPrompt = "You formed a defensive circle with your wagons. The riders continue on their way without incident.\n\n";
gameState.phase = PHASE_ENUM.EVENT; gameState.phase = PHASE_ENUM.EVENT;
gameState.subPhase = 0; gameState.subPhase = 0;
gameState.save(); gameState.save();
return gameFlow.executeCurrentPhase() return GameFlow.executeCurrentPhase(gameState)
default: default:
// Handle unexpected input (should be unreachable due to prior validation) // Handle unexpected input (should be unreachable due to prior validation)

View File

@ -3,7 +3,7 @@ import GameFlow from '../game/gameFlow';
import { MessageService, MessageFileName } from '../utils/MessageService' import { MessageService, MessageFileName } from '../utils/MessageService'
export class HandleSetup { export class HandleSetup {
static async handleSetupPhase(gameState: GameState, gameFlow: GameFlow, userInput?: string): Promise<void> { static async handleSetupPhase(gameState: GameState, userInput?: string): Promise<void> {
userInput = userInput?.toLowerCase() userInput = userInput?.toLowerCase()
let responseMessage = ""; let responseMessage = "";
// Logic to handle initial setup // Logic to handle initial setup
@ -23,7 +23,7 @@ export class HandleSetup {
if (purchaseResult.success) { 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 // If the purchase was successful, advance to the next subphase and recursively call handleSetupPhase without userInput to get the next set of instructions
gameState.subPhase++; gameState.subPhase++;
return HandleSetup.handleSetupPhase(gameState, gameFlow); return HandleSetup.handleSetupPhase(gameState);
} else { } else {
// If there was an error, include the error message in responseMessage // If there was an error, include the error message in responseMessage
responseMessage = `${purchaseResult.errorMessage}`; responseMessage = `${purchaseResult.errorMessage}`;
@ -46,7 +46,7 @@ export class HandleSetup {
const purchaseResult = HandleSetup.handleGenericPurchase(gameState, PurchaseOption.OXEN, userInput, 200, 300); const purchaseResult = HandleSetup.handleGenericPurchase(gameState, PurchaseOption.OXEN, userInput, 200, 300);
if (purchaseResult.success) { if (purchaseResult.success) {
gameState.subPhase++; gameState.subPhase++;
return HandleSetup.handleSetupPhase(gameState, gameFlow); // Call setup phase again for next subphase return HandleSetup.handleSetupPhase(gameState); // Call setup phase again for next subphase
} else { } else {
responseMessage = purchaseResult.errorMessage || ''; responseMessage = purchaseResult.errorMessage || '';
responseMessage += `\n\n${MessageService.getRandomMessage( responseMessage += `\n\n${MessageService.getRandomMessage(
@ -67,7 +67,7 @@ export class HandleSetup {
const purchaseResult = HandleSetup.handleGenericPurchase(gameState, PurchaseOption.FOOD, userInput); const purchaseResult = HandleSetup.handleGenericPurchase(gameState, PurchaseOption.FOOD, userInput);
if (purchaseResult.success) { if (purchaseResult.success) {
gameState.subPhase++; gameState.subPhase++;
return HandleSetup.handleSetupPhase(gameState, gameFlow); // Call setup phase again for next subphase return HandleSetup.handleSetupPhase(gameState); // Call setup phase again for next subphase
} else { } else {
responseMessage = purchaseResult.errorMessage || ''; responseMessage = purchaseResult.errorMessage || '';
responseMessage += `\n\n${MessageService.getRandomMessage( responseMessage += `\n\n${MessageService.getRandomMessage(
@ -88,7 +88,7 @@ export class HandleSetup {
const purchaseResult = HandleSetup.handleGenericPurchase(gameState, PurchaseOption.AMMO, userInput); const purchaseResult = HandleSetup.handleGenericPurchase(gameState, PurchaseOption.AMMO, userInput);
if (purchaseResult.success) { if (purchaseResult.success) {
gameState.subPhase++; gameState.subPhase++;
return HandleSetup.handleSetupPhase(gameState, gameFlow); // Call setup phase again for next subphase return HandleSetup.handleSetupPhase(gameState); // Call setup phase again for next subphase
} else { } else {
responseMessage = purchaseResult.errorMessage || ''; responseMessage = purchaseResult.errorMessage || '';
responseMessage += `\n\n${MessageService.getRandomMessage( responseMessage += `\n\n${MessageService.getRandomMessage(
@ -109,7 +109,7 @@ export class HandleSetup {
const purchaseResult = HandleSetup.handleGenericPurchase(gameState, PurchaseOption.CLOTHING, userInput); const purchaseResult = HandleSetup.handleGenericPurchase(gameState, PurchaseOption.CLOTHING, userInput);
if (purchaseResult.success) { if (purchaseResult.success) {
gameState.subPhase++; gameState.subPhase++;
return HandleSetup.handleSetupPhase(gameState, gameFlow); // Call setup phase again for next subphase return HandleSetup.handleSetupPhase(gameState); // Call setup phase again for next subphase
} else { } else {
responseMessage = purchaseResult.errorMessage || ''; responseMessage = purchaseResult.errorMessage || '';
responseMessage += `\n\n${MessageService.getRandomMessage( responseMessage += `\n\n${MessageService.getRandomMessage(
@ -130,7 +130,7 @@ export class HandleSetup {
const purchaseResult = HandleSetup.handleGenericPurchase(gameState, PurchaseOption.MISC, userInput); const purchaseResult = HandleSetup.handleGenericPurchase(gameState, PurchaseOption.MISC, userInput);
if (purchaseResult.success) { if (purchaseResult.success) {
gameState.subPhase++; gameState.subPhase++;
return HandleSetup.handleSetupPhase(gameState, gameFlow); // Call setup phase again for next subphase return HandleSetup.handleSetupPhase(gameState); // Call setup phase again for next subphase
} else { } else {
responseMessage = purchaseResult.errorMessage || ''; responseMessage = purchaseResult.errorMessage || '';
responseMessage += `\n\n${MessageService.getRandomMessage( responseMessage += `\n\n${MessageService.getRandomMessage(
@ -145,7 +145,7 @@ export class HandleSetup {
gameState.subPhase = 0; gameState.subPhase = 0;
gameState.phase === PHASE_ENUM.SETUP ? gameState.phase = PHASE_ENUM.START_TURN : gameState.phase = PHASE_ENUM.ACTION_CHOICE; gameState.phase === PHASE_ENUM.SETUP ? gameState.phase = PHASE_ENUM.START_TURN : gameState.phase = PHASE_ENUM.ACTION_CHOICE;
await gameState.save() await gameState.save()
gameFlow.executeCurrentPhase() GameFlow.executeCurrentPhase(gameState)
break; break;
default: default:
responseMessage = `@J something went wrong come and fix it.\n\n ${JSON.stringify(gameState, null, 4)}` responseMessage = `@J something went wrong come and fix it.\n\n ${JSON.stringify(gameState, null, 4)}`

View File

@ -0,0 +1,61 @@
import GameState, { PHASE_ENUM } from '../game/gameState';
import GameFlow from '../game/gameFlow';
import { MessageService } from '../utils/MessageService';
export class travelPhase {
static async handleTravel(gameState: GameState, userInput?: string | number): Promise<void> {
let responseMessage = "";
if (!userInput || userInput?.toString().toLowerCase() === "start") {
responseMessage = "DO YOU WANT TO EAT\n(1) POORLY\n(2) MODERATELY\n(3) WELL: ";
await MessageService.statusUpdate(gameState, responseMessage);
return;
}
// Check if userInput is a number or can be converted to a valid number
if (isNaN(Number(userInput))) {
responseMessage = "Invalid input. Please enter a number.\n\n"
responseMessage += "DO YOU WANT TO EAT\n(1) POORLY\n(2) MODERATELY\n(3) WELL: ";
await MessageService.statusUpdate(gameState, responseMessage);
return; // Exit if input is not a valid number
}
let eatingChoice: number = parseInt(userInput.toString(), 10);
// Validate eating choice
if (eatingChoice < 1 || eatingChoice > 3) {
responseMessage = "Invalid choice.\n\n"
responseMessage += "DO YOU WANT TO EAT\n(1) POORLY\n(2) MODERATELY\n(3) WELL: ";
await MessageService.statusUpdate(gameState, responseMessage);
return;
}
// Calculate potential food consumption without updating the game state yet
let potentialAmountSpentOnFood = gameState.amountSpentOnFood - (8 + 5 * eatingChoice);
// Check if the potential amount spent on food is negative
if (potentialAmountSpentOnFood < 0) {
// If it would result in a negative value, inform the user they can't eat that well
responseMessage = "YOU CAN'T EAT THAT WELL\n\n";
responseMessage += "DO YOU WANT TO EAT\n(1) POORLY\n(2) MODERATELY\n(3) WELL: ";
await MessageService.statusUpdate(gameState, responseMessage);
return; // Exit the method to prevent further execution
} else {
// If the amount is sufficient, update the game state with the new amount
gameState.amountSpentOnFood = potentialAmountSpentOnFood;
}
// Calculate total mileage
gameState.totalMileageWholeTrip += 200 + (gameState.amountSpentOnAnimals - 220) / 5 + 10 * Math.random();
gameState.blizzardFlag = gameState.insufficientClothingFlag = false;
gameState.phase = PHASE_ENUM.RIDERS_ATTACK;
// Save the game state after making changes
await gameState.save();
// Continue with the game flow
GameFlow.executeCurrentPhase(gameState);
}
}

View File

@ -18,8 +18,7 @@ class WorkflowOrchestrator {
let gameState = await GameState.load(comment) let gameState = await GameState.load(comment)
if (parsedComment.command === 'restart') gameState = await gameState.reset(); if (parsedComment.command === 'restart') gameState = await gameState.reset();
const gameFlow = new GameFlow(gameState) await GameFlow.executeCurrentPhase(gameState, parsedComment.command)
await gameFlow.executeCurrentPhase(parsedComment.command)
await gameState.save() await gameState.save()
} catch (error) { } catch (error) {