Source: fun/DieRoll.h


Annotated List
Files
Globals
Hierarchy
Index
//  DieRoll - finger it out
//  Copyright (C) 1999-2002 rusty@sgi.com & stephan@wanderinghorse.net
//
//  This program is free software; you can redistribute it and/or
//  modify it under the terms of the GNU General Public License
//  as published by the Free Software Foundation; either version 2
//  of the License, or (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

#ifndef _FUN_DIEROLL_H
#define _FUN_DIEROLL_H

#include 
#include 
#include 
#include 

namespace fun {

class SolidPlastic;  //  the internals of a die, of course.

/**
*  To plug in your own parsers, you'll need a PluginDieRollParser.
*  It will be 
*/
typedef SolidPlastic *(*PluginDieRollParser)(const QString &) ;

/**
*  A DieRoll is a fixed collection of dice, such as 3d6 or 1d20.  Its most
*  useful method is roll(), although it does have methods such as min(),
*  max(), isFlat(), and distribution() for examining its expected results.
*
*  DieRoll instances are not constructed directly; use
*  DieRoll::fromString().
*/
class DieRoll : public Serializable
{
	public:
	/**
	*  Creates a new (useless) DieRoll.
	*/
	DieRoll();
	/**
	*  Creates a new copy of the given DieRoll.  DieRolls use reference
	*  counting, so this is fast.
	*/
	DieRoll(const DieRoll &other);
	/**
	*/
	virtual ~DieRoll();
	/**
	*  Copies the given DieRoll.  DieRolls use reference counting, so
	*  this is fast.
	*/
	DieRoll &operator=(const DieRoll &other);

	/**
	*  Saves the DieRoll to the given Serializer.
	*/
	virtual void serialize(Serializer &ser) const;
	/**
	*  Loads the DieRoll from the given Deserializer.
	*/
	virtual void deserialize(const Deserializer &ser);

	/**
	*  Rolls the dice and returns the result.  This is what a DieRoll object
	*  lives for!
	*/
	virtual int roll() const;

	/**
	*  Returns the minimum possible result.
	*/
	virtual int min() const;

	/**
	*  Returns the maximum possible result.
	*/
	virtual int max() const;

	/**
	*  Returns true if the distribution of the DieRoll's results will be
	*  flat rather than a bell curve.  Note that this may be misleading
	*  for compound results involving multiplication, such as d6*2.  (This
	*  will likely return true in that case, even though your chance of
	*  rolling a 2 is considerably higher than your chance of rolling a 3,
	*  ha ha.)
	*/
	virtual bool isFlat() const;

	/**
	*  A list of WeightedValues is returned by distribution().
	*/
	struct WeightedValue
	{
		int value;
		double weight;
	};

	/**
	*  Returns a list of WeightedValues giving the DieRoll's expected
	*  distribution, or an empty list for DieRolls which do not support it.
	*  Each element in the list corresponds to a possible result.  For
	*  example, a d2 should generate a 1 50% of the time and a 2 50% of
	*  the time, so it would return a list of two elements: { 1, 0.5 } and 
	*  { 2, 0.5 }.  distribution() for 2d2 would return a list with three
	*  elements: { 2, 0.25 }, { 3, 0.5 }, and { 4, 0.25 }.
	*/
	virtual QValueList distribution();

	/**
	*  Returns the DieRoll in a format which should be readable by
	*  DieRoll::fromString() (as well as by people).  The result is
	*  most likely cached by the DieRoll, not recalculated every time
	*  this is called, so it should be fast.
	*/
	virtual QString toString() const;

//	/**
//	*  This returns a DieRoll using the given number of dice with the
//	*  given number of sides.  For more complex die rolls, you may
//	*  need to use DieRoll::fromString().
//	*
//	*  It might be better to use DieRoll::fromString() anyway, because
//	*  if you have a parser plugin which treats "normal" dice differently
//	*  (like the Silhouette system, which calls it "3d6" even though it's
//	*  not the sum of 3 six-sided dice), this will bypass it, and you'll
//	*  wind up with a "normal" 3d6.
//	*/
//	static DieRoll getDice(int dice, int sides);
//
//	/**
//	*  This creates a DieRoll using the given number of dice with the
//	*  given number of sides and the given modifier.  For more complex
//	*  die rolls, you may need to use DieRoll.fromString().
//	*
//	*  It might be better to use DieRoll::fromString() anyway, because
//	*  if you have a parser plugin which treats "normal" dice differently
//	*  (like the Silhouette system, which calls it "3d6" even though it's
//	*  not the sum of 3 six-sided dice), this will bypass it, and you'll
//	*  wind up with a "normal" 3d6.
//	*/
//	static DieRoll getDice(int dice, int sides, int mod);

	/**
	*  This creates DieRoll instances from strings such as "d6", "3d6",
	*  "3d6+3" and "3d6*3", and "d8+d12".
	*/
	static DieRoll fromString(const QString &src);

	/**
	*  Games which have their own concept of dice & rolled results can
	*  plug in DieRollParsers.  A PluginDieRollParser takes a QString,
	*  parses the entire thing if it can, and returns a SolidPlastic object.
	*  If it can't parse the entire string, it returns NULL; if the
	*  string contains any operators (+, -, *), the parser will be called
	*  again with the substrings.
	*
	*  Some examples:
	*  
	*      Dream Pod 9's Silhouette system uses "1d6", "2d6", etc., but
	*      the result is the highest single die roll, not the sum of the
	*      rolled dice.  There are two special cases: each additional 6
	*      after the first adds 1 to the total; and if all rolled dice
	*      come up 1, the result is 0 (a fumble), and any modifiers are
	*      not applied.  (Unfortunately, to keep from confusing "normal"
	*      3d6 from Silhouette's 3d6, you might want your parser to
	*      look for "3s6", "s3d6", "3s", or "s3" or something.  Also,
	*      because modifiers aren't supposed to be applied when a fumble
	*      is rolled, you might want your parser to handle modifiers.)
	*
	*      DemonBlade/xB9/Dark Tortoise's WarEngine uses "1k1", "2k1",
	*      etc., where the number before the "k" is the number of 6-sided
	*      dice rolled, and the number after the "k" is the number of dice
	*      "kept".  So "3k2" means roll 3d6 and return the sum of the
	*      highest two.
	*/
	static void addDieRollParser(PluginDieRollParser dp);

	/**
	*  Removes the given PluginDieRollParser from the list of plugged-in
	*  parsers.
	*/
	static void removeDieRollParser(PluginDieRollParser dp);

	/**
	*  This tests two things, and prints its results on cout.  First,
	*  it tests the distribution of the generated numbers; if we're rolling
	*  d6's, what percentage of the results will be 1's, 2's, 3's, etc.
	*  Second (optionally), for each result, what is the chance that the
	*  next result will be the same?  (Hopefully the chance of rolling two
	*  1's in a row will be the same as the chance of rolling a 1 followed
	*  by a 2).
	*
	*  @param   d                 the die roll to perform
	*  @param   rolls             the number of times to roll the dice
	*  @param   showSubs          true if subsequent results will be shown
	*                             (that is, when a number is rolled, whether
	*                             to keep track of what the next number rolled
	*                             is)
	*/
	static void testRolls(const DieRoll &d, int rolls, bool showSubs);

	private:
	DieRoll(SolidPlastic *dice);
	SolidPlastic *dice;
};

/**
*  Writes the given DieRoll's toString() to the ostream.
*/
extern std::ostream & operator<<(std::ostream &os, const DieRoll &d);

/**
*  I didn't want to make this public, but if you want to plug in your own
*  die roll parsers, you'll need it to return a subclass of this.  Each
*  method has the same semantics as the DieRoll method of the same name.
*/
class SolidPlastic
{
	public:
	SolidPlastic();
	virtual ~SolidPlastic();
	virtual QString toString() const = 0;
	virtual int roll() const = 0;
	virtual int min() const = 0;
	virtual int max() const = 0;
	virtual bool isFlat() const = 0;
	virtual QValueList distribution();

//	private:
	int refcount;
};

}  //  namespace fun

#endif  //  _FUN_DIEROLL_H

Generated by: stephan on cheyenne on Mon Aug 11 14:06:52 2003, using kdoc 2.0a54.