# Makefile for Victrix Abyssi
-OBJS=combat.o display-nc.o main.o map.o misc.o monsters.o mon2.o objects.o permobj.o permons.o pmon2.o rng.o sorcery.o u.o vector.o
+OBJS=combat.o display-nc.o fov.o main.o map.o misc.o monsters.o mon2.o objects.o permobj.o permons.o pmon2.o rng.o sorcery.o u.o vector.o
include dirs.mk
include features.mk
PRODUCTION_CFLAGS:=-c -Wall -Wstrict-prototypes -Wwrite-strings -Wmissing-prototypes -Wno-unused-but-set-variable -Wredundant-decls -Wunreachable-code -DMAJVERS=$(MAJVERS) -DMINVERS=$(MINVERS)
DEVELOPMENT_CFLAGS:=-c -g -Wall -Wstrict-prototypes -Wwrite-strings -Wmissing-prototypes -Wno-unused-but-set-variable -Wredundant-decls -Wunreachable-code -Werror -DMAJVERS=$(MAJVERS) -DMINVERS=$(MINVERS)
CFLAGS=$(PRODUCTION_CFLAGS)
-LINKFLAGS=-lpanelw -lncursesw -g
+LINKFLAGS=-lm -lpanelw -lncursesw -g
ARCHIVEDIR:=victrix-abyssi_$(MAJVERS).$(MINVERS)
all: $(GAME)
print_msg("You do %d damage.\n", damage);
}
damage_mon(mapmonster[y][x], damage, 1);
+ if ((mptr->used) && (wep->obj_id == PO_THUNDERBOW))
+ {
+ int kb = knockback_mon(mapmonster[y][x], sy, sx, true, true);
+ switch (kb)
+ {
+ case 0:
+ print_msg("Your foe staggers a little.\n");
+ break;
+ case 1:
+ print_msg("Your foe is knocked backwards by the force of the shot.\n");
+ break;
+ case 2:
+ /* message handled elsewhere */
+ break;
+ }
+ }
return 1;
}
else
return 0;
}
}
- else if ((terrain[y][x] == WALL) || (terrain[y][x] == DOOR))
+ else if ((terrain[y][x] == WALL) || (terrain[y][x] == HARDWALL) ||
+ (terrain[y][x] == DOOR))
{
- print_msg("Your %s hits the %s.\n", (wep->obj_id == PO_BOW) ? "arrow" : "bolt", (terrain[y][x] == WALL) ? "wall" : "door");
+ print_msg("Your %s hits the %s.\n", (wep->obj_id == PO_CROSSBOW) ? "bolt" : "arrow", (terrain[y][x] == DOOR) ? "door" : "wall");
return 0;
}
}
return '>';
case FLOOR:
return '.';
+ case HARDWALL:
+ // return '#' | colour_attrs[DBCLR_PURPLE];
case WALL:
return '#' | colour_attrs[wall_colour];
case DOOR:
{
back_buffer[y][x] = '@' | colour_attrs[you_colour];
}
- else if (!show_terrain && (mapmonster[y][x] != -1) && mon_visible(mapmonster[y][x]))
+ else if ((!show_terrain) && (mapmonster[y][x] != -1) && mon_visible(mapmonster[y][x]))
{
back_buffer[y][x] = monster_char(monsters[mapmonster[y][x]].mon_id);
}
else if (mapflags[y][x] & MAPFLAG_EXPLORED)
{
- if (!show_terrain && (mapobject[y][x] != -1))
+ if ((!show_terrain) && (mapobject[y][x] != -1))
{
back_buffer[y][x] = object_char(objects[mapobject[y][x]].obj_id);
}
void hide_inv(void)
{
+ show_panel(message_panel);
hide_panel(inventory_panel);
update_panels();
doupdate();
selection = ch - 'a';
if ((u.inventory[selection] != -1) && ((filter == POCLASS_NONE) || (permobjs[objects[u.inventory[selection]].obj_id].poclass == filter)))
{
+ hide_inv();
return selection;
}
/* Fall through */
if (!panel_hidden(inventory_panel))
{
hide_inv();
+ if (ch == 'i')
+ {
+ continue;
+ }
}
switch (ch)
{
--- /dev/null
+/*! \file display.h
+ * \brief Display-related definitions 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.
+ */
+
+#ifndef DISPLAY_H
+#define DISPLAY_H
+
+#define DBCLR_L_GREY 0
+#define DBCLR_D_GREY 1
+#define DBCLR_RED 2
+#define DBCLR_BLUE 3
+#define DBCLR_GREEN 4
+#define DBCLR_PURPLE 5
+#define DBCLR_BROWN 6
+#define DBCLR_CYAN 7
+#define DBCLR_WHITE 8
+#define DBCLR_L_RED 9
+#define DBCLR_L_BLUE 10
+#define DBCLR_L_GREEN 11
+#define DBCLR_L_PURPLE 12
+#define DBCLR_YELLOW 13
+#define DBCLR_L_CYAN 14
+
+extern void print_msg(const char *fmt, ...);
+extern int read_input(char *buffer, int length);
+extern void print_help(void);
+extern int display_init(void);
+extern void display_update(void);
+extern int display_shutdown(void);
+extern void newsym(int y, int x);
+extern void touch_back_buffer(void);
+extern int inv_select(enum poclass_num filter, const char *action, int accept_blank);
+extern enum game_cmd get_command(void);
+extern int select_dir(int *psy, int *psx);
+extern int getYN(const char *msg);
+extern int getyn(const char *msg);
+extern void press_enter(void);
+extern void pressanykey(void);
+extern void show_discoveries(void);
+extern void touch_one_screen(int y, int x);
+
+/* "I've changed things that need to be redisplayed" flags. */
+extern int hard_redraw;
+extern int status_updated;
+extern int map_updated;
+/* "Show the player the terrain only" flag. */
+extern int show_terrain;
+
+#endif
+
+/* display.h */
+// vim:cindent
--- /dev/null
+/*! \file fov.c
+ * \brief field-of-view computation (recursive shadowcasting)
+ *
+ * A recursive shadowcasting implementation using diamond (rather than whole-
+ * cell) occlusion rules.
+ */
+
+/* Copyright 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.
+ */
+
+#include "victrix-abyssi.h"
+#include "fov.h"
+#include <string.h>
+#include <math.h>
+
+int trn_dy[8] = {
+ 0, -1, 1, 0, 0, 1, -1, 0
+};
+
+int trn_dx[8] = {
+ 1, 0, 0, 1, -1, 0, 0, -1
+};
+
+int rdl_dy[8] = {
+ -1, 0, 0, 1, 1, 0, 0, -1
+};
+
+int rdl_dx[8] = {
+ 0, 1, 1, 0, 0, -1, -1, 0
+};
+
+static void compute_row(Radiance *rad, int octant, int radius, double inmost_slope, double outmost_slope);
+
+static bool dflt_blk(int y, int x)
+{
+ return ((y <= 0) || (x <= 0) || (y >= DUN_HEIGHT - 1) || (x >= DUN_WIDTH - 1) || (terrain[y][x] < FLOOR));
+}
+
+static bool mark_explored(int y, int x, void *pvt)
+{
+ mapflags[y][x] |= MAPFLAG_EXPLORED;
+ newsym(y, x);
+ return true;
+}
+
+/*! \fn
+ * \brief Return the inner (cardinal-wards) blocking limit of an octant-relative coordinate
+ */
+static inline double inner_slope(int rdl, int trn)
+{
+ return trn ? ((trn - 0.5) / ((double) rdl)) : 0.0;
+}
+
+static inline double inner_visible_slope(int rdl, int trn)
+{
+ return trn ? ((trn - 0.5) / (rdl - 0.5)) : 0.0;
+}
+/*! \fn
+ * \brief Return the outer (diagonal-wards) blocking limit of an octant-relative coordinate
+ */
+static inline double outer_slope(int rdl, int trn)
+{
+ return (rdl == trn) ? 1.0 : ((trn + 0.5) / (double) rdl);
+}
+
+static inline double outer_visible_slope(int rdl, int trn)
+{
+ return (rdl == trn) ? 1.0 : ((trn + 0.5) / (rdl - 0.5));
+}
+
+void clear_radiance(Radiance *rad)
+{
+ memset(&(rad->affected), '\0', sizeof rad->affected);
+}
+
+static inline void compute_octant(Radiance *rad, int octant)
+{
+ compute_row(rad, octant, 1, 0.0, 1.0);
+}
+
+static void compute_row(Radiance *rad, int octant, int radius, double inmost_slope, double outmost_slope)
+{
+ int trn;
+ int dy;
+ int dx;
+ bool block_flag = false;
+ int outer_idx;
+ int inner_idx;
+ if (inmost_slope >= outmost_slope)
+ {
+ return;
+ }
+ inner_idx = inmost_slope * radius;
+ outer_idx = 0.5 + (outmost_slope * radius);
+ dx = radius * rdl_dx[octant] + outer_idx * trn_dx[octant];
+ dy = radius * rdl_dy[octant] + outer_idx * trn_dy[octant];
+ for (trn = outer_idx; trn >= inner_idx; --trn)
+ {
+ if (outer_visible_slope(radius, trn) < inmost_slope)
+ {
+ continue;
+ }
+ if (inner_visible_slope(radius, trn) > outmost_slope)
+ {
+ continue;
+ }
+ rad->affected[MAX_FOV_RADIUS + dy][MAX_FOV_RADIUS + dx] = true;
+ if (block_flag)
+ {
+ if (rad->opaque_fun(dy + rad->centre_y, dx + rad->centre_x))
+ {
+ outmost_slope = inner_slope(radius, trn);
+ }
+ else
+ {
+ block_flag = false;
+ }
+ }
+ else
+ {
+ if (rad->opaque_fun(dy + rad->centre_y, dx + rad->centre_x))
+ {
+ block_flag = true;
+ if ((trn < outer_idx) && (radius < rad->radius))
+ {
+ compute_row(rad, octant, radius + 1, outer_slope(radius, trn), outmost_slope);
+ }
+ outmost_slope = inner_slope(radius, trn);
+ }
+ }
+ dx -= trn_dx[octant];
+ dy -= trn_dy[octant];
+ }
+ if ((radius < rad->radius) && !block_flag)
+ {
+ compute_row(rad, octant, radius + 1, inmost_slope, outmost_slope);
+ }
+}
+
+void compute_radiance(Radiance *rad)
+{
+ int oct;
+ for (oct = 0; oct < 8; ++oct)
+ {
+ compute_octant(rad, oct);
+ }
+ if (rad->exclude_centre)
+ {
+ rad->affected[MAX_FOV_RADIUS][MAX_FOV_RADIUS] = false;
+ }
+ else
+ {
+ rad->affected[MAX_FOV_RADIUS][MAX_FOV_RADIUS] = false;
+ }
+}
+
+void resolve_radiance(Radiance *rad)
+{
+ int y;
+ int x;
+ int i;
+ int j;
+ switch (rad->order)
+ {
+ case Reo_ascending:
+ for ((i = MAX_FOV_RADIUS - rad->radius), (y = rad->centre_y - rad->radius); y < rad->centre_y + rad->radius; ++y, ++i)
+ {
+ for ((j = MAX_FOV_RADIUS - rad->radius), (x = rad->centre_x - rad->radius); x < rad->centre_x + rad->radius; ++x, ++j)
+ {
+ if (rad->affected[i][j])
+ {
+ rad->effect_fun(y, x, rad->pvt);
+ }
+ }
+ }
+ break;
+ default:
+ print_msg("FATAL: attempt to use unimplemented radiance evaluation order %d\n", rad->order);
+ abort();
+ }
+}
+
+Radiance player_fov;
+
+void compute_fov(void)
+{
+ clear_radiance(&player_fov);
+ player_fov.centre_y = u.y;
+ player_fov.centre_x = u.x;
+ player_fov.radius = MAX_FOV_RADIUS;
+ player_fov.order = Reo_ascending;
+ player_fov.exclude_centre = false;
+ player_fov.opaque_fun = dflt_blk;
+ player_fov.effect_fun = mark_explored;
+ player_fov.pvt = NULL;
+ compute_radiance(&player_fov);
+ resolve_radiance(&player_fov);
+}
+/* fov.c */
+// vim:cindent
--- /dev/null
+/*! \file fov.h
+ * \brief field-of-view header
+ */
+
+/* Copyright 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.
+ */
+
+#ifndef FOV_H
+#define FOV_H
+
+#define MAX_FOV_RADIUS 10
+
+/*! \brief Specifies order in which to affect tiles
+ *
+ * Reo_ascending starts from top left and cycles LTR TTB.
+ *
+ * Reo_spiral_out starts from centre and spirals outward.
+ *
+ * Reo_spiral_in starts from top left and spirals inward.
+ */
+enum rad_eval_order {
+ Reo_ascending,
+ Reo_spiral_out,
+ Reo_spiral_in
+};
+
+typedef enum rad_eval_order Rad_eval_order;
+
+struct radiance_data
+{
+ bool affected[MAX_FOV_RADIUS * 2 + 1][MAX_FOV_RADIUS * 2 + 1];
+ int centre_y;
+ int centre_x;
+ int radius;
+ Rad_eval_order order; /*!< What order to iterate through affected squares */
+ bool exclude_centre; /*!< Exclude the centre from being affected. */
+ void *pvt;
+ bool (*opaque_fun)(int y, int x);
+ bool (*effect_fun)(int y, int x, void *pvt);
+};
+
+typedef struct radiance_data Radiance;
+
+extern void clear_radiance(Radiance *rad);
+extern void compute_radiance(Radiance *rad);
+extern void resolve_radiance(Radiance *rad);
+extern void compute_fov(void);
+extern Radiance player_fov;
+
+#endif
+
+/* fov.h */
+// vim:cindent
}
else
{
- print_msg("YOu aren't wearing any armour.\n");
+ print_msg("You aren't wearing any armour.\n");
return 0;
}
return 0;
case SHOW_TERRAIN:
show_terrain = 1;
- map_updated = 1;
- display_update();
+ touch_back_buffer();
+ display_update();
print_msg("Display of monsters and objects suppressed.\n");
press_enter();
show_terrain = 0;
- map_updated = 1;
+ touch_back_buffer();
display_update();
return 0;
case RNG_TEST:
-/* map.c
- *
- * Copyright 2005-2012 Martin Read
+/*! \file map.c
+ * \brief Map generation and population
+ */
+
+/* Copyright 2005-2013 Martin Read
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
*/
#include "victrix-abyssi.h"
-#include "monsters.h"
+#include "fov.h"
#include <string.h>
int mapobject[DUN_HEIGHT][DUN_WIDTH];
enum terrain_num terrain[DUN_HEIGHT][DUN_WIDTH];
int mapflags[DUN_HEIGHT][DUN_WIDTH];
int depth = 1;
+enum level_theme current_theme;
+enum level_layout current_layout;
static int get_levgen_mon_floor(int *y, int *x);
-static void put_stairs(void);
+static void build_level_shrine(void);
+static void build_level_intrusions(void);
+static void build_level_classic(void);
+static int excavation_write(int y, int x, void *data);
+static int intrusion_write(int y, int x, void *data);
void leave_level(void)
{
memset(mapflags, 0, sizeof mapflags);
for (i = 0; i < 100; i++)
{
- /* Throw away each monster */
- monsters[i].used = 0;
- /* and each object not carried by the player */
- if (!objects[i].with_you)
- {
- objects[i].used = 0;
- }
+ /* Throw away each monster */
+ monsters[i].used = 0;
+ /* and each object not carried by the player */
+ if (!objects[i].with_you)
+ {
+ objects[i].used = 0;
+ }
}
depth++;
status_updated = 1;
display_update();
}
-void put_stairs(void)
-{
- int y;
- int x;
- do
- {
- y = exclusive_flat(0, DUN_HEIGHT - 1);
- x = exclusive_flat(0, DUN_WIDTH - 1);
- } while (terrain[y][x] != FLOOR);
- terrain[y][x] = STAIRS;
-}
+typedef int (*rwalk_mod_funcptr)(int y, int x, void *data);
-static void run_random_walk(int oy, int ox, enum terrain_num write, enum terrain_num *overwrite, int overwrite_length, int cells)
+static void run_random_walk(int oy, int ox, rwalk_mod_funcptr func,
+ void *priv_ptr, int cells)
{
int i;
- int j;
int y = oy;
int x = ox;
- for (i = 0; i < cells; )
+ int bailout = 10000;
+
+ for (i = 0; (i < cells) && (bailout > 0); --bailout)
{
+ oy = y;
+ ox = x;
if (zero_die(2))
{
y += (zero_die(2) ? -1 : 1);
- if ((y == 0) || (y == DUN_HEIGHT - 1))
+ if (y == 0)
{
- y = DUN_HEIGHT / 2;
- x = DUN_WIDTH / 2;
+ y = 2;
+ }
+ else if (y == DUN_HEIGHT - 1)
+ {
+ y = DUN_HEIGHT - 3;
}
}
else
x = DUN_WIDTH - 3;
}
}
- for (j = 0; j < overwrite_length; ++j)
+ switch (func(y, x, priv_ptr))
{
- if (terrain[y][x] == overwrite[j])
- {
- ++i;
- terrain[y][x] = write;
- break;
- }
+ case 0:
+ /* nothing changed */
+ break;
+ case 1:
+ /* changed normally */
+ ++i;
+ break;
+ case 2:
+ /* reject! */
+ y = oy;
+ x = ox;
+ break;
}
}
+ if (bailout < 1)
+ {
+ print_msg("Bailed out while excavating level!\n");
+ }
+
}
void build_level(void)
{
- int y = DUN_HEIGHT / 2;
- int x = DUN_WIDTH / 2;
- enum terrain_num pool_flavour = FLOOR;
- int num_pools;
- enum terrain_num overwrite_array[2] = { WALL, FLOOR };
+ int theme_roll = zero_die(depth + 50);
/* Snapshot the running RNG state, so that we can rebuild the map from
* the saved RNG state at game reload. */
memcpy(saved_state, rng_state, sizeof saved_state);
- run_random_walk(y, x, FLOOR, overwrite_array, 1, LEVGEN_WALK_CELLS);
- if ((depth > 20) && !zero_die(4))
+ if (zero_die(7))
+ {
+ current_layout = LAYOUT_CAVE_INTRUSIONS;
+ }
+ else if (depth < 5)
+ {
+ current_layout = LAYOUT_CLASSIC_CAVE;
+ }
+ else if (!zero_die(10) && (depth >= 15))
+ {
+ current_layout = LAYOUT_CAVE_SHRINE;
+ }
+ if ((theme_roll < 50) || (depth < 10))
+ {
+ current_theme = THEME_NORMAL; /* no restrictions */
+ }
+ else if (theme_roll < 60)
+ {
+ current_theme = THEME_UNDEAD;
+ }
+ else if (theme_roll < 80)
+ {
+ current_theme = THEME_DRAGONS;
+ }
+ else if (theme_roll < 90)
+ {
+ current_theme = THEME_DEMONS;
+ }
+ switch (current_layout)
+ {
+ case LAYOUT_CAVE_SHRINE:
+ build_level_shrine();
+ break;
+ case LAYOUT_CAVE_INTRUSIONS:
+ build_level_intrusions();
+ break;
+ case LAYOUT_DUNGEONBASH:
+ /* fall through for now, not that we should get here! */
+ case LAYOUT_CLASSIC_CAVE:
+ build_level_classic();
+ break;
+ }
+}
+
+void build_level_classic(void)
+{
+ int y = DUN_HEIGHT / 2;
+ int x = DUN_WIDTH / 2;
+ int num_pools;
+ int walk_data[4] = { 1, FLOOR, WALL, FLOOR };
+
+ run_random_walk(y, x, excavation_write, walk_data, LEVGEN_WALK_CELLS);
+ run_random_walk(y, x, excavation_write, walk_data, LEVGEN_WALK_CELLS);
+ if ((current_theme != THEME_UNDEAD) && (depth > 20) && !zero_die(4))
{
num_pools = inclusive_flat(1, 4);
- pool_flavour = LAVA;
+ walk_data[0] = 2;
+ walk_data[1] = LAVA;
}
else if ((depth > 10) && !zero_die(3))
{
num_pools = inclusive_flat(1, 4);
- pool_flavour = WATER;
+ walk_data[0] = 2;
+ walk_data[1] = WATER;
}
else
{
{
int pool_size = inclusive_flat(9, 36);
- do
- {
+ do {
y = exclusive_flat(1, DUN_HEIGHT - 2);
x = exclusive_flat(1, DUN_WIDTH - 2);
} while (terrain[y][x] != FLOOR);
- run_random_walk(y, x, pool_flavour, overwrite_array, 2, pool_size);
+ run_random_walk(y, x, excavation_write, walk_data, pool_size);
--num_pools;
}
/* Add the stairs */
- put_stairs();
+ do
+ {
+ y = exclusive_flat(0, DUN_HEIGHT - 1);
+ x = exclusive_flat(0, DUN_WIDTH - 1);
+ } while (terrain[y][x] != FLOOR);
+ terrain[y][x] = STAIRS;
+}
+
+struct shrine shrines[4] =
+{
+ {
+ true,
+ {
+ "...........",
+ ".#########.",
+ ".#.......#.",
+ ".#..._...#.",
+ ".##.....##.",
+ ".+..###..+.",
+ ".##.....##.",
+ ".#..._...#.",
+ ".#.......#.",
+ ".#########.",
+ "...........",
+ },
+ },
+ {
+ true,
+ {
+ "...........",
+ ".LLL###LLL.",
+ ".####L####.",
+ ".#..L_L..#.",
+ ".##.....##.",
+ ".#..###..#.",
+ ".##.....##.",
+ ".#.......#.",
+ ".#.......#.",
+ ".#+#####+#.",
+ "...........",
+ },
+ },
+ {
+ true,
+ {
+ "...........",
+ ".#########.",
+ ".#WW...WW#.",
+ ".#W.._..W#.",
+ ".#..WWW..#.",
+ ".+..WWW..+.",
+ ".#..WWW..#.",
+ ".#W.._..W#.",
+ ".#WW...WW#.",
+ ".#########.",
+ "...........",
+ },
+ },
+ {
+ true,
+ {
+ "...........",
+ ".####+####.",
+ ".#.......#.",
+ ".#.#.#.#.#.",
+ ".#.......#.",
+ ".+.#._.#.+.",
+ ".#.......#.",
+ ".#.#.#.#.#.",
+ ".#.......#.",
+ ".####+####.",
+ "...........",
+ },
+ },
+};
+
+static void build_level_shrine(void)
+{
+ int y = DUN_HEIGHT / 2;
+ int x = DUN_WIDTH / 2;
+ int shrine_ty = inclusive_flat(DUN_HEIGHT / 4, DUN_HEIGHT / 2);
+ int shrine_lx = inclusive_flat(DUN_WIDTH / 4, DUN_WIDTH / 2);
+ int walk_data[4] = { 2, FLOOR, WALL, FLOOR };
+ int i, j;
+ int shrine_num = zero_die(sizeof shrines / sizeof shrines[0]);
+
+ for ((i = 0), (y = shrine_ty); i < SHRINE_HEIGHT; ++i, ++y)
+ {
+ for ((j = 0), (x = shrine_lx); j < SHRINE_WIDTH; ++j, ++x)
+ {
+ switch (shrines[shrine_num].grid[i][j])
+ {
+ case '.':
+ terrain[y][x] = FLOOR;
+ break;
+ case '#':
+ terrain[y][x] = WALL;
+ break;
+ case '+':
+ terrain[y][x] = DOOR;
+ break;
+ case '_':
+ terrain[y][x] = ALTAR;
+ break;
+ }
+ }
+ }
+ run_random_walk(y, x, excavation_write, walk_data, LEVGEN_WALK_CELLS);
+ run_random_walk(y, x, excavation_write, walk_data, LEVGEN_WALK_CELLS);
+ /* and now the stairs, which are not in the shrine */
+ do
+ {
+ y = exclusive_flat(0, DUN_HEIGHT - 1);
+ x = exclusive_flat(0, DUN_WIDTH - 1);
+ } while ((terrain[y][x] != FLOOR) &&
+ (y >= shrine_ty) && (y < shrine_ty + SHRINE_HEIGHT) &&
+ (x >= shrine_lx) && (x < shrine_lx + SHRINE_WIDTH));
+ terrain[y][x] = STAIRS;
+}
+
+static int excavation_write(int y, int x, void *data)
+{
+ const int *data_as_ints = (const int *) data;
+ const int *overwrite = data_as_ints + 2;
+ int newterr = data_as_ints[1];
+ int j;
+ if (mapflags[y][x] & MAPFLAG_HARDWALL)
+ {
+ /* Don't bite into hardened walls, but don't waste a step on
+ * them either. */
+ return 2;
+ }
+ for (j = 0; j < data_as_ints[0]; ++j)
+ {
+ if (terrain[y][x] == overwrite[j])
+ {
+ terrain[y][x] = newterr;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int intrusion_write(int y, int x, void *data)
+{
+ if (terrain[y][x] != WALL)
+ {
+ return 0;
+ }
+ if (mapflags[y][x] & MAPFLAG_HARDWALL)
+ {
+ return 0;
+ }
+ /* Don't intrude too closely on the centre of the level */
+ if ((y > ((DUN_HEIGHT / 2) - 4)) && (y < ((DUN_HEIGHT / 2) - 4)))
+ {
+ return 2;
+ }
+ if ((x > ((DUN_WIDTH / 2) - 4)) && (x < ((DUN_WIDTH / 2) - 4)))
+ {
+ return 2;
+ }
+ mapflags[y][x] |= MAPFLAG_HARDWALL;
+ terrain[y][x] = HARDWALL;
+ return 1;
+}
+
+void build_level_intrusions(void)
+{
+ int y;
+ int x;
+ int i;
+ int intrusion_size;
+ int walk_data[4] = { 1, FLOOR, WALL, FLOOR };
+
+ for (i = 0; i < 6; ++i)
+ {
+ do
+ {
+ if (zero_die(2))
+ {
+ x = inclusive_flat(1, DUN_WIDTH / 3);
+ }
+ else
+ {
+ x = inclusive_flat((2 * DUN_WIDTH) / 3, DUN_WIDTH - 2);
+ }
+ if (zero_die(2))
+ {
+ y = inclusive_flat(1, DUN_HEIGHT / 3);
+ }
+ else
+ {
+ y = inclusive_flat((2 * DUN_HEIGHT) / 3, DUN_HEIGHT - 2);
+ }
+ //print_msg("Trying y %d x %d for intrusion\n", y, x);
+ } while (mapflags[y][x] & MAPFLAG_HARDWALL);
+ intrusion_size = inclusive_flat(27, 54);
+ //print_msg("Building intrusion %d size %d y %d x %d\n", i, intrusion_size, y, x);
+ run_random_walk(y, x, intrusion_write, NULL, intrusion_size);
+ }
+ y = DUN_HEIGHT / 2;
+ x = DUN_WIDTH / 2;
+ run_random_walk(y, x, excavation_write, walk_data, LEVGEN_WALK_CELLS);
+ run_random_walk(y, x, excavation_write, walk_data, LEVGEN_WALK_CELLS);
+ /* and now the stairs */
+ do
+ {
+ y = exclusive_flat(0, DUN_HEIGHT - 1);
+ x = exclusive_flat(0, DUN_WIDTH - 1);
+ } while (terrain[y][x] != FLOOR);
+ terrain[y][x] = STAIRS;
}
int get_levgen_mon_floor(int *y, int *x)
{
- /* Get a vacant floor cell that isn't in the treasure zoo. */
int cell_try;
int ty, tx;
for (cell_try = 0; cell_try < 200; cell_try++)
}
if (ty == -1)
{
- return -1;
+ return -1;
}
*y = ty;
*x = tx;
int j;
int y, x;
int ic;
- /* Check for a "treasure zoo" */
/* Generate some random monsters */
for (i = 0; i < 10; i++)
{
- j = get_levgen_mon_floor(&y, &x);
- if (j == -1)
- {
- continue;
- }
- create_mon(-1, y, x);
+ j = get_levgen_mon_floor(&y, &x);
+ if (j == -1)
+ {
+ continue;
+ }
+ create_mon(-1, y, x);
}
ic = 3 + depth;
if (ic > 40)
{
- /* Never create more than 40 items. */
- ic = 40;
+ /* Never create more than 40 items. */
+ ic = 40;
}
/* Generate some random treasure */
for (i = 0; i < ic; i++)
{
- j = get_levgen_mon_floor(&y, &x);
- if (j == -1)
- {
- continue;
+ j = get_levgen_mon_floor(&y, &x);
+ if (j == -1)
+ {
+ continue;
}
create_obj(-1, 1, 0, y, x);
}
void explore_around(int y, int x)
{
- int y2, x2;
+ /*int y2, x2;*/
+ compute_fov();
+ touch_back_buffer();
+ /*
for (y2 = y - 10; y2 <= y + 10; y2++)
{
- if ((y2 < 0) || (y2 >= DUN_HEIGHT))
- {
- continue;
- }
- for (x2 = x - 10; x2 <= x + 10; x2++)
- {
- if ((x2 < 0) || (x2 >= DUN_WIDTH))
- {
- continue;
- }
- if (!(mapflags[y2][x2] & MAPFLAG_EXPLORED))
- {
- mapflags[y2][x2] |= MAPFLAG_EXPLORED;
- }
- newsym(y2, x2);
- }
+ if ((y2 < 0) || (y2 >= DUN_HEIGHT))
+ {
+ continue;
+ }
+ for (x2 = x - 10; x2 <= x + 10; x2++)
+ {
+ if ((x2 < 0) || (x2 >= DUN_WIDTH))
+ {
+ continue;
+ }
+ if (!(mapflags[y2][x2] & MAPFLAG_EXPLORED))
+ {
+ mapflags[y2][x2] |= MAPFLAG_EXPLORED;
+ }
+ newsym(y2, x2);
+ }
}
+ */
}
/* map.c */
-// vim:cindent
+// vim:cindent:ts=8:sw=4:expandtab
--- /dev/null
+/*! \file map.h
+ * \brief Map-related header
+ */
+
+/* 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.
+ */
+
+#ifndef MAP_H
+#define MAP_H
+
+#ifndef VICTRIX_ABYSSI_H
+#include "victrix-abyssi.h"
+#endif
+
+/* XXX enum terrain_num */
+enum terrain_num {
+ // cheap hack: opaque terrain goes first, and walls very first.
+ WALL = 0, HARDWALL, DOOR, FLOOR, ALTAR, STAIRS, LAVA, WATER
+};
+
+
+#define MAPFLAG_EXPLORED 0x00000001
+#define MAPFLAG_HARDWALL 0x00000002
+enum level_theme {
+ THEME_NORMAL = 0, THEME_DRAGONS, THEME_DEMONS, THEME_UNDEAD
+};
+
+enum level_layout
+{
+ LAYOUT_CLASSIC_CAVE = 0,
+ LAYOUT_CAVE_INTRUSIONS, /* the cave has hardened intrusions */
+ LAYOUT_CAVE_SHRINE, /* the cave contains a shrine */
+ LAYOUT_DUNGEONBASH /* maybe not for this version: dungeonbash-style room grid */
+};
+
+#define LEVGEN_WALK_CELLS 300
+#define DUN_WIDTH 42
+#define DUN_HEIGHT 42
+#define ROOM_HT_DELTA 4
+#define ROOM_WD_DELTA 4
+#define MAX_ROOMS 9
+
+#define SHRINE_HEIGHT 11
+#define SHRINE_WIDTH 11
+
+struct shrine
+{
+ bool used;
+ const char *grid[SHRINE_HEIGHT];
+};
+
+/* XXX map.c data and funcs*/
+extern int mapobject[DUN_HEIGHT][DUN_WIDTH];
+extern int mapmonster[DUN_HEIGHT][DUN_WIDTH];
+extern enum terrain_num terrain[DUN_HEIGHT][DUN_WIDTH];
+extern int mapflags[DUN_HEIGHT][DUN_WIDTH];
+extern int depth;
+extern enum level_theme current_theme;
+extern enum level_layout current_layout;
+
+extern void leave_level(void);
+extern void make_new_level(void);
+extern void build_level(void);
+extern void populate_level(void);
+extern void inject_player(void);
+extern void explore_around(int y, int x);
+
+#endif
+
+/* map.h */
+// vim:cindent:expandtab
/* TODO: Convert missile AI to a new-style AI function. */
#define MON2_C
#include "victrix-abyssi.h"
-#include "bmagic.h"
+#include "sorcery.h"
#include "monsters.h"
#include "combat.h"
}
else if (pmon_is_magician(mptr->mon_id))
{
- special_used = use_black_magic(mon);
+ special_used = mon_use_sorcery(mon);
}
if (!special_used)
{
/* In sight. */
if (pmon_is_magician(mptr->mon_id))
{
- /* Two-thirds of the time, try to use black magic. */
+ /* Two-thirds of the time, try to use sorcery. */
if (zero_die(6) < 4)
{
- special_used = use_black_magic(mon);
+ special_used = mon_use_sorcery(mon);
}
if (special_used)
{
return;
}
- /* Didn't, or couldn't, use black magic; converge
+ /* Didn't, or couldn't, use sorcery; converge
* as if an archer. */
select_space(&y, &x, dy, dx, 1);
}
/* Magicians may have spells that are used when
* you are out of sight. For example, some magicians
* may teleport themselves to your vicinity. */
- special_used = use_black_magic(mon);
+ special_used = mon_use_sorcery(mon);
}
if (special_used)
{
-/* monsters.c
- *
- * Copyright 2005-2012 Martin Read
+/*! \file monsters.c
+ * \brief Monster-related functions
+ */
+
+/* Copyright 2005-2012 Martin Read
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
int mon_can_pass(int mon, int y, int x)
{
+ enum terrain_num terr;
if ((y < 0) || (x < 0) || (y >= DUN_HEIGHT) || (x >= DUN_WIDTH))
{
return 0;
/* Sanity check! */
return 0;
}
- if (monsters[mon].mon_id == PM_WRAITH)
- {
- /* Wraiths can walk through walls. */
- return 1;
- }
- if (terrain[y][x] == WALL)
+ if (mon_is_ethereal(mon))
{
- return 0;
+ return 1;
}
- if ((terrain[y][x] == LAVA) &&
- !pmon_resists_fire(monsters[mon].mon_id))
+ terr = terrain[y][x];
+ switch (terr)
{
+ case WALL:
+ case HARDWALL:
return 0;
+ case LAVA:
+ if (!mon_can_fly(mon) && !mon_resists_fire(mon))
+ {
+ return 0;
+ }
+ break;
+ case WATER:
+ if (!mon_can_fly(mon) && !mon_resists_drowning(mon))
+ {
+ return 0;
+ }
+ default:
+ break;
}
- if (terrain[y][x] == WATER)
+ if ((terrain[y][x] == WATER) && !mon_resists_drowning(mon))
{
return 0;
}
if (permons[monsters[mon].mon_id].name[0] == '\0')
{
print_msg("GROB THE VOID (%d)", monsters[mon].mon_id);
+ return;
}
switch (article)
{
}
if (success)
{
- move_mon(mon, y, x);
+ reloc_mon(mon, y, x);
print_mon_name(mon, 2);
print_msg(" appears in a puff of smoke.\n");
return 1;
x = exclusive_flat(0, DUN_WIDTH - 1);
if ((mapmonster[y][x] == -1) && (terrain[y][x] == FLOOR) && ((y != u.y) || (x != u.x)))
{
- move_mon(mon, y, x);
+ reloc_mon(mon, y, x);
rval = 0;
break;
}
return rval;
}
+int knockback_mon(int mon, int sy, int sx, bool cansee, bool by_you)
+{
+ /* 0 = blocked, 1 = knocked, 2 = killed */
+ struct mon *mptr = monsters + mon;
+ int y = mptr->y + sy;
+ int x = mptr->x + sx;
+ enum terrain_num terr = terrain[y][x];
+
+ if (mon_resists_knockback(mon))
+ {
+ if (cansee)
+ {
+ print_mon_name(mon, 3);
+ print_msg(" wobbles slightly.\n");
+ }
+ return 0;
+ }
+ switch (terr)
+ {
+ case WALL:
+ case HARDWALL:
+ return 0;
+ case LAVA:
+ if (cansee)
+ {
+ print_mon_name(mon, 3);
+ print_msg(" tumbles into a pool of molten rock.\n");
+ }
+ if (!mon_resists_fire(mon))
+ {
+ damage_mon(mon, 9999, by_you);
+ return 2;
+ }
+ break;
+ case WATER:
+ if (cansee)
+ {
+ print_mon_name(mon, 3);
+ print_msg(" tumbles into the water.\n");
+ }
+ if (!mon_resists_drowning(mon))
+ {
+ damage_mon(mon, 9999, by_you);
+ return 2;
+ }
+ break;
+ default:
+ break;
+ }
+ reloc_mon(mon, mptr->y + sy, mptr->x + sx);
+ return 1;
+}
+
+void reloc_mon(int mon, int y, int x)
+{
+ struct mon *mptr = monsters + mon;
+ mapmonster[mptr->y][mptr->x] = -1;
+ newsym(mptr->y, mptr->x);
+ mptr->y = y;
+ mptr->x = x;
+ mapmonster[mptr->y][mptr->x] = mon;
+ newsym(mptr->y, mptr->x);
+}
+
void move_mon(int mon, int y, int x)
{
struct mon *mptr;
press_enter();
return;
}
- mapmonster[mptr->y][mptr->x] = -1;
- newsym(mptr->y, mptr->x);
- mptr->y = y;
- mptr->x = x;
- mapmonster[mptr->y][mptr->x] = mon;
- newsym(mptr->y, mptr->x);
+ reloc_mon(mon, y, x);
display_update();
}
{
return 0;
}
- dy = u.y - monsters[mon].y;
- dx = u.x - monsters[mon].x;
+ dy = monsters[mon].y - u.y;
+ dx = monsters[mon].x - u.x;
/* Cave Chop FoV: The screen. */
if (((dy > -11) && (dy < 11) && (dx > -11) && (dx < 11)))
{
- return 1;
+ return player_fov.affected[MAX_FOV_RADIUS + dy][MAX_FOV_RADIUS + dx];
}
else
{
}
}
+bool mon_resists_cold(int mon)
+{
+ return pmon_resists_cold(monsters[mon].mon_id);
+}
+
+bool mon_resists_fire(int mon)
+{
+ return pmon_resists_fire(monsters[mon].mon_id);
+}
+
+bool mon_resists_poison(int mon)
+{
+ return pmon_resists_poison(monsters[mon].mon_id);
+}
+
+bool mon_resists_necro(int mon)
+{
+ return pmon_resists_necro(monsters[mon].mon_id);
+}
+
+bool mon_resists_elec(int mon)
+{
+ return pmon_resists_elec(monsters[mon].mon_id);
+}
+
+bool mon_can_fly(int mon)
+{
+ return pmon_can_fly(monsters[mon].mon_id);
+}
+
+bool mon_is_ethereal(int mon)
+{
+ return pmon_is_ethereal(monsters[mon].mon_id);
+}
+
+bool mon_resists_drowning(int mon)
+{
+ return pmon_resists_drowning(monsters[mon].mon_id);
+}
+
+bool mon_resists_knockback(int mon)
+{
+ return pmon_resists_knockback(monsters[mon].mon_id);
+}
/* monsters.c */
// vim:cindent
-/* monsters.h
- *
- * Copyright 2005-2012 Martin Read
+/*! \file monsters.h
+ * \brief Monster-related header
+ */
+
+/* Copyright 2005-2013 Martin Read
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#include "victrix-abyssi.h"
#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)
+
+#define PMF_RESIST_FIRE 0x00000001
+#define PMF_RESIST_COLD 0x00000002
+#define PMF_RESIST_ELEC 0x00000004
+#define PMF_RESIST_POIS 0x00000008
+#define PMF_RESIST_NECR 0x00000010
+#define PMF_RESIST_SLAM 0x00000020
+#define PMF_RESIST_DRWN 0x00000040
+#define PMF_UNDEAD 0x00010000
+#define PMF_DEMONIC 0x00020000
+#define PMF_MAGICIAN 0x00040000
+#define PMF_ARCHER 0x00080000
+#define PMF_SMART 0x00100000
+#define PMF_STUPID 0x00200000
+#define PMF_ETHEREAL 0x00400000
+#define PMF_FLYING 0x00800000
+
+struct permon {
+ const char name[48];
+ const char plural[48];
+ char sym;
+ int colour;
+ int rarity; /* Chance in 100 of being thrown back and regen'd. */
+ int power; /* Used to determine OOD rating. */
+ /* All OOD-improved stats cap out at base + (power * base) */
+ int hp; /* Improved by OOD rating at 1:1. */
+ int mtohit; /* Improved by OOD rating at 1:3. */
+ int rtohit; /* Improved by OOD rating at 1:3. */
+ int mdam; /* Improved by OOD rating at 1:5. */
+ int rdam; /* Improved by OOD rating at 1:5. */
+ enum damtyp rdtyp; /* type of damage used by ranged attack. */
+ const char shootverb[48]; /* 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. */
+};
+extern struct permon permons[NUM_OF_PERMONS];
+
+/* XXX struct mon */
+#define MONSTERS_IN_PLAY 100
+struct mon {
+ int mon_id;
+ int y;
+ int x;
+ int ai_lasty; /* AI's belief about your last position. -1 == lost you. */
+ int ai_lastx; /* AI's belief about your last position. -1 == lost you. */
+ int used;
+ int hpmax; /* Improved by OOD rating at 1:1. */
+ int hpcur; /* <= 0 is dead. */
+ int mtohit; /* Improved by OOD rating at 1:3. */
+ int rtohit; /* Improved by OOD rating at 1:3. */
+ int defence; /* Improved by OOD rating at 1:3. */
+ int mdam; /* Improved by OOD rating at 1:5. */
+ int rdam; /* Improved by OOD rating at 1:5. */
+ int awake;
+ int next_summon;
+};
+extern struct mon monsters[MONSTERS_IN_PLAY];
+
/* XXX monsters.c data and funcs */
extern void update_mon(int mon);
extern void mon_acts(int mon);
extern void damage_mon(int mon, int amount, int by_you);
extern int mon_can_pass(int mon, int y, int x);
extern int mon_visible(int mon);
+extern int knockback_mon(int mon, int sy, int sx, bool cansee, bool by_you);
extern void move_mon(int mon, int y, int x);
-extern int teleport_mon(int mon); /* Randomly relocate monster. */
-extern int teleport_mon_to_you(int mon); /* Relocate monster to your vicinity. */
+extern void reloc_mon(int mon, int y, int x);
+extern int teleport_mon(int mon); /* Randomly relocate monster. */
+extern int teleport_mon_to_you(int mon); /* Relocate monster to your vicinity. */
extern void heal_mon(int mon, int amount, int cansee);
+extern bool mon_resists_cold(int mon);
+extern bool mon_resists_fire(int mon);
+extern bool mon_resists_poison(int mon);
+extern bool mon_resists_necro(int mon);
+extern bool mon_resists_elec(int mon);
+extern bool mon_resists_drowning(int mon);
+extern bool mon_can_fly(int mon);
+extern bool mon_is_ethereal(int mon);
+extern bool mon_resists_knockback(int mon);
/* XXX mon2.c data and funcs */
extern void select_space(int *py, int *px, int dy, int dx, int selection_mode);
extern bool pmon_resists_poison(int pm);
extern bool pmon_resists_necro(int pm);
extern bool pmon_resists_elec(int pm);
+extern bool pmon_resists_drowning(int pm);
+extern bool pmon_can_fly(int pm);
+extern bool pmon_is_ethereal(int pm);
+extern bool pmon_resists_knockback(int pm);
#endif
/* monsters.h */
-// vim:cindent
+// vim:cindent:expandtab
--------------
Welcome to the Abyss, Princess.
-Your younger brother, a bastard in every sense, has deprived you of your
-rightful inheritance and condemned you to these inescapable caverns, in the
-expectation that you will either starve or be devoured.
+Your younger brother, a bastard in every sense of the word, has deprived you of
+your rightful inheritance and condemned you to these inescapable caverns, in
+the expectation that you will either starve or be devoured.
You have a dagger, a token supply of food, your favorite armoured dress, and no
-intention of obliging him.
+intention of obliging him. There is power to be had here.
Discussion of Victrix Abyssi is on-topic for the newsgroup
rec.games.roguelike.misc ; please put -victrix-abyssi- in the Subject: header
--- /dev/null
+/*! \file objects.h
+ * \brief object-related header 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.
+ */
+
+#ifndef OBJECTS_H
+#define OBJECTS_H
+
+/* XXX enum poclass_num */
+/* Categories of permanent object. */
+enum poclass_num {
+ POCLASS_NONE = 0, POCLASS_WEAPON, POCLASS_POTION,
+ POCLASS_SCROLL, POCLASS_FLASK, POCLASS_ARMOUR, POCLASS_RING,
+ POCLASS_FOOD
+};
+
+/* XXX enum Permobj_nums */
+enum Permobj_nums
+{
+ // weapons
+ PO_DAGGER=0, PO_LONG_SWORD, PO_MACE, PO_RUNESWORD, PO_BOW, PO_CROSSBOW,
+ PO_THUNDERBOW, PO_TORMENTORS_LASH, PO_STAFF_OF_FIRE,
+ // potions
+ PO_POT_HEAL, PO_POT_BODY, PO_POT_AGILITY, PO_POT_RESTORATION,
+ // flasks
+ PO_FLASK_POISON, PO_FLASK_FIRE, PO_FLASK_WEAKNESS,
+ // scrolls
+ PO_SCR_TELEPORT, PO_SCR_FIRE, PO_SCR_PROTECTION,
+ // armour
+ PO_LEATHER_ARMOUR, PO_CHAINMAIL, PO_PLATE_ARMOUR, PO_MAGE_ARMOUR, PO_ROBE,
+ PO_ROBE_SWIFTNESS, PO_ROBE_SHADOWS, PO_DRAGON_ARMOUR, PO_METEOR_ARMOUR,
+ PO_SACRED_MAIL, PO_RAGGED_SHIFT, PO_BATTLE_BALLGOWN, PO_IMPERATRIX_GOWN,
+ PO_RIBBONS,
+ // rings
+ PO_RING_REGEN, PO_RING_FIRE, PO_RING_VAMPIRE, PO_RING_FROST,
+ PO_RING_TELEPORT,
+ // food
+ PO_IRON_RATION, PO_DRIED_FRUIT, PO_ELVEN_BREAD, PO_DEVIL_SPLEEN
+};
+
+#define PO_FIRST_WEAPON PO_DAGGER
+#define PO_LAST_WEAPON PO_STAFF_OF_FIRE
+#define PO_FIRST_POTION PO_POT_HEAL
+#define PO_LAST_POTION PO_POT_RESTORATION
+#define PO_FIRST_FLASK PO_FLASK_POISON
+#define PO_LAST_FLASK PO_FLASK_WEAKNESS
+#define PO_FIRST_SCROLL PO_SCR_TELEPORT
+#define PO_LAST_SCROLL PO_SCR_PROTECTION
+#define PO_FIRST_ARMOUR PO_LEATHER_ARMOUR
+#define PO_LAST_ARMOUR PO_RIBBONS
+#define PO_FIRST_RING PO_RING_REGEN
+#define PO_LAST_RING PO_RING_TELEPORT
+#define PO_FIRST_FOOD PO_IRON_RATION
+#define PO_LAST_FOOD PO_DEVIL_SPLEEN
+#define NUM_OF_PERMOBJS ((PO_LAST_FOOD) + 1)
+
+/* XXX struct permobj */
+struct permobj {
+ const char name[48];
+ const char plural[48];
+ const char *description;
+ enum poclass_num poclass;
+ int rarity; /* Chance in 100 of being thrown away and regen'd. */
+ int sym;
+ int power; /* AC for armour; damage for weapons; colour/title for
+ * scrolls and potions and rings and such. */
+ int used; /* Set to 1 for valid entries. */
+ int depth; /* If greater than 1, this item cannot be given out
+ * by get_random_pobj() before the specified depth. */
+};
+extern struct permobj permobjs[NUM_OF_PERMOBJS];
+
+/* XXX struct obj */
+#define OBJ_MAX_DUR 100
+#define OBJECTS_IN_PLAY 100
+struct obj {
+ int obj_id;
+ int quan;
+ int with_you; /* Preserved when item DB is reaped on level change. */
+ int y;
+ int x;
+ int used; /* Entry is occupied. */
+ int durability; /* Weapons and armour degrade with use. */
+};
+extern struct obj objects[OBJECTS_IN_PLAY];
+
+/* XXX objects.c data and funcs */
+extern void flavours_init(void);
+extern void sprint_obj_name(char *s, int obj, int len);
+extern void fprint_obj_name(FILE *fp, int obj);
+extern void print_obj_name(int obj);
+extern void describe_object(int obj);
+extern int create_obj(int po_idx, int quantity, int with_you, int y, int x);
+extern int drop_obj(int inv_idx);
+extern int consume_obj(int obj);
+extern int create_obj_class(enum poclass_num pocl, int quantity, int with_you, int y, int x);
+extern int create_obj_random(int y, int x);
+extern int read_scroll(int obj);
+
+#endif
+
+/* objects.h */
+// vim:cindent
{
"crossbow", "crossbows", "A crossbow.", POCLASS_WEAPON, 70, '(', 16, 1, 6
},
+ [PO_THUNDERBOW] =
+ {
+ "thunderbow", "thunderbows", "A recurve composite bow decorated with eldritch signs.\nArrows fired with this bow strike with staggering force.", POCLASS_WEAPON, 70, '(', 16, 1, 30
+ },
[PO_TORMENTORS_LASH] =
{
"tormentor's lash", "tormentor's lash", "A bone-handled whip that crackles with malefic energies.", POCLASS_WEAPON, 80, ')', 20, 1, 30
{
"sacred chainmail", "suits of sacred chainmail", "This suit of interlocking rings has been consecrated to\nthe gods of the Light.", POCLASS_ARMOUR, 90, '[', 15, 1, 24
},
+ [PO_RAGGED_SHIFT] =
+ {
+ "ragged shift", "ragged shifts", "This sorry-looking collection of rags is all that remains\nof a battle ballgown.", POCLASS_ARMOUR, 100, '[', 1, 0, 1
+ },
[PO_BATTLE_BALLGOWN] =
{
- "battle ballgown", "battle ballgowns", "This lightly armoured dress is a beloved heirloom of\nyour house.", POCLASS_ARMOUR, 100, '[', 3, 1, 1
+ "battle ballgown", "battle ballgowns", "Partially armoured dresses such as this are a\ntraditional part of a princess's wardrobe.", POCLASS_ARMOUR, 95, '[', 3, 1, 1
+ },
+ [PO_IMPERATRIX_GOWN] =
+ {
+ "imperatrix gown", "imperatrix gowns", "This armoured, enchanted, and elaborately decorated dress\nwould be worthy of an empress regnant.", POCLASS_ARMOUR, 95, '[', 15, 1, 24
},
[PO_RIBBONS] =
{
/* inspired by DoomRL's Necroarmor and my own creepiness. */
- "set of ribbons", "sets of ribbons", "These ribbons, arranged as if to form an alleged\ngarment, make your fingers tingle with magic.", POCLASS_ARMOUR, 90, '[', 15, 1, 27
+ "set of ribbons", "sets of ribbons", "These ribbons, arranged as if to form an alleged\ngarment, make your fingers tingle with magic.", POCLASS_ARMOUR, 90, '[', 15, 1, 30
},
[PO_RING_REGEN] =
{
-/* permons.c
- *
- * Copyright 2005-2012 Martin Read
+/*! \file permons.c
+ * \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
#define PERMONS_C
#include "victrix-abyssi.h"
+/*! \brief Array housing the monster database.
+ */
struct permon permons[NUM_OF_PERMONS] = {
[PM_NEWT] =
{
},
[PM_WIZARD] =
{
- /* Uses black magic against you; see bmagic.c for details. */
+ /* Uses sorcery against you; see sorcery.c for details. */
"wizard", "wizards", 'w', DBCLR_BLUE, 80, 12, 40, 10, 20, 10, 10, DT_ELEC, "casts", 15, 200, 1, PMF_SMART | PMF_MAGICIAN
},
[PM_ARCHMAGE] =
{
- /* Uses black magic against you; see bmagic.c for details. */
+ /* Uses sorcery against you; see sorcery.c for details. */
"archmage", "archmagi", 'w', DBCLR_L_BLUE, 80, 24, 80, 15, 30, 15, 15, DT_ELEC, "casts", 15, 1500, 1, PMF_SMART | PMF_MAGICIAN | PMF_RESIST_ELEC
},
[PM_ZOMBIE] =
},
[PM_LICH] =
{
- /* Uses black magic against you; see bmagic.c for details. */
+ /* Uses sorcery against you; see sorcery.c for details. */
"lich", "liches", 'L', DBCLR_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
},
- [PM_VAMPIRE] =
- {
- /* Vampires heal by hitting you. */
- "vampire", "vampires", 'V', DBCLR_RED, 55, 18, 70, 25, -1, 15, -1, DT_PHYS, "", 22, 750, 1, PMF_SMART | PMF_UNDEAD | PMF_RESIST_COLD | PMF_RESIST_POIS | PMF_RESIST_NECR
- },
[PM_MASTER_LICH] =
{
- /* Master liches use black magic against you, more powerfully
+ /* Master liches use sorcery against you, more powerfully
* than lesser practitioners. */
"master lich", "master liches", 'L', DBCLR_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
},
+ [PM_VAMPIRE] =
+ {
+ /* Vampires heal by hitting you. */
+ "vampire", "vampires", 'V', DBCLR_RED, 55, 18, 70, 25, -1, 15, -1, DT_PHYS, "", 22, 750, 1, PMF_SMART | PMF_UNDEAD | PMF_RESIST_COLD | PMF_RESIST_POIS | PMF_RESIST_NECR
+ },
[PM_DEMON] =
{
/* Demons summon more demons if you don't kill them
},
[PM_DEFILER] =
{
- /* Defilers use black magic against you. */
+ /* Defilers use sorcery (mostly curses) against you. */
"defiler", "defilers", '&', DBCLR_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
},
[PM_CENTAUR] =
/* Breathes fire. */
"dragon", "dragons", 'D', DBCLR_RED, 50, 15, 80, 20, 20, 20, 20, DT_FIRE, "breathes", 18, 300, 1, PMF_RESIST_FIRE | PMF_ARCHER
},
+ [PM_MOONDRAKE] =
+ {
+ /* Breathes eldritchness. */
+ "moondrake", "moondrakes", 'D', DBCLR_L_CYAN, 50, 15, 80, 20, 20, 20, 20, DT_FIRE, "breathes", 24, 500, 1, PMF_RESIST_FIRE | PMF_RESIST_COLD | PMF_RESIST_NECR | PMF_ARCHER
+ },
};
/* permons.c */
-/* pmon2.c
- *
- * Copyright 2005-2012 Martin Read
+/*! \file pmon2.c
+ * \brief permons flag-check functions
+ */
+
+/* Copyright 2005-2013 Martin Read
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
bool pmon_resists_fire(int pm)
{
- return !!(permons[pm].flags & PMF_RESIST_FIRE);
+ return !!(permons[pm].flags & PMF_RESIST_FIRE);
}
bool pmon_resists_cold(int pm)
{
- return !!(permons[pm].flags & PMF_RESIST_COLD);
+ return !!(permons[pm].flags & PMF_RESIST_COLD);
}
bool pmon_resists_poison(int pm)
{
- return !!(permons[pm].flags & PMF_RESIST_POIS);
+ return !!(permons[pm].flags & PMF_RESIST_POIS);
}
bool pmon_resists_necro(int pm)
{
- return !!(permons[pm].flags & PMF_RESIST_NECR);
+ return !!(permons[pm].flags & PMF_RESIST_NECR);
}
bool pmon_resists_elec(int pm)
{
- return !!(permons[pm].flags & PMF_RESIST_ELEC);
+ return !!(permons[pm].flags & PMF_RESIST_ELEC);
+}
+
+bool pmon_resists_knockback(int pm)
+{
+ return !!(permons[pm].flags & PMF_RESIST_SLAM);
+}
+
+bool pmon_resists_drowning(int pm)
+{
+ return !!(permons[pm].flags & PMF_RESIST_DRWN);
}
bool pmon_is_undead(int pm)
{
- return !!(permons[pm].flags & PMF_UNDEAD);
+ return !!(permons[pm].flags & PMF_UNDEAD);
}
bool pmon_is_stupid(int pm)
{
- return !!(permons[pm].flags & PMF_STUPID);
+ return !!(permons[pm].flags & PMF_STUPID);
}
bool pmon_is_smart(int pm)
{
- return !!(permons[pm].flags & PMF_SMART);
+ return !!(permons[pm].flags & PMF_SMART);
}
bool pmon_is_magician(int pm)
{
- return !!(permons[pm].flags & PMF_MAGICIAN);
+ return !!(permons[pm].flags & PMF_MAGICIAN);
}
bool pmon_is_archer(int pm)
{
- return !!(permons[pm].flags & PMF_ARCHER);
+ return !!(permons[pm].flags & PMF_ARCHER);
+}
+
+bool pmon_can_fly(int pm)
+{
+ return !!(permons[pm].flags & PMF_FLYING);
+}
+
+bool pmon_is_ethereal(int pm)
+{
+ return !!(permons[pm].flags & PMF_ETHEREAL);
}
/* pmon2.c */
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "victrix-abyssi.h"
-#include "bmagic.h"
+#include "sorcery.h"
#include "monsters.h"
#include "combat.h"
print_msg(" points at you and curses horribly.\n");
}
-/* bmagic.c */
+/* sorcery.c */
// vim:cindent
switch (terrain[u.y + dy][u.x + dx])
{
case WALL:
+ case HARDWALL:
print_msg("You cannot go there.\n");
return 0;
case FLOOR:
case DOOR:
case STAIRS:
+ case ALTAR:
reloc_player(u.y + dy, u.x + dx);
return 1;
case LAVA:
explore_around(u.y, u.x);
map_updated = 1;
status_updated = 1;
+ display_update();
if (mapobject[y][x] != -1)
{
print_msg("You see here ");
print_obj_name(mapobject[y][x]);
print_msg(".\n");
}
- display_update();
return 0;
}
-/* victrix-abyssi.h
- *
- * Copyright 2005-2013 Martin Read
+/*! \file victrix-abyssi.h
+ * \brief Main header 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
WIZARD_LEVELUP, WIZARD_DESCEND
};
-/* XXX enum terrain_num */
-enum terrain_num {
- WALL = 0, FLOOR, DOOR, STAIRS, LAVA, WATER
-};
-
/* XXX enum death */
/* Sadly, there are not 52 kinds of way to die. */
enum death {
DEATH_LASH, DEATH_RIBBONS
};
-/* XXX enum poclass_num */
-/* Categories of permanent object. */
-enum poclass_num {
- POCLASS_NONE = 0, POCLASS_WEAPON, POCLASS_POTION,
- POCLASS_SCROLL, POCLASS_FLASK, POCLASS_ARMOUR, POCLASS_RING,
- POCLASS_FOOD
-};
-
-#define RESIST_MASK_TEMPORARY 0x0000FFFFu
-#define RESIST_MASK_PERM_EQUIP 0xFFFF0000u
-#define RESIST_RING 0x00010000u
-#define RESIST_ARMOUR 0x00020000u
+#define RESIST_MASK_TEMPORARY 0x0000FFFFu
+#define RESIST_MASK_PERM_EQUIP 0xFFFF0000u
+#define RESIST_RING 0x00010000u
+#define RESIST_ARMOUR 0x00020000u
/* XXX STRUCTURES XXX */
/* XXX struct player */
struct player {
- char name[17]; /* including '\0' the fencepost. */
- int y; /* y-coord */
- int x; /* x-coord */
- int body; /* determines mace to-hit, melee damage, max 99 */
- int bdam; /* current level of temporary body drain. */
- int agility; /* determines sword, dagger, missile to-hit, max 99 */
- int adam; /* current level of temporary agility drain. */
- int hpmax; /* Max hit points; max of 999. */
- int hpcur; /* Current hit points; <= 0 is dead. */
- int food; /* Current nutrition in body; < 0 is hungry. */
- int experience; /* Experience points earned. */
- int defence; /* To-hit target number for monsters */
- int protection; /* Temporary protection from cursing */
- int leadfoot; /* Feet-of-lead curse */
- int withering; /* Vile withering curse */
- int armourmelt; /* Armour-like-dust curse */
+ char name[17]; /* including '\0' the fencepost. */
+ int y; /* y-coord */
+ int x; /* x-coord */
+ int body; /* determines mace to-hit, melee damage, max 99 */
+ int bdam; /* current level of temporary body drain. */
+ int agility; /* determines sword, dagger, missile to-hit, max 99 */
+ int adam; /* current level of temporary agility drain. */
+ int hpmax; /* Max hit points; max of 999. */
+ int hpcur; /* Current hit points; <= 0 is dead. */
+ int food; /* Current nutrition in body; < 0 is hungry. */
+ int experience; /* Experience points earned. */
+ int defence; /* To-hit target number for monsters */
+ int protection; /* Temporary protection from cursing */
+ int leadfoot; /* Feet-of-lead curse */
+ int withering; /* Vile withering curse */
+ int armourmelt; /* Armour-like-dust curse */
int speed;
- uint32_t resistances[DT_COUNT]; /* Resistances to damage types. */
- int level; /* Each level gets you +1 body, +1 agility, +1 random
- point, and +(10+body/10) hit points */
- int inventory[19]; /* 19 inventory slots, leaving room for a prompt */
- int weapon; /* For now, you can only wield one weapon. */
- int armour; /* For now, you can only wear one item of armour. */
- int ring; /* For now, you can only wear one magic ring. */
-};
-
-#define DBCLR_L_GREY 0
-#define DBCLR_D_GREY 1
-#define DBCLR_RED 2
-#define DBCLR_BLUE 3
-#define DBCLR_GREEN 4
-#define DBCLR_PURPLE 5
-#define DBCLR_BROWN 6
-#define DBCLR_CYAN 7
-#define DBCLR_WHITE 8
-#define DBCLR_L_RED 9
-#define DBCLR_L_BLUE 10
-#define DBCLR_L_GREEN 11
-#define DBCLR_L_PURPLE 12
-#define DBCLR_YELLOW 13
-#define DBCLR_L_CYAN 14
-
-/* 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_VAMPIRE, PM_MASTER_LICH, PM_DEMON, PM_DEFILER, PM_ICE_MONSTER,
- PM_CENTAUR, PM_DRAGON
-};
-#define NUM_OF_PERMONS (1 + PM_DRAGON)
-
-#define PMF_RESIST_FIRE 0x00000001
-#define PMF_RESIST_COLD 0x00000002
-#define PMF_RESIST_ELEC 0x00000004
-#define PMF_RESIST_POIS 0x00000008
-#define PMF_RESIST_NECR 0x00000010
-#define PMF_UNDEAD 0x00010000
-#define PMF_DEMONIC 0x00020000
-#define PMF_MAGICIAN 0x00040000
-#define PMF_ARCHER 0x00080000
-#define PMF_SMART 0x00100000
-#define PMF_STUPID 0x00200000
-
-struct permon {
- const char name[48];
- const char plural[48];
- char sym;
- int colour;
- int rarity; /* Chance in 100 of being thrown back and regen'd. */
- int power; /* Used to determine OOD rating. */
- /* All OOD-improved stats cap out at base + (power * base) */
- int hp; /* Improved by OOD rating at 1:1. */
- int mtohit; /* Improved by OOD rating at 1:3. */
- int rtohit; /* Improved by OOD rating at 1:3. */
- int mdam; /* Improved by OOD rating at 1:5. */
- int rdam; /* Improved by OOD rating at 1:5. */
- enum damtyp rdtyp; /* type of damage used by ranged attack. */
- const char shootverb[48]; /* 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 resistances[DT_COUNT]; /* Resistances to damage types. */
+ int level; /* Each level gets you +1 body, +1 agility, +1 random
+ point, and +(10+body/10) hit points */
+ int inventory[19]; /* 19 inventory slots, leaving room for a prompt */
+ int weapon; /* For now, you can only wield one weapon. */
+ int armour; /* For now, you can only wear one item of armour. */
+ int ring; /* For now, you can only wear one magic ring. */
};
-extern struct permon permons[NUM_OF_PERMONS];
-/* XXX struct permobj */
-enum Permobj_nums
-{
- // weapons
- PO_DAGGER=0, PO_LONG_SWORD, PO_MACE, PO_RUNESWORD, PO_BOW, PO_CROSSBOW,
- PO_TORMENTORS_LASH, PO_STAFF_OF_FIRE,
- // potions
- PO_POT_HEAL, PO_POT_BODY, PO_POT_AGILITY, PO_POT_RESTORATION,
- // flasks
- PO_FLASK_POISON, PO_FLASK_FIRE, PO_FLASK_WEAKNESS,
- // scrolls
- PO_SCR_TELEPORT, PO_SCR_FIRE, PO_SCR_PROTECTION,
- // armour
- PO_LEATHER_ARMOUR, PO_CHAINMAIL, PO_PLATE_ARMOUR, PO_MAGE_ARMOUR, PO_ROBE,
- PO_ROBE_SWIFTNESS, PO_ROBE_SHADOWS, PO_DRAGON_ARMOUR, PO_METEOR_ARMOUR,
- PO_SACRED_MAIL, PO_BATTLE_BALLGOWN, PO_RIBBONS,
- // rings
- PO_RING_REGEN, PO_RING_FIRE, PO_RING_VAMPIRE, PO_RING_FROST,
- PO_RING_TELEPORT,
- // food
- PO_IRON_RATION, PO_DRIED_FRUIT, PO_ELVEN_BREAD, PO_DEVIL_SPLEEN
-};
-#define PO_FIRST_WEAPON PO_DAGGER
-#define PO_LAST_WEAPON PO_STAFF_OF_FIRE
-#define PO_FIRST_POTION PO_POT_HEAL
-#define PO_LAST_POTION PO_POT_RESTORATION
-#define PO_FIRST_FLASK PO_FLASK_POISON
-#define PO_LAST_FLASK PO_FLASK_WEAKNESS
-#define PO_FIRST_SCROLL PO_SCR_TELEPORT
-#define PO_LAST_SCROLL PO_SCR_PROTECTION
-#define PO_FIRST_ARMOUR PO_LEATHER_ARMOUR
-#define PO_LAST_ARMOUR PO_RIBBONS
-#define PO_FIRST_RING PO_RING_REGEN
-#define PO_LAST_RING PO_RING_TELEPORT
-#define PO_FIRST_FOOD PO_IRON_RATION
-#define PO_LAST_FOOD PO_DEVIL_SPLEEN
-#define NUM_OF_PERMOBJS ((PO_LAST_FOOD) + 1)
-
-struct permobj {
- const char name[48];
- const char plural[48];
- const char *description;
- enum poclass_num poclass;
- int rarity; /* Chance in 100 of being thrown away and regen'd. */
- int sym;
- int power; /* AC for armour; damage for weapons; colour/title for
- * scrolls and potions and rings and such. */
- int used; /* Set to 1 for valid entries. */
- int depth; /* If greater than 1, this item cannot be given out
- * by get_random_pobj() before the specified depth. */
-};
-extern struct permobj permobjs[NUM_OF_PERMOBJS];
+#ifndef MONSTERS_H
+#include "monsters.h"
+#endif
-/* XXX struct mon */
-#define MONSTERS_IN_PLAY 100
-struct mon {
- int mon_id;
- int y;
- int x;
- int ai_lasty; /* AI's belief about your last position. -1 == lost you. */
- int ai_lastx; /* AI's belief about your last position. -1 == lost you. */
- int used;
- int hpmax; /* Improved by OOD rating at 1:1. */
- int hpcur; /* <= 0 is dead. */
- int mtohit; /* Improved by OOD rating at 1:3. */
- int rtohit; /* Improved by OOD rating at 1:3. */
- int defence; /* Improved by OOD rating at 1:3. */
- int mdam; /* Improved by OOD rating at 1:5. */
- int rdam; /* Improved by OOD rating at 1:5. */
- int awake;
- int next_summon;
-};
-extern struct mon monsters[MONSTERS_IN_PLAY];
+#ifndef OBJECTS_H
+#include "objects.h"
+#endif
-/* XXX struct obj */
-#define OBJ_MAX_DUR 100
-#define OBJECTS_IN_PLAY 100
-struct obj {
- int obj_id;
- int quan;
- int with_you; /* Preserved when item DB is reaped on level change. */
- int y;
- int x;
- int used; /* Entry is occupied. */
- int durability; /* Weapons and armour degrade with use. */
-};
-extern struct obj objects[OBJECTS_IN_PLAY];
+#ifndef DISPLAY_H
+#include "display.h"
+#endif
-/* XXX display.c data and funcs */
-extern int read_input(char *buffer, int length);
-extern void print_msg(const char *fmt, ...);
-extern void print_help(void);
-extern int display_init(void);
-extern void display_update(void);
-extern int display_shutdown(void);
-extern void newsym(int y, int x);
-extern void touch_back_buffer(void);
-extern int inv_select(enum poclass_num filter, const char *action, int accept_blank);
-extern enum game_cmd get_command(void);
-extern int select_dir(int *psy, int *psx);
-extern int getYN(const char *msg);
-extern int getyn(const char *msg);
-extern void press_enter(void);
-extern void pressanykey(void);
-extern void show_discoveries(void);
-extern void touch_one_screen(int y, int x);
+#ifndef MAP_H
+#include "map.h"
+#endif
-/* "I've changed things that need to be redisplayed" flags. */
-extern int hard_redraw;
-extern int status_updated;
-extern int map_updated;
-/* "Show the player the terrain only" flag. */
-extern int show_terrain;
+#ifndef FOV_H
+#include "fov.h"
+#endif
/* XXX main.c data and funcs */
extern int exclusive_flat(int lower, int upper); /* l+1 ... u-1 */
extern int inclusive_flat(int lower, int upper); /* l ... u */
-extern int one_die(int sides); /* 1..n */
+extern int one_die(int sides); /* 1..n */
extern int dice(int count, int sides);
-extern int zero_die(int sides); /* 0..n-1 */
+extern int zero_die(int sides); /* 0..n-1 */
extern int do_command(enum game_cmd command);
extern uint32_t convert_range(int dy, int dx);
extern int game_finished;
extern int game_tick;
extern int wizard_mode;
-/* XXX map.c data and funcs*/
-extern void leave_level(void);
-extern void make_new_level(void);
-extern void build_level(void);
-extern void populate_level(void);
-extern void inject_player(void);
-extern void explore_around(int y, int x);
-
-#define LEVGEN_WALK_CELLS 600
-#define DUN_WIDTH 42
-#define DUN_HEIGHT 42
-#define ROOM_HT_DELTA 4
-#define ROOM_WD_DELTA 4
-#define MAX_ROOMS 9
-
-extern int mapobject[DUN_HEIGHT][DUN_WIDTH];
-extern int mapmonster[DUN_HEIGHT][DUN_WIDTH];
-extern enum terrain_num terrain[DUN_HEIGHT][DUN_WIDTH];
-#define MAPFLAG_EXPLORED 0x00000001
-extern int mapflags[DUN_HEIGHT][DUN_WIDTH];
-extern int depth;
-
/* XXX misc.c data and funcs */
extern const char *damtype_names[DT_COUNT];
-/* XXX objects.c data and funcs */
-extern void flavours_init(void);
-extern void sprint_obj_name(char *s, int obj, int len);
-extern void fprint_obj_name(FILE *fp, int obj);
-extern void print_obj_name(int obj);
-extern void describe_object(int obj);
-extern int create_obj(int po_idx, int quantity, int with_you, int y, int x);
-extern int drop_obj(int inv_idx);
-extern int consume_obj(int obj);
-extern int create_obj_class(enum poclass_num pocl, int quantity, int with_you, int y, int x);
-extern int create_obj_random(int y, int x);
-extern int read_scroll(int obj);
extern int quaff_potion(int obj);
extern int eat_food(int obj);
extern void attempt_pickup(void);
#endif
/* victrix-abyssi.h */
-// vim:cindent
+// vim:cindent:ts=8:sw=4:expandtab