Brace yourself because this topic is going into deep nerd territory. You've been warned!
Every now and again though I think of a particular gang name, "the Mushy Gun Militia", and wonder. Also it turns out that if you googled the gang name prior to me posting this topic you'd get one result:
(Google bought the Usenet archives in 2001 so that's a newsgroup posting from 1996 with just the name of the gang)
I think of the gang name because in the late '90s I stumbled across Andy Cowell's Necromunda page and was perplexed and excited by what I found. I wasn't really sure what I was looking at but it was some sort of program written for Necromunda. I think I thought it was something for randomly generating gangs or something like that. It wasn't, but that's the rough idea my younger self had.
Some years later, in 2005, I once again thought about it and decided to ask over on the Ubuntu forums. I was starting to get into using Linux as my main operating system and Andy's page seemed a lot like the more advanced stuff I'd seen related to Linux. (Side note: I no longer use Linux as my main desktop OS - instead I use macOS which under the hood essentially is Linux but with better support for commercial software. It's not technically Linux but they're very, very similar based on my experience using both)
The responses I got were helpful but I didn't truly understand what was going on, to be honest. I stopped thinking about it. Do you ever have those moments of "maybe I'll understand when I'm older?" and then reflect on them years later? I had one of those whilst trying to sleep last night. I'm older now...
I said earlier I don't use Linux as my desktop OS - I do still use it daily though. It's running on the VPS I use to run my websites. I can pull up a Linux command line as long as I have an internet connection - even from my phone. I don't know if it was Linux or some other *nix related system Andy was using back in the day but on my VPS I installed a couple of dependencies (Bison and Flex. These two are used to build something that can parse the input files into something workable - more on that in a bit). After that it threw a few warnings but otherwise compiled happily:
I don't speak enough C to know what's going on but it spat out a binary ("nec") which I then renamed to "sumper" as that's what Andy called it originally.
Okay, so what does the program do?
Well the thing I understand now that I didn't in 2005 is standard streams (stdin and stdout). This is standardised Unix thing (and so applies to Linux, *BSD, and so on too). Essentially it's text. A program spits out text and takes in text. You can take the output of one program and feed it into another.
So on Andy's page he gives this example:
What he's doing there is using the program cat to read the contents of militia.txt. Normally it'd just display it:
But instead he's using | ("pipe") to send that text into the sumper. It then reads it and outputs a nicely formatted bit of text.
Something's puzzling me about that though - as far as I can tell the code he released doesn't include a -t option! It has -s and -h options that output stats and HTML respectively but I don't see anything for -t!
Similarly in his other example there's something missing:
If I run the same militia.txt through the program I get this output:
Spot the difference.
Yeah, there's no wounding hits (and the headings are different). More to the point the file that contains the gang data doesn't contain wounding hits. The header file for it doesn't even have a structure for it!
It's not that it'd be hard to add it - just that it's not there!
So that makes me feel a bit better about not getting it to work "properly" back in '05. It looks like the examples on the page are based on a more advanced version of The Sumper that he didn't publish. Bit of a shame but no big deal.
The thing that strikes me about all of this is the sheer overkill of it when seen through a modern lens. Not overkill for the time, just compared to how I'd handle things. Let's talk about that for a bit.
Conceptually what Andy did was to design a data structure - a standardised way to record information about Necromunda gangs. He wrote a program that would read in that data. Once the data is in the program operations can be performed on it ("The grammar loads all the gang info into data structures, thus you can write a C rear-end to do whatever you want with it."). You'd have to write the functions yourself but you wouldn't be starting from scratch.
The reason this is a bit of a big deal is because the year was 1996. I'll come back to that in a moment.
If I wanted to write something similar these days I'd probably use something like Python or JavaScript. I'm comfortable in both languages and their syntax is a hell of a lot easier than C. I started learning C a while back but gave up as it seemed like a lot of faff for the sorts of things I want to do - way too low-level for messing about with text data. Python is just fine!
I'd want to store the gang data in a way that'd be easy to read. I'd probably use JSON ("JavaScript Object Notation" - it has JS in the name but it's used in loads of languages as it's a nice format).
That'd look something like this:
It's fairly human readable and you can see what each thing in it is. If I was designing from scratch I might fiddle around with how skills are handled and things like that but that's nitty-gritty stuff.
With the data laid out like this you could do things like this:
That'd give you the first gang member's name. It's easily possible to drill down to whatever bit of information you need with fairly clear code.
So why didn't Andy do something like that?
Well it was April 1996. Easily accessible data structures like JSON simply didn't exist yet!
JavaScript as a language wasn't standardised until 1997 so definitely no JSON (not until the early 2000s). What other options were there?
Well, maybe XML? Nope, not until 1998.
Uh... YAML? Nope. Not until 2001.
There's a few other formats but basically there was nothing around to handle this job! He had to figure it out and write his own! How cool is that!
Similarly Python in principle existed but it wasn't until version 2+ that I heard of anyone using it and that wasn't until 1998. Java existed but had only been released three months earlier.
Ruby? Well that was released onto Japanese news groups in December '95 but 1.0 wasn't until December '96.
C#? 2000.
No wonder Andy wrote it in C - there weren't exactly loads of mature alternatives! (C first saw release in 1972 so it had loads of support by 1996).
In general this has just been a wonderful bit of digital archaeology for me. Figuring out what Andy built, why, how, and how far ahead of his time he was. These days we have amazing tools like YakTribe's Necromunda tool but someone was working on its distant ancestor way back when the game was new!
Thanks for coming with me on this expedition. I hope I can now finally put my curiosity to rest. Then again, he also wrote weapon summaries in PostScript and I know naff-all about that at the time of writing...
Every now and again though I think of a particular gang name, "the Mushy Gun Militia", and wonder. Also it turns out that if you googled the gang name prior to me posting this topic you'd get one result:
(Google bought the Usenet archives in 2001 so that's a newsgroup posting from 1996 with just the name of the gang)
I think of the gang name because in the late '90s I stumbled across Andy Cowell's Necromunda page and was perplexed and excited by what I found. I wasn't really sure what I was looking at but it was some sort of program written for Necromunda. I think I thought it was something for randomly generating gangs or something like that. It wasn't, but that's the rough idea my younger self had.
Some years later, in 2005, I once again thought about it and decided to ask over on the Ubuntu forums. I was starting to get into using Linux as my main operating system and Andy's page seemed a lot like the more advanced stuff I'd seen related to Linux. (Side note: I no longer use Linux as my main desktop OS - instead I use macOS which under the hood essentially is Linux but with better support for commercial software. It's not technically Linux but they're very, very similar based on my experience using both)
The responses I got were helpful but I didn't truly understand what was going on, to be honest. I stopped thinking about it. Do you ever have those moments of "maybe I'll understand when I'm older?" and then reflect on them years later? I had one of those whilst trying to sleep last night. I'm older now...
I said earlier I don't use Linux as my desktop OS - I do still use it daily though. It's running on the VPS I use to run my websites. I can pull up a Linux command line as long as I have an internet connection - even from my phone. I don't know if it was Linux or some other *nix related system Andy was using back in the day but on my VPS I installed a couple of dependencies (Bison and Flex. These two are used to build something that can parse the input files into something workable - more on that in a bit). After that it threw a few warnings but otherwise compiled happily:
Bash:
flamekebab@mail:~/sumper# make
bison -d nec.y
flex nec.lex
gcc -g -o nec lex.yy.c nec.tab.c main.c -lfl
main.c: In function ‘do_stats’:
main.c:187:44: warning: passing argument 4 of ‘qsort’ from incompatible pointer type [enabled by default]
qsort(gangs, gang_count, sizeof(struct _gang *), reverse_gang_compare);
^
In file included from main.c:2:0:
/usr/include/stdlib.h:765:13: note: expected ‘__compar_fn_t’ but argument is of type ‘int (*)(struct _gang **, struct _gang **)’
extern void qsort (void *__base, size_t __nmemb, size_t __size,
^
main.c:208:48: warning: passing argument 4 of ‘qsort’ from incompatible pointer type [enabled by default]
qsort(members, member_count, sizeof(struct _member *), reverse_member_compare);
^
In file included from main.c:2:0:
/usr/include/stdlib.h:765:13: note: expected ‘__compar_fn_t’ but argument is of type ‘int (*)(struct _member **, struct _member **)’
extern void qsort (void *__base, size_t __nmemb, size_t __size,
^
flamekebab@mail:~/sumper# ls
lex.yy.c main.c Makefile militia.txt [B]nec[/B] nec.lex necro.h nec.tab.c nec.tab.h nec.y
Okay, so what does the program do?
Well the thing I understand now that I didn't in 2005 is standard streams (stdin and stdout). This is standardised Unix thing (and so applies to Linux, *BSD, and so on too). Essentially it's text. A program spits out text and takes in text. You can take the output of one program and feed it into another.
So on Andy's page he gives this example:
Bash:
mattel:[/blue/homes/cowell/src/nec] cat militia.txt | ./sumper -t
Gang: The Mushy Gun Milita [ 1327 ]
Member M BS WS S T W I A Ld
el Feygun...... 4 4 4 4 3 1 3 1 8 170 85
Leader EQ: Boltgun, Massive Axe
Sumo........... 4 3 3 3 3 1 3 1 7 195 72
Heavy EQ: Heavy Stubber, Laspistol
Full Otto...... 4 4 2 3 3 1 3 1 7 80 36
Ganger EQ: Autogun, Stub gun
IN: Lost 1 finger on left hand
Joey the Slug.. 4 3 3 3 3 1 3 1 7 100 30
Ganger EQ: Shotgun (sld/sctr/mstpr/bolt), Stub gun
Plasmo......... 4 3 3 3 3 1 3 1 7 110 29
Ganger EQ: Chainsword, Plasma pistol, Stub gun
Toothpick...... 4 3 3 3 3 1 3 1 7 110 26
Ganger EQ: Bolt pistol, Stub gun, Frag grenades
Sawtooth....... 4 3 3 4 3 1 3 1 7 105 32
Ganger EQ: Chainsword, Laspistol w/Hot shot
Wispy.......... 4 2 3 3 3 1 4 1 6 55 17
Juve EQ: Hand flamer, Stub gun
SK: Crack shot
Tyco........... 4 4 3 3 3 2 4 1 8 75 0
Scummer EQ: Knife, 2 Bolt Pistols
SK: Gunfighter, Quick Draw
Bash:
flamekebab@mail:~/sumper# cat militia.txt
Name "The Mushy Gun Milita"
Rating 1268
Territory Vents, Tunnels, Settlement, "Drinking hole", Slag
Stash 30
Hoard = ( "Heavy Stubber", "Your Mama" )
#Member "el Feygun" Leader 4 4 4 3 3 1 3 1 8 IN=("Old Battle Wounds", "Head Wound") EQ=("Boltgun", "Massive Axe") SK=(Infiltration) 170 66
Member "el Feygun" Leader 4 4 4 3 3 1 3 1 8 IN=() EQ=("Boltgun", "Massive Axe") SK=() 170 66
Member Sumo Heavy 4 3 3 3 3 1 3 1 7 IN=() EQ=("Heavy Stubber", Laspistol) SK=() 195 64
Member "Full Otto" Ganger 4 3 3 3 3 1 3 1 7 IN=() EQ=(Autogun, "Stub gun") SK=() 80 21
Member "Joey the Slug" Ganger 4 3 3 3 3 1 3 1 7 IN=() EQ=("Shotgun (sld/sctr/mstpr/bolt)", "Stub gun") SK=() 100 23
Member Plasmo Ganger 4 3 3 3 3 1 3 1 7 IN=() EQ=(Chainsword, "Plasma pistol", "Stub gun") SK=() 110 21
Member Toothpick Ganger 4 3 3 3 3 1 3 1 7 IN=() EQ=("Bolt pistol", "Stub gun", "Frag grenades") SK=() 110 21
Member Sawtooth Ganger 4 3 3 3 3 1 3 1 7 IN=() EQ=(Chainsword, Laspistol) SK=() 90 22
Member "Louie the Punk" Juve 4 2 2 3 3 1 3 1 6 IN=() EQ=("Stub gun", Maul) SK=() 45 0
Member Wispy Juve 4 2 2 3 3 1 3 1 6 IN=() EQ=("Hand flamer", "Stub gun") SK=() 55 0
Member Tyco Scummer 4 3 4 3 3 2 4 1 8 IN=() EQ=(Knife, "2 Bolt Pistols") SK=(Gunfighter, "Quick Draw") 15 60
flamekebab@mail:~/sumper#
Something's puzzling me about that though - as far as I can tell the code he released doesn't include a -t option! It has -s and -h options that output stats and HTML respectively but I don't see anything for -t!
Similarly in his other example there's something missing:
Bash:
mattel:[/blue/homes/cowell/src/nec] cat militia.txt | ./sumper -s
Rank of gangs by rating:
The Mushy Gun Milita: 1327
Sort gang members by experience.
el Feygun (The Mushy Gun Milita): 85
Sumo (The Mushy Gun Milita): 72
Full Otto (The Mushy Gun Milita): 36
Sawtooth (The Mushy Gun Milita): 32
Joey the Slug (The Mushy Gun Milita): 30
Plasmo (The Mushy Gun Milita): 29
Toothpick (The Mushy Gun Milita): 26
Wispy (The Mushy Gun Milita): 17
Tyco (The Mushy Gun Milita): 0
Sort gang members by wounding hits
Tyco (The Mushy Gun Milita): 2
Wispy (The Mushy Gun Milita): 2
Full Otto (The Mushy Gun Milita): 2
el Feygun (The Mushy Gun Milita): 1
Joey the Slug (The Mushy Gun Milita): 0
Toothpick (The Mushy Gun Milita): 0
Sawtooth (The Mushy Gun Milita): 0
Sumo (The Mushy Gun Milita): 0
Plasmo (The Mushy Gun Milita): 0
If I run the same militia.txt through the program I get this output:
Bash:
flamekebab@mail:~/sumper# cat militia.txt | ./sumper -s
We have 1 gangs.
The Mushy Gun Milita:1268
We have 10 members.
el Feygun (The Mushy Gun Milita): 66
Sumo (The Mushy Gun Milita): 64
Tyco (The Mushy Gun Milita): 60
Joey the Slug (The Mushy Gun Milita): 23
Sawtooth (The Mushy Gun Milita): 22
Full Otto (The Mushy Gun Milita): 21
Plasmo (The Mushy Gun Milita): 21
Toothpick (The Mushy Gun Milita): 21
Louie the Punk (The Mushy Gun Milita): 0
Wispy (The Mushy Gun Milita): 0
Spot the difference.
Yeah, there's no wounding hits (and the headings are different). More to the point the file that contains the gang data doesn't contain wounding hits. The header file for it doesn't even have a structure for it!
C:
struct _member {
char *name, *pos;
int m, ws, bs, s, t, w, i, a, ld;
char *injuries, *equipment, *skills;
int cost, exp;
char *gang_name;
struct _member *next;
};
So that makes me feel a bit better about not getting it to work "properly" back in '05. It looks like the examples on the page are based on a more advanced version of The Sumper that he didn't publish. Bit of a shame but no big deal.
The thing that strikes me about all of this is the sheer overkill of it when seen through a modern lens. Not overkill for the time, just compared to how I'd handle things. Let's talk about that for a bit.
Conceptually what Andy did was to design a data structure - a standardised way to record information about Necromunda gangs. He wrote a program that would read in that data. Once the data is in the program operations can be performed on it ("The grammar loads all the gang info into data structures, thus you can write a C rear-end to do whatever you want with it."). You'd have to write the functions yourself but you wouldn't be starting from scratch.
The reason this is a bit of a big deal is because the year was 1996. I'll come back to that in a moment.
If I wanted to write something similar these days I'd probably use something like Python or JavaScript. I'm comfortable in both languages and their syntax is a hell of a lot easier than C. I started learning C a while back but gave up as it seemed like a lot of faff for the sorts of things I want to do - way too low-level for messing about with text data. Python is just fine!
I'd want to store the gang data in a way that'd be easy to read. I'd probably use JSON ("JavaScript Object Notation" - it has JS in the name but it's used in loads of languages as it's a nice format).
That'd look something like this:
JSON:
{
"Name": "The Mushy Gun Milita",
"Rating": 1268,
"Territory": ["Vents", "Tunnels", "Settlement", "Drinking Hole", "Slag"],
"Stash": 30,
"Hoard": ["Heavy Stubber", "Your Mama"],
"Members": [{
"memberName": "El Feygun",
"position": "Leader",
"characteristics": {
"M": 4,
"WS": 4,
"BS": 4,
"S": 3,
"T": 3,
"W": 1,
"I": 3,
"A": 1,
"LD": 8
},
"injuries": [],
"equipment": ["Boltgun", "Massive Axe"],
"skills": [],
"cost": 170,
"experience": 66
},
{
"memberName": "Sumo",
"position": "Heavy",
"characteristics": {
"M": 4,
"WS": 3,
"BS": 3,
"S": 3,
"T": 3,
"W": 1,
"I": 3,
"A": 1,
"LD": 7
},
"injuries": [],
"equipment": ["Heavy Stubber", "Laspistol"],
"skills": [],
"cost": 195,
"experience": 64
},
{
"memberName": "Full Otto",
"position": "Ganger",
"characteristics": {
"M": 4,
"WS": 3,
"BS": 3,
"S": 3,
"T": 3,
"W": 1,
"I": 3,
"A": 1,
"LD": 7
},
"injuries": [],
"equipment": ["Autogun", "Stub gun"],
"skills": [],
"cost": 80,
"experience": 21
},
{
"memberName": "Joey the Slug",
"position": "Ganger",
"characteristics": {
"M": 4,
"WS": 3,
"BS": 3,
"S": 3,
"T": 3,
"W": 1,
"I": 3,
"A": 1,
"LD": 7
},
"injuries": [],
"equipment": ["Shotgun (sld/sctr/mstpr/bolt)", "Stub gun"],
"skills": [],
"cost": 100,
"experience": 23
},
{
"memberName": "Plasmo",
"position": "Ganger",
"characteristics": {
"M": 4,
"WS": 3,
"BS": 3,
"S": 3,
"T": 3,
"W": 1,
"I": 3,
"A": 1,
"LD": 7
},
"injuries": [],
"equipment": ["Chainsword", "Plasma pistol", "Stub gun"],
"skills": [],
"cost": 110,
"experience": 21
},
{
"memberName": "Toothpick",
"position": "Ganger",
"characteristics": {
"M": 4,
"WS": 3,
"BS": 3,
"S": 3,
"T": 3,
"W": 1,
"I": 3,
"A": 1,
"LD": 7
},
"injuries": [],
"equipment": ["Bolt pistol", "Stub gun", "Frag grenades"],
"skills": [],
"cost": 110,
"experience": 21
},
{
"memberName": "Sawtooth",
"position": "Ganger",
"characteristics": {
"M": 4,
"WS": 3,
"BS": 3,
"S": 3,
"T": 3,
"W": 1,
"I": 3,
"A": 1,
"LD": 7
},
"injuries": [],
"equipment": ["Chainsword", "Laspistol"],
"skills": [],
"cost": 90,
"experience": 22
},
{
"memberName": "Louie the Punk",
"position": "Juve",
"characteristics": {
"M": 4,
"WS": 2,
"BS": 2,
"S": 3,
"T": 3,
"W": 1,
"I": 3,
"A": 1,
"LD": 6
},
"injuries": [],
"equipment": ["Stub gun", "Maul"],
"skills": [],
"cost": 45,
"experience": 0
},
{
"memberName": "Wispy",
"position": "Juve",
"characteristics": {
"M": 4,
"WS": 2,
"BS": 2,
"S": 3,
"T": 3,
"W": 1,
"I": 3,
"A": 1,
"LD": 6
},
"injuries": [],
"equipment": ["Hand flamer", "Stub gun"],
"skills": [],
"cost": 55,
"experience": 0
},
{
"memberName": "Tyco",
"position": "Scummer",
"characteristics": {
"M": 4,
"WS": 3,
"BS": 4,
"S": 3,
"T": 3,
"W": 2,
"I": 4,
"A": 1,
"LD": 8
},
"injuries": [],
"equipment": ["Knife", "2 Bolt Pistols"],
"skills": ["Gunfighter - Quick Draw"],
"cost": 15,
"experience": 60
}
]
}
With the data laid out like this you could do things like this:
gang.members[0].memberName
That'd give you the first gang member's name. It's easily possible to drill down to whatever bit of information you need with fairly clear code.
So why didn't Andy do something like that?
Well it was April 1996. Easily accessible data structures like JSON simply didn't exist yet!
JavaScript as a language wasn't standardised until 1997 so definitely no JSON (not until the early 2000s). What other options were there?
Well, maybe XML? Nope, not until 1998.
Uh... YAML? Nope. Not until 2001.
There's a few other formats but basically there was nothing around to handle this job! He had to figure it out and write his own! How cool is that!
Similarly Python in principle existed but it wasn't until version 2+ that I heard of anyone using it and that wasn't until 1998. Java existed but had only been released three months earlier.
Ruby? Well that was released onto Japanese news groups in December '95 but 1.0 wasn't until December '96.
C#? 2000.
No wonder Andy wrote it in C - there weren't exactly loads of mature alternatives! (C first saw release in 1972 so it had loads of support by 1996).
In general this has just been a wonderful bit of digital archaeology for me. Figuring out what Andy built, why, how, and how far ahead of his time he was. These days we have amazing tools like YakTribe's Necromunda tool but someone was working on its distant ancestor way back when the game was new!
Thanks for coming with me on this expedition. I hope I can now finally put my curiosity to rest. Then again, he also wrote weapon summaries in PostScript and I know naff-all about that at the time of writing...