17 June 2015

the joy of rotozoom()

A quick update: I've been working on a new routine to display tiles, with support for animated sprites. Instead of the epitomal @, you are a pair of footprints wanderig around. There are some dogs pawing about, as well, and the system currently supports critters up to 4 hexes big (mounts and pachyderms, I reckon). Further down the road, I'm opting for some kind of speech system with speech bubbles, and probably typographic sound effects (comic book onomatopoeia like "clank" and "boom").

All animations can be switched off in the configuration menu, of course. Even then, I've a nice system where you can switch between resolution levels (and, theoretically, tile sets) at a whim, to support both small and big screens. All very much thanks to pygame's smoothscale() and rotozoom() functions.

The next release is probably going to be all about a desert biotope, with pseudo-random species of animals and plants. I've been moving a lot of the content over in data files, to make it easier to add new stuff. The very template-like desert dog that's currently in the game, is contained in the following lines in the data files:
cri small dog # "cri" means "critter", as in "define new critter"
inherit "critter" # get some basic stats
nom ["a","big chihuahua","chihuahuas",""]
max_health (2,1)
tags ["animal"]
causes ['self-preservation','zombi moves'] # define behavious
hands "bite" # natural attack
size 2 # two hexes big
tile ((2,2),(2,2),(2,2),(2,2)) # refers to four (identical) paw sprites
end # end entry for critter "small dog"

# the following three entries make up a very simple "reptile brain" AI plugin:
cause self-preservation # "cause" = preferences/ethos of being
bias [(('harm',0,0,'self',0),('aggravate','agent'))] # hate attackers
states['relaxing'] ["zombi wander"] # when relaxing, just walk randomly
states['attacking'] ['zombi attack'] # need to be able to fight
state zombi wander # the "relaxing" state of the critter
actions [(30,("relaxing",0),("finish",0))] # 30% find other pastime
actions [(10,("wait",0),("finish",0))] # 10% stand still
actions [(100,("wander",0),("finish",0))] # 100% walk randomly
bias [((0,'foe',0,0,0),('attacking','agent'))] # attack foes on sight
state zombi attack # attacking state
actions [(100,("is_dead","q"),("return",0))] # if quarry q is dead, exit state
actions [(100,('ally','q'),('return',0))] # is q is an ally, exit state
actions [(1,('nil',0),('return',0))] # 1% P of randomly exiting state
actions [(40 ,('approach','q'),('finish',0))] # 40% try to approach quarry
actions [(100,('attack','q'),('finish',0))] # 100% try to attack quarry
actions [(100,('approach','q'),('finish',0)), (100,('wander',0),('finish',0)) # backup strategy: charge!

As you can see from such snippets, I'm not aiming for this to be expandable by anyone except me ;) but there is support for "modules" in the game, so you can theoretically mix and match packages of content. In the long run, one could release expansion packs, maybe stuff like a "steampunk mod" or an "undead apocalypse mod", for people who are into that kind of weird west, and the players could choose to include or exclude the various modules at their leisure (I would love a "postapocalypitic cowgirls/Burroughs/Genet queerporn mod", mesself).

Dreaming about long term goals such as this, is of course a very important part of RL development. I think I'll celebrate the next release with a meatier blog post detailing my sterling Slow Application Development (SAD) Method. In the meantime, interested parties can get your snapshot release here (python sources).

The next big thing to do, is to systemize how random elements are picked, so that I can start adding more content; the encounter tables, so to speak. I'm going to use the kind of rhizomatic data entries examplified above, but they need lines beginning with something like "frequency". There needs to be a module or object to make sense of cases like how, if an oasis appears in the desert, it might possibly contain the tent of a travelling salesboy (but probably not a nest of poison ugguks, which you'd be more likely to encounter underground), and in that tent (possibly) of box of posessions, amongst which (possibly) a handgun which (possibly) only holds four bullets, but scores deadly shots with a 1/6 accuracy (just possibly).

The devil, of course, is in the details, that is to say the content. The anatomy of a critical hit, and of the revolver itself, not to mention the salesboy and his tent, the oasis, the desert … With small steps I might be able to slowly populate the current waste land and build a world of biotopes subtle and sprawling, struggling centres of civilization, and a gruesome, mysterious subterranea.

By the way, rescaling the sprites can also be used to get a nifty overview map, although it would be risky to navigate around that, once I get some dangerous encounters up and going in the desert. On the long todo-list is a "travel mode" which zooms out to a larger map view. But here and now, it's more pressing to fix various issues with map generation, some of which become apparent from this very screenshot.

As always,