Skip to content

Commit

Permalink
Merge pull request #30 from mmacy/tui-character-mgmt
Browse files Browse the repository at this point in the history
auto-gen character and dungeon work
  • Loading branch information
mmacy committed Nov 30, 2023
2 parents 1d261ab + 4360b5e commit 505dad5
Show file tree
Hide file tree
Showing 19 changed files with 601 additions and 267 deletions.
Binary file modified images/exploration-screen-01.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 4 additions & 2 deletions osrgame/osrgame/osrgame.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import random
from textual.app import App, ComposeResult
from screen_character import CharacterScreen
from screen_welcome import WelcomeScreen
from screen_explore import ExploreScreen
from screen_adventure_browser import AdventureBrowserScreen

from osrlib.adventure import Adventure
from osrlib.constants import ADVENTURE_NAMES, DUNGEON_NAMES
from osrlib.dungeon import Dungeon
from osrlib.dungeon_master import DungeonMaster
from osrlib.game_manager import logger
Expand Down Expand Up @@ -57,7 +59,7 @@ def set_active_adventure(self, adventure: Adventure = None) -> None:
if adventure is not None:
self.adventure = adventure
else:
default_adventure = Adventure("Raving Mad Under the Mystic Forest")
default_adventure = Adventure(random.choice(ADVENTURE_NAMES))
default_adventure.description = "An adventure for 4-6 characters of levels 1-3."
default_adventure.introduction = (
"In the heart of the cursed Mystic Forest, a tale as old as time stirs once again. Legends "
Expand All @@ -72,7 +74,7 @@ def set_active_adventure(self, adventure: Adventure = None) -> None:
"Mad Mage."
)

dungeon = Dungeon.get_random_dungeon("Dungeon of the Raving Mage",
dungeon = Dungeon.get_random_dungeon(random.choice(DUNGEON_NAMES),
"The first level of the home of the ancient wizard lich Glofarnux, its "
"entrance hidden in a forgotten glade deep in the cursed Mystic Forest.",
num_locations=50, use_ai=True, openai_model=self.openai_model)
Expand Down
3 changes: 2 additions & 1 deletion osrgame/osrgame/screen_adventure_browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from textual.widgets import Footer, Header, Static

from osrlib.adventure import Adventure
from osrlib.utils import get_data_dir_path

from widgets import JsonFilteredDirectoryTree

Expand All @@ -24,7 +25,7 @@ class AdventureBrowserScreen(Screen):
def compose(self) -> ComposeResult:
"""Compose our UI."""
# Set the path to the current user's home directory.
path = os.path.expanduser("~") + "/"
path = get_data_dir_path("osrlib")# / "adventures"
yield Header()
with Container():
yield JsonFilteredDirectoryTree(path, id="tree-view")
Expand Down
11 changes: 11 additions & 0 deletions osrgame/osrgame/screen_character.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from typing import Any, Coroutine
from textual import events
from textual.app import ComposeResult
from textual.screen import Screen
from textual.widgets import Button, Header, Footer, Log
from textual.events import Event

from widgets import CharacterStatsBox, AbilityTable, ItemTable, SavingThrowTable, CharacterScreenButtons

Expand Down Expand Up @@ -58,6 +61,14 @@ def action_next_character(self) -> None:
self.app.adventure.active_party.set_next_character_as_active()
self.on_mount()


def on_event(self, event: Event) -> Coroutine[Any, Any, None]:
"""Handle events."""
# HACK: This is a hack to get the screen to update when the user switches to it.
if isinstance(event, events.ScreenResume):
self.on_mount()
return super().on_event(event)

def reroll(self):
"""Rolls the ability scores of the active character."""
self.app.adventure.active_party.active_character.roll_abilities()
Expand Down
2 changes: 1 addition & 1 deletion osrgame/osrgame/screen_explore.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def perform_move_action(self, direction: Direction, log_message: str) -> None:
dm_response = self.dungeon_master.move_party(direction)

self.query_one("#dm_log").write_line(
"> " + str(self.dungeon_master.adventure.active_dungeon.current_location)
""#"> " + str(self.dungeon_master.adventure.active_dungeon.current_location)
)
self.query_one("#dm_log").write_line(wrap_text(dm_response))

Expand Down
12 changes: 9 additions & 3 deletions osrgame/osrgame/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@
from textual.widgets import Button, DataTable, Log, Static, DirectoryTree


from osrlib import Item
from osrlib.item import Item
from osrlib.utils import format_modifiers


class WelcomeScreenButtons(Container):
def compose(self) -> ComposeResult:
yield Button("Start default adventure", id="btn-adventure-default", classes="button")
yield Button("Random adventure", id="btn-adventure-default", classes="button")
yield Button("Load adventure", id="btn-adventure-load", classes="button")
yield Button("Create adventure", id="btn-adventure-create", classes="button")
yield Button("Quit", id="btn-quit", classes="button")
Expand All @@ -33,7 +33,7 @@ class CharacterStatsBox(Container):
pc_hp = reactive(0)
pc_ac = reactive(0)

BORDER_TITLE = "CHARACTER RECORD SHEET"
BORDER_TITLE = "Character Record Sheet"

def compose(self) -> ComposeResult:
yield Static(id="name")
Expand Down Expand Up @@ -110,6 +110,12 @@ def update_table(self):
]
table.add_row(*row_data, key=pc.name)

def on_data_table_row_selected(self, event: DataTable.RowSelected) -> None:
"""Called when the user selects a row in the party roster table."""
event.stop()
party = self.app.adventure.active_party
party.set_active_character(party.members[event.cursor_row])
#self.update_table()

class SavingThrowTable(Container):
def compose(self) -> ComposeResult:
Expand Down
9 changes: 5 additions & 4 deletions osrgame/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

99 changes: 1 addition & 98 deletions osrlib/osrlib/__init__.py
Original file line number Diff line number Diff line change
@@ -1,98 +1 @@
from .ability import (
AbilityType,
Ability,
Strength,
Dexterity,
Constitution,
Intelligence,
Wisdom,
Charisma,
)
from .adventure import (
Adventure,
)
from .character_classes import (
CharacterClass,
CharacterClassType,
ClassLevel,
all_character_classes,
class_levels,
cleric_levels,
commoner_levels,
dwarf_levels,
elf_levels,
fighter_levels,
halfling_levels,
magic_user_levels,
thief_levels,
)
from .combat import (
AttackType,
ModifierType,
)
from .dice_roller import (
DiceRoll,
roll_dice,
)
from .dungeon_master import (
DungeonMaster,
)
from .dungeon import (
Dungeon,
Encounter,
Exit,
Location,
LocationNotFoundError,
Direction,
)
from .enums import (
CharacterClassType,
PartyReaction,
OpenAIModelVersion,
)
from .game_manager import (
GameManager,
StorageType,
)
from .inventory import Inventory
from .item import (
Item,
ItemType,
Armor,
Weapon,
Spell,
ItemAlreadyHasOwnerError,
ItemAlreadyInInventoryError,
ItemAlreadyInQuestError,
ItemEquippedError,
ItemNotEquippedError,
ItemNotInInventoryError,
ItemNotUsableError,
)
from .item_factories import (
armor_data,
magic_armor_data,
ArmorFactory,
equipment_data,
EquipmentFactory,
weapon_data,
magic_weapon_data,
WeaponFactory,
ItemDataNotFoundError,
equip_party,
)
from .monster import (
Monster,
)
from .party import (
Party,
PartyAtCapacityError,
PartyInStartedAdventureError,
CharacterNotInPartyError,
CharacterAlreadyInPartyError,
get_default_party,
)
from .player_character import PlayerCharacter, Alignment
from .quest import Quest
from .saving_throws import saving_throws
from .utils import format_modifiers
"""OSR Library is a Python library for powering old-school turn-based role-playing games (OSRPGs)."""
10 changes: 6 additions & 4 deletions osrlib/osrlib/adventure.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from osrlib.dungeon import Dungeon
from osrlib.party import Party
from osrlib.quest import Quest
from osrlib.utils import get_data_dir_path, create_dir_tree_if_not_exist


class DungeonNotFoundError(Exception):
Expand Down Expand Up @@ -168,7 +169,7 @@ def save_adventure(self, file_path: str = None) -> str:
Args:
file_path (str, optional): The path where the file will be saved.
If None, saves in the user's home directory.
If None, saves in the default data directory.
Returns:
str: The path where the file was saved.
Expand All @@ -183,8 +184,9 @@ def save_adventure(self, file_path: str = None) -> str:
now = datetime.datetime.now()
timestamp = now.strftime("%Y%m%d_%H%M%S") # YYYYMMDD_HHMMSS
filename = f"{self.name}_{timestamp}.json".replace(" ", "_").lower()
home_dir = os.path.expanduser("~")
file_path = os.path.join(home_dir, filename)
save_dir = get_data_dir_path("osrlib")# / "adventures"
create_dir_tree_if_not_exist(save_dir)
file_path = save_dir / filename

try:
with open(file_path, "w") as file:
Expand All @@ -194,7 +196,7 @@ def save_adventure(self, file_path: str = None) -> str:
logger.error(f"Failed to save adventure to {file_path}: {e}")
raise

return file_path
return str(file_path)

@staticmethod
def load_adventure(file_path: str = None) -> "Adventure":
Expand Down
Loading

0 comments on commit 505dad5

Please sign in to comment.