Tiefling has asked for the wisdom of the Perl Monks concerning the following question:
All well and good. The small problem here is that every discussion of modules which I've encountered either jumps in the deep end or assumes prior knowledge which I haven't got. So, I'm going to ask for help with a trivial case:
In Dungeons and Dragons Third Edition, all ability score modifiers are drawn from a single table. This table's values are trivial: given a score of n, the modifier is (n/2)-5. (ie: 8-9: -1; 10-11: 0; 12-13: +1). In the first shot at the character generator, I stupidly plugged these values into a list. Simpler, cleaner, and more transferable, I now realise, to call a function modifier($n) for an arbitrary value of $n. So:
sub modifier { int($_[0]/2)-5 }
(I hope that does what I said it did - I just wrote it on the fly.) The question is, how can I turn that into an element of the (as yet unwritten) Module RPG::DND, and how will the function then be called?
Thanks very much,
Tiefling, Known Lazy Bastard
-----BEGIN GEEK CODE BLOCK----- Version: 3.1 GAT d++ s:- a-- C++ UL P++ L++(+) E? W+(++) N+ o? K w+(--) !O M- V? PS+ PE- Y PGP- t+ 5 X+ R+++ tv- b+++ DI++++ D+ G+ e++ h!(-) y +? ------END GEEK CODE BLOCK------
|
---|
Replies are listed 'Best First'. | |
---|---|
Re: Modules: Building blocks for the Daft Adventure
by davorg (Chancellor) on Jun 12, 2001 at 15:47 UTC | |
In RPG/DND.pm
In another_script.pl -- <http://www.dave.org.uk> Perl Training in the UK <http://www.iterative-software.com> | [reply] [d/l] [select] |
by Tiefling (Monk) on Jun 12, 2001 at 15:52 UTC | |
Tiefling, seeking enlightenment
| [reply] [d/l] |
by davorg (Chancellor) on Jun 12, 2001 at 16:06 UTC | |
@ISA does the same thing here that it does in an OO module. It defines other modules that Perl should search for subroutines that you don't define in your module. For example, in this case use Module is (almost) the same as:
So Perl tries to call the import function in your module. Your module doesn't have an import function so Perl searches the modules in @ISA and calls the first instance of import that it finds. This is in Exporter. Exporter::import does all sorts of clever things and exports the contents of your @EXPORT_OK array into the calling package. Update: Ridiculous typo corrected. Thanks to ryddler. --<http://www.dave.org.uk> Perl Training in the UK <http://www.iterative-software.com> | [reply] [d/l] |
by ryddler (Monk) on Jun 12, 2001 at 19:14 UTC | |
Re: Modules: Building blocks for the Daft Adventure
by dragonchild (Archbishop) on Jun 12, 2001 at 16:33 UTC | |
You are looking to write a series of modules that will help you develop a comprehensive D&D application. The key word there is "application". I don't know what your background is in Perl or programming, but the first instinct I've seen in a lot of decent programmers has been to treat Perl with less respect than they would C, Java, or any other compiled language. If you're looking to write a stable app, you need to realize that's what you're doing and design this a bit. If you intend on using this over and over, and/or extending it, this week or two in the beginning where you define where stuff lives will be absolutely critical. "Why?", you might ask. Well, you talk about a dice-rolling function called dice(). Then, you talk about a modifer() function. As someone who plays D&D, these, to me, instinctively seem as if they belong in the same place. This is because they both deal with ability scores. Now, the immediate response would be that dice() also deals with combat. Ok. So, dice() may need to live elsewhere, and that's fine. The question would be "Where?" modifier() seems to imply a character module. This would have things help you generate stats, choose skills, choose spells, and moderate when someone can cast a spell or not. Sounds like a lot? Well, it is ... and it isn't. Who says every bit of code has to be in RPG::D&D::Character? A case could be made that the top level should not know how to roll dice. All the top level should know about is characters, spells, and combat. Why? Because it doesn't care how combat is resolved. All it cares about is that combat is resolved. All the details should be taken care of by RPG::D&D::Combat. No-one else wants to know, cares to know, or should know. Same goes with character generation, skill/spell adjudication, etc. Creating a RPG::Randomize module is definitely appropriate. Within this module could be dice(), as well as other methods of randomization. coin_flip() could be here. (1d2 is different than flipping a coin, and you should code it that way, even if it would seem that, from the theory, it is the same.) However, the high-level manager doesn't know about RPG::Randomize. It doesn't care about the mechanics of it. (If only I could draw a picture here!) I hope this helps you understand a little of the deeper thinking behind sane package construction. Also, please use strict in everything you do. It will make your code much cleaner and clearer. | [reply] |
by Tiefling (Monk) on Jun 12, 2001 at 17:08 UTC | |
Have you read the Daft text adventure project thread? That contains the original brief and a lot of the suggestions and responses initially produced. It also describes the origin of the program I was intending to create, and my own background in BASIC. The first instinct I've seen in a lot of decent programmers has been to treat Perl with less respect than they would C, Java, or any other compiled language. What does this mean, specifically? I was under the impression that Perl was the proverbial Swiss Army Chainsaw, capable of bringing more than enough power to bear on a wide range of tasks. How do I risk making an unstable app? (On re-reading, that question sounds silly, but I can't express it better right now.) "Why?", you might ask. Well, you talk about a dice-rolling function called dice(). Then, you talk about a modifer() function. As someone who plays D&D, these, to me, instinctively seem as if they belong in the same place. This is because they both deal with ability scores. I humbly disagree. dice() has nothing to do with ability scores specifically, or with D&D. dice() should be relevant to Call of Cthulhu or even In Nomine, as well as to D&D. modifier(), on the other hand, deals exclusively and explicitly with a property of D&D's ability scores. Perhaps an RPG::DND::Character module is mandated, perhaps not. I would incline toward thinking 'yes' here, especially given the modular nature of 3e's rules. (The dwarven defender and the barbarian have very different special abilities utilising 90% of the same 'code'.) modifier() clearly belongs in such a module, since it is absolutely specific to D&D characters. I'm inclined to think that the top level should know how to roll dice, since it might need to use them for explicitly defined game features (as opposed to emulation of a given rules set). However, 99% of the calls to dice() and its cousins (the functions of RPG::Dice) will indeed be made by RPG::DND::Character, Combat, etc. I'm opposed to the idea of coin_flip as a separate function. However, if it were required, the following line could go into Dice.pm:
(Something tells me I can't take an element from a constant list, in which case that would have to change.) Apart from the difference covered by the above line, how is a coin flip different from 1d2? Certainly your answer has got me thinking about sane package construction. However, I'm not sure where you stand on the topic - or where I stand. This is, of course, the kind of discussion I have hoped to promote by discussing my project here at PerlMonks. Thanks again, Tiefling the Lazy
| [reply] [d/l] [select] |
by dragonchild (Archbishop) on Jun 12, 2001 at 17:42 UTC | |
I have read the Daft Adventure thread, and I've also written similar programs myself (back in Apple BASIC). This was actually my first program over 100 lines, back in the day. However, given your responses, I wonder if you'd read everything I wrote. Yes, I originally said: "Why?", you might ask. Well, you talk about a dice-rolling function called dice(). Then, you talk about a modifer() function. As someone who plays D&D, these, to me, instinctively seem as if they belong in the same place. This is because they both deal with ability scores. However, I then said that both RPG::D&D::Character and RPG::Dice would be needed. That implies that dice() would be located in a non-D&D spot. However, I don't want to start a flame-war. This project is obviously something dear to your heart and I apologize if you felt that I was insulting your intelligence or your design capabilities. I was merely attempting to humbly offer up some ideas of my own. Now, onto the project! The basic functionality you're probably going to need involves (at least) the following areas: Note that this is from an extremely high level. There is no mention of how things are adjudicated. From a DM/player perspective, this is what the game is all about - making a character, choose skills/magic, and then running around a world. Occasionally, you might have to fight stuff. Every single action you take from this high a level should call some method contained in another module. There are several reasons for this: Now, we don't know exactly how these modules will go about doing their thing. In fact, we don't even know if they will be modules or classes. (RPG::D&D::Character may very well be a class - I find it easier to think of a PC or monster as an thing that knows how to do stuff versus a set of methods to be run on a data structure you have to maintain.) Each module will have an API (set of methods that other modules know about) and a mandate (what it takes care of for you). Once you have sketched this out, it becomes very simple to flesh out the skeleton. | [reply] |
by Tiefling (Monk) on Jun 12, 2001 at 18:20 UTC | |
by dragonchild (Archbishop) on Jun 12, 2001 at 18:44 UTC | |
| |
Re: Modules: Building blocks for the Daft Adventure
by modred (Pilgrim) on Jun 12, 2001 at 15:39 UTC | |
If you use the Exporter module when creating your module, then you can (optionally) import the function name into the current namespace and just call it is as
If you make RPG::DND an object, you would create an object of that type, something like my $rpg = new RPG::DND;, and then you would call it like
Also, you might want to name it something like getModifer rather than just modifier so it is slightly clearer on what the subroutine does. | [reply] [d/l] [select] |
by Tiefling (Monk) on Jun 12, 2001 at 15:47 UTC | |
Now I need to know why would I want to use or not use Exporter. I can't see the advantage of having to write eight more characters every time I call the sub - what are the other pros and cons? As for making RPG::DND an object, I'm a little confused now. I had thought I understood objects, but now I'm all at sea again. I thought an object was, or was the target of, a blessed reference. (Apologies if that's not expressed in a canonically clear manner.) What does it mean for a module to be an object? As for the name of the sub, the name was chosen to bring readability to the final code. If I'm able to say modifier($strength), it'll make the finished text easier for me to read. Hope this helps. Thanks for your advice. Tiefling, KLB
| [reply] [d/l] [select] |
by modred (Pilgrim) on Jun 12, 2001 at 15:55 UTC | |
As far as the object goes, I think you have a good grasp of what an object is. For a package to define an object, it must contain a subroutine that returns the blessed reference. This is typically named "new" but it does not have to be. I may have caused some confusion by using the terms module and package interchangeably - which they are (for the most part) in my own mind. I am not sure of what the actual difference between the terms is though. | [reply] |
Re: Modules: Building blocks for the Daft Adventure
by Masem (Monsignor) on Jun 12, 2001 at 15:41 UTC | |
The way I've been using coderefs is as follows: That is, the &$mod is a function call of a deref'ed coderef. To actually call this, you can do it by one of two ways: (The \& here creates a reference to the function modify). What's nice about coderefs is that they then can be used as variables, and allow you to quickly do different functions depending on what you pass: </CODE> Dr. Michael K. Neylon - mneylon-pm@masemware.com || "You've left the lens cap of your mind on again, Pinky" - The Brain | [reply] [d/l] [select] |
Re: Modules: Building blocks for the Daft Adventure
by mbond (Beadle) on Jun 12, 2001 at 15:51 UTC | |
because this is a learning experience, i'm just giving the skeleton of what i did.:) The ideas will be the same for making dice rolls into a module. in a file called "comm.pm" which is in the same directory as the main perl script. It actually calls it through a funtion and the above line is completely variable (so that it works from any function call) Michael Bond | [reply] [d/l] |
Re: Modules: Building blocks for the Daft Adventure
by Syrkres (Sexton) on Jun 12, 2001 at 21:56 UTC | |
We should work together on this. I have already created a RPG: module system with several modules. The first being :Dice. I also have :Name, and have started working on :Classes and :Char. Another one is :RULGen which uses a rule structure for generating random things. I am currently re-writing this to work with XML templates. Syrkres (syrkres@miniworld.com) | [reply] |
by Tiefling (Monk) on Jun 14, 2001 at 15:16 UTC | |
I'd be happy to have you working with us on this project! (See elsewhere in the threads for copyright points.) What do the modules you've already got actually do? How transferable is the system you have devised? How would it relate to the proposed Text Adventure interface? Tiefling (in search of answers)
| [reply] [d/l] |
Re: Modules: Building blocks for the Daft Adventure
by Malkavian (Friar) on Jun 13, 2001 at 01:59 UTC | |
I've been working on a Rolemaster set of tools in Perl. If it looks like the code is being generated as an ongoing Monastery members thing, I'd be happy to add routines and char gen tools for RM. Malk. | [reply] |
Re: Modules: Building blocks for the Daft Adventure
by coreolyn (Parson) on Jun 13, 2001 at 02:15 UTC | |
Has anyone even checked Dice::Dice? If so what makes it impracticle? It handles 3d6 type of calls and other functionality is already built in. Your modifiers could then be implemented from thier own module outside of the roll and your modifier routine doesn't have to know squat about the roll type and would be far easier to maintain. coreolyn | [reply] |
by Tiefling (Monk) on Jun 13, 2001 at 16:15 UTC | |
1: I want to be able to parse a string and return the appropriate roll. This is the main thrust of the module in question. Dice::Dice has some ability to do this - however, there are situations (particularly in games like Warhammer) where large bucketfuls of dice are needed. Dice::Dice might well not be efficient here, as I don't want persistent objects - only answers. 2: Dice::Dice, by your own admission, requires a re-write because of the use of deprecated features - unless the re-write has already taken place and I missed the note that says so. 3: I don't _want_ well-behaved object dice. I want a function which takes appropriate input and brings back a number, by munging the input and totting up a bunch of rand() calls. Perhaps I need to clarify what I expect my own module to do. Desirable calls: stringdice() - a function to take a string like '3d4 + 2d6 +4d8 +9' and return a properly-distributed random number in the appropriate range. listdice() - a function to take a couplet ($x, $y) and return the individual values of xdy as a list. bestdice() - bestdice($x, $y, $z) returns the best $z values of listdice($x, $y). topdice() - topdice($x, $y, $z) returns the values of listdice($x, $y) exceeding or equalling $z. (For World of Darkness, for example). Looking at the documentation for Dice::Dice, it could probably be persuaded to do the above, but I'm not sure if it's the best way to proceed. All this is not intended to suggest Dice::Dice is at all bad - far from it - but TMTOWTDI. Also, I'm interested in being able to develop this stuff myself, and Dice were not a feature of the implementation which screamed to be OO. Tiefling
| [reply] [d/l] |
by coreolyn (Parson) on Jun 13, 2001 at 17:38 UTC | |
Thanks for the explanation, and yes the code was re-written, but I'm not completely sold on them either for performance reasons -- I'm just shamelessly trolling for opinions :) Having coded many of the DnD charcter generation and battle tables in several languages over the years (It's my favorite way to learn and compare languages) separating the dice makes it easier to run the rolls against matrices as well as clearly delineating whose dice are being operated on. Plus in the game design I've always pondered I've looked for ways to put the dice back in the hands of the players. In table top gaming picking and rolling your own dice is a part of the fun. coreolyn | [reply] |
by Tiefling (Monk) on Jun 13, 2001 at 17:50 UTC | |
Re: Modules: Building blocks for the Daft Adventure
by mattr (Curate) on Jun 13, 2001 at 15:42 UTC | |
Anyway you might want to check out Games::Maze in CPAN just for an idea of how to generate mazes and populate them. Maybe you don't want this because the mazes are all preprepared, but the point I wanted to make is to think about how this system will actually be used and try to conceive of the main scenarios for use. This may help you decide what metaphors for game play are useful and the objects can be defined naturally from that. I'm not sure if you are trying to build something like an intelligent gaming board on a server somewhere that interacts with many browsers, or if it is just a totally abstract system of descriptions of gaming and objects in a game that doesn't suggest a certain implementation. Or is this maybe just for a single user? I think the real question is, are you trying to build a general simulation system (it might work for military simulations too) or a simpler gaming aid for a DM to use. The nice thing about modules is that it helps you compartmentalize your thinking, and keep it simple. Of course you can just dive in and not worry about doing lots of revisions! If you are trying to a general system to describe and run all kinds of simulations of players in virtual worlds, then you can start from the ground up and try to describe what D&D is all about from the ground up instead of starting with advanced concepts like monsters and multisided dice. But the idea of respecting Perl that came out above I think has more to do with taking care of how you choose the underlying metaphors on which your system is built. If they are powerful metaphors which resonate strongly with the realities of gaming, you will be able to extend them for a long, long time. | [reply] |
by Tiefling (Monk) on Jun 13, 2001 at 17:17 UTC | |
Granted. You'll have noticed, elsewhere in this thread, discussion of Call of Cthulhu and other systems. A major part of this project is the development of a text adventure system that can accept rules sets as additions. In that case I'd try and boil down your huge knowledge of D&D to the absolute basic minimum number of concepts you need to describe what playing D&D is about. I was thinking of boiling it down to 'what is a text adventure' and 'how do we make the format extensible' myself. Maybe the basic ideas of players, monsters, and Dungeon Master are something you want to use. Curiously combat and monsters in the sense of physical adversaries are inessential. And the Dungeon Master in my original concept was to be me, coding the behaviour of rooms, characters, etc, to be interacted with by the players. I don't know how you intend to use the module(s) but I just read Neil Stephenson's The Big U and it describes using a huge computer to run the game (with a DM seated in front of it) while the players actually run through the sewers in 2-way radio contact. How can I say that this would be a very bad idea? I am a member of a Live Roleplay group, and any suggestion that players might be sent into a genuinely inimical environment without any form of direct supervision is...frowned upon. The intended format would be players sitting at one or more terminals, taking turns to issue actions, to be parsed by the computer and used to alter the state of play. Something like a MUD, people will say, although my idea of the passage of game time mandates a turn-based approach which means it won't actually be a MUD. Sample output of a modern-idiom version:
That's just an idea, but I hope it captures something of where I'm coming from. D&D, CoC or whatever other rules system and campaign idiom the operator chose could be applied to the core program to produce an appropriate campaign. I've looked at Games::Maze - it looks interesting, but the idea of the system at hand is that it should produce a realistic, deterministic, mimetic world for game play. As to monsters, I agree with you - not yet. I suggested the production of a dice module because doing so would make the subsequent implementation of _any_ deeper rules system easier. So it's not what D&D is about, because if you ask that, the answer is 'first and foremost, it's a work of creation and imagination, and not about rules at all'. What does all this talk of metaphors mean? I've just got out of a meeting packed with talk of 'frameworks' and 'outcomes' and other civil service bafflegab, and I need a breath of fresh English/French/Swedish/Latin. Tiefling
| [reply] [d/l] [select] |
Re: Modules: Building blocks for the Daft Adventure
by Syrkres (Sexton) on Jun 13, 2001 at 22:29 UTC | |
Here is my dice package below. It allows for computing dice expressions, which I have created a bit of syntax for. Please give comments on it as this is my first package ever made public. And though it works, it may not be the best. Syrkres
| [reply] [d/l] |