changeset 168:7f6e8f94394e alpha

Traipse Alpha 'OpenRPG' {091210-01} Traipse is a distribution of OpenRPG that is designed to be easy to setup and go. Traipse also makes it easy for developers to work on code without fear of sacrifice. 'Ornery-Orc' continues the trend of 'Grumpy' and adds fixes to the code. 'Ornery-Orc's main goal is to offer more advanced features and enhance the productivity of the user. Update Summary (Keeping up with Beta) New Features: Added Bookmarks Added 'boot' command to remote admin Added confirmation window for sent nodes Minor changes to allow for portability to an OpenSUSE linux OS Miniatures Layer pop up box allows users to turn off Mini labels, from FlexiRPG Zoom Mouse plugin added Images added to Plugin UI Switching to Element Tree Map efficiency, from FlexiRPG Added Status Bar to Update Manager New TrueDebug Class in orpg_log (See documentation for usage) Portable Mercurial Tip of the Day added, from Core and community New Reference Syntax added for custom PC sheets New Child Reference for gametree New Parent Reference for gametree New Gametree Recursion method, mapping, context sensitivity, and effeciency.. New Features node with bonus nodes and Node Referencing help added Dieroller structure from Core Added 7th Sea die roller method; ie [7k3] = [7d10.takeHighest(3).open(10)] New 'Mythos' System die roller added Added new vs. die roller method for WoD; ie [3v3] = [3d10.vs(3)]. Includes support for Mythos roller Fixes: Fix to Text based Server Fix to Remote Admin Commands Fix to Pretty Print, from Core Fix to Splitter Nodes not being created Fix to massive amounts of images loading, from Core Fix to Map from gametree not showing to all clients Fix to gametree about menus Fix to Password Manager check on startup Fix to PC Sheets from tool nodes. They now use the tabber_panel Fixed Whiteboard ID to prevent random line or text deleting. Modified ID's to prevent non updated clients from ruining the fix. default_manifest.xml renamed to default_upmana.xml Fix to Update Manager; cleaner clode for saved repositories Fixes made to Settings Panel and no reactive settings when Ok is pressed Fixes to Alternity roller's attack roll. Uses a simple Tuple instead of a Splice
author sirebral
date Thu, 10 Dec 2009 10:57:46 -0600
parents 5c9a118476b2
children ebe2bb19e18d
files orpg/dieroller/HOWTO.txt orpg/dieroller/__init__.py orpg/dieroller/dieroller.txt orpg/dieroller/utils.py orpg/orpg_version.py
diffstat 4 files changed, 484 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/orpg/dieroller/HOWTO.txt	Thu Dec 10 10:57:46 2009 -0600
@@ -0,0 +1,72 @@
+HOW TO CREATE A NEW DIE ROLLER
+
+So you want a make a new roller or add a new option? here's a short guide.
+
+
+Step 1:  Create a new die roller sub class.
+
+You need to derive a new die roller class from an existing die roller class.  
+Most likely, this will be the std die roller class. 
+
+The basics would look like this:
+
+class new_roller(std):
+    def __init__(self,source=[]):
+        std.__init__(self,source)
+        .....
+
+    ....
+
+Step 2: Implement new methods and/or override existing ones.
+
+Now, you just need to implement any new die options and override any 
+existing ones that you want to act differently.  The most common options 
+to override are the sum and __str__ functions.  Sum is used to determine 
+the result of the rolls and __str__ is used to display the results in 
+a user friendly string.
+
+For example:
+
+class new_roller(std):
+    def __init__(self,source=[]):
+        std.__init__(self,source)
+        .....
+
+    def myoption(self,param):
+        ....
+
+    def sum(self):
+        ....
+
+    def __str__(self):
+        ....
+
+REMEMBER!
+Always return an instance of your die roller for each option expect str and sum.
+
+
+Step 3:
+
+Modify Utils.py
+
+You need to make some minor modifications to utils.py to facilitate 
+your new roller.  You need to a) add an import call for your roller, 
+and b) add your roller to the list of available rollers. 
+
+For example:
+
+from die import *
+# add addtional rollers here
+from myroller import *
+....
+
+rollers = ['std','wod','d20','myroller']
+
+Step 4:  You're done! 
+
+Test it and make sure it works.  When you think its done, send it to 
+the openrpg developers and they might include it in future releases.
+
+-Chris Davis
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/orpg/dieroller/dieroller.txt	Thu Dec 10 10:57:46 2009 -0600
@@ -0,0 +1,309 @@
+The New Dicing System:  A Proposal for OpenRPG
+----------------------------------------------
+
+The current dice system for OpenRPG has several limitations.  Foremost
+among these are the fact that adding a new, non-standard dicing mechanism
+requires editing of the basic dice code.  There are several secondary 
+limitations, such as the fact that while the dice system can handle math,
+it cannot be used as a calculator -- it will not allow expressions that do
+not involve dice.
+
+This proposal is for a new dicing system to replace the current one in
+OpenRPG.  Since the dicing system is something that users will interact
+with frequently, a new system needs to be considered carefully.  This
+document attempts to describe the new dicing system so that such 
+consideration can be given to it.  It is expected that this document will
+grow and change as it is scrutinized.
+
+
+Design goals for this dicing system:
+
+ 1. Should be easy for new users to get started with, based on knowing
+    standard RPG dice notation (NdX) and basic math.
+
+ 2. Should, as far as practical, maintain compatibility with existing
+    character sheets, etc., that use the current dice system.
+
+ 3. Should allow users to create new dice types and new ways of 
+    counting dice.  Ideally, this should not require programming, except
+    in exceptional cases.
+
+ 4. The dice system should be usable for doing basic math that does
+    not involve dice.
+
+ 5. The dice system should be able to handle most current RPG dicing
+    systems.
+
+Things this dicing system is designed to NOT do:
+
+ 1. Be a programming language.  There are no facilities in it for 
+    user input, output formatting, loops, if-then-else, or similar
+    things.  If these are desired for something involving dice, an
+    appropriate node and nodehandler can be created.
+
+ 2. Handle all theoretically possible dicing systems without the
+    need for programming plugins.  First off, this is impossible.  
+    Second, even making an attempt to would require supporting 
+    dicing methods that don't actually turn up in any real game.
+
+ 3. Handle floating-point math.  I don't know of any systems that
+    use it in their dice schemes right now.  If there are some,
+    we might have to consider adding it.
+
+
+Syntax Specification 
+
+What follows is a BNF specification for the proposed dicing system, with
+explanatory text interleaved.  At the end of this document is a copy of
+the BNF with no explanations, for those who would like to look at it "all
+together".  Note that BNF describes only syntax, and not semantics; thus,
+while anything generated with this grammar should be syntactically correct,
+that doesn't mean it will make sense or be allowed.
+
+
+dice string ::= <expression>
+                <expression> of <comparison> | <comparison>
+
+This is the top level.  The major thing of note here is that comparisons
+only occur at this level.  This is intentional; the result of a comparison
+is a boolean true/false flag rather than a number.  Thus, it makes no 
+sense to allow people to perform further numerical operations on the 
+result of a comparison.  Systems where dice are triggered by the results 
+of other dice are left for the realm of plugins.
+
+                
+comparison ::= <expression> <relation> <expression>
+
+expression ::= <factor> | <factor> <low-op> <factor>
+
+The separation into "low-op" and "high-op" of the operators is to allow
+order of operations to be handled more easily.  Syntactically, it's not
+really necessary, but it should be helpful in implementation.
+
+
+factor :: = <term> | <term> <high-op> <term> |
+            <multi-dice> | <multi-dice> <high-op> <term> |
+            <term> <high-op> <multi-dice>
+
+Here we start to hit some complication.  The intent of the different 
+entries for multi-dice is that we don't want to allow things like
+[3d6 each * 2d6 each].  We are *not* doing vector multiplication!
+The "expression" level doesn't have any such limitation on syntax; 
+things like [3d6 each + 2d6 each] we'll have to either think of a 
+logical way to handle, or disallow on a semantic level.  (Well... I 
+suppose it could be handled in the BNF, but I think it would get
+kind of messy.)
+
+
+term ::= <dice> | <unit>
+
+unit ::= <number> | ( <expression> )
+
+Dice are not considered a unit.  This means that things like [3d6d10] can't
+be done without using parentheses.  I consider that to be a win for 
+clarity.
+
+
+dice ::= <unit>d<unit> | <unit>d<name> | <dice> <flag> | lastroll
+
+The <name> entry here allows for user-created dice (in the syntax, at 
+least...).
+
+
+multi-dice ::= ( <dice>, <dice>+ ) |               # (1d6,1d8)
+               <dice> each |                       # 3d6 each
+               ( <expression> of <expression> ) |  # (3 of 2d6)
+               lastroll |                          # lastroll
+               <multi-dice> <flag>                 # (3 of 2d6) best 2
+
+"lastroll" by itself can be either dice or multi-dice.  I'm thinking that it
+ 
+should be whatever type the last roll was.
+
+
+flag ::= reroll <condition> |          # repeats
+         reroll <slice> |              # once only
+         grow <condition> |            # reroll and add
+         shrink <condition> |          # reroll and subtract
+         drop <condition> |
+         drop <slice> |
+         take <condition> |
+         take <slice> |
+         <slice> |                     # implied "take"
+         <name> <condition> |          # user-created
+         <name>                        # user-created
+
+Technically, we don't need both "drop" and "take" -- one implies the 
+other.  However, having both should make the language easier to use.
+
+"reroll" will work differently depending on whether a condition or a 
+slice is given.  If a condition is given, it will reroll until none of
+the dice in the set meet the reroll condition (or until it hits a maximum
+allowed number of rerolls).  If a slice is given, it will reroll those
+dice once.  IMHO, this behavior makes the most sense.
+
+The <name> entries here are to allow for user-created flags.  Note that
+as I've specified things right now, a user-created flag can have a
+ condition,
+but not a slice.  That's mostly because I couldn't think of a case where
+a slice would be useful... should we add it anyways?
+
+
+slice ::= highest | lowest | highest <number> | lowest <number>
+
+"highest" and "lowest" without a number are equivalent to doing them with
+1 as the number.  This is to simplify things like [4d6 drop lowest].
+
+
+condition ::= <relation> <unit>
+
+This is for conditions on flags.  Note that it can take a unit, so you could
+
+use dice in a condition; however, I think the unit should only be evaluated 
+
+once, to make things faster.  Anyone for repetitive evaluation?
+
+
+low-op ::= + | - | min | max
+
+"min" takes two values and returns the highest of them, and "max"
+returns the lowest of them.  This might seem counterintuitive, but
+it's meant to be used with dice, like so:
+
+  3d6 min 8   - always returns 8 or higher
+
+  3d6 max 15  - always returns 15 or lower
+
+I decided to put min and max as having the same precedence as + and -,
+because if they had higher precedence, then:
+
+  3d6+2 min 10 
+
+would be equivalent to 3d6+10.  (It would take the max of 2 and 10, then
+add that to 3d6).  One problem that does arise here is with multiplication 
+and division:  [1d6 min 5 * 2] will be equivalent to [1d6 min 10], since
+multiplication has higher precedence.  We may just want to warn people 
+that min and max can be screwy unless you parenthesize, unless someone can
+think of a better way to handle them.
+
+
+high-op ::= * | / | mod
+
+The / is integer division, of course, since we're doing integer math.  
+
+
+number ::= <digit>+ | -<digit>+
+
+Positive and negative numbers are allowed.  This means that, syntactically,
+[-2d-4] is legal.  Do we want to modify the BNF to disallow this, or handle
+it on a semantic level?
+
+
+name ::= <letter>[<letter>|<digit>]*
+
+We may want to expand to allow underscores and dashes in user-created names.
+
+
+
+letter ::= A-Z | a-z
+
+digit ::= 0-9
+
+relation ::= < | > | <= | >= | => | =< | = | ==
+
+
+
+Well, that's the BNF.  Again, at the end is a copy without all the running
+commentary.
+
+
+Thoughts on Implementation:
+
+First, I think a sort of "dice library" of common functions needs to be
+created.  This would include rolling a set of dice, getting the highest
+of a group of dice, growing and shrinking dice from a set based on 
+conditions, and so on.  These functions should be available for use by
+custom-written dice types.
+
+Next, that library should be used as a tool in implementing a dice-string
+interpreter.  That will require creating a parser for the dice-string 
+'language'.  This could be either a custom-written parser, or possibly
+one created with some of the Python parser generators.  A custom-written
+parser may take longer to do and be a bit more finicky to maintain, but
+it would remove a dependency from the code.
+
+User-created flags and dice types could be supported in two ways:
+
+ - First, by allowing users to specify strings in the dice language
+   that the flags/expressions would expand to -- basically, allowing
+   dice macros.
+
+ - Second, by adding hooks for python modules to be associated with
+   user-created dice or flag types.  This is likely to be the more
+   complicated of the two solutions, but it would also be more 
+   flexible.
+
+Personally, I think both are desirable -- the first, so that 
+non-programming users can create simple die and flag types.  The
+second, because by design, there are some things this dice system 
+just won't do.
+
+
+Further work needed:
+
+ - specs for the "dice library"
+
+ - specs on an interface for python modules meant to be dice and
+   flag types.
+
+----------------------------------------------------------------
+
+start ::= <expression> |
+          <comparison>
+
+comparison ::= <expression> <condition>
+
+expression ::= <term> | <term> <low-op> <factor>
+
+term ::= <factor> | <factor> <high-op> <unit>
+
+factor ::= <atom> | <dice_set>
+
+atom ::= <number> | ( <expression> )
+
+dice_set ::= <dice> <dice_set>, <dice> | <expr> of <dice> | <dice> each |
+             lastroll
+
+dice ::= <atom>d<atom> | <atom>d<name> | <dice> <flag>
+
+flag ::= reroll <condition> |
+         reroll <slice> |
+         grow <condition> |  
+         shrink <condition> |        
+         drop <condition> |
+         drop <slice> |
+         take <condition> |
+         take <slice> |
+         <slice> |         
+         <name> <condition> |
+	 <name> <slice> |
+         <name>
+
+slice ::= highest | lowest | highest <number> | lowest <number>
+
+condition ::= <relation> <unit>
+
+low-op ::= + | -
+
+high-op ::= * | / | mod| max | min
+
+number ::= <digit>+ | -<digit>+
+
+name ::= <letter>[<letter>|<digit>]*
+
+letter ::= A-Z | a-z
+
+digit ::= 0-9
+
+relation ::= < | > | <= | >= | => | =< | = | ==
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/orpg/dieroller/utils.py	Thu Dec 10 10:57:46 2009 -0600
@@ -0,0 +1,102 @@
+#!/usr/bin/env python
+# Copyright (C) 2000-2001 The OpenRPG Project
+#
+#       openrpg-dev@lists.sourceforge.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+# --
+#
+# File: dieroller/utils.py
+# Author: OpenRPG Team
+# Maintainer:
+# Version:
+#   $Id: utils.py,v 1.22 2007/05/05 05:30:10 digitalxero Exp $
+#
+# Description: Classes to help manage the die roller
+#
+
+__version__ = "$Id: utils.py,v 1.22 2007/05/05 05:30:10 digitalxero Exp $"
+
+import re
+
+import orpg.dieroller.rollers
+from orpg.dieroller.base import die_rollers
+
+class roller_manager(object):
+    def __new__(cls):
+        it = cls.__dict__.get("__it__")
+        if it is not None: return it
+        cls.__it__ = it = object.__new__(cls)
+        it._init()
+        return it
+
+    def _init(self):
+        self.setRoller('std')
+
+    def setRoller(self, roller_class):
+        try: self.roller_class = die_rollers[roller_class]
+        except KeyError: raise Exception("Invalid die roller!")
+
+    def getRoller(self):
+        return self.roller_class.name
+
+    def listRollers(self):
+        return die_rollers.keys()
+
+    def stdDieToDClass(self,match):
+        s = match.group(0)
+        num_sides = s.split('d')
+        if len(num_sides) > 1: num_sides; num = num_sides[0]; sides = num_sides[1]
+        else: return self.non_stdDieToDClass(s) # Use a non standard converter.
+
+        if sides.strip().upper() == 'F': sides = "'f'"
+        try:
+            if int(num) > 100 or int(sides) > 10000: return None
+        except: pass
+        ret = ['(', num.strip(), "**die_rollers['", self.getRoller(), "'](",
+                sides.strip(), '))']
+        return ''.join(ret)
+
+    def non_stdDieToDClass(self, s):
+        num_sides = s.split('v')
+        if len(num_sides) > 1: 
+            num_sides; num = num_sides[0]; sides = num_sides[1]
+            if self.getRoller() == 'mythos': sides = '12'; target = num_sides[1]
+            elif self.getRoller() == 'wod': sides = '10'; target = num_sides[1]
+            ret = ['(', num.strip(), "**die_rollers['", self.getRoller(), "'](",
+                    sides.strip(), ')).vs(', target, ')']
+            return ''.join(ret)
+
+        num_sides = s.split('k')
+        if len(num_sides) > 1: 
+            num_sides; num = num_sides[0]; sides = '10'; target = num_sides[1]
+            ret = ['(', num.strip(), "**die_rollers['", self.getRoller(), "'](",
+                    sides.strip(), ')).takeHighest(', target, ').open(10)']
+            return ''.join(ret)
+
+    #  Use this to convert ndm-style (3d6) dice to d_base format
+    def convertTheDieString(self,s):
+        reg = re.compile("(?:\d+|\([0-9\*/\-\+]+\))\s*[a-zA-Z]+\s*[\dFf]+")
+        (result, num_matches) = reg.subn(self.stdDieToDClass, s)
+        if num_matches == 0 or result is None:
+            try:
+                s2 = self.roller_class + "(0)." + s
+                test = eval(s2)
+                return s2
+            except: pass
+        return result
+
+    def proccessRoll(self, s):
+        return str(eval(self.convertTheDieString(s)))
--- a/orpg/orpg_version.py	Thu Dec 10 10:53:33 2009 -0600
+++ b/orpg/orpg_version.py	Thu Dec 10 10:57:46 2009 -0600
@@ -4,7 +4,7 @@
 #BUILD NUMBER FORMAT: "YYMMDD-##" where ## is the incremental daily build index (if needed)
 DISTRO = "Traipse Alpha"
 DIS_VER = "Ornery Orc"
-BUILD = "091210-00"
+BUILD = "091210-01"
 
 # This version is for network capability.
 PROTOCOL_VERSION = "1.2"