roll.cxx 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. //
  2. // roll.cxx
  3. // dice-roll
  4. //
  5. // Created by Sam Jaffe on 12/1/18.
  6. // Copyright © 2018 Sam Jaffe. All rights reserved.
  7. //
  8. #include "dice-roll/roll.h"
  9. #include <numeric>
  10. #include "dice-roll/random.h"
  11. namespace dice {
  12. int add_outcome(int accum, die_outcome const & die) {
  13. return accum + (!die.dropped ? die.roll : 0);
  14. }
  15. die_roll::operator int() const {
  16. return sgn(sign) *
  17. std::accumulate(rolled.begin(), rolled.end(), 0, &add_outcome);
  18. }
  19. dice_roll::operator int() const {
  20. auto subtotal = std::accumulate(sub_rolls.begin(), sub_rolls.end(), 0) +
  21. std::accumulate(modifiers.begin(), modifiers.end(), 0);
  22. if (dc.comp != difficulty_class::test::None) {
  23. return static_cast<int>(dc(subtotal));
  24. } else {
  25. return subtotal;
  26. }
  27. }
  28. std::variant<int, outcome> dice_roll::result() const {
  29. auto value = static_cast<int>(*this);
  30. if (dc.comp != difficulty_class::test::None) {
  31. return value ? outcome::PASS : outcome::FAIL;
  32. }
  33. return value;
  34. }
  35. die_roll roll_impl(die const & d, engine::random & gen) {
  36. std::vector<die_outcome> hits;
  37. for (int i = 0; i < d.num; ++i) {
  38. hits.push_back(
  39. {.roll = static_cast<int>(gen.roll(d.sides)), .sides = d.sides});
  40. }
  41. switch (d.keep.method) {
  42. case keep::Highest:
  43. for (int i = 0; i < d.num - d.keep.amount; ++i) {
  44. std::min_element(hits.begin(), hits.end())->dropped = true;
  45. }
  46. break;
  47. case keep::Lowest:
  48. for (int i = 0; i < d.num - d.keep.amount; ++i) {
  49. std::max_element(hits.begin(), hits.end())->dropped = true;
  50. }
  51. break;
  52. default:
  53. break;
  54. }
  55. return {d.sgn, hits};
  56. }
  57. dice_roll roll_impl(dice const & d, engine::random & gen) {
  58. std::vector<die_roll> hits;
  59. for (die const & di : d.of) {
  60. hits.push_back(roll_impl(di, gen));
  61. }
  62. return {hits, d.modifier, d.dc};
  63. }
  64. roller::roller() : gen() {}
  65. roller::roller(engine::random && g) : gen(std::forward<engine::random>(g)) {}
  66. std::vector<dice_roll> roller::operator()(dice const & d) {
  67. std::vector<dice_roll> out;
  68. for (int i = 0; i < d.num; ++i) {
  69. out.emplace_back(roll_impl(d, gen));
  70. }
  71. return out;
  72. }
  73. }