mirror of
https://github.com/rr-/pq-cli.git
synced 2026-09-29 06:44:00 -06:00
mechanic: refactor creating new player
This commit is contained in:
+14
-19
@@ -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",
|
||||
|
||||
+142
-17
@@ -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
|
||||
)
|
||||
|
||||
+18
-30
@@ -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()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user