249 lines
8.8 KiB
Python
249 lines
8.8 KiB
Python
import atexit
|
||
from typing import List, Tuple
|
||
|
||
from marvin import ai_fn
|
||
from numpy import character
|
||
import pydantic
|
||
from pydantic import Field
|
||
from rich.panel import Panel
|
||
from rich.prompt import Prompt
|
||
from rich.table import Table
|
||
|
||
from marvin_sw_text_adventure.console import console
|
||
|
||
|
||
@ai_fn
|
||
def get_star_wars_character() -> str:
|
||
"return a brand new never before heard of star wars character"
|
||
|
||
|
||
@ai_fn
|
||
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")
|
||
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"
|
||
)
|
||
|
||
@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)
|
||
|
||
return table
|
||
|
||
@property
|
||
def describe(self) -> str:
|
||
table = Table(show_header=False)
|
||
table.add_row(self.stats, self.description)
|
||
return table
|
||
|
||
|
||
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")
|
||
|
||
|
||
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"
|
||
)
|
||
|
||
@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))
|
||
return table
|
||
|
||
@property
|
||
def describe(self):
|
||
table = Table(show_header=False, show_edge=False)
|
||
table.add_row(self.stats, self.description)
|
||
return table
|
||
|
||
|
||
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"
|
||
)
|
||
previous_missions: List[Tuple[Mission, MissionResult]] = Field(
|
||
[], 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))
|
||
return table
|
||
|
||
@property
|
||
def describe(self):
|
||
table = Table(show_header=False, show_edge=False)
|
||
table.add_row(self.stats, self.backstory)
|
||
table.add_row()
|
||
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",
|
||
)
|
||
|
||
|
||
@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:
|
||
"""given a character, their action and the last mission success, return the next mission"""
|
||
|
||
|
||
@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")
|
||
|
||
prompt = Prompt(console=console)
|
||
|
||
character = create_character()
|
||
game = create_game(character)
|
||
|
||
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 ❯")
|
||
result = did_complete_mission(character, action)
|
||
character.previous_missions.append((character.mission, result))
|
||
# keep only the last 5 missions
|
||
character.previous_missions = character.previous_missions[-5:]
|
||
character.imperial_credits -= result.imperial_credits_spent
|
||
character.imperial_credits += result.imperial_credits_earned
|
||
character.health -= result.health_lost
|
||
character.health += result.health_gained
|
||
character.ship.fuel_level -= result.fuel_used
|
||
console.print()
|
||
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")
|
||
character.mission = get_next_mission(character, action, result.success)
|
||
|
||
if character.health <= 0:
|
||
console.print("You are dead")
|
||
if character.imperial_credits <= 0:
|
||
console.print("You lost all your imperial credits")
|
||
if character.ship.fuel_level <= 0:
|
||
console.print("You lost all your fuel")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
game()
|