Pol  Revision:cb584c9
dice.cpp
Go to the documentation of this file.
1 
8 #include "dice.h"
9 
10 #include <cstring>
11 #include <ctype.h>
12 #include <exception>
13 #include <stdlib.h>
14 
15 #include "../clib/logfacility.h"
16 #include "../clib/random.h"
17 #include "../clib/rawtypes.h"
18 #include "../clib/stlutil.h"
19 
20 namespace Pol
21 {
22 namespace Core
23 {
24 Dice::Dice() : die_count( 0 ), die_type( 0 ), plus_damage( 0 ) {}
25 
26 unsigned short Dice::roll() const
27 {
28  int total = 0;
29  for ( unsigned i = 0; i < die_count; i++ )
30  {
31  // random_int produces [0,die_type]
32  total += Clib::random_int( die_type - 1 ) + 1;
33  }
34  total += plus_damage;
35 
36  if ( total < 0 )
37  return 0;
38  else
39  return static_cast<unsigned short>( total );
40 }
41 
42 bool Dice::load( const char* dicestr, std::string* errormsg )
43 {
44  try
45  {
46  const char* str = dicestr;
47  char* endptr;
48 
49 
50  if ( strchr( str, 'D' ) || strchr( str, 'd' ) )
51  { // xdy or xdy+n or dy + nform
52  if ( toupper( *str ) == 'D' )
53  {
54  str += 1;
55  die_count = 1;
56  }
57  else
58  {
59  if ( !isdigit( *str ) )
60  {
61  *errormsg = "Error reading die string '";
62  *errormsg += dicestr;
63  *errormsg += "': ";
64  *errormsg += "Expected digit at beginning";
65  return false;
66  }
67 
68  die_count = strtoul( str, &endptr, 0 );
69  if ( die_count == 0 )
70  {
71  *errormsg = "Error reading die string '";
72  *errormsg += dicestr;
73  *errormsg += "': ";
74  *errormsg += "Got a die count of 0? strtoul failed?";
75  return false;
76  }
77  // str should point at the 'D'
78  if ( toupper( *endptr ) != 'D' )
79  {
80  *errormsg = "Error reading die string '";
81  *errormsg += dicestr;
82  *errormsg += "': ";
83  *errormsg += "Didn't expect '";
84  *errormsg += *endptr;
85  *errormsg += "' before the 'D'";
86  return false;
87  }
88  str = endptr + 1;
89  }
90  // now, we point just past the 'D'. Get the die type.
91  if ( !isdigit( *str ) )
92  {
93  *errormsg = "Error reading die string '";
94  *errormsg += dicestr;
95  *errormsg += "': ";
96  *errormsg += "expected a number after the 'D', got '";
97  *errormsg += *str;
98  *errormsg += "'";
99  return false;
100  }
101  die_type = strtoul( str, &endptr, 0 );
102  if ( !die_type )
103  {
104  *errormsg = "Error reading die string '";
105  *errormsg += dicestr;
106  *errormsg += "': ";
107  *errormsg += "Die type of '";
108  *errormsg += str;
109  *errormsg += "' doesn't make sense!";
110  return false;
111  }
112 
113  str = endptr;
114  while ( *str && isspace( *str ) )
115  str++;
116  if ( *str == '\0' )
117  {
118  plus_damage = 0;
119  }
120  else
121  {
122  // Now, we point at the + or - part.
123  char sign = *str;
124  if ( sign != '+' && sign != '-' )
125  {
126  *errormsg = "Error reading die string '";
127  *errormsg += dicestr;
128  *errormsg += "': ";
129  *errormsg += "Expected '+' or '-' after xDy, got '";
130  *errormsg += sign;
131  *errormsg += "'";
132  return false;
133  }
134  str += 1;
135  plus_damage = strtoul( str, nullptr, 0 );
136  if ( sign == '-' )
138  }
139  }
140  else // just a number
141  {
142  if ( !isdigit( *str ) )
143  {
144  *errormsg = "Error reading die string '";
145  *errormsg += dicestr;
146  *errormsg += "': ";
147  *errormsg += "Expected digit at beginning, got '";
148  *errormsg += *str;
149  *errormsg += "'";
150  return false;
151  }
152  die_count = 0;
153  die_type = 0;
154  plus_damage = strtoul( str, nullptr, 0 );
155  }
156  return true;
157  }
158  catch ( std::exception& ex )
159  {
160  ERROR_PRINT << "Uh, looks like I found damage of " << dicestr << " confusing.\n"
161  << "Valid formats look like: 3D6+2, 2D8, D10, 4, 2d20-4\n"
162  << "No spaces please!\n";
163  POLLOG.Format( "Dice String {} hurt me!: {}\n" ) << dicestr << ex.what();
164  *errormsg = "An exception occured trying to decipher dice '";
165  *errormsg += dicestr;
166  *errormsg += "'";
167  return false;
168  }
169 }
170 
171 void Dice::die_string( std::string& str ) const
172 {
173  OSTRINGSTREAM os;
174  os << die_count << "d" << die_type << "+" << plus_damage;
175  str = OSTRINGSTREAM_STR( os );
176 }
177 
178 unsigned short Dice::min_value() const
179 {
180  int total = die_count + plus_damage;
181 
182  if ( total < 0 )
183  return 0;
184  else
185  return static_cast<u16>( total );
186 }
187 
188 unsigned short Dice::max_value() const
189 {
190  int total = ( die_count * die_type ) + plus_damage;
191 
192  if ( total < 0 )
193  return 0;
194  else
195  return static_cast<u16>( total );
196 }
197 }
198 }
unsigned short roll(void) const
Definition: dice.cpp:26
unsigned die_count
Definition: dice.h:27
unsigned short min_value(void) const
Definition: dice.cpp:178
#define OSTRINGSTREAM_STR(x)
Definition: stlutil.h:76
unsigned die_type
Definition: dice.h:28
unsigned short u16
Definition: rawtypes.h:26
int random_int(int i)
Definition: random.cpp:34
#define OSTRINGSTREAM
Definition: stlutil.h:75
void die_string(std::string &str) const
Definition: dice.cpp:171
#define POLLOG
Definition: logfacility.h:219
unsigned short max_value(void) const
Definition: dice.cpp:188
int plus_damage
Definition: dice.h:29
#define ERROR_PRINT
Definition: logfacility.h:230
bool load(const char *dice, std::string *errormsg)
Definition: dice.cpp:42
Definition: berror.cpp:12