// // roll.cxx // dice-roll // // Created by Sam Jaffe on 12/1/18. // Copyright © 2018 Sam Jaffe. All rights reserved. // #include "dice-roll/roll.h" #include #include "dice-roll/random.h" namespace dice { int add_outcome(int accum, die_outcome const & die) { return accum + (!die.dropped ? die.roll : 0); } die_roll::operator int() const { return sgn(sign) * std::accumulate(rolled.begin(), rolled.end(), 0, &add_outcome); } dice_roll::operator int() const { auto subtotal = std::accumulate(sub_rolls.begin(), sub_rolls.end(), 0) + std::accumulate(modifiers.begin(), modifiers.end(), 0); if (dc.comp != difficulty_class::test::None) { return static_cast(dc(subtotal)); } else { return subtotal; } } std::variant dice_roll::result() const { auto value = static_cast(*this); if (dc.comp != difficulty_class::test::None) { return value ? outcome::PASS : outcome::FAIL; } return value; } die_roll roll_impl(die const & d, engine::random & gen) { std::vector hits; for (int i = 0; i < d.num; ++i) { hits.push_back( {.roll = static_cast(gen.roll(d.sides)), .sides = d.sides}); } switch (d.keep.method) { case keep::Highest: for (int i = 0; i < d.num - d.keep.amount; ++i) { std::min_element(hits.begin(), hits.end())->dropped = true; } break; case keep::Lowest: for (int i = 0; i < d.num - d.keep.amount; ++i) { std::max_element(hits.begin(), hits.end())->dropped = true; } break; default: break; } return {d.sgn, hits}; } dice_roll roll_impl(dice const & d, engine::random & gen) { std::vector hits; for (die const & di : d.of) { hits.push_back(roll_impl(di, gen)); } return {hits, d.modifier, d.dc}; } roller::roller() : gen() {} roller::roller(engine::random && g) : gen(std::forward(g)) {} std::vector roller::operator()(dice const & d) { std::vector out; for (int i = 0; i < d.num; ++i) { out.emplace_back(roll_impl(d, gen)); } return out; } }