job board checkpoint
This commit is contained in:
parent
0d2662a2b6
commit
4bf15b8b4f
|
@ -1,12 +1,29 @@
|
|||
import random
|
||||
import collections
|
||||
from pathlib import Path
|
||||
|
||||
from rolltable.tables import RollTable
|
||||
from npc.generator.base import generate_npc
|
||||
|
||||
|
||||
Crime = collections.namedtuple('Crime', ['name', 'min_bounty', 'max_bounty'])
|
||||
|
||||
|
||||
def generate_location(frequency='default'):
|
||||
source = Path("sources/locations.yaml")
|
||||
rt = RollTable([source.read_text()], hide_rolls=True, frequency=frequency)
|
||||
return random.choice(rt.rows[1:])[1]
|
||||
|
||||
|
||||
def nearest(value, step=50):
|
||||
if value < step:
|
||||
return step
|
||||
remainder = value % step
|
||||
if remainder > int(step / 2):
|
||||
return value - remainder + step
|
||||
return value - remainder
|
||||
|
||||
|
||||
class BaseJob:
|
||||
"""
|
||||
The base class for random odd jobs.
|
||||
|
@ -22,7 +39,7 @@ class BaseJob:
|
|||
self._name = name
|
||||
self._details = details
|
||||
self._reward = reward
|
||||
self._contact = contact
|
||||
self._contact = contact or generate_npc()
|
||||
self._location = location
|
||||
|
||||
@property
|
||||
|
@ -87,8 +104,7 @@ class Bounty(BaseJob):
|
|||
self._dead_or_alive = ' or '.join(dead_or_alive)
|
||||
|
||||
if not self._reward:
|
||||
# need to round to the nearest 10 < 100, nearest 100 otherwise
|
||||
reward = round(random.randint(self.crime.min_bounty, self.crime.max_bounty), 5)
|
||||
reward = nearest(random.randint(self.crime.min_bounty, self.crime.max_bounty))
|
||||
self._reward = f"{reward} Gold Pieces"
|
||||
|
||||
if not self._name:
|
||||
|
@ -117,6 +133,48 @@ class Bounty(BaseJob):
|
|||
return self._target
|
||||
|
||||
|
||||
class Determinant(BaseJob):
|
||||
"""
|
||||
Hiring the services of a Determinant to resolve a dispute.
|
||||
"""
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
class Escort(BaseJob):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self._contact = generate_npc()
|
||||
self._location = generate_location('settlements')
|
||||
self._destination = generate_location('default')
|
||||
self._reward = f"{nearest(random.randint(5, 20), step=5)} GP/day"
|
||||
self._name = (
|
||||
f"Accompany {self.contact} from {self.location} to "
|
||||
f"{self._destination}. {self.reward}"
|
||||
)
|
||||
|
||||
|
||||
class Foraging(BaseJob):
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
source = Path("sources/flora.yaml")
|
||||
rt = RollTable([source.read_text()], hide_rolls=True)
|
||||
|
||||
# [ rarity, name, descr, val ]
|
||||
self._ingredient = random.choice(rt.rows)
|
||||
|
||||
self._amount = nearest(random.randint(0, 300), step=25)
|
||||
value = self._amount * int(self._ingredient[3].split(' ')[0])
|
||||
bonus = nearest(random.randint(0, 200))
|
||||
self._reward = f"{value} GP + {bonus} GP Bonus"
|
||||
|
||||
self._name = f"{self.reward} for {self._amount} {self._ingredient[1]}"
|
||||
self._contact = "Andok"
|
||||
self._location = "Andok's Apothecary, Tano's Edge"
|
||||
|
||||
|
||||
classes = BaseJob.__subclasses__()
|
||||
job_types = [c.__name__ for c in classes]
|
||||
|
||||
|
@ -126,4 +184,5 @@ def generate_job():
|
|||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(Bounty())
|
||||
for i in range(10):
|
||||
print(Escort())
|
||||
|
|
|
@ -142,7 +142,7 @@ Weird:
|
|||
- A jet black conical mushroom. The soil around it turns jet black. Said to grant visions when ingested.
|
||||
- 5 GP
|
||||
- Rolling Cactus:
|
||||
- A globular cactus that rolls and bounces freely in the wind. 1 gallon of water can be harvested from 10 cacti.
|
||||
- A globular cactus that rolls and bounces freely in the wind.
|
||||
- 5 GP
|
||||
- Orc's Fart:
|
||||
- A large succulent up to 4ft in height, which continually produces a pungent gas, swelling the bulb. When the bulb is forced open, a toxic cloud 20ft in diameter is expelled. DC 13 CON save or 1d4 poison dmg.
|
||||
|
|
27
deadsands/sources/locations.yaml
Normal file
27
deadsands/sources/locations.yaml
Normal file
|
@ -0,0 +1,27 @@
|
|||
# locations
|
||||
metadata:
|
||||
headers:
|
||||
- Name
|
||||
frequencies:
|
||||
default:
|
||||
Settlements: 0.5
|
||||
Sahwat: 0.5
|
||||
settlements:
|
||||
Settlements: 1.0
|
||||
Sahwat: 0.0
|
||||
sahwat:
|
||||
Settlements: 0.0
|
||||
Sahwat: 1.0
|
||||
Settlements:
|
||||
- Tano's Edge
|
||||
- The Heap
|
||||
- Gazakh Noch
|
||||
- Poshni Koth
|
||||
Sahwat:
|
||||
- Blooming Wastes
|
||||
- Dust River Canyon
|
||||
- Gopher Gulch
|
||||
- Calamity Ridge
|
||||
- The Haunted Hills
|
||||
- Bone City
|
||||
- The Undersands
|
21
deadsands/test/test_jobs.py
Normal file
21
deadsands/test/test_jobs.py
Normal file
|
@ -0,0 +1,21 @@
|
|||
import pytest
|
||||
|
||||
from site_tools import jobs
|
||||
|
||||
|
||||
@pytest.mark.parametrize('value, step, expected', [
|
||||
(0, 50, 50),
|
||||
(49, 50, 50),
|
||||
(51, 50, 50),
|
||||
(99, 50, 100),
|
||||
(100, 50, 100),
|
||||
(101, 50, 100),
|
||||
(124, 50, 100),
|
||||
(125, 50, 100),
|
||||
(126, 50, 150),
|
||||
(150, 50, 150),
|
||||
(151, 50, 150),
|
||||
(199, 50, 200)
|
||||
])
|
||||
def test_nearest(value, step, expected):
|
||||
assert jobs.nearest(value, step=step) == expected
|
Loading…
Reference in New Issue
Block a user