I have recently made a small program to generate D&D (original edition) monster stat blocks in text form. I use this program myself to generate stats block so that I can then copy and paste them in the adventures I am writing.
The main reason for using a program is to have the program roll the random values.
Here is an example of usage:
monsterGenerator:monster("Kobold", 3).
Here is an example of output:
Kobold(3), AC 7, HD 1/2, HP (1, 4, 2), Att 1 weapon, Dmg (Club 1d3-1, Dagger 1d4-1, Dagger 1d4-1),
Save Normal Man, Morale 6, Treasure (2 cp, 12 cp, 21 cp), XP 5
Here is the code in question:
monsterGenerator.erl
-module(monsterGenerator).
-export([monster/2]).
monster(Name, Number) -> case Name of
"Bugbear" -> io:format("~s(~p), AC 5, HD 3+1, HP ~p, Att 1 weapon, Dmg ~s +1 ~n",
[Name, Number, [monster_hp(3, 1) || _ <- lists:seq(1, Number)],
[monsterWeapons:generate_weapon(large) || _ <- lists:seq(1, Number)]]),
io:format("Save Normal Man, Morale 6, Treasure ~s ~s, XP 50 ~n",
[monsterTreasures:generate_treasure(p), monsterTreasures:generate_treasure(q)]);
"Kobold" -> io:format("~s(~p), AC 7, HD 1/2, HP ~p, Att 1 weapon, Dmg ~s -1 ~n",
[Name, Number, [monster_hp(0.5) || _ <- lists:seq(1, Number)],
[monsterWeapons:generate_weapon(small) || _ <- lists:seq(1, Number)]]),
io:format("Save Normal Man, Morale 6, Treasure ~s, XP 5 ~n",
[monsterTreasures:generate_treasure(p)]);
"Skeleton" -> io:format("~s(~p), AC 7, HD 1, HP ~p, Att 1 weapon, Dmg Claws 1d2 ~n",
[Name, Number, [monster_hp(1) || _ <- lists:seq(1, Number)]]),
io:format("Save F1, Morale 12, Treasure ~s, XP 10 ~n",
[monsterTreasures:generate_treasure(nil)]);
"Goblin" -> io:format("~s(~p), AC 6, HD 1-1, HP ~p, Att 1 weapon, Dmg ~s ~n",
[Name, Number, [monster_hp(1, -1) || _ <- lists:seq(1, Number)],
[monsterWeapons:generate_weapon(small) || _ <- lists:seq(1, Number)]]),
io:format("Save Normal Man, Morale 6, Treasure ~s, XP 5 ~n",
[[monsterTreasures:generate_treasure(r) || _ <- lists:seq(1, Number)]]);
"Centaur" -> io:format("~s(~p), AC 5, HD 4, HP ~p, Att 2 hooves / 1 weapon, Dmg 1d6/1d6/by weapon ~s ~n",
[Name, Number, [monster_hp(4) || _ <- lists:seq(1, Number)],
[monsterWeapons:generate_weapon(medium) || _ <- lists:seq(1, Number)]]),
io:format("Save Normal F4, Morale 8, Treasure ~s, XP 75 ~n",
[monsterTreasures:generate_treasure(nil)]);
"Neanderthal" -> io:format("~s(~p), AC 8, HD 2, HP ~p, Att 1 weapon ~s ~n",
[Name, Number, [monster_hp(2) || _ <- lists:seq(1, Number)],
[monsterWeapons:generate_weapon(primitive) || _ <- lists:seq(1, Number)]]),
io:format("Save Normal F2, Morale 8, Treasure ~s, XP 20 ~n",
[monsterTreasures:generate_treasure(nil)]);
"Harpy" -> io:format("~s(~p), AC 7, HD 3, HP ~p, Att 3 2 claws / 1 weapon 1d4/1d4/ ~s ~n",
[Name, Number, [monster_hp(3) || _ <- lists:seq(1, Number)],
[monsterWeapons:generate_weapon(medium) || _ <- lists:seq(1, Number)]]),
io:format("Save Normal F2, Morale 8, Treasure ~s, XP 20 ~n",
[monsterTreasures:generate_treasure(nil)]);
_ -> io:format("Unknown.~n")
end.
monster_hp(0.5) -> random:uniform(round(4));
monster_hp(HitDice) -> lists:foldl(fun(X, Sum) -> X + Sum end, 0, [random:uniform(round(8)) || _ <- lists:seq(1, HitDice)]).
monster_hp(HitDice, Modifier) -> monster_hp(HitDice) + Modifier.
monsterTreasures.erl
-module(monsterTreasures).
-export([generate_treasure/1]).
generate_treasure(Type) -> case Type of
p -> [integer_to_list(roll_dice(3, 8)), " cp"];
q -> [integer_to_list(roll_dice(3, 6)), " sp"];
r -> [integer_to_list(roll_dice(2, 6)), " ep"];
s -> [integer_to_list(roll_dice(2, 4)), " gp", conditional_treasure(5, 1, "gems")];
t -> [integer_to_list(roll_dice(1, 6)), " pp", conditional_treasure(5, 1, "gems")];
u -> [conditional_treasure(10, 100, "cp "), conditional_treasure(10, 100, "sp "),
conditional_treasure(5, 100, "gp "), conditional_treasure(5, 2, "gems "),
conditional_treasure(5, 4, "jewelry "), conditional_treasure(2, 1, "special treasure "),
conditional_treasure(2, 1, "magical items ")];
v -> [conditional_treasure(10, 100, "sp "), conditional_treasure(5, 100, "ep "),
conditional_treasure(10, 100, "gp "), conditional_treasure(5, 100, "pp "),
conditional_treasure(10, 2, "gems "), conditional_treasure(10, 4, "jewelry "),
conditional_treasure(5, 1, "special treasure "), conditional_treasure(5, 1, "magical items ")];
_ -> ["No treasure"]
end.
conditional_treasure(Chance, Number, TreasureName) -> Result = random:uniform(100),
if Result =< Chance ->
[integer_to_list(random:uniform(Number)), " ", TreasureName];
true -> ""
end.
roll_dice(Number, DiceType) -> lists:foldl(fun(_, Sum) -> random:uniform(DiceType) + Sum end, 0, lists:seq(1, Number
monsterWeapons.erl
-module(monsterWeapons).
-export([generate_weapon/1]).
generate_weapon(Type) when Type == small -> Weapons = ["Hand Axe 1d6 ", "Blackjack 1d2 ", "Torch 1d4 ", "Dagger 1d4 ",
"Short Sword 1d6 ", "Small club 1d2 ", "Sling 1d4 "],
pick_random_from_list(Weapons);
generate_weapon(Type) when Type == medium -> Weapons = ["Battle Axe 1d8 ", "Club 1d4 ", "War Hammer 1d6 ", "Mace 1d6 ",
"Staff 1d6 ", "Trident 1d6 ", "Normal Sword 1d8 ", "Whip 1d2 ",
"Bow, Short 1d6 ", "Crossbow, Lt 1d6 ", "Throwing Hammer 1d4 ",
"Shield, Sword 1d4 +2 "],
pick_random_from_list(Weapons);
generate_weapon(Type) when Type == primitive -> Weapons = ["Blackjack 1d2 ", "Sling 1d4 ", "Small club 1d2 ",
"Staff 1d6 ", "Club 1d4 ", "Stone Mace 1d6 ",
"Stone Spear 1d6 "],
pick_random_from_list(Weapons);
generate_weapon(Type) when Type == large -> Weapons = ["Battle Axe 1d8 ", "Halberd 1d10 ", "Polearm 1d10 ",
"Two-Handed Sword 1d10 ", "Normal Sword 1d8 ", "Club 1d4 "],
pick_random_from_list(Weapons).
pick_random_from_list(List) -> Index = random:uniform(length(List)),
lists:nth(Index, List).
I welcome review on any aspect of the code. Note that I am a novice with Erlang.