job board checkpoint
This commit is contained in:
parent
0d2662a2b6
commit
4bf15b8b4f
|
@ -1,12 +1,29 @@
|
||||||
import random
|
import random
|
||||||
import collections
|
import collections
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from rolltable.tables import RollTable
|
||||||
from npc.generator.base import generate_npc
|
from npc.generator.base import generate_npc
|
||||||
|
|
||||||
|
|
||||||
Crime = collections.namedtuple('Crime', ['name', 'min_bounty', 'max_bounty'])
|
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:
|
class BaseJob:
|
||||||
"""
|
"""
|
||||||
The base class for random odd jobs.
|
The base class for random odd jobs.
|
||||||
|
@ -22,7 +39,7 @@ class BaseJob:
|
||||||
self._name = name
|
self._name = name
|
||||||
self._details = details
|
self._details = details
|
||||||
self._reward = reward
|
self._reward = reward
|
||||||
self._contact = contact
|
self._contact = contact or generate_npc()
|
||||||
self._location = location
|
self._location = location
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -87,8 +104,7 @@ class Bounty(BaseJob):
|
||||||
self._dead_or_alive = ' or '.join(dead_or_alive)
|
self._dead_or_alive = ' or '.join(dead_or_alive)
|
||||||
|
|
||||||
if not self._reward:
|
if not self._reward:
|
||||||
# need to round to the nearest 10 < 100, nearest 100 otherwise
|
reward = nearest(random.randint(self.crime.min_bounty, self.crime.max_bounty))
|
||||||
reward = round(random.randint(self.crime.min_bounty, self.crime.max_bounty), 5)
|
|
||||||
self._reward = f"{reward} Gold Pieces"
|
self._reward = f"{reward} Gold Pieces"
|
||||||
|
|
||||||
if not self._name:
|
if not self._name:
|
||||||
|
@ -117,6 +133,48 @@ class Bounty(BaseJob):
|
||||||
return self._target
|
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__()
|
classes = BaseJob.__subclasses__()
|
||||||
job_types = [c.__name__ for c in classes]
|
job_types = [c.__name__ for c in classes]
|
||||||
|
|
||||||
|
@ -126,4 +184,5 @@ def generate_job():
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
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.
|
- A jet black conical mushroom. The soil around it turns jet black. Said to grant visions when ingested.
|
||||||
- 5 GP
|
- 5 GP
|
||||||
- Rolling Cactus:
|
- 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
|
- 5 GP
|
||||||
- Orc's Fart:
|
- 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.
|
- 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