BitD Example #9
Replies: 3 comments 2 replies
-
Thanks for the question, @synthality! There are a ton of ways to skin that proverbial cat, some more esoteric and complicated than others. Some of those might be fun puzzles, or useful exercises for optimizing performance in environments calling for dozens (or hundreds!) of dice. But I have found it's best to start simple and obvious and move from there. To that end, I think
With that out of the way, here's a translation about as close in spirit and form to original source as I can muster: from dyce import H, P
d6 = H(6)
def blades(roll):
if roll[-1] == 6:
return 2 + (len(roll) > 1 and roll[-2] == 6)
return int(roll[-1] >= 4)
results = {
n: P.foreach(blades, roll=P((2@P(d6)).h(0)) if n == 0 else n@P(d6))
for n in range(0, 8)
} I don't find that particularly helpful as a learning tool, however, because there's a lot of ball-hiding there. To that end, I've created a much more thorough exploration of iterations on that approach that try to leverage I hope that helps, but I also know that designing ergonomic interfaces is hard. If you are willing, I'm curious to hear your take on what might have made a |
Beta Was this translation helpful? Give feedback.
-
FYI, I'm currently working on what I hope to be a slightly more flexible/ergonomic solution than from enum import IntEnum
from dyce import H, P
from dyce.expandable import HResult, PResult, expandable
class BitdResult(IntEnum):
BAD_TIMES = 0
MESSY_SUCCESS = 1
CLEAN_SUCCESS = 2
CRITICAL_SUCCESS = 3
d6bitd = H((
BitdResult.BAD_TIMES, # 1
BitdResult.BAD_TIMES, # 2
BitdResult.BAD_TIMES, # 3
BitdResult.MESSY_SUCCESS, # 4
BitdResult.MESSY_SUCCESS, # 5
BitdResult.CLEAN_SUCCESS, # 6
))
@expandable
def blades(result: HResult | PResult):
if isinstance(result, PResult): # from n@P(6) where n > 0
best = result.roll[-1]
next_best = result.roll[-2] if len(result.roll) > 1 else 0
elif isinstance(result, HResult): # from least_of_2d6bitd where n is 0
best = result.outcome
next_best = 0
else:
assert False, "unrecognized result type {result!r}"
if best == BitdResult.CLEAN_SUCCESS == next_best:
return BitdResult.CRITICAL_SUCCESS
else:
return BitdResult(best)
pool_2d6bitd: P = 2@P(d6bitd)
least_of_2d6bitd: H = pool_2d6bitd.h(0)
results = {
n: blades(result=least_of_2d6bitd if n == 0 else n@P(d6bitd))
for n in range(0, 8)
} |
Beta Was this translation helpful? Give feedback.
-
It's been awhile since I offered anything here, and while the above approaches still work, I wanted to revisit in light of introducing the from dyce import H, P
from dyce.evaluation import PResult, PWithSelection, foreach
from enum import IntEnum, auto
class BitdResult(IntEnum):
BAD_TIMES = auto()
MESSY_SUCCESS = auto()
CLEAN_SUCCESS = auto()
CRITICAL_SUCCESS = auto()
d_bitd = H((
BitdResult.BAD_TIMES, # 1
BitdResult.BAD_TIMES, # 2
BitdResult.BAD_TIMES, # 3
BitdResult.MESSY_SUCCESS, # 4
BitdResult.MESSY_SUCCESS, # 5
BitdResult.CLEAN_SUCCESS, # 6
))
def bitd(n: int) -> H:
assert n >= 0
def _mechanic(res: PResult):
assert len(res.roll) >= 2
if res.roll[-2] == BitdResult.CLEAN_SUCCESS:
# Because rolls are ordered least-to-greatest, if the penultimate
# value is a clean success (i.e., a six), then the ultimate value
# must be one as well; in other words, we have at least two clean
# successes (sixes) and therefore a critical success
return BitdResult.CRITICAL_SUCCESS
else:
# Return the highest value, whatever it may be
return BitdResult(res.roll[-1])
if n == 0:
# Take lower of two dice (no critical success possible)
return (2 @ P(d_bitd)).h(0)
elif n == 1:
# Just return a single die (also no critical success possible)
return d_bitd
else:
# We're rolling a pool of dice, so engage our mechanic
return foreach(_mechanic, PWithSelection(n @ P(d_bitd), (slice(-2, None),))) On my machine:
This makes generating outcomes for zero through eight dice pretty easy (the eighth being where a critical success is more likely than any other outcome): As an aside, I was also able to address the visual shortcomings via substantial changes to |
Beta Was this translation helpful? Give feedback.
-
https://anydice.com/articles/blades-in-the-dark/
I'm guessing this is pretty trivial to produce in dyce, but I can't easily figure out how to do it. Any help would be appreciated!
Beta Was this translation helpful? Give feedback.
All reactions