118 lines
2.6 KiB
Python
118 lines
2.6 KiB
Python
'''RPG Attributes Generator'''
|
|
|
|
from itertools import islice
|
|
from random import randint
|
|
from operator import eq
|
|
|
|
|
|
# heroes :: Gen IO [(Int, Int, Int, Int, Int, Int)]
|
|
def heroes(p):
|
|
'''Non-finite list of heroes matching
|
|
the requirements of predicate p.
|
|
'''
|
|
while True:
|
|
yield tuple(
|
|
until(p)(character)([])
|
|
)
|
|
|
|
|
|
# character :: () -> IO [Int]
|
|
def character(_):
|
|
'''A random character with six
|
|
integral attributes.
|
|
'''
|
|
return [
|
|
sum(sorted(map(
|
|
randomRInt(1)(6),
|
|
enumFromTo(1)(4)
|
|
))[1:])
|
|
for _ in enumFromTo(1)(6)
|
|
]
|
|
|
|
|
|
# ------------------------- TEST --------------------------
|
|
# main :: IO ()
|
|
def main():
|
|
'''Test :: Sample of 10'''
|
|
|
|
# seventyFivePlusWithTwo15s :: [Int] -> Bool
|
|
def seventyFivePlusIncTwo15s(xs):
|
|
'''Sums to 75 or more,
|
|
and includes at least two 15s.
|
|
'''
|
|
return 75 <= sum(xs) and (
|
|
1 < len(list(filter(curry(eq)(15), xs)))
|
|
)
|
|
|
|
print('A sample of 10:\n')
|
|
print(unlines(
|
|
str(sum(x)) + ' -> ' + str(x) for x
|
|
in take(10)(heroes(
|
|
seventyFivePlusIncTwo15s
|
|
))
|
|
))
|
|
|
|
|
|
# ------------------------- GENERIC -------------------------
|
|
|
|
# curry :: ((a, b) -> c) -> a -> b -> c
|
|
def curry(f):
|
|
'''A curried function derived
|
|
from an uncurried function.
|
|
'''
|
|
return lambda x: lambda y: f(x, y)
|
|
|
|
|
|
# enumFromTo :: Int -> Int -> [Int]
|
|
def enumFromTo(m):
|
|
'''Enumeration of integer values [m..n]'''
|
|
return lambda n: range(m, 1 + n)
|
|
|
|
|
|
# randomRInt :: Int -> Int -> IO () -> Int
|
|
def randomRInt(m):
|
|
'''The return value of randomRInt is itself
|
|
a function. The returned function, whenever
|
|
called, yields a a new pseudo-random integer
|
|
in the range [m..n].
|
|
'''
|
|
return lambda n: lambda _: randint(m, n)
|
|
|
|
|
|
# take :: Int -> [a] -> [a]
|
|
# take :: Int -> String -> String
|
|
def take(n):
|
|
'''The prefix of xs of length n,
|
|
or xs itself if n > length xs.
|
|
'''
|
|
return lambda xs: (
|
|
xs[0:n]
|
|
if isinstance(xs, (list, tuple))
|
|
else list(islice(xs, n))
|
|
)
|
|
|
|
|
|
# unlines :: [String] -> String
|
|
def unlines(xs):
|
|
'''A single string formed by the intercalation
|
|
of a list of strings with the newline character.
|
|
'''
|
|
return '\n'.join(xs)
|
|
|
|
|
|
# until :: (a -> Bool) -> (a -> a) -> a -> a
|
|
def until(p):
|
|
'''The result of repeatedly applying f until p holds.
|
|
The initial seed value is x.
|
|
'''
|
|
def go(f, x):
|
|
v = x
|
|
while not p(v):
|
|
v = f(v)
|
|
return v
|
|
return lambda f: lambda x: go(f, x)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|