Explorar el Código

Adding documentation

Sam Jaffe hace 7 años
padre
commit
69fa10fda9
Se han modificado 4 ficheros con 102 adiciones y 5 borrados
  1. 15 0
      include/exception.h
  2. 7 0
      include/random.h
  3. 38 2
      include/roll.h
  4. 42 3
      src/die.cxx

+ 15 - 0
include/exception.h

@@ -13,8 +13,23 @@
 namespace dice {
   class unexpected_token : public std::runtime_error {
   public:
+    /**
+     * @brief An error for failure to parse a string into a dice::dice object
+     * @param reason The specific reason that this error occured
+     * @param position The index into the string that the error was located at,
+     * or -1(EOF) if the error was a 'we ran out of buffer' type.
+     */
     unexpected_token(std::string const & reason, long long position);
     
+    /**
+     * @brief Create a string matching the regex '~*^', that points to the error
+     * covered by this exception class.
+     * @param backup_length If {@see unexpected_token::position} == -1, use
+     * this value instead as N.
+     * @return A string of N '~' and one '^', pointing to the character in the
+     * parse string that the error occured at.
+     * "<END>" if position and backup_length are both -1
+     */
     std::string pointer(long long backup_length = -1) const;
     
   private:

+ 7 - 0
include/random.h

@@ -15,6 +15,13 @@ namespace dice { namespace engine {
     using super = ::engine::random_number_generator;
   public:
     using super::random_number_generator;
+    /**
+     * @brief Roll 1dN
+     * @param sides The number of sides (N) on a die. e.g. d20
+     * Domain: sides > 0
+     * @return A number in the range [1, N]
+     * @throws Produces UB if sides = 0
+     */
     unsigned int roll(unsigned int sides) const {
       return super::exclusive(sides) + 1;
     }

+ 38 - 2
include/roll.h

@@ -8,7 +8,43 @@
 
 #pragma once
 
+#include <vector>
+
+#include "die.h"
+
 namespace dice {
-  struct dice;
-  void roll(dice const & d);
+  // Describe the actual result of rolling (+/-)NdM
+  struct die_roll {
+    // Collapse this roll into its actual value
+    operator int() const;
+    // Is this being added, or subtracted from the total
+    sign sign;
+    // Since this roll was composed on NdM, rolled.size() == N. Each element
+    // of rolled is within the integer range [1, M].
+    std::vector<int> rolled;
+  };
+
+  // Describe the actual result of rolling an arbitrary set of dice with mods
+  struct dice_roll {
+    // Collapse this roll into its actual value
+    operator int() const;
+    // A vector of component roll results, each on representing a single NdM
+    // expression.
+    std::vector<die_roll> sub_rolls;
+    // A vector of every modifier attached to the system.
+    std::vector<mod> modifiers;
+  };
+
+  /**
+   * @param d Some dice roll structure, containing any number of dice sets 'NdM'
+   * as well as any number of roll modifiers (fixed numbers). Additionally,
+   * can contain a repetition parameter.
+   * @return A vector of actualized rolls, where `vector.size() == d.num`.
+   */
+  std::vector<dice_roll> roll(dice const & d);
+  /**
+   * Print out the component elements of an actualized dice roll.
+   * Use instead `out << int(r)` to print the final summation.
+   */
+  std::ostream & operator<<(std::ostream & out, dice_roll const & r);
 }

+ 42 - 3
src/die.cxx

@@ -18,8 +18,9 @@ static void advance_over_whitespace(std::istream & in, char const * also = "") {
 }
 
 static std::string carrot(long long pos) {
-  if (pos == -1) return "<END>";
+  if (pos == -1) return "<END>"; // For safety
   std::string out;
+  // resize(0) followed by back() will cause UB
   out.resize(std::max(pos, 1ll), '~');
   out.back() = '^';
   return out;
@@ -66,6 +67,7 @@ namespace dice {
     return out;
   }
 }
+
 namespace dice { namespace {
   struct parser {
     void parse(sign s);
@@ -76,6 +78,20 @@ namespace dice { namespace {
     dice & d;
   };
   
+  /**
+   * @sideeffect This function advances the input stream over a single numeric
+   * token. This token represents the number of sides in the die roll.
+   * This function appends a new die into {@see d.of}, representing (+/-)NdM,
+   * where N is the input parameter 'value', and M is retrieved internally.
+   * @param s The arithmatic sign attached to this roll, denoting whether this
+   * die increases or decreases the total result of the roll. For example, the
+   * 5E spell Bane imposes a -1d4 modifier on attack rolls, an attack roll might
+   * go from '1d20+2+3' (1d20 + Proficiency + Ability) to '1d20+2+3-1d4'.
+   * @param value The number of dice to be rolled.
+   * Domain: value >= 0
+   * @throw dice::unexpected_token if we somehow call parse_dN while the first
+   * non-whitespace token after the 'd' char is not a number.
+   */
   void parser::parse_dN(sign s, int value) {
     advance_over_whitespace(in, "dD");
     d.of.push_back({s, value, 0});
@@ -86,15 +102,36 @@ namespace dice { namespace {
     parse(ZERO);
   }
   
+  /**
+   * @param s The arithmatic sign attached to this numeric constant. Because
+   * value is non-negative, this token contains the +/- effect.
+   * @param value The value associated with this modifier term.
+   * Domain: value >= 0
+   */
   void parser::parse_const(sign s, int value) {
-    if (value) {
+    if (value) { // Zero is not a modifier we care about
       d.modifier.push_back({s, std::abs(value)});
     }
   }
   
+  /**
+   * Main dispatch function for parsing a dice roll.
+   * @param s The current +/- sign attached to the parse sequence. s is ZERO
+   * when parsing the first token, or after parsing a die. This means an
+   * expression like '1d4+5+1d6+2d8' is evaluated as a sequence like so:
+   * [1d4][+][5+][1d6][+][2d8]. This produces the following states of (SIGN,
+   * input stream):
+   * 1) ZERO, 1d4+5+1d6+2d8
+   * 2) ZERO, +5+1d6+2d8
+   * 3) PLUS, 5+1d6+2d8
+   * 4) PLUS, 1d6+2d8
+   * 5) ZERO, +2d8
+   * 6) PLUS, 2d8
+   */
   void parser::parse(sign s) {
-    // Allow implicit 1
     advance_over_whitespace(in);
+    // By defaulting this to zero, we can write a more elegant handling of
+    // expressions like 1d4+1d6+5+1
     int value = 0;
     if (isnumber(in.peek())) { in >> value; }
     else if (in.peek() == EOF && s != ZERO) {
@@ -105,7 +142,9 @@ namespace dice { namespace {
       case 'd': case 'D':
         return parse_dN(s, value);
       case '+': case '-':
+        // Handle 5+... cases
         parse_const(s, value);
+        // Add another token
         parse((in.get() == '+') ? PLUS : MINUS);
         break;
       default: