From ffdc6f08cac536664b632b2c527dbc272c7fe3da Mon Sep 17 00:00:00 2001 From: Martin Read Date: Mon, 10 Feb 2014 20:53:33 +0000 Subject: [PATCH] Switched permons database to parsed autogen --- .gitignore | 2 + MANIFEST | 5 +- Makefile | 34 ++-- default.permobjs | 1 - default.permons | 469 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ display-nc.cc | 13 ++ log.cc | 2 - monsters.hh | 25 ++- objects.hh | 4 +- permons.cc | 135 ---------------- pmon2.cc | 28 ++-- pmon_comp | 375 +++++++++++++++++++++++++++++++++++++++++++ victrix-abyssi.hh | 2 + 13 files changed, 907 insertions(+), 188 deletions(-) create mode 100644 default.permons delete mode 100644 permons.cc create mode 100755 pmon_comp diff --git a/.gitignore b/.gitignore index ecc4336..f238f05 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/MANIFEST b/MANIFEST index 8fb85c1..5ea9d1e 100644 --- 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 diff --git a/Makefile b/Makefile index bf3d61f..310e6f0 100644 --- 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 diff --git a/default.permobjs b/default.permobjs index b415a9c..1847bbc 100644 --- a/default.permobjs +++ b/default.permobjs @@ -515,4 +515,3 @@ POWER 0 POWER2 0 DEPTH 1 - diff --git a/default.permons b/default.permons new file mode 100644 index 0000000..aed7925 --- /dev/null +++ b/default.permons @@ -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 diff --git a/display-nc.cc b/display-nc.cc index 83cde0b..98d13b7 100644 --- a/display-nc.cc +++ b/display-nc.cc @@ -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 --- 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(); diff --git a/monsters.hh b/monsters.hh index 150f632..070a13c 100644 --- a/monsters.hh +++ b/monsters.hh @@ -34,15 +34,7 @@ #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) diff --git a/objects.hh b/objects.hh index 97e695f..53c7f9e 100644 --- a/objects.hh +++ b/objects.hh @@ -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 index fe8f322..0000000 --- a/permons.cc +++ /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 diff --git a/pmon2.cc b/pmon2.cc index 56af796..10e7a3d 100644 --- a/pmon2.cc +++ b/pmon2.cc @@ -32,72 +32,72 @@ 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 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 = ; +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 diff --git a/victrix-abyssi.hh b/victrix-abyssi.hh index 2b9c49a..667074f 100644 --- a/victrix-abyssi.hh +++ b/victrix-abyssi.hh @@ -47,6 +47,8 @@ #include "rng.hh" #endif +#define ALPHA_LEVEL 1 + enum Comparison { Lesser = -1, -- 2.11.0