Sunday, September 14, 2008

Roguelikes for the blind?

I'm the sort of guy that likes to plan ahead.

Part of planning ahead is foreseeing potential problems and preparing for them beforehand. This means, I think about things like special needs. Because I may well have a need of it myself some day.

This is why I want a single-story house. If I wind up in a wheelchair some day, I don't want to deal with stairs. Plus, if I'm just old and enfeebled, I could fall down the stairs and break my back. Stairs are dangerous. Stairs kill.

Anyway, I was working on PyGame support in STEW, and looking at how PyGame handles keycode input. It occurred to me that it only has the capacity to tell me that keys have changed state, and it certainly doesn't appear to have any built-in accessibility features. Things like sticky-shift states would need to be accomidated at the application-layer. (Why sticky shift states? Well, a number of neurological disabilities could cause me to be unable to simultainously press the correct modifier keys with the correct target key.)

While I was thinking about this, it occurred to me that it would be nice to play a roguelike if I was blind. Of course, that would cause things to get much weirder, though. Ideally, I'd want to present an interface that could not only be read by screen readers, but could actually interface directly with a screen reader. This makes the whole visual representation of the map/rooms hard to present.

It also starts turning the result in to something more resembling a single-user MUD. I was actually thinking of keeping the internal representation of the map, but each room also needs an identifier -- a number will probably do, though we could just as easily do named rooms when something special comes along.

Then, there's the contents of the room. In general, I think I favor a bucket approach. A room has a certain size, and that size is filled by things in the room, with no relationship to the real-world shape of those things.

Melee combat is one thing that doesn't take in to account, though. If we're dealing with two creatures, we can easily take the empty space in the room and pick a random amount of space between the two opponents. However, some rooms are literally packed with creatures. While we can easily state that at most 6 or 9 creatures can attack you at once (depending on whether we want an implied hex map or a standard roguelike grid) you still have things like wands and breath weapons that can strike a large number, bounce off walls, and hit even more.

We could go with a literal roguelike grid, with the ability to look various attackable directions. We'd need short-cuts so that you could also just look at and attack a particular monster type. Sometimes attacking a monster would have implied movement to reach it.

It does seem to me that after thinking about it a little, we need to retain the roguelike map. We'll just need to have sufficient short-cuts to make visual representations of the map unneeded.

Here's a potential example of what it could look like:
You travel 10 feet. You turn east to follow the corridor. You travel 60 feet. You stop 10 feet from the doorway to room 1 on floor 7.

To the easy, you see:
  • a broken door
  • an orc chieftain
  • 3 orc soldiers
To the west, you see:
  • an acid blob
This would break down the line-of-sight by cardinal direction. There could then be eleven direction labels, one for the eight cardinal directions, above, below, and around (for when you get swallowed by something).

Above isn't normally used on roguelikes. Below has common meaning when you're levitating over hazardous ground. Each of those should describe your cell only. The cardinal directions, however, cover more than just the usual lines. Each cardinal direction covers a 45 degree arc in that general direction.

The order is sorted first by monster type, and then by proximity to player. Once the list is sorted, it is compressed so that adjacent monsters in the list form a single line. This means that if 4 orcs are all 100 feet from you in the same general direction, they would show as "4 orcs", and if there is a line of 4 orcs coming toward you at 70, 80, 90, and 100 feet from you they would also show as "4 orcs". If there was a bat amist the orcs, though, in the earlier cast it would always continue to bundle the orcs, but in the later case it would likely wind up splitting the orcs in to two groups with a bat in the middle.

You would need to be able to query how close a given monster type is, what monsters are at a given distance, as well as what monsters are in a given attackable direction.

Doors will also need identifiers. I think we can go with letters, so that a room number + door letter unique identifies a door. This would allow us to say:

You enter room 6. It is 30x60. There are four doors here (A, B, C, D).

There appear to be no monsters in the room. The room contains:
  • ...amulets...
  • ...gems...
  • ...wands...
That is, we identify doors solely by the letter. While we could state, "Door A is on the north wall, and 20 feet from the north-east corner." It just starts getting harder to remember, and having less value. Likewise, we can drop the number of steps taken when walking the corridors. When intersections are presented we should state the direction we came from, and the directions now available. When monsters are nearby the behavior should be as earlier described whether in a room or not.

When monsters are not visible in a room, we can do as described in the most recent example, and bundle all objects together. While this doesn't make as much sense on an open-plain map, rooms are small enough that it makes little difference where an object is within the room. They should still be sorted by proximity, so after you take the first object you can always modify your path. (Assuming we don't short-cut that behavior when in a room and monsters aren't around. I wouldn't be against picking up objects as being 1 turn activities -- particularly if we make entering a room a multi-turn activity.)

Yeah, we can see where I suffer from a case of feature-bloat. Particularly for this project.

Saturday, September 13, 2008

Things that slow STEW down...

So, STEW was reasonably documented... in SDF, which I'm no longer using. I'm now favoring RST all-around.

I had ncurses working reasonably well, but... the goal is full Unicode support, and it certainly appears ncurses wasn't the best choice there. Ncurses itself isn't available everywhere. I needed a GUI version to work everywhere.

My first thought was Tkinter. I even started working towards that end. But, of course, Tkinter doesn't reliably ship with Unicode support.

The goal is always rich colors, rich fonts, while still holding onto the heart of the roguelike genre. No graphics, except to enhance the text. I do want to have some things now normally allowed in TTY mode.

Things like, on old-school terminals:
  • 88/256 color mode on an xterm
  • unicode support (widechar in ncurses)
  • separate background/foreground color

Of course, with a GUI-based setup we can make things much better:
  • full true-color support (better than normal, as we can have fore/back colors different than each other, everything becomes more legible)
  • font characteristics (nornal, italic, bold, strike-through, etc.)
  • atypical diacritic marks (etc) (d with a cedilla.)
  • background/foreground color
  • cell boxing lines which do not interfere with primary glyph
  • cell "glow" color -- blob of color smaller than background color in the middle of the cell
  • underline/strikethrough/shadow a different color than foreground
It is possible to take it a little further, and provide the map-grid with a large primary glyph, plus a small subscript/superscript glyph.

But, of course, first I need to get something working in a GUI with some chance of success. I'm currently thinking PyGame. Yeah, I know it seems quite unlike something used by a true Rogue-like. Still, it should provide what I need, and it is portable. The native full-screen support makes it present itself more like a true rogue-like than something designed first for a GUI.

Tuesday, August 19, 2008

Current dirt

Spending less time online: I'm been spending more time making stuff and less time talking. I've a project publicly hosted, though it isn't in very good shape. This has provided an invigorating drive to get it to 1.0 and be done with it.

As a side-effect, I've found myself writing an extension to Python's distutils to support (1) generation of POT files from source, and (2) generation of MO files from PO files. This'll be a genuinely useful patch, which will be spun off of the current project. I'll then create 3 downloads: patches to distutils, patches to setuptools, and a stand-alone immediately useful in someone's file.

Thursday, January 3, 2008

Backup season

I decided it was time to have some more recent backups.

Most of the time, my personal stuff has had a fairly lax backup policy. I have earlier versions of most of the stuff spanning multiple machines, and a lot of my stuff changes fairly slowly. (Due to lack of time.)

In any case, I figured the start of the year was a good time to make a complete backup.

I say complete backup, but I install new versions of operating systems often enough that I never *really* need a complete backup. I just need a backup of my home directory.

For my personal backups I've long been taking to simple tar files split in to managable chunks. (I've had issues in the past with DVDs with files larger than 1gig. They'll work in some machines but not in others.) Back when everything fit on a CD I could use a simple single tar file.

These days, I make md5sums of the individual files and the final archive. I've also taken to using par2 to create parity files incase the media becomes a little flaky as time passes.

There are disadvantages to my approach, certainly. Specifically, it requires plenty of space while creating the files that will be burned. However, it is nice to be able to have backups from 12 years ago that still work, and to know that my current backups are expected to work as long as the media holds out.