From 5c80a224ceed67d8ece1f28fd76036947f4b8456 Mon Sep 17 00:00:00 2001 From: rr- Date: Fri, 2 Nov 2018 14:28:53 +0100 Subject: [PATCH] mechanic: refactor creating new player --- pqcli/config.py | 33 ++++---- pqcli/mechanic.py | 159 ++++++++++++++++++++++++++++++++++---- pqcli/ui/new_game_view.py | 48 +++++------- 3 files changed, 174 insertions(+), 66 deletions(-) diff --git a/pqcli/config.py b/pqcli/config.py index 5ece9c2..ca8bee7 100644 --- a/pqcli/config.py +++ b/pqcli/config.py @@ -3,11 +3,6 @@ import typing as T from dataclasses import dataclass -def level_up_time(level) -> int: - # seconds - return 20 * level * 60 - - class Traits(enum.Enum): name = "Name" race = "Race" @@ -26,6 +21,20 @@ class Stat(enum.Enum): mp_max = "MP Max" +class Equipment(enum.Enum): + weapon = "Weapon" + shield = "Shield" + helm = "Helm" + hauberk = "Hauberk" + brassairts = "Brassairts" + vambraces = "Vambraces" + gauntlets = "Gauntlets" + gambeson = "Gambeson" + cuisses = "Cuisses" + greaves = "Greaves" + sollerets = "Sollerets" + + PRIME_STATS = [ Stat.strength, Stat.condition, @@ -38,20 +47,6 @@ PRIME_STATS = [ ALL_STATS = PRIME_STATS + [Stat.hp_max, Stat.mp_max] -EQUIPS = [ - "Weapon", - "Shield", - "Helm", - "Hauberk", - "Brassairts", - "Vambraces", - "Gauntlets", - "Gambeson", - "Cuisses", - "Greaves", - "Sollerets", -] - SPELLS = [ "Slime Finger", "Rabbit Punch", diff --git a/pqcli/mechanic.py b/pqcli/mechanic.py index 15e3c73..b3ff9de 100644 --- a/pqcli/mechanic.py +++ b/pqcli/mechanic.py @@ -1,9 +1,15 @@ import datetime +import enum import random import typing as T -from dataclasses import dataclass +from dataclasses import dataclass, field -from pqcli.config import CLASSES, PRIME_STATS, RACES, Class, Race, Stat +from pqcli.config import * + + +def level_up_time(level: int) -> int: + # seconds + return 20 * level * 60 def generate_name() -> str: @@ -20,7 +26,7 @@ def generate_name() -> str: @dataclass class Stats: - def __init__(self): + def __init__(self) -> None: self.values = {stat: 0 for stat in Stat} def __iter__(self) -> T.Iterable[T.Tuple[Stat, int]]: @@ -34,24 +40,145 @@ class Stats: @dataclass -class Player: +class Item: name: str - stats: Stats - race: Race - class_: Class - birthday: datetime.datetime + quantity: int + + +@dataclass +class Spell: + name: str + level: int + + +class Inventory: + def __init__(self, items: T.Optional[T.List[Item]] = []) -> None: + self.items = [] if items is None else items + + def add(self, item_name: str, quantity: int) -> None: + for item in self.items: + if item.name == item_name: + item.quantity += quantity + break + else: + self.items.append(Item(name=item_name, quantity=quantity)) + + +class SpellBook: + def __init__(self, spells: T.Optional[T.List[Item]] = None) -> None: + self.spells = [] if spells is None else spells + + def add(self, spell_name: str, level: int) -> None: + for item in self.spells: + if item.name == spell_name: + item.level += level + break + else: + self.spells.append(Spell(name=spell_name, level=level)) + + +class Bar: + def __init__(self, max_: int, position: int = 0) -> None: + self.position = position + self.max_ = max_ + + +class TaskType(enum.Enum): + task = "task" + plot = "plot" + + +@dataclass +class Task: + task_type: TaskType + length: int + description: str + + +class Player: + def __init__( + self, + name: str, + birthday: datetime.datetime, + race: Race, + class_: Class, + stats: Stats, + ) -> None: + self.name: str = name + self.birthday: datetime.datetime = birthday + self.race: Race = race + self.class_: Class = class_ + self.stats: Stats = stats + self.level = 1 + self.act = 0 + + self.queue: T.List[Task] = [ + Task( + TaskType.task, + 10, + "Experiencing an enigmatic and foreboding night vision", + ), + Task( + TaskType.task, + 6, + "Much is revealed about that wise old bastard you'd underestimated", + ), + Task( + TaskType.task, + 6, + "A shocking series of events leaves you alone and bewildered, but resolute", + ), + Task( + TaskType.task, + 4, + "Drawing upon an unrealized reserve of determination, you set out on a long and dangerous journey", + ), + Task(TaskType.plot, 2, "Loading"), + ] + + self.exp_bar = Bar(max_=level_up_time(1)) + self.encum_bar = Bar(max_=stats[Stat.strength] + 10) + self.quest_bar = Bar(max_=1) + self.task_bar = Bar(max_=2000) + self.plot_bar = Bar(max_=sum(task.length for task in self.queue)) + + self.inventory = Inventory([Item(name="Gold", quantity=0)]) + self.spell_book = SpellBook() + self.equipment: T.Dict[Equipment, str] = { + Equipment.weapon: "Sharp Rock", + Equipment.hauberk: "-3 Burlap", + } + + +def special_item() -> str: + return interesting_item() + " of " + random.choice(ITEM_OFS) + + +def interesting_item() -> str: + return random.choice(ITEM_ATTRIB) + " " + random.choice(SPECIALS) + + +def boring_item() -> str: + return random.choice(BORING_ITEMS) + + +def win_item(player: Player) -> None: + player.inventory.add(special_item(), 1) class Roster: def __init__(self) -> None: self.players: T.List[Player] = [] + def add_player(self, player: Player) -> None: + self.players.append(player) + class StatsBuilder: - def __init__(self): + def __init__(self) -> None: self.history: T.List[Stats] = [] - def roll(self): + def roll(self) -> Stats: stats = Stats() for stat in PRIME_STATS: stats[stat] = ( @@ -67,18 +194,16 @@ class StatsBuilder: self.history.append(stats) return stats - def unroll(self): + def unroll(self) -> Stats: self.history.pop() return self.history[-1] -def create_player(stats_builder: StatsBuilder) -> Player: +def create_player( + name: str, race: Race, class_: Class, stats: Stats +) -> Player: now = datetime.datetime.now() random.seed(now) return Player( - birthday=now, - name=generate_name(), - stats=stats_builder.roll(), - race=random.choice(RACES), - class_=random.choice(CLASSES), + birthday=now, name=name, race=race, class_=class_, stats=stats ) diff --git a/pqcli/ui/new_game_view.py b/pqcli/ui/new_game_view.py index 2b2fc76..2321ac4 100644 --- a/pqcli/ui/new_game_view.py +++ b/pqcli/ui/new_game_view.py @@ -5,15 +5,15 @@ import urwid import urwid_readline from pqcli.config import CLASSES, PRIME_STATS, RACES -from pqcli.mechanic import Player, StatsBuilder, create_player, generate_name +from pqcli.mechanic import Stats, StatsBuilder, generate_name from pqcli.ui.button import MenuButton from pqcli.ui.line_box import LineBox class StatsBox(urwid.Filler): - def __init__(self, player: Player, stats_builder: StatsBuilder) -> None: - self.player = player - self.stats_builder = stats_builder + def __init__(self) -> None: + self.stats_builder = StatsBuilder() + self.stats = self.stats_builder.roll() self.stat_labels = {stat: urwid.Text("0") for stat in PRIME_STATS} self.total_label = urwid.Text("0") self.update_values() @@ -59,48 +59,46 @@ class StatsBox(urwid.Filler): ) def on_roll_press(self, _user_data: T.Any) -> None: - self.player.stats = self.stats_builder.roll() + self.stats = self.stats_builder.roll() self.update_values() def on_unroll_press(self, _user_data: T.Any) -> None: try: - self.player.stats = self.stats_builder.unroll() + self.stats = self.stats_builder.unroll() except IndexError: return self.update_values() def update_values(self) -> None: for stat, edit in self.stat_labels.items(): - edit.set_text(str(self.player.stats[stat])) + edit.set_text(str(self.stats[stat])) self.total_label.set_text( - str( - sum( - self.player.stats[stat] for stat in self.stat_labels.keys() - ) - ) + str(sum(self.stats[stat] for stat in self.stat_labels.keys())) ) class RaceBox(LineBox): - def __init__(self, player: Player) -> None: + def __init__(self) -> None: race_checkboxes = [] + self.race = random.choice(RACES) for race in RACES: urwid.RadioButton( group=race_checkboxes, label=race.name, - state=race.name == player.race.name, + state=race.name == self.race.name, ) super().__init__(urwid.ListBox(race_checkboxes), title="Race") class ClassBox(LineBox): - def __init__(self, player: Player) -> None: + def __init__(self) -> None: class_checkboxes = [] + self.class_ = random.choice(CLASSES) for class_ in CLASSES: urwid.RadioButton( group=class_checkboxes, label=class_.name, - state=class_.name == player.class_.name, + state=class_.name == self.class_.name, ) super().__init__(urwid.ListBox(class_checkboxes), title="Class") @@ -110,24 +108,17 @@ class NewGameView(urwid.Pile): self.on_confirm = on_confirm self.on_cancel = on_cancel - stats_builder = StatsBuilder() - self.player = create_player(stats_builder) - - race_box = RaceBox(self.player) - class_box = ClassBox(self.player) - stats_box = StatsBox(self.player, stats_builder) + race_box = RaceBox() + class_box = ClassBox() + stats_box = StatsBox() self.char_name_edit = urwid_readline.ReadlineEdit( - "Name: ", self.player.name + "Name: ", generate_name() ) generate_char_name_btn = MenuButton( "Generate random name", on_press=self.on_generate_char_name_press ) - urwid.connect_signal( - self.char_name_edit, "postchange", self.on_char_name_change - ) - super().__init__( [ (1, urwid.Filler(self.char_name_edit)), @@ -154,9 +145,6 @@ class NewGameView(urwid.Pile): self.char_name_edit.edit_text = generate_name() self.char_name_edit.edit_pos = len(self.char_name_edit.edit_text) - def on_char_name_change(self, widget: urwid.Text, old_text: str) -> None: - self.player.name = widget.edit_text - def on_generate_char_name_press(self, _user_data: T.Any) -> None: self.generate_random_char_name()