Lacking Natural Simplicity

Random musings on books, code, and tabletop games.

OpenRPG

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.

More on VMS BASIC and Re-dimensioning Dynamically Allocated Arrays

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.

Diceless Roleplaying Games

These descriptions were part of or inspired by a discussion on rec.games.frp.advocacy

Epiphany

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

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.

VMS Code from the Past

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 now.

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.

2014-11-03

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.

http://h71000.www7.hp.com/doc/73final/cobol/bas_ref_013.htm#noisn

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.)

RPG Maps

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.

Aubrey and Maturin

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.

Consistent Game Worlds and Levels of Detail

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?

B&B: The Missing Kit

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.

Attending

  • T.K.B. — GM

  • B.B. — a bunny

  • T.A. — maybe; watching us play?

Actual 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.

B.B.'s Fudge Bunnies & Burrows Game, Session 1

Attending

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

  • P.B. —

Actual Play

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.

I think this was the first time I ran a roleplaying game for one of the kids. I ran at least four Fudge Bunnies & Burrows for B.B. and various of the kids and their parents.