diff --git a/marvin_sw_text_adventure/console.py b/marvin_sw_text_adventure/console.py index a9463af..2298462 100644 --- a/marvin_sw_text_adventure/console.py +++ b/marvin_sw_text_adventure/console.py @@ -1,3 +1,3 @@ from rich.console import Console -console = Console() +console = Console(record=True, width=80) diff --git a/marvin_sw_text_adventure/game.py b/marvin_sw_text_adventure/game.py index 459aa70..b6c2c02 100644 --- a/marvin_sw_text_adventure/game.py +++ b/marvin_sw_text_adventure/game.py @@ -1,11 +1,12 @@ -from marvin import ai_fn -from rich.table import Table +from typing import List, Tuple +import atexit +from marvin import ai_fn import pydantic from pydantic import Field -from typing import List, Tuple from rich.panel import Panel from rich.prompt import Prompt +from rich.table import Table from marvin_sw_text_adventure.console import console @@ -20,29 +21,42 @@ def create_backstory(name: str) -> str: "create a backstory for a character" +class Game(pydantic.BaseModel): + name: str = Field(..., description="The name of the game") + id: str = Field(..., description="The id of the game") + + class Mission(pydantic.BaseModel): - name: str = Field(..., description='The name of a brand new never before heard of star wars mission') - place: str = Field(..., description='The place of the mission') - leader: str = Field(..., description='The name of the leader of the mission') - year: int = Field(..., description='The year of the mission') + name: str = Field( + ..., + description="The name of a brand new never before heard of star wars mission", + ) + place: str = Field(..., description="The place of the mission") + leader: str = Field(..., description="The name of the leader of the mission") + year: int = Field(..., description="The year of the mission") description: str = Field( - ..., description='The description of the brand new never before heard of star wars mission with important words surrounded by [b][/b]') - risk: int = Field(..., - description='The risk of the mission in health the character will loose') - reward: int = Field(..., - description='The reward of the mission in imperial credits') - image_prompt: str = Field(..., - description='An ai image generator prompt of the mission') + ..., + description="The description of the brand new never before heard of star wars mission with important words surrounded by [b][/b]", + ) + risk: int = Field( + ..., description="The risk of the mission in health the character will loose" + ) + reward: int = Field( + ..., description="The reward of the mission in imperial credits" + ) + image_prompt: str = Field( + ..., description="An ai image generator prompt of the mission" + ) @property def stats(self) -> Table: table = Table(title=self.name, show_edge=False, show_header=False) # table = Table(show_header=False) - table.add_row('place', self.place) - table.add_row('year', str(self.year)) - table.add_row('risk', f'{self.risk} hp') - table.add_row('reward', f'{self.reward} credits') - table.add_row('leader', self.leader) + table.add_row("place", self.place) + table.add_row("year", str(self.year)) + table.add_row("risk", f"{self.risk} hp") + table.add_row("reward", f"{self.reward} credits") + table.add_row("leader", self.leader) return table @@ -54,37 +68,41 @@ class Mission(pydantic.BaseModel): class MissionResult(pydantic.BaseModel): - success: bool = Field(..., description='The success of the mission') - imperial_credits_spent: int = Field(..., - description='The imperial credits spent on the mission') - imperial_credits_earned: int = Field(..., - description='The imperial credits earned on the mission') - health_lost: int = Field(..., description='The health lost on the mission') - health_gained: int = Field(..., description='The health gained on the mission') - story: str = Field(..., description='The story of the mission') - image_prompt: str = Field(..., - description='An ai image generator prompt of the mission') - fuel_used: int = Field(..., description='The fuel used on the mission') + success: bool = Field(..., description="The success of the mission") + imperial_credits_spent: int = Field( + ..., description="The imperial credits spent on the mission" + ) + imperial_credits_earned: int = Field( + ..., description="The imperial credits earned on the mission" + ) + health_lost: int = Field(..., description="The health lost on the mission") + health_gained: int = Field(..., description="The health gained on the mission") + story: str = Field(..., description="The story of the mission") + image_prompt: str = Field( + ..., description="An ai image generator prompt of the mission" + ) + fuel_used: int = Field(..., description="The fuel used on the mission") class Ship(pydantic.BaseModel): - name: str = Field(..., description='The name of the ship') - description: str = Field(..., description='The description of the ship') - capacity: int = Field(..., description='The capacity of the ship') - ship_type: str = Field(..., description='The type of the ship') - year_built: int = Field(..., description='The year built of the ship') - capacity: int = Field(..., description='The capacity of the ship') - fuel_type: str = Field(..., description='The fuel type of the ship') - fuel_level: int = Field(..., description='The fuel level of the ship') - image_prompt: str = Field(..., - description='An ai image generator prompt of the mission') + name: str = Field(..., description="The name of the ship") + description: str = Field(..., description="The description of the ship") + capacity: int = Field(..., description="The capacity of the ship") + ship_type: str = Field(..., description="The type of the ship") + year_built: int = Field(..., description="The year built of the ship") + capacity: int = Field(..., description="The capacity of the ship") + fuel_type: str = Field(..., description="The fuel type of the ship") + fuel_level: int = Field(..., description="The fuel level of the ship") + image_prompt: str = Field( + ..., description="An ai image generator prompt of the mission" + ) @property def stats(self) -> Table: table = Table(title=self.name, show_edge=False, show_header=False) - table.add_row('year built', str(self.year_built)) - table.add_row('capacity', str(self.capacity)) - table.add_row('fuel level', str(self.fuel_level)) + table.add_row("year built", str(self.year_built)) + table.add_row("capacity", str(self.capacity)) + table.add_row("fuel level", str(self.fuel_level)) return table @property @@ -95,40 +113,50 @@ class Ship(pydantic.BaseModel): class StarWarsCharacter(pydantic.BaseModel): - name: str = Field(..., - description='The name of a brand new never before heard of star wars character') - imperial_credits: int = Field(..., - description='The imperial credits of the character') - health: int = Field(..., description='The health of the character') - home_planet: str = Field(..., - description='The name of the planet where the character was born') - age: int = Field(..., description='The age of the character') - birth_year_bby: int = Field(..., description='The birth year of the character') - backstory: str = Field(..., description='The backstory of the character') - ship: Ship = Field(..., - description='The name of the ship where the character operates') - side: str = Field(..., description='The side of the character') - city: str = Field(..., description='The name of the city where the character lives') - friends: List[str] = Field(..., - description='The names of the friends of the character') - team: str = Field(..., - description='The name of the team that the character belongs to') - enemies: List[str] = Field(..., - description='The names of the enemies of the character') - mission: Mission = Field(..., description='The current mission of the character') - role: str = Field(..., description='The role of the character') - image_prompt: str = Field(..., - description='An ai image generator prompt of the mission') + name: str = Field( + ..., + description="The name of a brand new never before heard of star wars character", + ) + imperial_credits: int = Field( + ..., description="The imperial credits of the character" + ) + health: int = Field(..., description="The health of the character") + home_planet: str = Field( + ..., description="The name of the planet where the character was born" + ) + age: int = Field(..., description="The age of the character") + birth_year_bby: int = Field(..., description="The birth year of the character") + backstory: str = Field(..., description="The backstory of the character") + ship: Ship = Field( + ..., description="The name of the ship where the character operates" + ) + side: str = Field(..., description="The side of the character") + city: str = Field(..., description="The name of the city where the character lives") + friends: List[str] = Field( + ..., description="The names of the friends of the character" + ) + team: str = Field( + ..., description="The name of the team that the character belongs to" + ) + enemies: List[str] = Field( + ..., description="The names of the enemies of the character" + ) + mission: Mission = Field(..., description="The current mission of the character") + role: str = Field(..., description="The role of the character") + image_prompt: str = Field( + ..., description="An ai image generator prompt of the mission" + ) previous_missions: List[Tuple[Mission, MissionResult]] = Field( - [], description='The previous missions of the character') + [], description="The previous missions of the character" + ) @property def stats(self) -> Table: table = Table(title=self.name, show_edge=False, show_header=False) # table = Table(show_header=False) - table.add_row('health', str(self.health)) - table.add_row('imperial credits', str(self.imperial_credits)) - table.add_row('fuel level', str(self.ship.fuel_level)) + table.add_row("health", str(self.health)) + table.add_row("imperial credits", str(self.imperial_credits)) + table.add_row("fuel level", str(self.ship.fuel_level)) return table @property @@ -139,34 +167,57 @@ class StarWarsCharacter(pydantic.BaseModel): table.add_row(self.ship.stats, self.ship.description) table.add_row() table.add_row(self.mission.stats, self.mission.description) - return Panel(table, title=f'{self.name}\'s Mission Card', title_align='left', ) + return Panel( + table, + title=f"{self.name}'s Mission Card", + title_align="left", + ) -@ ai_fn +@ai_fn def did_complete_mission(character: StarWarsCharacter, action: str) -> MissionResult: "check if a character completed the mission or if they failed" -@ ai_fn -def get_next_mission(character: StarWarsCharacter, action: str, last_mission_success: bool) -> Mission: +@ai_fn +def get_next_mission( + character: StarWarsCharacter, action: str, last_mission_success: bool +) -> Mission: """given a character, their action and the last mission success, return the next mission""" -@ ai_fn +@ai_fn +def create_game(character: StarWarsCharacter) -> Game: + "create a new game" + + +@ai_fn def create_character() -> StarWarsCharacter: "create a new character" + console.save_text(f"{game.name}-{character.name}-{game.id}.txt") + def game(): - console.print('generating your character') + console.print("generating your character") prompt = Prompt() character = create_character() + game = create_game(character) - while character.health > 0 and character.imperial_credits > 0 and character.ship.fuel_level > 0: + def save(): + console.save_text(f"{game.name}-{character.name}-{game.id}.txt") + + atexit.register(save) + + while ( + character.health > 0 + and character.imperial_credits > 0 + and character.ship.fuel_level > 0 + ): console.print(character.describe) - action = prompt.ask('What do you do ❯') + action = prompt.ask("What do you do ❯") result = did_complete_mission(character, action) character.previous_missions.append((character.mission, result)) # keep only the last 5 missions @@ -177,21 +228,21 @@ def game(): character.health += result.health_gained character.ship.fuel_level -= result.fuel_used console.print() - console.print('Your mission has been completed') + console.print("Your mission has been completed") console.print(result.story) - console.print(f'You earned {result.imperial_credits_earned} imperial credits') - console.print(f'You spent {result.imperial_credits_spent} imperial credits') - console.print(f'You gained {result.health_gained} health') - console.print(f'You lost {result.health_lost} health') + console.print(f"You earned {result.imperial_credits_earned} imperial credits") + console.print(f"You spent {result.imperial_credits_spent} imperial credits") + console.print(f"You gained {result.health_gained} health") + console.print(f"You lost {result.health_lost} health") character.mission = get_next_mission(character, action, result.success) if character.health <= 0: - console.print('You are dead') + console.print("You are dead") if character.imperial_credits <= 0: - console.print('You lost all your imperial credits') + console.print("You lost all your imperial credits") if character.ship.fuel_level <= 0: - console.print('You lost all your fuel') + console.print("You lost all your fuel") -if __name__ == '__main__': +if __name__ == "__main__": game()