Switched permons database to parsed autogen
authorMartin Read <martin@blackswordsonics.com>
Mon, 10 Feb 2014 20:53:33 +0000 (20:53 +0000)
committerMartin Read <martin@blackswordsonics.com>
Mon, 10 Feb 2014 20:53:33 +0000 (20:53 +0000)
13 files changed:
.gitignore
MANIFEST
Makefile
default.permobjs
default.permons [new file with mode: 0644]
display-nc.cc
log.cc
monsters.hh
objects.hh
permons.cc [deleted file]
pmon2.cc
pmon_comp [new file with mode: 0755]
victrix-abyssi.hh

index ecc4336..f238f05 100644 (file)
@@ -9,6 +9,8 @@ victrix-abyssi
 *.bak
 spong.txt
 permobj.cc
+permons.cc
+pmon_id.hh
 pobj_id.hh
 victrix-abyssi.log
 victrix-abyssi.sav
index 8fb85c1..5ea9d1e 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -8,6 +8,7 @@ combat.cc
 combat.hh
 coord.hh
 default.permobjs
+default.permons
 display.hh
 display-nc.cc
 fov.cc
@@ -25,11 +26,9 @@ notify.hh
 notify-local-tty.cc
 objects.cc
 objects.hh
-permobj.cc
-permons.cc
 pmon2.cc
+pmon_comp
 pobj_comp
-pobj_id.hh
 rng.cc
 rng.hh
 sorcery.cc
index bf3d61f..310e6f0 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -5,10 +5,10 @@
 include dirs.mk
 include features.mk
 
-GENERATED_OBJS:=permobj.o
-GENERATED_SOURCE:=permobj.cc pobj_id.hh
+GENERATED_OBJS:=permobj.o permons.o 
+GENERATED_SOURCE:=permobj.cc pobj_id.hh permons.cc pmon_id.hh
 GENERATED_MAKES:=dirs.mk features.mk
-HANDWRITTEN_OBJS:=combat.o display-nc.o fov.o log.o main.o map.o misc.o monsters.o mon2.o notify-local-tty.o objects.o permons.o pmon2.o rng.o sorcery.o u.o util.o
+HANDWRITTEN_OBJS:=combat.o display-nc.o fov.o log.o main.o map.o misc.o monsters.o mon2.o notify-local-tty.o objects.o pmon2.o rng.o sorcery.o u.o util.o
 OBJS:=$(GENERATED_OBJS) $(HANDWRITTEN_OBJS)
 GAME:=victrix-abyssi
 MAJVERS:=1
@@ -88,37 +88,39 @@ $(GAME): $(OBJS)
 permobj.cc pobj_id.hh: default.permobjs $(srcdir)/pobj_comp
        $(srcdir)/pobj_comp $<
 
+permons.cc pmon_id.hh: default.permons $(srcdir)/pmon_comp
+       $(srcdir)/pmon_comp $<
 ## Dependencies for the build
-combat.o: combat.cc combat.hh victrix-abyssi.hh monsters.hh objects.hh notify.hh pobj_id.hh
+combat.o: combat.cc combat.hh victrix-abyssi.hh monsters.hh objects.hh notify.hh pobj_id.hh pmon_id.hh
 
-display-nc.o: display-nc.cc victrix-abyssi.hh display.hh pobj_id.hh
+display-nc.o: display-nc.cc victrix-abyssi.hh display.hh pobj_id.hh pmon_id.hh
 
-main.o: main.cc combat.hh victrix-abyssi.hh monsters.hh notify.hh pobj_id.hh
+main.o: main.cc combat.hh victrix-abyssi.hh monsters.hh notify.hh pobj_id.hh pmon_id.hh
 
-map.o: map.cc victrix-abyssi.hh notify.hh objects.hh
+map.o: map.cc victrix-abyssi.hh notify.hh objects.hh pobj_id.hh pmon_id.hh
 
-monsters.o: monsters.cc victrix-abyssi.hh monsters.hh notify.hh objects.hh
+monsters.o: monsters.cc victrix-abyssi.hh monsters.hh notify.hh objects.hh pobj_id.hh pmon_id.hh
 
-mon2.o: mon2.cc victrix-abyssi.hh sorcery.hh monsters.hh notify.hh objects.hh
+mon2.o: mon2.cc victrix-abyssi.hh sorcery.hh monsters.hh notify.hh objects.hh pobj_id.hh pmon_id.hh
 
-notify-local-tty.o: notify-local-tty.cc victrix-abyssi.hh combat.hh monsters.hh notify.hh objects.hh sorcery.hh pobj_id.hh
+notify-local-tty.o: notify-local-tty.cc victrix-abyssi.hh combat.hh monsters.hh notify.hh objects.hh sorcery.hh pobj_id.hh pmon_id.hh
 
 # NOTICE: permobj.cc does not depend on pobj_id.hh because they are both
 # generated from the same input file and should not be hand-edited. If you
 # file a bug report over this, I will close it NOTABUG; if you submit a
 # patch to add such a dependency, I will reject it out of hand.
 
-permobj.o: permobj.cc victrix-abyssi.hh objects.hh
+permobj.o: permobj.cc victrix-abyssi.hh objects.hh pobj_id.hh pmon_id.hh
 
-permons.o: permons.cc victrix-abyssi.hh monsters.hh
+permons.o: permons.cc victrix-abyssi.hh monsters.hh pobj_id.hh pmon_id.hh
 
-pmon2.o: pmon2.cc victrix-abyssi.hh notify.hh monsters.hh
+pmon2.o: pmon2.cc victrix-abyssi.hh notify.hh monsters.hh pobj_id.hh pmon_id.hh
 
-objects.o: objects.cc victrix-abyssi.hh notify.hh objects.hh monsters.hh pobj_id.hh
+objects.o: objects.cc victrix-abyssi.hh notify.hh objects.hh monsters.hh pobj_id.hh pmon_id.hh
 
-sorcery.o: sorcery.cc victrix-abyssi.hh notify.hh sorcery.hh objects.hh monsters.hh
+sorcery.o: sorcery.cc victrix-abyssi.hh notify.hh sorcery.hh objects.hh monsters.hh pobj_id.hh pmon_id.hh
 
-u.o: u.cc combat.hh victrix-abyssi.hh notify.hh monsters.hh objects.hh pobj_id.hh
+u.o: u.cc combat.hh victrix-abyssi.hh notify.hh monsters.hh objects.hh pobj_id.hh pmon_id.hh
 
 util.o: util.c util.h
 
index b415a9c..1847bbc 100644 (file)
@@ -515,4 +515,3 @@ POWER 0
 POWER2 0
 DEPTH 1
 
-
diff --git a/default.permons b/default.permons
new file mode 100644 (file)
index 0000000..aed7925
--- /dev/null
@@ -0,0 +1,469 @@
+monster newt
+ascii 'n'
+utf8 "n"
+desc A small, not very threatening, vaguely lizard-like creature.
+colour red
+rarity 20
+power 1
+hp 3
+mtohit 0
+mdam 2
+defence 1
+exp 1
+speed 0
+STUPID
+
+monster rat
+ascii 'r'
+utf8 "r"
+desc A large and bad-tempered rodent not noted for its dental hygeine.
+colour brown
+power 1
+rarity 15
+hp 4
+mhit 0
+mdam 2
+defence 4
+exp 2
+speed 2
+STUPID
+
+monster wolf
+plural wolves
+ascii 'c'
+utf8 "c"
+desc A hungry canid, probably weighing nearly as much as you do in your skin.
+colour brown
+rarity 30
+power 6
+hp 20
+mhit 8
+mdam 10
+defence 6
+exp 15
+speed 2
+
+monster snake
+desc Probably venomous. You'd prefer to not find out.
+ascii 'c'
+utf8 "c"
+colour red
+rarity 20
+power 6
+hp 15
+mhit 10
+mdam 3
+defence 9
+experience 40
+speed 2
+STUPID
+
+monster thug
+desc Likes pushing people's faces through the backs of their heads.
+ascii 't'
+utf8 "t"
+colour brown
+rarity 30
+power 1
+hp 8
+mhit 5
+mdam 5
+defence 4
+experience 5
+speed 1
+
+monster goon
+desc Really good at pushing people's faces through the backs of their heads.
+ascii 't'
+utf8 "t"
+colour yellow
+rarity 20
+power 3
+hp 15
+mhit 6
+mdam 7
+defence 8
+experience 10
+speed 1
+
+monster hunter
+desc More at home in other people's forests, the glint in his eye as he nocks an arrow tells you princesses are in season.
+ascii 'h'
+utf8 "h"
+colour green
+rarity 30
+power 9
+hp 40
+mhit 6
+rhit 20
+mdam 6
+rdam 10
+shootverb shoots an arrow
+defence 10
+experience 50
+speed 1
+ARCHER
+
+monster duellist
+desc A talented swordsman with a fondness for single combat.
+ascii 'f'
+utf8 "f"
+colour red
+rarity 40
+power 12
+hp 60
+mhit 30
+mdam 15
+defence 15
+experience 130
+speed 1
+SMART
+
+monster warlord
+desc A truly exceptional warrior, strong of arm and fleet of foot.
+ascii 'f'
+utf8 "f"
+colour l_red
+rarity 30
+power 15
+hp 80
+mhit 25
+mdam 20
+defence 20
+experience 400
+speed 2
+SMART
+
+monster goblin
+desc A short, scrawny humanoid with no love for surface folk.
+ascii 'g'
+utf8 "g"
+colour brown
+rarity 20
+power 1
+hp 6
+mhit 1
+mdam 3
+defence 3
+experience 3
+speed 1
+
+monster bad elf
+plural bad elves
+desc Tall, slender, and androgynous, with a sharp knife in hand and a malicious glint in their eye.
+ascii 'e'
+utf8 "e"
+colour l_grey
+rarity 40
+power 3
+hp 15
+mhit 10
+mdam 6
+defence 8
+experience 15
+speed 2
+SMART
+
+monster troll
+desc Half again as tall as a tall Kafdaran, this lanky green-skinned humanoid is notorious for its indiscriminate appetite. Best do what you can to keep princess off the menu.
+ascii 'T'
+utf8 "T"
+colour green
+rarity 20
+power 12
+hp 80
+mhit 15
+mdam 15
+defence 13
+experience 150
+speed 1
+STUPID
+
+monster giant
+desc Half again as tall as a towering troll, and scarcely smarter.
+ascii 'H'
+utf8 "H"
+colour brown
+rarity 20
+power 21
+hp 80
+mhit 15
+mdam 25
+defence 20
+experience 500
+speed 1
+STUPID
+
+monster giant jarl
+desc A rarity among giants, this one has used its great strength and unusually sharp wits to persuade its dimmer brethren to obey.
+ascii 'H'
+utf8 "H"
+colour l_grey
+rarity 80
+power 25
+hp 160
+mhit 20
+mdam 30
+defence 22
+experience 1000
+speed 1
+
+monster wizard
+desc A practitioner of the arcane arts. Beware his command over the power of the storm!
+ascii 'w'
+utf8 "w"
+colour blue
+rarity 80
+power 12
+hp 40
+mhit 10
+rhit 20
+mdam 10
+rhit 10
+rdtyp ELEC
+shootverb casts
+defence 15
+experience 200
+speed 1
+SMART
+MAGICIAN
+
+monster archmage
+plural archmagi
+desc A grand master of the arcane arts, armed with spells of surpassing might.
+ascii 'w'
+utf8 "w"
+colour l_blue
+rarity 80
+power 24
+hp 80
+mhit 15
+rhit 30
+mdam 15
+rdam 15
+rdtyp ELEC
+shootverb casts
+defence 15
+experience 1500
+speed 1
+SMART
+MAGICIAN
+RESIST_ELEC
+
+monster zombie
+desc A half-rotted corpse, galvanized to a mockery of life by forbidden magic.
+ascii 'z'
+utf8 "z"
+colour l_grey
+rarity 25
+depth 3
+hp 30
+mhit 2
+mdam 10
+defence 1
+experience 7
+speed 0
+STUPID
+UNDEAD
+RESIST_COLD
+RESIST_POIS
+RESIST_NECR
+
+monster wraith
+desc The ethereal remnant of some long-dead unfortunate, wracked with eternal hunger for the light that shines within the living. No obstacle can bar its path.
+ascii 'W'
+utf8 "W"
+colour white
+rarity 25
+depth 12
+hp 40
+mhit 25
+mdam 5
+defence 5
+experience 100
+speed 0
+SMART
+UNDEAD
+RESIST_COLD
+RESIST_POIS
+RESIST_NECR
+
+monster lich
+plural liches
+desc A long-dead practitioner of the magic of death, clad in mouldering finery and sustained by their forbidden arts.
+ascii 'L'
+utf8 "L"
+colour l_grey
+rarity 70
+power 15
+hp 70
+mhit 15
+rhit 25
+mdam 15
+rdam 15
+rdtyp NECRO
+shootverb casts
+defence 15
+experience 250
+speed 1
+SMART
+UNDEAD
+RESIST_COLD
+RESIST_POIS
+RESIST_NECR
+MAGICIAN
+
+monster master lich
+plural master liches
+desc A long-dead master of the deepest magics of death, clad in mouldering finery and sustained by their forbidden arts.
+ascii 'L'
+utf8 "L"
+colour purple
+rarity 60
+power 30
+hp 150
+mhit 30
+rhit 30
+mdam 20
+rdam 30
+rdtyp NECRO
+shootverb casts
+defence 30
+experience 3000
+speed 1
+SMART
+UNDEAD
+RESIST_COLD
+RESIST_POIS
+RESIST_NECR
+MAGICIAN
+
+monster vampire
+desc A gaunt red-eyed figure with throat-tearing fangs, afflicted by an eternal hunger for the blood of the living.
+ascii 'V'
+utf8 "V"
+colour red
+rarity 55
+power 18
+hp 70
+mhit 25
+mdam 15
+defence 22
+experience 750
+speed 1
+SMART
+UNDEAD
+RESIST_COLD
+RESIST_POIS
+RESIST_NECR
+
+monster demon
+desc A red-skinned and long-taloned horror spat up from some corner or other of the Hells. Presented with prey, it is quick to call its brethren into the world.
+ascii '3'
+utf8 "3"
+colour red
+rarity 60
+power 18
+hp 40
+mhit 25
+mdam 20
+defence 15
+experience 500
+speed 1
+SMART
+DEMONIC
+RESIST_FIRE
+
+monster defiler
+desc Whatever shape this hellish horror has, it can scarcely be seen through the foetid green haze that surrounds it.
+ascii '2'
+utf8 "2"
+colour l_green
+rarity 65
+power 27
+hp 120
+mhit 30
+mdam 20
+defence 25
+experience 2000
+speed 1
+SMART
+DEMONIC
+MAGICIAN
+RESIST_POIS
+
+monster centaur
+desc A strange magical hybrid of horse and man.
+ascii 'C'
+utf8 "C"
+colour brown
+rarity 30
+power 9
+hp 40
+mhit 15
+mdam 10
+defence 10
+experience 50
+speed 2
+
+monster ice monster
+desc A ponderous, shambling half-humanoid figure of ice and snow.
+ascii 'I'
+utf8 "I"
+colour white
+rarity 50
+power 6
+hp 40
+mhit 10
+rhit 20
+mdam 15
+rdam 15
+rdtyp COLD
+shootverb launches a blast of
+defence 10
+experience 35
+speed 0
+RESIST_COLD
+ARCHER
+
+monster dragon
+desc A bulky beast of scales and fangs and fumes, capable of spewing searing flames to roast its enemies and rumoured to have a preference for char-grilled princess.
+ascii 'D'
+utf8 "D"
+colour red
+rarity 50
+power 15
+hp 80
+mhit 20
+rhit 20
+mdam 20
+rdam 20
+rdtyp FIRE
+shootverb breathes
+defence 18
+experience 300
+speed 1
+RESIST_FIRE
+ARCHER
+
+monster moondrake
+desc A bat-winged serpent with eyes that shimmer like quicksilver and a breath that chills the living to the bone.
+colour l_cyan
+ascii 'D'
+utf8 "D"
+rarity 60
+power 18
+hp 80
+mhit 20
+rhit 20
+mdam 20
+rdam 20
+rdtyp COLD
+shootverb breathes
+defence 24
+experience 500
+speed 2
+RESIST_FIRE
+RESIST_COLD
+RESIST_NECR
+ARCHER
index 83cde0b..98d13b7 100644 (file)
@@ -123,6 +123,11 @@ static void draw_main_menu(void)
     mvwprintw(fullscreen_window, 10, 25, "S)tart new game\n");
     mvwprintw(fullscreen_window, 11, 25, "R)esume existing game\n");
     mvwprintw(fullscreen_window, 12, 25, "Q)uit\n");
+#ifdef ALPHA_LEVEL
+    mvwprintw(fullscreen_window, 23, 25, "Version %d.%2d Alpha %d\n", MAJVERS, MINVERS, ALPHA_LEVEL);
+#else
+    mvwprintw(fullscreen_window, 23, 25, "Version %d.%2d\n", MAJVERS, MINVERS, ALPHA_LEVEL);
+#endif
     show_panel(fullscreen_panel);
     update_panels();
     doupdate();
@@ -436,6 +441,14 @@ int launch_user_interface(void)
     {
         force_ascii = true;
     }
+    {
+        char const *term = getenv("TERM");
+        if (term && (strstr(term, "xterm") || strstr (term, "rxvt")))
+        {
+            fputs("\033]0;Victrix Abyssi 1.0 Alpha 1\007", stdout);
+            fflush(stdout);
+        }
+    }
     initscr();
     noecho();
     cbreak();
diff --git a/log.cc b/log.cc
index 9cd018b..fa72f25 100644 (file)
--- a/log.cc
+++ b/log.cc
@@ -173,7 +173,6 @@ void save_game(void)
     tmp = htonl(game_tick);
     fwrite(&tmp, 1, sizeof tmp, fp);
     serialize_level(fp, &lvl);
-    fwrite(permobjs, sizeof (Permobj), NUM_OF_PERMOBJS, fp);
     fwrite(monsters, sizeof (Mon), MONSTERS_IN_PLAY, fp);
     fwrite(objects, sizeof (Obj), OBJECTS_IN_PLAY, fp);
     /* Clean up */
@@ -232,7 +231,6 @@ int load_game(void)
     wrapped_fread(&game_tick, 1, sizeof game_tick, fp);
     game_tick = ntohl(game_tick);
     deserialize_level(fp, &lvl);
-    wrapped_fread(permobjs, sizeof (Permobj), NUM_OF_PERMOBJS, fp);
     wrapped_fread(monsters, sizeof (Mon), MONSTERS_IN_PLAY, fp);
     wrapped_fread(objects, sizeof (Obj), OBJECTS_IN_PLAY, fp);
     rebuild_mapobjs();
index 150f632..070a13c 100644 (file)
 #endif
 
 /* XXX struct permon */
-enum Permon_num
-{
-    PM_NEWT = 0, PM_RAT, PM_WOLF, PM_SNAKE, PM_THUG, PM_GOON, PM_HUNTER,
-    PM_DUELLIST, PM_WARLORD, PM_WIZARD, PM_ARCHMAGE, PM_GOBLIN, PM_BAD_ELF,
-    PM_TROLL, PM_GIANT, PM_GIANT_JARL, PM_ZOMBIE, PM_WRAITH, PM_LICH,
-    PM_MASTER_LICH, PM_VAMPIRE, PM_DEMON, PM_DEFILER, PM_ICE_MONSTER,
-    PM_CENTAUR, PM_DRAGON, PM_MOONDRAKE
-};
-#define NUM_OF_PERMONS (1 + PM_MOONDRAKE)
+#include "pmon_id.hh"
 
 #define PMF_RESIST_FIRE 0x00000001
 #define PMF_RESIST_COLD 0x00000002
@@ -60,10 +52,13 @@ enum Permon_num
 #define PMF_ETHEREAL    0x00400000
 #define PMF_FLYING      0x00800000
 
-struct permon {
-    char const name[48];
-    char const plural[48];
+#define PERMON_FLAG_FIELDS 1
+struct Permon {
+    char const *name;
+    char const *plural;
+    char const *description;
     char sym;
+    char const *unicode;
     int colour;
     int rarity;         /* Chance in 100 of being thrown back and regen'd. */
     int power;          /* Used to determine OOD rating. */
@@ -74,13 +69,13 @@ struct permon {
     int mdam;           /* Improved by OOD rating at 1:5. */
     int rdam;           /* Improved by OOD rating at 1:5. */
     Damtyp rdtyp;  /* type of damage used by ranged attack. */
-    char const shootverb[48];   /* shooting verb e.g. "fires an arrow", "breathes". */
+    char const *shootverb;   /* shooting verb e.g. "fires an arrow", "breathes". */
     int defence;        /* Improved by OOD rating at 1:3. */
     int exp;            /* Unaffected by OOD rating. */
     int speed;          /* 0 = slow; 1 = normal; 2 = quick */
-    int flags;          /* resistances, AI settings, etc. */
+    uint32_t flags[PERMON_FLAG_FIELDS];          /* resistances, AI settings, etc. */
 };
-extern struct permon permons[NUM_OF_PERMONS];
+extern struct Permon permons[NUM_OF_PERMONS];
 
 #define NO_ATK (-1)
 #define NO_PMON (-1)
index 97e695f..53c7f9e 100644 (file)
@@ -62,8 +62,8 @@ enum poclass_num {
 
 /*! \brief The 'permanent object' database */
 struct Permobj {
-    char const name[48]; //!< English-language name of item
-    char const plural[48]; //!< English-language plural of item
+    char const *name; //!< English-language name of item
+    char const *plural; //!< English-language plural of item
     char const *description; //!< English-language description of item
     enum poclass_num poclass; //!< Category of item
     int rarity; //!< Chance in 100 of being thrown away and regen'd.
diff --git a/permons.cc b/permons.cc
deleted file mode 100644 (file)
index fe8f322..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/*! \file permons.cc
- *  \brief monster database for Victrix Abyssi
- */
-
-/* Copyright 2005-2013 Martin Read
- * 
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define PERMONS_CC
-#include "victrix-abyssi.hh"
-
-/*! \brief Array housing the monster database.
- */
-struct permon permons[NUM_OF_PERMONS] = {
-    {
-        "newt", "newts", 'n', Gcol_red, 20, 1, 3, 0, NO_ATK, 2, NO_ATK, DT_PHYS, "", 1, 1, 0, PMF_STUPID
-    },
-    {
-        "rat", "rats", 'r', Gcol_brown, 15, 1, 4, 0, NO_ATK, 2, NO_ATK, DT_PHYS, "", 4, 2, 2, PMF_STUPID
-    },
-    {
-        "wolf", "wolves", 'c', Gcol_brown, 30, 6, 20, 8, NO_ATK, 10, NO_ATK, DT_PHYS, "", 6, 15, 2, 0
-    },
-    {
-        /* Saps one Body on a really good hit */
-        "snake", "snakes", 's', Gcol_red, 20, 6, 15, 10, NO_ATK, 3, NO_ATK, DT_PHYS, "", 9, 40, 2, PMF_STUPID
-    },
-    {
-        /* may drop a mace or leather armour */
-        "thug", "thugs", 't', Gcol_brown, 30, 1, 8, 5, NO_ATK, 5, NO_ATK, DT_PHYS, "", 4, 5, 1, 0
-    },
-    {
-        "goon", "goons", 't', Gcol_yellow, 20, 3, 15, 6, NO_ATK, 7, NO_ATK, DT_PHYS, "", 8, 10, 1, 0
-    },
-    {
-        /* Has a ranged attack - arrows */
-        "hunter", "hunters", 'h', Gcol_green, 30, 9, 40, 6, 20, 6, 10, DT_PHYS, "shoots an arrow", 10, 50, 1, PMF_ARCHER
-    },
-    {
-        "duellist", "duellists", 'f', Gcol_red, 40, 12, 60, 30, NO_ATK, 15, NO_ATK, DT_PHYS, "", 15, 130, 1, PMF_SMART
-    },
-    {
-        "warlord", "warlords", 'f', Gcol_l_red, 30, 15, 80, 25, NO_ATK, 20, NO_ATK, DT_PHYS, "", 20, 400, 2, PMF_SMART
-    },
-    {
-        /* may drop a dagger */
-        "goblin", "goblins", 'g', Gcol_brown, 20, 1, 6, 1, NO_ATK, 3, NO_ATK, DT_PHYS, "", 3, 3, 1, 0
-    },
-    {
-        "bad elf", "bad elves", 'e', Gcol_l_grey, 40, 3, 15, 10, NO_ATK, 6, NO_ATK, DT_PHYS, "", 8, 15, 2, PMF_SMART
-    },
-    {
-        "troll", "trolls", 'T', Gcol_green, 20, 12, 80, 15, NO_ATK, 15, NO_ATK, DT_PHYS, "", 13, 150, 1, PMF_STUPID
-    },
-    {
-        "giant", "giants", 'H', Gcol_brown, 20, 21, 80, 15, NO_ATK, 25, NO_ATK, DT_PHYS, "", 20, 500, 1, PMF_STUPID
-    },
-    {
-        "giant jarl", "giant jarls", 'H', Gcol_l_grey, 80, 25, 160, 20, NO_ATK, 30, NO_ATK, DT_PHYS, "", 22, 1000, 1, 0
-    },
-    {
-        /* Uses sorcery against you; see sorcery.c for details. */
-        "wizard", "wizards", 'w', Gcol_blue, 80, 12, 40, 10, 20, 10, 10, DT_ELEC, "casts", 15, 200, 1, PMF_SMART | PMF_MAGICIAN
-    },
-    {
-        /* Uses sorcery against you; see sorcery.c for details. */
-        "archmage", "archmagi", 'w', Gcol_l_blue, 80, 24, 80, 15, 30, 15, 15, DT_ELEC, "casts", 15, 1500, 1, PMF_SMART | PMF_MAGICIAN | PMF_RESIST_ELEC
-    },
-    {
-        "zombie", "zombies", 'z', Gcol_l_grey, 25, 3, 30, 2, NO_ATK, 10, NO_ATK, DT_PHYS, "", 1, 7, 0, PMF_STUPID | PMF_UNDEAD | PMF_RESIST_COLD | PMF_RESIST_POIS | PMF_RESIST_NECR
-    },
-    {
-        "wraith", "wraiths", 'W', Gcol_white, 25, 12, 40, 25, NO_ATK, 5, NO_ATK, DT_PHYS, "", 5, 100, 0, PMF_SMART | PMF_UNDEAD | PMF_RESIST_COLD | PMF_RESIST_POIS | PMF_RESIST_NECR
-    },
-    {
-        /* Uses sorcery against you; see sorcery.c for details. */
-        "lich", "liches", 'L', Gcol_l_grey, 70, 15, 70, 15, 25, 15, 15, DT_NECRO, "casts", 15, 250, 1, PMF_SMART | PMF_UNDEAD | PMF_RESIST_COLD | PMF_MAGICIAN | PMF_RESIST_POIS | PMF_RESIST_NECR
-    },
-    {
-        /* Master liches use sorcery against you, more powerfully
-         * than lesser practitioners. */
-        "master lich", "master liches", 'L', Gcol_purple, 60, 30, 150, 30, 30, 20, 30, DT_NECRO, "", 30, 3000, 1, PMF_SMART | PMF_UNDEAD | PMF_RESIST_COLD | PMF_MAGICIAN | PMF_RESIST_POIS | PMF_RESIST_NECR
-    },
-    {
-        /* Vampires heal by hitting you. */
-        "vampire", "vampires", 'V', Gcol_red, 55, 18, 70, 25, NO_ATK, 15, NO_ATK, DT_PHYS, "", 22, 750, 1, PMF_SMART | PMF_UNDEAD | PMF_RESIST_COLD | PMF_RESIST_POIS | PMF_RESIST_NECR
-    },
-    {
-        /* Demons summon more demons if you don't kill them
-         * quickly. */
-        "demon", "demons", '&', Gcol_red, 60, 18, 40, 25, NO_ATK, 20, NO_ATK, DT_PHYS, "", 15, 500, 1, PMF_SMART | PMF_DEMONIC | PMF_RESIST_FIRE
-    },
-    {
-        /* Defilers use sorcery (mostly curses) against you. */
-        "defiler", "defilers", '&', Gcol_l_green, 65, 27, 120, 30, 30, 20, 30, DT_FIRE, "", 25, 2000, 1, PMF_SMART | PMF_DEMONIC | PMF_RESIST_FIRE | PMF_MAGICIAN | PMF_RESIST_POIS
-    },
-    {
-        "centaur", "centaurs", 'C', Gcol_brown, 30, 9, 40, 15, NO_ATK, 10, NO_ATK, DT_PHYS, "", 10, 50, 2, 0
-    },
-    {
-        /* Fires ice blasts. */
-        "ice monster", "ice monsters", 'I', Gcol_white, 50, 6, 40, 10, 20, 15, 15, DT_COLD, "launches a blast of", 10, 35, 0, PMF_RESIST_COLD | PMF_ARCHER
-    },
-    {
-        /* Breathes fire. */
-        "dragon", "dragons", 'D', Gcol_red, 50, 15, 80, 20, 20, 20, 20, DT_FIRE, "breathes", 18, 300, 1, PMF_RESIST_FIRE | PMF_ARCHER
-    },
-    {
-        /* Breathes eldritchness represented as cold. I should work on that. */
-        "moondrake", "moondrakes", 'D', Gcol_l_cyan, 50, 15, 80, 20, 20, 20, 20, DT_COLD, "breathes", 24, 500, 1, PMF_RESIST_FIRE | PMF_RESIST_COLD | PMF_RESIST_NECR | PMF_ARCHER
-    },
-};
-
-/* permons.c */
-// vim:cindent
index 56af796..10e7a3d 100644 (file)
--- a/pmon2.cc
+++ b/pmon2.cc
 
 bool pmon_resists_fire(int pm)
 {
-    return !!(permons[pm].flags & PMF_RESIST_FIRE);
+    return !!(permons[pm].flags[0] & PMF_RESIST_FIRE);
 }
 
 bool pmon_resists_cold(int pm)
 {
-    return !!(permons[pm].flags & PMF_RESIST_COLD);
+    return !!(permons[pm].flags[0] & PMF_RESIST_COLD);
 }
 
 bool pmon_resists_poison(int pm)
 {
-    return !!(permons[pm].flags & PMF_RESIST_POIS);
+    return !!(permons[pm].flags[0] & PMF_RESIST_POIS);
 }
 
 bool pmon_resists_necro(int pm)
 {
-    return !!(permons[pm].flags & PMF_RESIST_NECR);
+    return !!(permons[pm].flags[0] & PMF_RESIST_NECR);
 }
 
 bool pmon_resists_elec(int pm)
 {
-    return !!(permons[pm].flags & PMF_RESIST_ELEC);
+    return !!(permons[pm].flags[0] & PMF_RESIST_ELEC);
 }
 
 bool pmon_resists_knockback(int pm)
 {
-    return !!(permons[pm].flags & PMF_RESIST_SLAM);
+    return !!(permons[pm].flags[0] & PMF_RESIST_SLAM);
 }
 
 bool pmon_resists_drowning(int pm)
 {
-    return !!(permons[pm].flags & PMF_RESIST_DRWN);
+    return !!(permons[pm].flags[0] & PMF_RESIST_DRWN);
 }
 
 bool pmon_is_undead(int pm)
 {
-    return !!(permons[pm].flags & PMF_UNDEAD);
+    return !!(permons[pm].flags[0] & PMF_UNDEAD);
 }
 
 bool pmon_is_stupid(int pm)
 {
-    return !!(permons[pm].flags & PMF_STUPID);
+    return !!(permons[pm].flags[0] & PMF_STUPID);
 }
 
 bool pmon_is_smart(int pm)
 {
-    return !!(permons[pm].flags & PMF_SMART);
+    return !!(permons[pm].flags[0] & PMF_SMART);
 }
 
 bool pmon_is_magician(int pm)
 {
-    return !!(permons[pm].flags & PMF_MAGICIAN);
+    return !!(permons[pm].flags[0] & PMF_MAGICIAN);
 }
 
 bool pmon_is_archer(int pm)
 {
-    return !!(permons[pm].flags & PMF_ARCHER);
+    return !!(permons[pm].flags[0] & PMF_ARCHER);
 }
 
 bool pmon_can_fly(int pm)
 {
-    return !!(permons[pm].flags & PMF_FLYING);
+    return !!(permons[pm].flags[0] & PMF_FLYING);
 }
 
 bool pmon_is_ethereal(int pm)
 {
-    return !!(permons[pm].flags & PMF_ETHEREAL);
+    return !!(permons[pm].flags[0] & PMF_ETHEREAL);
 }
 
 /* pmon2.c */
diff --git a/pmon_comp b/pmon_comp
new file mode 100755 (executable)
index 0000000..fbd3f3d
--- /dev/null
+++ b/pmon_comp
@@ -0,0 +1,375 @@
+#! /usr/bin/env perl
+
+use strict;
+use warnings;
+use English;
+use Time::HiRes qw( time );
+
+sub usage()
+{
+    print "Usage:\n    pmon_comp INPUT_FILE\n\npmon_comp reads a single .permon file INPUT_FILE and generates a permon.cc\nand pmon_id.hh based on its contents.";
+    exit(1);
+}
+
+our @monsters;
+
+our %flag_indices =
+(
+    'RESIST_FIRE' => 0,
+    'RESIST_COLD' => 0,
+    'RESIST_ELEC' => 0,
+    'RESIST_POIS' => 0,
+    'RESIST_NECR' => 0,
+    'RESIST_SLAM' => 0,
+    'RESIST_DRWN' => 0,
+    'UNDEAD' => 0,
+    'DEMONIC' => 0,
+    'MAGICIAN' => 0,
+    'ARCHER' => 0,
+    'SMART' => 0,
+    'STUPID' => 0,
+    'ETHEREAL' => 0,
+    'FLYING' => 0
+);
+
+
+sub macroify_name($)
+{
+    my $name = "".shift @_;
+    $name =~ tr/'//d;
+    return uc(($name =~ tr/a-zA-Z/_/csr));
+}
+
+sub flag_string($)
+{
+    my $aref = shift @_;
+    my @flag_fields = ();
+    if (!defined($aref) || scalar(@$aref == 0))
+    {
+        return "0";
+    }
+    else
+    {
+        my $name;
+        for $name (@$aref)
+        {
+            die("Attempt to generate a flag string containing an undefined flag $name!") if !exists($flag_indices{$name});
+            my $idx = $flag_indices{$name};
+            $#flag_fields = $idx if ($idx > $#flag_fields);
+            if (!defined($flag_fields[$idx]))
+            {
+                $flag_fields[$idx] = "0 ";
+            }
+            $flag_fields[$idx] .= "| PMF_$name ";
+        }
+    }
+    return join(", ", @flag_fields);
+}
+
+sub commit_monster($)
+{
+    my $href = shift(@_);
+    die("Attempt to commit an unnamed monster!") if !exists($href->{name});
+    die("Attempt to commit a ASCIIless monster ".$href->{name}."!") if !exists($href->{ascii});
+    die("Attempt to commit a UTF8less monster ".$href->{name}."!") if !exists($href->{uni});
+    if (!exists($href->{plural}))
+    {
+        # naive fallback, guaranteed to look shit sooner or later
+        $href->{plural} = $href->{name}."s";
+    }
+    my $new_hash = {
+        'name' => $href->{name},
+        'plural' => $href->{plural},
+        'desc' => $href->{desc},
+        'ascii' => $href->{ascii},
+        'uni' => $href->{uni},
+        'colour' => $href->{colour},
+        'rarity' =>  $href->{rarity},
+        'power' =>  $href->{power},
+        'hp' =>  $href->{hp},
+        'mtohit' =>  $href->{mtohit},
+        'rtohit' =>  $href->{rtohit},
+        'mdam' =>  $href->{mdam},
+        'rdam' =>  $href->{rdam},
+        'rdtyp' =>  $href->{rdtyp},
+        'shootverb' => $href->{shootverb},
+        'defence' =>  $href->{defence},
+        'exp' =>  $href->{exp},
+        'speed' =>  $href->{speed},
+        'power' =>  $href->{power},
+        'flags' => $href->{flags}
+    };
+    push @monsters, $new_hash;
+}
+
+our $argc = scalar(@ARGV);
+usage() if ($argc != 1);
+our $output_fname;
+our $input_fname = "$ARGV[0]";
+open(INFILE, "<", $input_fname) or die "pmon_comp: could not open $input_fname for read: $!";
+our @input_file = <INFILE>;
+close INFILE;
+our %blank_monster = (
+    'desc' => "An monster some useless slacker hasn't bothered to describe.",
+    'colour' => "l_grey",
+    'rarity' => 100,
+    'power' => 1,
+    'hp' => 1,
+    'mtohit' => 0,
+    'rtohit' => -1,
+    'mdam' => 0,
+    'rdam' => -1,
+    'rdtyp' => "PHYS",
+    'shootverb' => "shoots",
+    'defence' => 0,
+    'exp' => 0,
+    'speed' => 0
+);
+
+our %working_monster;
+
+sub reinit_working_monster($)
+{
+    %working_monster = %blank_monster;
+    $working_monster{name} = shift;
+    $working_monster{plural} = "$working_monster{name}s";
+    $working_monster{flags} = [];
+}
+
+my $input_line;
+
+our $start_time = time();
+print "Processing permons database $input_fname";
+for $input_line (@input_file)
+{
+    chomp $input_line;
+    next if ($input_line =~ /^\s*$/);
+    next if ($input_line =~ /^\s*#/);
+    if ($input_line =~ /^\s*monster\s+([^[:space:]].*)$/i)
+    {
+        my $name = $1;
+        if (exists($working_monster{name}))
+        {
+            commit_monster(\%working_monster);
+            %working_monster = ();
+        }
+        reinit_working_monster($name);
+        print ".";
+    }
+    elsif (!exists($working_monster{name}))
+    {
+        die("Attempt to specify monster properties without starting an monster");
+    }
+    elsif ($input_line =~ /^\s*(power|depth)\s+/i)
+    {
+        my $pm = "$POSTMATCH";
+        if ($pm =~ /^(-?[0-9]+)/)
+        {
+            $working_monster{power} = $1;
+        }
+        else
+        {
+            die("Non-numeric power value $pm in monster $working_monster{name}");
+        }
+    }
+    elsif ($input_line =~ /^\s*hp\s+/i)
+    {
+        my $pm = "$POSTMATCH";
+        if ($pm =~ /^(-?[0-9]+)/)
+        {
+            $working_monster{hp} = $1;
+        }
+        else
+        {
+            die("Non-numeric hp value $pm in monster $working_monster{name}");
+        }
+    }
+    elsif ($input_line =~ /^\s*m(elee)?(to)?hit\s+/i)
+    {
+        my $pm = "$POSTMATCH";
+        if ($pm =~ /^([0-9]+)/)
+        {
+            $working_monster{mtohit} = $1;
+        }
+        else
+        {
+            die("Negative or non-numeric mtohit value $pm in monster $working_monster{name}");
+        }
+    }
+    elsif ($input_line =~ /^\s*m(elee)?dam\s+/i)
+    {
+        my $pm = "$POSTMATCH";
+        if ($pm =~ /^([0-9]+)/)
+        {
+            $working_monster{mdam} = $1;
+        }
+        else
+        {
+            die("Negative or non-numeric mdam value $pm in monster $working_monster{name}");
+        }
+    }
+    elsif ($input_line =~ /^\s*r(anged)?(to)?hit\s+/i)
+    {
+        my $pm = "$POSTMATCH";
+        if ($pm =~ /^([0-9]+)/)
+        {
+            $working_monster{rtohit} = $1;
+        }
+        else
+        {
+            die("Negative or non-numeric rtohit value $pm in monster $working_monster{name}");
+        }
+    }
+    elsif ($input_line =~ /^\s*sp(ee)?d\s+/i)
+    {
+        my $pm = "$POSTMATCH";
+        if ($pm =~ /^([0-9]+)/)
+        {
+            $working_monster{speed} = $1;
+        }
+        else
+        {
+            die("Negative or non-numeric speed value $pm in monster $working_monster{name}");
+        }
+    }
+    elsif ($input_line =~ /^\s*exp(erience)?\s+/i)
+    {
+        my $pm = "$POSTMATCH";
+        if ($pm =~ /^([0-9]+)/)
+        {
+            $working_monster{exp} = $1;
+        }
+        else
+        {
+            die("Negative or non-numeric exp value $pm in monster $working_monster{name}");
+        }
+    }
+    elsif ($input_line =~ /^\s*def(en[cs]e)?\s+/i)
+    {
+        my $pm = "$POSTMATCH";
+        if ($pm =~ /^([0-9]+)/)
+        {
+            $working_monster{defence} = $1;
+        }
+        else
+        {
+            die("Negative or non-numeric defence value $pm in monster $working_monster{name}");
+        }
+    }
+    elsif ($input_line =~ /^\s*r(anged)?dam\s+/i)
+    {
+        my $pm = "$POSTMATCH";
+        if ($pm =~ /^([0-9]+)/)
+        {
+            $working_monster{rdam} = $1;
+        }
+        else
+        {
+            die("Negative or non-numeric rdam value $pm in monster $working_monster{name}");
+        }
+    }
+    elsif ($input_line =~ /^\s*rarity\s+/i)
+    {
+        my $pm = "$POSTMATCH";
+        if ($pm =~ /^([0-9]+)/)
+        {
+            $working_monster{rarity} = $1;
+        }
+        else
+        {
+            die("Negative or non-numeric rarity value $pm in monster $working_monster{name}");
+        }
+    }
+    elsif ($input_line =~ /^\s*shootverb\s+/i)
+    {
+        $working_monster{shootverb} = "$POSTMATCH";
+    }
+    elsif ($input_line =~ /^\s*colour\s+/i)
+    {
+        $working_monster{colour} = "$POSTMATCH";
+    }
+    elsif ($input_line =~ /^\s*desc\s+/i)
+    {
+        $working_monster{desc} = "$POSTMATCH";
+    }
+    elsif ($input_line =~ /^\s*plural\s+/i)
+    {
+        $working_monster{plural} = "$POSTMATCH";
+    }
+    elsif ($input_line =~ /^\s*r(anged)?dtyp\s+/i)
+    {
+        $working_monster{rdtyp} = "$POSTMATCH";
+    }
+    elsif ($input_line =~ /^\s*ascii\s+/i)
+    {
+        my $pm = "$POSTMATCH";
+        if ($pm =~ /^'[[:ascii:]]'/)
+        {
+            $working_monster{ascii} = "$MATCH";
+        }
+        else
+        {
+            die("Malformed 'ASCII' argument $pm in monster $working_monster{name}");
+        }
+    }
+    elsif ($input_line =~ /^\s*utf-?8\s+/i)
+    {
+        my $pm = "$POSTMATCH";
+        if ($pm =~ /^"[^"]+"/)
+        {
+            $working_monster{uni} = "$MATCH";
+        }
+        else
+        {
+            die("Malformed 'UTF8' argument $pm in monster $working_monster{name}");
+        }
+    }
+    else
+    {
+        my $test_line = "$input_line";
+        $test_line =~ s/\s+//;
+        if (exists($flag_indices{$test_line}))
+        {
+            my $aref = $working_monster{flags};
+            push @$aref, $test_line;
+        }
+        else
+        {
+            die("Malformed/unrecognized line $input_line in monster $working_monster{name}");
+        }
+    }
+}
+commit_monster(\%working_monster);
+print "\n";
+
+open(HEADERFILE, ">", "pmon_id.hh") or die "pmon_comp: could not open pmon_id.hh for write: $!";
+open(SOURCEFILE, ">", "permons.cc") or die "pmon_comp: could not open permons.cc for write: $!";
+print HEADERFILE "// pmon_id.hh\n// This file is autogenerated from $input_fname\n// and is subject to the same copyright licensing terms as that file.\n// Do not edit this file directly; edit $input_fname\n// then use pmon_comp to regenerate this file and permons.cc\n#pragma once\nenum Pmon_id {\n";
+print SOURCEFILE "// permons.cc\n// This file is autogenerated from $input_fname\n// and is subject to the same copyright licensing terms as that file.\n// Do not edit this file directly; edit $input_fname then use pmon_comp to\n// regenreate this file and pmon_id.hh\n#include \"victrix-abyssi.hh\"\nPermon permons[NUM_OF_PERMONS] = {\n";
+my $phref;
+my $i;
+my $total_mons = 0;
+my @firsts;
+my $tagname;
+
+for ($i = 0; $i <= $#monsters; ++$i, ++$total_mons)
+{
+    $phref = $monsters[$i];
+    $tagname = "PM_".macroify_name($phref->{name});
+    if ($total_mons != 0)
+    {
+        print HEADERFILE ",\n";
+    }
+    print HEADERFILE "    ${tagname}";
+    printf SOURCEFILE "    { \"%s\", \"%s\", \"%s\", %s, %s, Gcol_%s, %d, %d, %d, %d, %d, %d, %d, DT_%s, \"%s\", %d, %d, %d, { %s } },\n", $phref->{name}, $phref->{plural}, $phref->{desc}, $phref->{ascii}, $phref->{uni}, $phref->{colour}, $phref->{rarity}, $phref->{power}, $phref->{hp}, $phref->{mtohit}, $phref->{rtohit}, $phref->{mdam}, $phref->{rdam}, $phref->{rdtyp}, $phref->{shootverb}, $phref->{defence}, $phref->{exp}, $phref->{speed},  flag_string($phref->{flags});
+}
+
+print SOURCEFILE "};\n// permons.cc\n";
+printf HEADERFILE "};\n".join('', @firsts)."\n#define NUM_OF_PERMONS %d\n\n// pmon_id.hh\n", $total_mons;
+
+close(SOURCEFILE);
+close(HEADERFILE);
+our $end_time = time();
+printf "Processed $total_mons monsters in %1.4f seconds.\n", ($end_time - $start_time);
+
+# vim:autoindent:smartindent
index 2b9c49a..667074f 100644 (file)
@@ -47,6 +47,8 @@
 #include "rng.hh"
 #endif
 
+#define ALPHA_LEVEL 1
+
 enum Comparison
 {
     Lesser = -1,