// // io.h // dice-roll // // Created by Sam Jaffe on 7/24/24. // Copyright © 2024 Sam Jaffe. All rights reserved. // #pragma once #include #include "dice-roll/die.h" #include "dice-roll/roll.h" namespace dice { template OStream & operator<<(OStream & os, outcome e) { switch (e) { case outcome::PASS: return os << "PASS"; case outcome::FAIL: return os << "FAIL"; } } template OStream & operator<<(OStream & os, sign s) { switch (s) { case sign::PLUS: return os << '+'; case sign::MINUS: return os << '-'; case sign::ZERO: return os; } } template OStream & operator<<(OStream & os, difficulty_class::test t) { switch (t) { case difficulty_class::test::None: return os; case difficulty_class::test::Less: return os << '<'; case difficulty_class::test::LessOrEqual: return os << '<' << '='; case difficulty_class::test::Greater: return os << '>'; case difficulty_class::test::GreaterOrEqual: return os << '>' << '='; } } template OStream & operator<<(OStream & os, keep const & k) { switch (k.method) { case keep::Highest: return os << 'k' << 'h' << k.amount; case keep::Lowest: return os << 'k' << 'l' << k.amount; default: return os; } } template OStream & operator<<(OStream & os, dice const & d) { if (d.num != 1) os << d.num << '{'; for (die const & di : d.of) { os << di.sgn << di.num << 'd' << di.sides << di.keep; } for (mod m : d.modifier) { os << m.sign << m.value; } if (d.dc.comp != difficulty_class::test::None) { os << d.dc.comp << d.dc.against; } if (d.num != 1) os << '}'; return os; } template OStream & operator<<(OStream & os, die_outcome const & r) { return os << r.roll; } template OStream & operator<<(OStream & os, die_roll const & r) { os << r.sign; switch (r.rolled.size()) { case 0: // Prevent crashes if we somehow get a 0dM expression return os << "0"; case 1: // Don't bother with braces if there's only a single roll, // the braces are for grouping purposes. return os << r.rolled[0]; default: os << "[ "; os << r.rolled[0]; for (int i = 1; i < r.rolled.size(); ++i) { os << ", " << r.rolled[i]; } return os << " ]"; } } template OStream & operator<<(OStream & os, dice_roll const & r) { for (die_roll const & dr : r.sub_rolls) { os << dr; } for (mod const & m : r.modifiers) { os << m.sign << m.value; } return os; } template OStream & operator<<(OStream & os, std::pair> const & pair) { os << "Result of '" << pair.first << "':"; if (pair.second.size() == 1) { os << ' '; std::visit([&os](auto v) { os << v; }, pair.second[0].result()); return os << ' ' << '(' << pair.second[0] << ')'; } for (int i = 0; i < pair.second.size(); ++i) { os << "\n Result/" << i << ": "; std::visit([&os](auto v) { os << v; }, pair.second[i].result()); os << ' ' << '(' << pair.second[i] << ')'; } return os; } }