OpenRPG is a client server application for playing table-top roleplaying games over the Internet. It runs on Windows, Mac OS X, and various other versions Unix. It provides interactive chat with integrated dice rolling, a simple map display, game server browsing, and a tree-structured data organizer for character sheets, setting information, adventures, and so forth. It's a bit rough around the edges, but it's certainly functional enough to be useful.
Random musings on books, code, and tabletop games.
Wreck of the River of Stars, by Michael F. Flynn.
Hell's Faire, by John Ringo.
March to the Stars, by David Weber and John Ringo.
Nameless Magery and Of Swords and Spells, by Delia Marshall Turner. These two books remind me in some ways of Doris Piserchia's books.
Monday, 19 May 2003
As I mentioned earlier, VMS BASIC doesn't allow you to redimension dynamically allocated arrays inside procedures that they have been passed to as arguments. One of the folks at HP saw my post about this in comp.os.vms and passed it to a VMS BASIC engineer, who confirmed that my workaround was reasonable and should work, which was good to know, although I had tested it and it seemed to work fine.
I don't think Epiphany's ranged combat is equivalent to Rock-Paper- Scissors, though. In R/P/S each side chooses randomly between three choices and there is no intrinsic reason to choose one or the other. In Epiphany's ranged combat each side totals up their advantages and all the attacker's advantages are used for offense and all the defendor's advantages are used for defense. This is non-random and it depends on what applicable abilities are available to each side. I don't think these two are that similar.
I don't think Epiphany's resolution mechanism is analogous to Rock-Paper-Scissors, nor do I think that result is random. In R/P/S you pick one of the three choices, your opponent picks one of the choices, there is no reason to pick one of the choices over the others, and the result is random. In Epiphany, each side counts up the number of Advantages they have that apply to the situation and decides how many to apply to Offense and how many to apply to Defense. (The number of Advantages one side has is the total of the Attributes and Abilities that they have that apply in this situation, minus any Disadvantages.) That's not random at all, and has the tactical issue of allocating Advantages to Offense and Defense, which makes it even more like unlike R/P/S.
(I think Epiphany's resolution is often compared to R/P/S because they both indicate the what each side is doing by holding out fingers, but the choices behind and effects of those choices are very different, so this apparent similarity of finger- pointing is actually misleading.)
Nobilis is a bit more crunchy than most diceless games. All Characters have four Attributes--Aspect, Domain, Realm, and Spirit-- which are rated from zero to five and describe the character's level of ability in four broad areas of effect. Each attribute also has a number of associated Miracle Points. Characters can also have other abilities, called Gifts, which have a more focused or limited area of effect. All actions are rated in difficulty from zero to nine. Actions in a particular area of effect that have a difficulty less than that of the attribute that governs that area are automatically successful. Actions that have a difficulty greater than the appropriate attribute require spending miracle points to succeed. There are tables that indicate the level of power each level of difficulty provides, and there are lists of example actions and their difficulty levels.
Listening to: Hawkwind, Chronicle of the Black Sword.
I've been reading a lot of VMS BASIC 1 source code from the early 1990s 2 recently, and the one lesson it has taught me is that refactoring source code is vital for maintainability. Much of this source code originated in one program that was copied and edited whenever a new program was needed, so each new program generally ended up with a lot of rag-tag odds-and-ends code from the original program that was not actually needed for the functionality of the new program. Unfortunately, when one is trying to change some existing functionality one has to look at each and every program and figure out if that functionality is actually implemented and used in that program, and to do this you have to mentally trace the execution of the code! The moral? When you copy code, delete everything you don't actually use! Refactor, refactor, refactor!
And why didn't we use
%INCLUDE more? There are hundress of lines of
external function declarations that are used time and again in several
programs; we should have put them in a couple of include files.
I really wish VMS Basic allowed redimensioning array formal parameters, but I understand why it's not allowed. (Perhaps there should have been a specific descriptor for arrays that can be redimensioned?)
I was shocked to rediscover that there was no way of reliably building
the system from the source code. MMS was too expensive for us at the
time and if MMK existed we
didn't know about it. We used a bunch of ad-hoc DCL command
procecudures to compile whatever program we were working on (most of
them were all in one source file, and linked against one library of
utility routines) and these were never collected. So, you couldn't
easily tell if the current set of executables was actually built from
up-to-date source. Since I've been doing the odd bit of maintenance on
this system every six months or so I finally broke down and created
DESCRIP.MMS files for use with MMK, and I'm much easier in my mind
There were a number of things in this system that I think were well done, though, so it hasn't been all pain looking at it again.
I'm working with it on an Alpha so I can't call it VAX BASIC anymore.
The original version of this system ran on PDP-11 running RSTS/E. I've been involved in two major conversions of systems running on PDP-11 RSTS/E to VAX/VMS, both using the POISE DMS-Plus on both RSTS/E and VMS, with extensive homegrown applications written in VMS BASIC and using the POISE SPL API.
Here's the text of my post to comp.os.vms:
The BASIC for OpenVMS Reference Manual says, in the fifth item of the Remarks section:
The executable DIM statement cannot be used to dimension virtual arrays, arrays received as formal parameters, or arrays declared in COMMON, MAP, or nonexecutable DIM statements.
The "no formal parameters" rule is inconvienent. It means that you can't pass an array to a function, redimension it, fill it with values, and then use LBOUND and UBOUND in the caller to find out its new size.
Presumably it is illegal because there is no way at compile time to know if the function will be called with a dynamic array created with the executable DIM statement or a static array created with a non-executable DIM statement.
However, the programmer can know, so it ought to be safe to redimension the array directly when the programmer knows it was created by an executable DIM statement.
Using Alpha BASIC V1.4-000 under OpenVMS V7.2 and looking at the listing of some code with some executable dimension statements compiled with /LIST/MACHINE revealed the existance of DBASIC$RT_DIM and after a little experimentation lead to a program that used DBASIC$RT_DIM directly to redimension dynamically dimensioned arrays in functions, included below.
DBASIC$RT_DIM is not documented for users (probably by design) and could theoretically lead to flying monkeys and access violations, and is probably bad style. However, are there any practical reasons why this wouldn't work safely? Are there any conditions under which this hack would fail to work?
Here is an example program:program redim option type = explicit, constant type = integer, & size = integer long, size = real double external sub redim_in_sub (string dim()) external long function my_redim (string dim(), long) declare long i, r i = 10 dim string vs(i) ! has to be a variable to make it an executable dim. r = my_redim (vs(), 30) print "ubound(vs):"; ubound(vs) for i = lbound(vs) to ubound(vs) \ vs(i) = "vs 30-" + num1$(i) \ next i gosub print_vs call redim_in_sub (vs()) print "ubound(vs):"; ubound(vs) gosub print_Vs exit program print_vs: for i = lbound(vs) to ubound(vs) \ print i; ": "; vs(i) \ next i return ! from print_vs end program ! redim function long my_redim (long s by value, long n) option type = explicit, constant type = integer, & size = integer long, size = real double declare long r external long function dbasic$rt_dim (long by value, long by value) r = dbasic$rt_dim (s, n) end function r ! my_redim sub redim_in_sub (string s()) option type = explicit, constant type = integer, & size = integer long, size = real double external sub set_strings (string dim(), string) declare long i call my_redim (s(), 40) for i = 0 to 40 \ s(i) = "redim in sub " + num1$(i) \ next i end sub ! redim_in_sub
(Interestingly, a slightly different approach was necessary using VAX BASIC V3.5 under VMS V5.5-2: using BY VALUE in function definition statements is not allowed by this version of VAX BASIC, and BAS$RT_DIM had to be used instead of DBASIC$RT_DIM, of course.)
One of the things that I really enjoyed when I first started playing roleplaying games was drawing maps: dungeons, towns, countries, continents, and worlds. Even if I had no plans to actually use them I enjoyed drawing them. I haven't done that for a long time, but recently I found AutoREALM, a GPLed Mapping Program. It looks like fun; I think I'll go draw some maps.
I think that one of the things that helps Patrick O'Brian's Aubrey and Maturin series transcend its genre is the skillful embedding of the main character's lives in their world. In most Napoleonic-era-military genre fiction the characters are seen through the events of their lives as members of the military establishment. For example, all of Rifleman Dodd's actions in Rifleman Dodd and the Gun by C.S. Forester concern his military mission. Aubrey and Maturin, however, often do things that are not part of their military life: music, natural history, local politics, and so forth, and places them in a wider scope than many characters from the genre.
It is easier to create a consistent game world if it is not too detailed, and it is arguably easier to start playing in such a world, since each roleplaying game group will create their own vision of the world with their own details, and will feel a greater connection to the world and it's unfolding history. However, if game play generates additional detail (as opposed to simply generating new history) then inconsitences can arise. This is not a problem for gamers who don't care about details at all, but most care at least a little about the details: they don't want taverns to switch from one side of the river to another, for instance.
When gaming in more detailed worlds, the gamers have to expend more effort up front to work within the details: learning how Tékumel societies work, or the religions of the Lunar Empire of Glorantha, but the additional detail can add depth to the roleplaying experience and can provide additional inspiration for the game. How can such detail be best presented to prevent the gamer from becoming overloaded and turned away by the detail? Is it possible to present things in such a way that there is as little up front work for the gamer to start playing in a detailed world as an undetailed world, and can the continuing effort of working within the details be kept close to the level of effort required to play in an undetailed world?
This was probably the second RPG session I ran for any of the kids. It carries on from the session B.B., and probably C.B. and P.B., played. As before, it uses Steffan O'Sullivan's Fudge Bunnies example characters, and the farm from the adventure “The Herbmaster's Plea”, which starts on page 94 of GURPS Bunnies & Burrows and uses the farm map from page 97. My notes are very sketchy, not even including who played.
T.K.B. — GM
B.B. — a bunny
T.A. — maybe; watching us play?
A mother is wailing about her missing kit.
My original notes, transcribed:
Bunny kit (Buttercup) is missing — last seen on the east side of the warren. Violet is mom.
Cat in barn — Cleverness: Fair; Self Control: Good; Notice Things: Good; Nose: Mediocre; Agility: Superb; Strength: Great; Fitness: Good; Speed: Great; Move Quietly: Superb; Combat: Good.
Cottonmouth by River — Agility: Good; Strength: Great; Fitness: Good; Speed: Mediocre. Poison, then wait for struggle to end.
Pair of Foxes — Agility: Good, Bite: Great; Strength: Great (+2)
Track kit to creek, cross before swamp, cross back at east side of duck pond, picked up by human child, kit put in cage in hayloft (loose hay), cat above grain box by ladder/steps to loft, cage latched & up on wall.
Followed human tracks (boy picked up the kit) to the barn & are about to go in looking for the kit.
Everything down to the next-to-last paragraph is my spur-of-the-moment setup for the adventure, while the last paragraph is the report of what actually happened during the session.
This is a timewarp entry.
GURPS Bunnies & Burrows, “The Herbmaster's Plea”, p. 94.
I'm guessing at who attended (although I know B.B. was definitely there) based on player names printed on the character sheets, but they may or may not have played in this session. I think they did, because I wrote something “They did manage to gather some vegetables as they fled.” in my original notes.
T.K.B. — GM
B.B. — Chamomile, a bunny
C.B. — Nimble, a bunny
I ran the first example adventure from GURPS Bunnies & Burrows, “The Herbmaster's Plea”, p. 94, for my nephew B.B. using Fudge. 1 He successfully rescued Rosin. Ended up in the Orchard on the way to the bean field, after a run-in with the thugs. They did manage to gather some vegetables as they fled. It looks like I named the captain of the Owsla Bayberry.
This is a timewarp entry.