Showing posts with label Scripts. Show all posts
Showing posts with label Scripts. Show all posts

Friday, January 1, 2021

Undercity Dungeons and the Union-Find Algorithm

And since we've got no place to go
Write some code, write some code, write some code

The line-map of Herculaneum reminded me of a project I had back in college doing random maze generation using the union-find algorithm.  Since I have some free time over the holidays and nowhere to go, I figured I'd play with it some more and see if I couldn't get decent dungeon results out of it.

I may have also bombed a "generate a maze" question on a coding interview a few years back, and could maybe use the refresher.  I had 45 minutes to do it during the interview; doing it this time took me about two hours to get the result below (but I also had to do drawing).


This is an example of a maze generated using union-find.  It would not make a very good dungeon.  Union-find guarantees that there is exactly one path from each cell to each other cell, which is the very opposite of jayquaying, and this also means that there won't be anything resembling a room, since an open 2x2 square has two paths from each corner to each other corner (first moving vertically, then horizontally, or first moving horizontally, then moving vertically).

What we can do though, is carve out structure beforehand, and then let the mazing fill in the rest and make sure it's all connected.

Here's what that looks like with rooms:

This still doesn't give us loops though.  When I first started working on this post I was thinking about trying to do something like two independent passes of union-find to generate multiple paths most of the time between each pair of cells.  That sounds tricky though.  Having gotten most of the way there, I think I could just do the same thing with loops that I did with rooms - just punch loops into the grid before we do the mazing.  Likewise, if we wanted long "road" corridors and a forum in the middle where they cross, we could put those in before mazing.  This is similar to what I did manually in Rathell, adding intentional loops and then creating tree structures inside them.

Adding loops (highlighted in red) and regenerating, we can get something like this:

So this is getting better.  Sometimes the loops all end up in one part of the map, which is unfortunate, and I should probably do something to make sure they're a little more evenly-distributed.  I might need the variance on the dimensions of the loops to be higher, so that full rooms end up contained inside them more often, for that "city block full of buildings which contain rooms" feel.  The other thing obviously missing for this to be a dungeon map is doors.  Having a loop always contain a secret door makes it less obviously a rectangular loop.  But those are more annoying to draw.  Adding secret doors to random edge removal could be both really interesting and really dangerous, because you could cut off a whole section of the dungeon, but you could also just get a small secret section, which is desirable.

Other potential extensions: 

  • Add options for roads and forum.  
  • Number the rooms on the map.  
  • It's sort of annoying how frilly, nooksome, etc these maps are; I could see them being super-annoying to describe in play to a mapper.  Might be good for a melee+mapping gauntlet level though - just add minotaurs!  
  • Add ability to serialize dungeon levels to some sort of format which can be processed by subsequent programs (for eg stocking rooms)
  • Add the ability to take partially-specified (manually-generated) dungeon files as input and then maze / fill in the unspecified parts.
  • Generate multiple levels (slightly varying map generation parameters for each one) and link them together with stairwells
  • Unreasonably huge recursive dungeon, where each cell of the outer map represents a whole dungeon level, and the links or walls between its neighbors indicate passages between dungeon levels.

Anyway, it's on github.  It was a fun afternoon project.

Sunday, August 21, 2016

The Wilderness Machine

Reflecting on my attempts to automate the wilderness (eg hexstocking), I realize that there was a failure of...  ambition, almost.  And definitely some failures of engineering, which made greater ambitions untenable.

If I'm going to automate, I should go whole-hog for a level of complexity which would be utterly unmanageable by a human, and design the system for that from the beginning, rather than just doing what a human DM would do given an abundance of free time and a dearth of creativity.  Does a submarine swim?
  • Stock lairs in hexes according to terrain type.  Dwelling-type may be chosen from the random dungeon types table, if reasonable for monsters of this type to live in a hole in the ground.
    • Actually, looking at the end of this where I'm considering migration, the more-correct solution is to start with an empty wilderness and run like 10 years of immigration and migration beforehand.
  • For each lair, construct a "hunting range" of other hexes into which its monsters frequently wander.  Hunting range primarily based on monster speed, movement type, diet, and hex types.  Range concretizes some of Trilemma's nonmechanical difficulty elements.
    • Sentient monsters taken prisoner can serve as wilderness guides throughout the range of their lair
    • Monsters unlikely to pursue parties beyond the edge of their range
  • Construct per-hex random encounter tables, based on the lairs whose hunting ranges contain that hex.
    • Do not attempt to manually query these tables.  The user interface for this is "Machine, give me a random encounter for hex 0423" -> "Goblin warband from the village in hex 0625, with n champions, m goblins on wargs, 15kcp and a sword +1 interacting with 4 wild boars from lair in hex 0321".
      • Actually though, I should drop lame-ass animal lairs and assume a reasonable, dense distribution of mundane wildlife (eg herd animals, normal-sized hawks, rats, ...).  If it isn't going to ever kill a wilderness-level PC, I don't need to track it as a monster.
    • Favor monsters from lairs that the players have met before.  This both encourages narrative recurrence / campaign capital development, and is generally reasonable in terms of shared movement habits - if you reuse the same game trails and they reuse the same game trails, you're likely to run into each other again.
    • Optionally, vary encounter tables with time of day, weather, season.  Bears hibernate in the winter, big cats hunt at dusk and dawn, giant bats are nocturnal, humanoids don't like hunting in the rain, ...
      • Cut the day into 4-hour blocks - dawn (4-8), morning (8-12), afternoon (12-4), dusk (4-8), first watch (8-midnight), second watch (midnight-4)
  • Likewise, vary probability of random encounter by individual hex, day/night, weather, season, ... instead of just terrain type.
  • Manual update with results of encounter -> "goblin warband from village in hex 0625 destroyed"
  • Monthly, check for monster migration. Monsters migrate based on monster-density in their hunting range, terrain types, season.  Monsters can also migrate in off the edges of the map (bounded area being simulated), and migrate off the edge of the map (though maybe known lairs do not migrate off-map).  Monsters less likely to migrate if they have a village, dungeon-lair, or lots of treasure.  Maybe also kill off some lairs during monthly rollover.
    • Changing ranges might be a better approach, with lair migration only if no workable range is achievable that includes that lair hex.  On month rollover, greedy search from each lair for a set of hexes which generate an amount of population support sufficient for the lair and which minimize exposure to predation.  If no satisfying solution found, the lair migrates.  Perform updates in ascending order of speed; fast predators can reactively update their ranges in response to slow prey migration.
    • Or each lair has a fixed amount of time/effort/utilization available to it, and this can be assigned to hexes to derive population support from them or to travel through them, with environmental factors and presence of predators making this less efficient.  Utilization of each hex also determines on a per-hex basis the weighting of the lair in that hex's random encounter table - you're more likely to have an encounter with wyverns in their hunting grounds than in the hexes under their flight path between hunting grounds and lair.  High utilization also means greater familiarity with the hex among captured sentients.
And then you feed the machine a big-ass hexmap, press go, and run an illegible Western Marches, where regions emerge from complex monster behavior over varied geography but don't have names and don't stay the same.  A really illegible approach would do away with hexes entirely, and make rollover a continuous rather than discrete process, but that's a lot more annoying for a computer (you can only approximate continuity, via very granular time or space), and this is probably crazy enough already.

The obvious question is "would this be fun to play in?"  And that I do not know.

Thursday, March 19, 2015

Of Strategy and Software Engineering

This post has nothing to do with gaming.  Probably.

I've been continuing to work my way through The Transformation of War, and hit something somewhat interesting last night.  Van Creveld commented on the traditional division between strategy and tactics, that tactics is the art of winning battles while strategy is the groundwork, to make sure that the battle will be fought under advantageous circumstances, that men and equipment will be in good order on arrival, and that victory can be capitalized on to achieve a campaign's objectives.  Further, he argued that much of successful strategy is working around three sorts of difficulties; uncertainty and friction (the tendency for things to go wrong and impede progress) were recognized by Clauswitz, while van Creveld also adds inflexibility.

This is probably not news to those familiar with Western strategy, but it did make an interesting connection with software engineering for me.  You see, software engineering isn't really engineering as one might use the term for, say, civil or mechanical engineering.  A mechanical engineer can look up the strength of various alloys of steel in reasonably reputable sources, crunch the numbers, and figure out what he needs in order to make the thing he's designing meet the requirements.  When he's done, he can be reasonably certain that the thing he's built will more-or-less work as intended if he has done his job properly.  Software engineers cannot do this.  The performance benchmarks available are gamed all to hell, the mathematics taught in school are primarily concerned with asymptotic behavior and completely neglect very substantial performance concerns, nobody outside of Intel and maybe some of the agencies actually knows the full instruction set most general-purpose computers are running, and next year that library you're using is going to break its interface out from under you with no warning.  Not only do we not know the 'laws of physics' of the area we're working in, but those laws are constantly changing, often adversarially.

(And of course, the client wants it done yesterday with a completely different set of requirements than they asked for six months ago, but I figure that's probably normal for most engineering disciplines)

At the end of the day, software engineering has more in common with art and alchemy than with traditional mathematically-rigorous engineering approaches.  The proof of this, I think, is that we see reflections of strategy's aims and obstables in modern software engineering practices.  Waterfall has fallen by the wayside because its timetables failed to account for friction.  Its fixed requirements led to inflexibility and may have been wrong or useless by the time the project was brought to completion.  Test-driven development makes a tradeoff between flexibility and friction, as codified tests somewhat reduce your ability to adapt to changing requirements but also reduce the impact of random failures.  The Agile family of methodologies seems focused on flexibility to changing requirements and reducing uncertainty about customer requirements through communication, which is good, but may come at the cost of a flavor of friction as developer-time is lost playing Meetings & Metrics (have you heard of my new game?  Best-selling the world over...).

(Exercise for the reader: commission a civil engineering firm to design a highway suspension bridge using Agile.  Be sure the change the requirements regularly to keep them on their toes.  Record the stand-up meetings and put them on youtube.)

Anyway: at the end of the day, software engineering is about establishing a context to programming, where the unpleasant, messy work of one's developers can actually achieve the objective despite uncertainty and both human and machine failures.  In this it is like strategy.

Thursday, March 12, 2015

Henchinator v0.1

Some folks have been asking me about my ACKS scripts lately.  They're not really packaged for general human consumption, though, so instead I threw together something resembling a website (webapp would be overselling it) this afternoon for the most-asked-about one, henchman generation.  Go take a look (but do try not to knock my server over; it is not a beefy machine at all).

Sunday, August 10, 2014

Open vs Living Worlds

Or, my sandbox games have not been all that they could have been.

In considering them and Alex's sandbox Traveller game, I came to the conclusion that I had made a choice without realizing it.  I had been running an open world in the Morrowind style - things mostly static except where the PCs acted and set off chains of events.  The advantage of this idiom is that the blame for everything almost always falls back on the PCs.  This is good, because it places the focus on the consequences of the actions of the PCs; player agency is emphasized.  It is eminently suited to classically tragic play; mistakes born in hubris come back and lay the mighty low.  Finally, this style works well for post-apocalypses where things have stabilized and everyone is afraid to leave their homes, or for wildernesses where a ecological equilibrium can be assumed.

It is, however, no less fundamentally exceptionalist than the 1st-to-20th adventure path railroad.  The PCs are necessarily unlike NPCs, in that they are (the only) causal agents in the world.  What's more, this makes for a pretty lousy simulation of settings where NPCs have any degree of power, as well as settings where the world is undergoing substantial changes.  But I am a lazy DM, and like to roll with material my players give me.

The pure-open world also has the disadvantage of leaving the PCs sans hooks or direction unless provided by themselves.  Reacting to external threats is easy; picking from the infinite menu is difficult.  Threat also unifies, while selection divides parties.

If I were to run more games, I think I would desire more world-engines; systems which drive the world in patterns, assist me with adjudication, and remind me that the Mongols are due to invade this winter.  One of the places ACKS shows great promise is in the noble court; we know how many vassals and henchmen everyone has, and those henchmen's henchmen, and so on down the chain. This cast of underlings could be a rich source for plotting, conspiracy, roleplaying, and other such shenanigans.  Part of the fun of the low-level ACKS game was the treachery; the competition for the allegiance of henchmen, the bribery and charm personing, and the never-quite-actual backstabbing were all quite entertaining for me as a DM, and it sounded like the crew I was playing with at the time enjoyed it too.  I suspect that an intriguey game could be fun for even my non-treacherous / Lawful Good players, provided that the party remained unified and plotted against NPCs.  But managing the sort of personality traits and relationships between NPCs that I'd need is at least an O(n^2) task, and beyond my brain - hence the necessity of tools.  Renegade Crowns' personality and relationship material was a good start, but I think I could do better.  VBAM's AIX stats are also moderately inspiring, while Pendragon's virtues might also come pretty close to what I'm looking for if I added a relationship score (persistent modifier to reaction rolls) on top of it.  I dunno; it's a hard problem.  People are complicated.  But if I did it right, it could become an endless font of procedural rumors, plots, allies, and enemies.

Posts potentially in the pipeline:
  • Barbarians are still coming (strongly related to living worlds / part of the impetus for this post)
  • Domains at War - Battles sub-platoon scale?  Six-man mercenary squads in a standard dungeon 10x10 square (er, hex)? 
  • Domains at War - Putting together a sample campaign?  I think I want to set it in Midnight, in a section of the Ice Forests.  The orcs have a line of forts guarding a supply line to the south; the rebels have a set of villages out in the sticks.  The orcs have a stronger supply situation and a larger force, but lack intel and need to balance striking at the enemy with guarding their supply train, while the rebels have better intel but need to feed off of orcish supplies and rely on attrition from small skirmishes in order to survive.
  • The time may have come for me to turn the ACKStools into a webapp.  I think I am going to use Flask; we're using it at work, and might benefit from some extra familiarity with it.  It is not going to be pretty, but it will work.
Mostly I think I am out of patience.  Previous job involved a lot of waiting (months and months).  Now I am burned out on waiting, which is not conducive to complex games.

Thursday, January 30, 2014

Minimal News

  • Good post over at Hack and Slash on the nature of heroism in RPGs, and how incentivizing heroic play actually makes it less heroic, because heroism is about risk and sacrifice.  I quite like his Solution #4, which ACKS supports through reserve XP awards (karma).
  • By request, added functionality for generating characters of just a particular class to the Henchinator script.  Not elegantly, but it does work and doesn't break anything else.
  • Been playing a lot of Crusader Kings II... poorly.  Yesterday I learned about the perils of legitimizing my bastard sons, having foreigners tutor my heirs, being captured on the field of battle and imprisoned, heretic court chaplains, and inbreeding my heirs.  On the plus side, I also learned how to strip my vassals of their titles and claim them for myself without incurring tyranny penalties (wait until they rebel, crush the rebellion, then revoke their titles for treason)!  It's a process, but one which yields a wealth of inspiration for a domain-level ACKS game.  Loyalty rolls for everyone, all the time!  Hopefully tonight I will not lose my duchy.

Monday, December 30, 2013

ACKS Scripts Now on Github

Just what it says on the tin.  Caveats: written for linux, command-line, python 2.7.  Tested less-than-extensively but I've only had one crash on me during a game (and that was due to a bug in the config file, not the script itself).  Code quality is lackluster, as a result of a combination of factors including learning the language as I was going, hacked-together-in-an-afternoon development timescales per script, and occasionally whiskey.  Despite these flaws, quite useful.  I await your hatemail insightful user feedback.

Monday, November 18, 2013

Quality Software Design

As noted previously, I have been writing scripts to automate parts of ACKS.  One of those scripts is a treasure generator, for which I designed a configuration file language (really it's a random table description language, but the treasure generator is the main thing I use it for).  I've gradually added in support for rolling dice of dice ( (1d6)d6 and such) and other esoteric features to support hex-stocking, but that's not something I use all that much (well, not recently).

Today, however, while deciding to condition scroll contents on scroll language, however (so that dwarven spell scrolls are always divine, or turtleman spell scrolls have a chance at unique / Player's Companion turtleman spells, or so forth, as part of my grand designs to customize my treasure tables), I ran into a failure in my own foresight in design.  While loading giant lists of spells-by-race-and-level into my main treasure table config, I realized that said file was starting to get a bit lengthy...  up towards a thousand lines.  Not a technical hurdle for my Text Editor of Choice, but somewhat inconvenient to dig through.  And here I had failed to add a #include, import, or other "let me load this other file" feature into my description language!

The danger in actually using a thing you designed is that you might find bugs in it.  This hazard is even more probable if you let other people use a thing you designed.

(And yes, players, I know I should be working on a dungeon instead.  But you haven't told me which dungeon to build first!  I did figure out where the elven treasure map (er, letter) points, though, so that's a thing prepped)

Wednesday, October 16, 2013

Hijinks Again Follow-Up

After consultation about this prosposal with my former spymasters and the internet at large, comments were as follows:

  • Additional complexity is annoying
  • Reduction of thief income might have unclear ramifications for the domain ecology
    • On the other hand, our thieves were generating operating revenues far in excess of that intended by the system's designers.  Scaling a cash-generating Fraud hijink to intended levels might solve this problem, with extra cash from stealing and selling cargos of treasure mapping being a bonus for work done
  • Agreement that reduction of timescales down to weeks is a nice idea, but punishment remains problematic
  • Realization of incompatibility between the mid-level wilderness exploration style of play and thief hijinks being town-centric
    • The immediate nominal counter is that magic research is also town-centric, but the counter to that is that wizards can be gathering monster parts and unknown spells while wilderness adventuring, whereas the thief can't really use wilderness adventuring as leverage for hijinks
    • Treasure hunting and stealing are both enablers for the wilderness game, but there is nothing in the wilderness that compels a gold-desiring mid-level thief out into it except want of magic items.
      • Upon further reflection, Witness' comment on previous post solves this to some degree.  The thing in the wilderness for thieves is not being in town while law enforcement are investigating the case.  Hate to use the term, but an 'aggro'-like mechanic might serve.  Multiple hijinks in rapid succession boost probability of being caught, lying low reduces probability of being caught, and being out of town reduces it even further (but sometimes they figure it out anyway, the wanted posters go up, and the bounty hunters come out...).
And if resolving lots of hijinks and investigations for a pile of thieves sounds like paperwork...  well, guess I might have to write a script.  Feed it a list of thieves, their levels and proficiencies, what hijink they're attempting, and it spits out results.  Good way to run lots of tests of a new hijinks system, too.

Speaking of scripts, been thinking about the Mother of All Scripts again.  Some stuff from work has me thinking about ncurses and XML (both sort of groty technologies, but serviceable).  In particular, XML seems like it might be somewhat useful for encoding deep structures in text; all the contents of a 24-mile hex, subdivided by 6- and 1.5-mile hex, including NPC and monster stats down to treasure, spells known, and Markov-generated names is not an easy thing to put into a text file in an organized and reloadable fashion (see: the Art of Unix Programming).  XML could do it, but it would be verbose about it.  I guess that's the tradeoff.  The other option is to handle depth via directory structures in the filesystem, and then put hundreds of small text files all over the places throughout that directory tree.  They're sort of equivalent; seek a way to handle a gross use case, end up with gross alternatives.  As for ncurses, the problem there is one of displaying deep data in a useful way, as well as handling hex-mapping (and zooming in multiple layers of hexes) in a way that doesn't involve actual graphics...

So yeah...  cue the A(CKS|X)ML jokes...

Monday, September 30, 2013

Hexographer

So the thing I was looking at building last week was a recursive world-generator and hexmapper for procedurally building ACKS worlds down to the 1.5-mile level of detail that Cameron suggested here.  But there comes a point where it's easier to drop $25 on a Hexographer license and try that first before devoting a couple months of nights and weekends to a project like that (especially since front-end work, which is reasonably necessary for mapping, is not at all my forte).  I do hate to pay for closed-source and licensed code, but if it's the right tool, it's the right tool (and if it's the wrong tool, then I get a good idea of features I need when I build something different).

Having fiddled with the paid version for an hour or so now, I'm somewhat disappointed with the state of the advertised "child map" feature, in that (to the best of my ability to tell) it produces an unlinked map from its parent.  As a result, updates to the parent do not produce updates in the child, nor vice versa.  This is less functionality that I hoped for, but fortunately the files Hexographer generates are flat-text Unicode of some sort, and amenable to manipulation by command-line tools.  So I'm thinking a suite of Hexographer submap scripts might be in order, for tracking which maps are submaps of which parts of which other maps at what scales, and updating sub- and super-maps when either linked map changes.  Need to suss out all the details of how features and lines and whatnot are stored first, but it'll to be a lot easier than if it were an obfuscated binary file format.

The fact that the map files are flat text and use a very straightforward "note" format also means that I could fairly easily automate the addition of notes with randomly-generated terrain-appropriate hex contents.  Though I object to their selection of tab-delimited tables as their storage format (supposedly they're going to switch to XML in the near future, which is better in terms of text display but worse in terms of verbosity.  If it changes, I will adapt).

Anyway, it looks like a decent tool, and one which will save me a fair bit of labor.

Monday, September 23, 2013

State of the Gamist, September 2013

Still kickin'.  Had fun at DragonCon, but was also somewhat disappointed with the panels (almost to the point of writing rebuttal posts).  Mostly done travelling for a while, but travel time expenditures have been replaced with girlfriend time expenditures (less billable, but more enjoyable).  No gaming to speak of outside of Natural Selection 2 (at which I am bad) and Dwarf Fortress (at which I am less bad).

Spent some time this last week hunting typos in the final Domains at War: Campaigns draft, though (and was pleased by the fact that dwarven crossbow-cavalry ride mules).  Then the Wilderlands bug bit me again, but upon further examination I realized (again) that the Wilderlands are just too big and inconsistent for my liking.  Resolved to run an ACKS-ified Western Marches-esque game in the near* future instead ("civilization" being a place akin to Roman Germany or Roman Britain at Hadrian's Wall, with a wilderness of vikings and giants and naked berserker Celt-orcs to the north).  Started design work on the Mother Of All ACKS Scripts to aid in this endeavour.  Further updates forthcoming as actual work is completed.

"World creation, has begun..."

* Part of me knows that this is completely the wrong approach, and that I'm falling into the over-prep trap.  So I guess I'll just have to set really aggressive deadlines for myself (or be contented with building an awesome tool and never actually using it to run a game).

Thursday, June 6, 2013

Markov-Chain Name Generation

I haven't had internet for the last week, and honestly it was mostly rather nice.  Moved, got furniture, did a lot of leisure reading largely undistracted.  My modem came in today, though, so now I'm back, and am pleased to report that last night I wrote a simple script to tear apart names from the Onomastikon, find general probabilistic patterns of "given that the last n letters have been 'abc', the probability the next letter is 'd' is .9" using a markov chain of arbitrary order, and then generate great heaping piles of NPC or PC names which sound vaguely like they're from a particular part of the world.

Here's a sample of names derived from Medieval male German names (note that this set of names is comprised solely of names generated by the algorithm that were not in the original sample):

Adalberdus
Adalbertus
Adelstein
Aganhard
Aginhardus
Aginmund
Alarich
Albert
Albgastne
Albirichart
Amalrichart
Andhariman
Anshelm
Anshelmhart
Ansoberct
Ansobertus
Aranoldus
Archari
Archimbald
Arenher
Arenheri
Arenheribehrt
Arnolf
Arnwaldheri
Audegerus
Audes
Bald
Baldemar
Beraht
Berht
Berhtolfus
Berich
Bericus
Berinhart
Bernandus
Bert
Burcharat
Burgundo
Chonradus
Chonrat
Chustaf
Cunrad
Deigenandus
Diderich
Ditmar
Draganald
Ebert
Eburhard
Eckardis
Edelstan
Egino
Eidhere
Eidheri
Eidheribehrt
Einolf
Embricus
Emelrich
Emmericus
Ercanbaldavin
Ermenold
Ermenolf
Ernoldus
Ernus
Faramundo
Faramus
Fersomeric
Fersomerich
Fersomericus
Filiberct
Filibertus
Flanberct
Fraomanifred
Frid
Frideberht
Frideric
Fridus
Gadfridus
Gairbertus
Gairhart
Garih
Gast
Gautzelinus
Gebhardus
Gelfradulf
Gerbert
Gerbodolev
Gerbodoloff
Gerhard
Gerhartmudus
Gernardus
Giselbertilo
Gisilbertus
Glaupertus
Godafridus
Godesmann
Godohard
Godohelmhart
Godscalo
Gomerico
Gomericus
Gosberthar
Gosbertus
Gotzstaffus
Gundo
Gundus
Guntar
Guntmarus
Guntramund
Haimiricho
Hannes
Hapert
Hari
Harimannus
Hariwaldhere
Harpernust
Hart
Hartmann
Heimer
Heimeric
Heimeris
Helfradulnus
Helm
Helmus
Heri
Hertwinus
Hildebert
Hildebraht
Hildegar
Hildibragtus
Hluodohardus
Hnaufrid
Hrodeberhtolf
Hrodebertus
Hrodricho
Hrudoldus
Hrudolfus
Hruodlandico
Hunbert
Hunbertus
Isenbardo
Jofrid
Johanno
Judberthard
Judbertilo
Kuonrad
Lallobaudus
Land
Landeberht
Landeberhtolf
Landobald
Landobertus
Launobaud
Leonhart
Liukardus
Luitfrid
Luitgar
Lvfridericus
Lvfridurih
Madulf
Maganbold
Maganboldus
Magin
Maginfridus
Maginmund
Maginradus
Malberdus
Mallo
Mallobaudus
Manifrid
Manius
Meinfred
Meinfrid
Merobaud
Merobaudus
Mund
Nordemannus
Nordemar
Nordemarus
Ortolf
Radus
Raga
Raganbold
Raganboldus
Raganhardus
Raganheri
Raginmundo
Ragino
Raginolf
Reinbold
Richo
Ricohardus
Rudegaud
Rudolf
Rutha
Rutharimann
Sibert
Sibold
Sibrandus
Sifrid
Sigenhard
Stallobaud
Starchembalt
Tallobaudes
Thanchard
Theodemannus
Theodila
Theodorieks
Thiudoricus
Ulrich
Walahfridus
Wald
Waldhari
Waldhariwald
Waldhart
Waldheri
Walhbertus
Warenvald
Warin
Warinhard
Weidhar
Weidhartmann
Wercho
Wibilo
Widogastne
Willehelmus
Winther
Withar

I want to do town names next.  Still working on getting a good place to store my scripts for proper sharing, though...

Sunday, May 26, 2013

Scripts and Things

Mostly scripts.

Upgraded the henchinator script to allow generation of NPCs of arbitrary levels and to generate magic gear at the standard 5% per character level rate for NPCs (though 'useful' is a funny categorization for some of these results...  10th-level Explorer with the Ring of Weakness and clerics with a handful of magic arrows, I'm looking at you).  Now useful for generating NPC parties, bandit heroes, and a host of other folks of greater than 4th level.  Added names while I was at it, pulling down part of the Onomastikon and adding both gender and naming to the scripts (first did random names, then started getting combinations like "Wulfram the Valkyrie" and decided I needed to separate names by gender and add gender probabilities by class).  Next up: general proficiency generation.  Don't think I really want to do class profs, but general profs I can generate mostly based on ability scores.  Class profs depend more on weapon selection, spell availability, and other factors.  I also added waypointing to the merchant demandinator a while back, so that's now in a more-or-less finished state except some output formatting improvements (sorting outputs into a sensible order, possibly a csv output option).  Would be nice to have a save/load function for when market classes change, but that's not all that interesting of a problem.  The recursive hex-stocker of awesome is mostly functional, but I'm bogged down on data entry / transcription; I got up through Leech, Giant before my brain and fingers shut down.  Considering regex / pdfgrep, but that will involve doing a lot of manual post-processing too.  My output formatting on this one is also really, really terrible, but there isn't a particularly good way to print the list of warbands in an orcish village down to the gang level along with each of their treasures.  Still need to add support for taking a csv or text map file and combining auto-stocking with trade value generation to get a whole region fully-stocked and ready to go in a single command, too.  Also unfortunately, my webspace is disappearing since it was through my college, so I need to find somewhere else to host this stuff.  Still considering a github.

Have also been working on setting stuff for the summer game.  Coming along nicely.  More on that soon (perhaps tomorrow).

Friday, April 5, 2013

ACKS Scripts - Magic Item Availability

One thing which can sometimes be annoying in ACKS is when your players ask "Well, what magic items are available in town this month?"  When it comes to most goods like war galleys and military oil, indexing into the availability table and rolling the percent chance isn't so bad, because there just aren't that many things.  But depending on how you count scrolls, there are close on 300 magic items in ACKS Core, which can make playing the "magic item availability guessing game" a right royal pain in the arse if your players have a long wish-list of low-probability items.

So I automated it.  Here's a python script that checks availability for each item in this text file based on price and market class.  I'm reasonably certain it would work on Windows if you passed the input file in with Windows-style path separators, but don't actually have any (working) Windows machines to test it on :\ .  Works on linux, though.

Writing and running this script has also made me realize that scrolls are much more available than we thought, though the selection of available spells is pretty random.  This has a number of interesting implications.  First, wizards can use bought scrolls to expand their spell selection with a bit more control than learning from a master, and with a higher rate of success than doing research (as long as the spell is one available on bought scrolls, ie in Core).  Likewise, high-power scrolls of Death Spell, Disintegrate, Flesh to Stone, and similar are a nice (if pricey) way for a mid-level party to add some one-shot punch.  On the other side, high-level cleric scrolls of Restore Life and Limb, Remove Curse, Remove Disease, and Neutralize Poison can provide super-healing in the wilderness for a high price (something I know the Grim Fist has done; I kind of wondered where they had gotten two RL&L scrolls...).  Finally, with scrolls more readily available, the thief and bard ability to read scrolls is suddenly much more useful than when they were only found as random treasure or crafted.

In any case, this is the most recent of a decent pile of scripts I've written for ACKS.  I'll release more as I clean them up.  Others of interest include a treasure generator (there's already a good online version but I needed to write a recursive parser anyway, and didn't want trade goods in hoards by default), automatic hex-stocker (needs expanding with the recursive parser from the treasure generator, more monster data files), a henchman generator (needs naming, proficiencies, and hench magic items, but does choose class intelligently based on stats and generate wizard spells known), and one that takes in a text file containing information on a region's towns and their relative locations and generates all the mercantile demand modifiers (needs waypointing to cut down on the number of links you have to specify - all traffic from the Mediterranean to ports on the Atlantic has to pass through Gibraltar or Suez, so it would be better to specify distance from each Med port to Gibraltar and Suez and each Atlantic port to Gibraltar and Suez, but as it stands you'd need to specify the distance from each Mediterranean port to each Atlantic port, which is a real pain).  And I guess I should get a github or something for storing these, rather than throwing them in a web-public directory...