initial checkin
This commit is contained in:
commit
19d30819ae
|
@ -0,0 +1,2 @@
|
|||
nexus: Makefile defs.h nexus.c nexus.h ai.c ai.h attack.c attack.h flag.c flag.h io.c io.h lf.c lf.h map.c map.h move.c move.h objects.c objects.h text.c text.h save.c save.h
|
||||
gcc -g -o nexus nexus.c ai.c attack.c flag.c io.c lf.c map.c move.c objects.c text.c save.c -lncurses
|
|
@ -0,0 +1,124 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "ai.h"
|
||||
#include "defs.h"
|
||||
#include "flag.h"
|
||||
#include "lf.h"
|
||||
#include "map.h"
|
||||
#include "objects.h"
|
||||
|
||||
extern lifeform_t *player;
|
||||
|
||||
void aimove(lifeform_t *lf) {
|
||||
int dir;
|
||||
int db = B_TRUE;
|
||||
flag_t *f;
|
||||
lifeform_t *target;
|
||||
char buf[BUFLEN];
|
||||
if (db) dblog("AIMOVE: %s", lf->race->name);
|
||||
|
||||
// if lifeform isn't alive, skip turn
|
||||
if (isdead(lf)) {
|
||||
taketime(lf, SPEED_DEAD);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
f = hasflag(lf->flags, F_TARGET);
|
||||
if (f) {
|
||||
int targid;
|
||||
targid = f->val[0];
|
||||
target = findlf(lf->cell->map, targid);
|
||||
if (target) {
|
||||
if (haslos(lf, target->cell)) {
|
||||
movetowards(lf, target->cell);
|
||||
return;
|
||||
} else {
|
||||
// TODO: move towards last known location
|
||||
|
||||
// just try to move in a random direction
|
||||
dorandommove(lf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// not attacking anyone in particular
|
||||
|
||||
// TODO: are we hostile? if so, look for a target
|
||||
f = hasflag(lf->flags, F_HOSTILE);
|
||||
if (f) {
|
||||
int x,y;
|
||||
cell_t *c;
|
||||
// look around for a target
|
||||
// TODO: use our vis rang einstead of 10!
|
||||
for (y = lf->cell->y - 10; y <= lf->cell->y + 10; y++) {
|
||||
for (x = lf->cell->x - 10; x <= lf->cell->x + 10; x++) {
|
||||
c = getcellat(lf->cell->map, x, y);
|
||||
// cell exists and we can see it?
|
||||
if (c && haslos(lf, c)) {
|
||||
// player there?
|
||||
if (c->lf && c->lf->controller == C_PLAYER) {
|
||||
// target them!
|
||||
addflag(lf->flags, F_TARGET, c->lf->id, -1, -1, "");
|
||||
// tell the player
|
||||
if (haslos(player, lf->cell)) {
|
||||
getlfname(lf, buf);
|
||||
capitalise(buf);
|
||||
msg("%s sees you!", buf);
|
||||
}
|
||||
// then move towards them...
|
||||
movetowards(lf, c);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// just try to move in a random direction
|
||||
dorandommove(lf);
|
||||
return;
|
||||
}
|
||||
|
||||
// if we get this far, just wait
|
||||
dowait(lf);
|
||||
}
|
||||
|
||||
int getdirtowards(lifeform_t *lf, cell_t *dst) {
|
||||
int d;
|
||||
cell_t *c;
|
||||
int mindist=9999,bestdir=D_NONE;
|
||||
|
||||
for (d = DC_N; d <= DC_NW; d++) {
|
||||
c = getcellindir(lf->cell, d);
|
||||
if (!c) continue;
|
||||
if (c == dst) {
|
||||
// destination is adjacent!
|
||||
bestdir = d;
|
||||
break;
|
||||
}
|
||||
|
||||
if (canmove(lf, d)) {
|
||||
int thisdist;
|
||||
thisdist = getcelldist(c, dst);
|
||||
if (thisdist < mindist) {
|
||||
mindist = thisdist;
|
||||
bestdir = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: handle ties
|
||||
|
||||
return bestdir;
|
||||
}
|
||||
|
||||
void movetowards(lifeform_t *lf, cell_t *dst) {
|
||||
int dir;
|
||||
// move towards them
|
||||
dir = getdirtowards(lf, dst);
|
||||
if (dir != D_NONE) {
|
||||
trymove(lf, dir);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
#include "defs.h"
|
||||
|
||||
void aimove(lifeform_t *lf);
|
||||
int getdirtowards(lifeform_t *lf, cell_t *dst);
|
||||
void movetowards(lifeform_t *lf, cell_t *dst);
|
|
@ -0,0 +1,50 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "attack.h"
|
||||
#include "defs.h"
|
||||
|
||||
extern lifeform_t *player;
|
||||
|
||||
void doattack(lifeform_t *lf, lifeform_t *victim) {
|
||||
int dam;
|
||||
char buf[BUFLEN];
|
||||
char attackername[BUFLEN];
|
||||
char victimname[BUFLEN];
|
||||
int fatal = B_FALSE;
|
||||
|
||||
// depends on weapon, race attackspeed modifier flag, etc
|
||||
taketime(lf, getattackspeed(lf));
|
||||
|
||||
// TODO: figure out if you hit
|
||||
// TODO: figure out if you do damage
|
||||
dam = 1;
|
||||
|
||||
getlfname(lf, attackername);
|
||||
getlfname(victim, victimname);
|
||||
|
||||
losehp(victim, dam, lf, attackername); // TODO: use player name if required
|
||||
|
||||
if (victim->hp <= 0) {
|
||||
fatal = B_TRUE;
|
||||
}
|
||||
|
||||
// announce it
|
||||
if (lf->controller == C_PLAYER) {
|
||||
msg("You %s %s%s",
|
||||
fatal ? "kill" : "hit",
|
||||
victimname,
|
||||
fatal ? "!" : ".");
|
||||
|
||||
// don't also say "the xx dies"
|
||||
addflag(victim->flags, F_NODEATHANNOUNCE, B_TRUE, -1, -1, "");
|
||||
} else {
|
||||
if (haslos(player, lf->cell)) {
|
||||
// capitalise first letter
|
||||
sprintf(buf, "%s",attackername);
|
||||
capitalise(buf);
|
||||
|
||||
msg("%s hits %s.", buf, victimname);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
#include "defs.h"
|
||||
|
||||
void doattack(lifeform_t *lf, lifeform_t *victim);
|
|
@ -0,0 +1,374 @@
|
|||
#ifndef __DEFS_H
|
||||
#define __DEFS_H
|
||||
|
||||
// MACROS
|
||||
#define MAXOF(a,b) (a > b ? a : b)
|
||||
|
||||
// save/load
|
||||
#define MAPDIR "data/maps"
|
||||
#define SAVEDIR "data/save"
|
||||
|
||||
// SPECIAL NUMBERS/CONSTANTS
|
||||
#define UNLIMITED (-9876)
|
||||
#define ALL (-9875)
|
||||
#define NA (-9874)
|
||||
|
||||
|
||||
// STRINGS
|
||||
#define BUFLENSMALL 64
|
||||
#define BUFLEN 128
|
||||
#define HUGEBUFLEN 1024
|
||||
|
||||
|
||||
#define MORESTRING "--More--"
|
||||
|
||||
|
||||
// LIMITS
|
||||
|
||||
|
||||
#define SCREENW 80
|
||||
#define SCREENH 24
|
||||
|
||||
#define MAXPILEOBS 52
|
||||
|
||||
#define MAXRANDOMOBCANDIDATES 100
|
||||
|
||||
#define MAX_MAPW 80
|
||||
#define MAX_MAPH 50
|
||||
//#define MAX_MAPROOMS 10
|
||||
|
||||
#define MIN_ROOMH 4
|
||||
#define MIN_ROOMW 4
|
||||
#define MAX_ROOMW (MAX_MAPW / 5)
|
||||
#define MAX_ROOMH (MAX_MAPH / 5)
|
||||
|
||||
#define MAXDIR_ORTH 4
|
||||
#define MAXDIR_COMPASS 8
|
||||
|
||||
// MAP BUILDING
|
||||
#define DEF_TURNPCT 40
|
||||
#define DEF_SPARSENESS 14
|
||||
//#define DEF_SPARSENESS 0
|
||||
#define DEF_LOOPPCT 70
|
||||
//#define DEF_LOOPPCT 0
|
||||
#define MINROOMS 15
|
||||
#define MAXROOMS 25
|
||||
#define DEF_WINDOWPCT 5
|
||||
|
||||
//
|
||||
#define ANIMDELAY (1000000 / 100) // 1/100 of a second
|
||||
|
||||
// CONTROLLERS
|
||||
#define C_AI 0
|
||||
#define C_PLAYER 1
|
||||
|
||||
// speed settings (lower is faster)
|
||||
#define SPEED_ATTACK 10
|
||||
#define SPEED_DEAD 50
|
||||
#define SPEED_MOVE 10
|
||||
#define SPEED_DROP 5
|
||||
#define SPEED_PICKUP 5
|
||||
#define SPEED_THROW 10
|
||||
#define SPEED_WAIT 10
|
||||
|
||||
|
||||
// DIRECTION TYPES
|
||||
#define DT_ORTH 0
|
||||
#define DT_COMPASS 1
|
||||
|
||||
// DIRECTIONS
|
||||
|
||||
|
||||
#define D_NONE -1
|
||||
#define D_UNKNOWN -2
|
||||
|
||||
// Orthogonal directions
|
||||
#define D_N 0
|
||||
#define D_E 1
|
||||
#define D_S 2
|
||||
#define D_W 3
|
||||
|
||||
// Compass directions
|
||||
#define DC_N 4
|
||||
#define DC_NE 5
|
||||
#define DC_E 6
|
||||
#define DC_SE 7
|
||||
#define DC_S 8
|
||||
#define DC_SW 9
|
||||
#define DC_W 10
|
||||
#define DC_NW 11
|
||||
|
||||
|
||||
|
||||
// Cell types
|
||||
#define CT_WALL 0
|
||||
#define CT_ROOMWALL 1
|
||||
#define CT_CORRIDOR 2
|
||||
#define CT_ROOM 3
|
||||
#define CT_DOOROPEN 4
|
||||
#define CT_DOORCLOSED 5
|
||||
#define CT_LOOPCORRIDOR 6
|
||||
|
||||
// Object Classes
|
||||
enum OBCLASS {
|
||||
OC_MONEY,
|
||||
OC_WEAPON,
|
||||
OC_ARMOUR,
|
||||
OC_SCROLL,
|
||||
OC_POTION,
|
||||
OC_FOOD,
|
||||
OC_ROCK,
|
||||
OC_MISC,
|
||||
OC_NULL = -999
|
||||
};
|
||||
|
||||
enum BLESSTYPE {
|
||||
B_UNCURSED = 0,
|
||||
B_BLESSED = 1,
|
||||
B_CURSED = -1
|
||||
};
|
||||
|
||||
enum HABITAT {
|
||||
H_DUNGEON = 1,
|
||||
H_ALL = 999
|
||||
};
|
||||
|
||||
enum RARITY {
|
||||
RR_NEVER = 6,
|
||||
RR_VERYRARE = 5,
|
||||
RR_RARE = 4,
|
||||
RR_UNCOMMON = 3,
|
||||
RR_COMMON = 2,
|
||||
RR_FREQUENT = 1,
|
||||
};
|
||||
|
||||
|
||||
enum RACE {
|
||||
R_BAT,
|
||||
R_GIANTFLY,
|
||||
R_GIANTBLOWFLY,
|
||||
R_HUMAN,
|
||||
R_GOBLIN,
|
||||
};
|
||||
|
||||
// Object Materials
|
||||
enum MATERIAL {
|
||||
MT_STONE,
|
||||
MT_FIRE,
|
||||
MT_PLASTIC,
|
||||
MT_METAL,
|
||||
MT_FLESH,
|
||||
MT_WOOD,
|
||||
MT_GOLD
|
||||
};
|
||||
|
||||
// Object Types
|
||||
enum OBTYPE {
|
||||
// rocks
|
||||
OT_GOLD,
|
||||
OT_STONE,
|
||||
// corpses
|
||||
OT_CORPSEHUMAN,
|
||||
OT_CORPSEGOBLIN,
|
||||
OT_CORPSEBAT,
|
||||
OT_CORPSEFLY,
|
||||
};
|
||||
|
||||
enum FLAG {
|
||||
// object flags
|
||||
F_STACKABLE, // can stack multiple objects togethr
|
||||
F_NO_PLURAL, // this obname doesn't need an 's' for plurals (eg. gold, money)
|
||||
F_NO_A, // this obname doesn't need to start with 'a' for singular (eg. gold)
|
||||
F_EDIBLE, // you can eat this. val2 = nutrition
|
||||
// lifeform flags
|
||||
F_CORPSETYPE, // text field specifies what corpse obtype to leave
|
||||
F_FLYING, // lf is flying
|
||||
F_HOSTILE, // lf will attack anything the player if in sight
|
||||
F_NODEATHANNOUNCE, // don't say 'the xx dies' if this lf dies
|
||||
F_TARGET, // lf will attack this lf id
|
||||
F_ATTACKSPEED, // override default attack speed
|
||||
F_MOVESPEED, // override default move speed
|
||||
F_RARITY, // val[0] = habitat, val[1] = rarity
|
||||
F_NUMAPPEAR, // when randomly appearing, can have > 1. val[0] = min, val[1] = max
|
||||
//
|
||||
F_NULL = -1
|
||||
};
|
||||
|
||||
|
||||
// probabilities
|
||||
//#define CH_DEADENDOB 35
|
||||
//#define CH_EMPTYCELLOB 3
|
||||
#define CH_PILLAR 5
|
||||
|
||||
// Booleans
|
||||
#define B_FALSE (0)
|
||||
#define B_TRUE (-1)
|
||||
|
||||
#define B_NOSTACK (0)
|
||||
#define B_STACK (-1)
|
||||
#define B_STACKOK (-1)
|
||||
|
||||
#define NOOWNER (NULL)
|
||||
#define NOLOC (NULL)
|
||||
|
||||
#define B_NOTSOLID (0)
|
||||
#define B_EMPTY (0)
|
||||
#define B_SOLID (-1)
|
||||
|
||||
#define B_OPAQUE (0)
|
||||
#define B_TRANSPARENT (-1)
|
||||
#define B_TRANS (-1)
|
||||
|
||||
|
||||
// errors
|
||||
enum ERROR {
|
||||
E_OK = 0,
|
||||
E_WALLINWAY = 1,
|
||||
E_LFINWAY = 2,
|
||||
E_NOSPACE = 3
|
||||
};
|
||||
|
||||
typedef struct map_s {
|
||||
int id;
|
||||
char *name; // name of this map
|
||||
enum HABITAT habitat; // eg. dungeon, forest, etc
|
||||
unsigned int seed;
|
||||
int w,h; // width/height of this map
|
||||
struct cell_s *cell[MAX_MAPW*MAX_MAPH]; // list of cells in this map
|
||||
int nextmap[MAXDIR_ORTH]; // which map is in each direction
|
||||
|
||||
long nextlfid;
|
||||
struct lifeform_s *lf,*lastlf;
|
||||
|
||||
struct map_s *next, *prev;
|
||||
} map_t; //////////////// remember to modify save/load for new props!!
|
||||
|
||||
typedef struct cell_s {
|
||||
map_t *map; // pointer back to map
|
||||
int x,y; // map coords
|
||||
int roomid;
|
||||
struct celltype_s *type;
|
||||
struct obpile_s *obpile;
|
||||
|
||||
// lifeform pile
|
||||
struct lifeform_s *lf;
|
||||
// known to player?
|
||||
int known;
|
||||
|
||||
// FOR CONSTRUCTION
|
||||
int visited;
|
||||
} cell_t;
|
||||
|
||||
typedef struct celltype_s {
|
||||
int id; // eg. dungeonfloor, wall, door
|
||||
char glyph; // how to display it
|
||||
int solid; // can you walk through it?
|
||||
int transparent; // can you see through it?
|
||||
struct celltype_s *next, *prev;
|
||||
} celltype_t;
|
||||
|
||||
typedef struct race_s {
|
||||
enum RACE id;
|
||||
char *name;
|
||||
char glyph;
|
||||
struct flagpile_s *flags;
|
||||
// speed modifiers
|
||||
// hit dice
|
||||
struct race_s *next, *prev;
|
||||
} race_t;
|
||||
|
||||
typedef struct lifeform_s {
|
||||
int id;
|
||||
int controller;
|
||||
struct race_s *race;
|
||||
int hp,maxhp;
|
||||
int alive;
|
||||
char *lastdam;
|
||||
|
||||
int timespent;
|
||||
int sorted;
|
||||
|
||||
struct obpile_s *pack;
|
||||
|
||||
struct flagpile_s *flags;
|
||||
|
||||
// for loading
|
||||
long oblist[MAXPILEOBS];
|
||||
int x,y;
|
||||
|
||||
|
||||
struct cell_s *cell;
|
||||
struct lifeform_s *next, *prev;
|
||||
} lifeform_t;
|
||||
|
||||
|
||||
typedef struct obpile_s {
|
||||
lifeform_t *owner;// } Only one of these
|
||||
cell_t *where; // } should be filled in
|
||||
struct object_s *first,*last;
|
||||
|
||||
// for loading
|
||||
long oblist[MAXPILEOBS];
|
||||
} obpile_t;
|
||||
|
||||
|
||||
typedef struct flagpile_s {
|
||||
struct flag_s *first,*last;
|
||||
} flagpile_t;
|
||||
|
||||
typedef struct flag_s {
|
||||
enum FLAG id;
|
||||
int nvals;
|
||||
int val[3];
|
||||
char *text;
|
||||
struct flagpile_s *pile;
|
||||
struct flag_s *next, *prev;
|
||||
} flag_t;
|
||||
|
||||
typedef struct material_s {
|
||||
int id;
|
||||
char *name;
|
||||
struct material_s *next,*prev;
|
||||
} material_t;
|
||||
|
||||
typedef struct objectclass_s {
|
||||
enum OBCLASS id;
|
||||
char *name;
|
||||
char glyph;
|
||||
struct objectclass_s *next, *prev;
|
||||
} objectclass_t;
|
||||
|
||||
typedef struct objecttype_s {
|
||||
enum OBTYPE id;
|
||||
char *name;
|
||||
char *desc;
|
||||
struct objectclass_s *obclass;
|
||||
material_t *material;
|
||||
float weight; // in kilograms
|
||||
struct flagpile_s *flags;
|
||||
struct objecttype_s *next, *prev;
|
||||
} objecttype_t;
|
||||
|
||||
typedef struct object_s {
|
||||
long id; // unique for every ob in the game!
|
||||
struct objecttype_s *type;
|
||||
struct obpile_s *pile; // reverse pointer back to pile
|
||||
// these variables are initially
|
||||
// inherited from objecttype:
|
||||
material_t *material;
|
||||
float weight; // in kilograms
|
||||
// flags
|
||||
// these variables are NOT inherited
|
||||
char *inscription;
|
||||
char letter;
|
||||
enum BLESSTYPE blessed;
|
||||
int blessknown;
|
||||
int amt; // for stackable objects
|
||||
flagpile_t *flags;
|
||||
|
||||
struct object_s *next, *prev;
|
||||
} object_t;
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
when adding a new obejct class:
|
||||
|
||||
In defs.h:
|
||||
add its OC_ enum
|
||||
|
||||
In objects.c:
|
||||
define the class with addoc()
|
||||
add the class to sortorder[] at the top
|
|
@ -0,0 +1,11 @@
|
|||
defs.h:
|
||||
add RACE enum (R_xx)
|
||||
add OT_CORPSExxx obtype
|
||||
|
||||
lf.c:
|
||||
addrace(R_xx)
|
||||
+ flagso
|
||||
|
||||
objects.c:
|
||||
addot(OTCORPSE)
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "defs.h"
|
||||
#include "flag.h"
|
||||
#include "text.h"
|
||||
|
||||
flag_t *addflag(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text) {
|
||||
flag_t *f;
|
||||
int i;
|
||||
|
||||
if (fp->first == NULL) {
|
||||
fp->first = malloc(sizeof(flag_t));
|
||||
f = fp->first;
|
||||
f->prev = NULL;
|
||||
} else {
|
||||
// go to end of list
|
||||
f = fp->last;
|
||||
f->next = malloc(sizeof(flag_t));
|
||||
f->next->prev = f;
|
||||
f = f->next;
|
||||
}
|
||||
fp->last = f;
|
||||
|
||||
f->next = NULL;
|
||||
|
||||
// fill in props
|
||||
f->id = id; // increment next ob id
|
||||
|
||||
// first blank values
|
||||
for (i = 0; i < 3; i++) {
|
||||
f->val[i] = 0;
|
||||
}
|
||||
|
||||
f->val[0] = val1;
|
||||
f->nvals = 1;
|
||||
if (val2 != NA) {
|
||||
f->val[1] = val2;
|
||||
f->nvals++;
|
||||
}
|
||||
if (val3 != NA) {
|
||||
f->val[2] = val2;
|
||||
f->nvals++;
|
||||
}
|
||||
if (text) {
|
||||
f->text = strdup(text);
|
||||
} else {
|
||||
f->text = strdup("");
|
||||
}
|
||||
|
||||
f->pile = fp;
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
flagpile_t *addflagpile(void) {
|
||||
flagpile_t *fp;
|
||||
fp = malloc(sizeof(flagpile_t));
|
||||
fp->first = NULL;
|
||||
fp->last = NULL;
|
||||
|
||||
return fp;
|
||||
}
|
||||
|
||||
flag_t *hasflag(flagpile_t *fp, int id) {
|
||||
flag_t *f;
|
||||
for (f = fp->first ; f ; f = f->next) {
|
||||
if (f->id == id) return f;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
flag_t *hasflagval(flagpile_t *fp, int id, int val1, int val2, int val3, char *text) {
|
||||
flag_t *f;
|
||||
for (f = fp->first ; f ; f = f->next) {
|
||||
if (f->id == id) {
|
||||
if ( ((val1 == -1) || (f->val[0] == val1)) &&
|
||||
((val2 == -1) || (f->val[1] == val2)) &&
|
||||
((val3 == -1) || (f->val[2] == val3)) &&
|
||||
((text == NULL) || strstr(f->text, text))) {
|
||||
return f;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void killflag(flag_t *f) {
|
||||
int i;
|
||||
flag_t *nextone, *lastone;
|
||||
|
||||
// free mem
|
||||
|
||||
// remove from list
|
||||
nextone = f->next;
|
||||
if (nextone != NULL) {
|
||||
nextone->prev = f->prev;
|
||||
} else { /* last */
|
||||
f->pile->last = f->prev;
|
||||
}
|
||||
|
||||
if (f->prev == NULL) {
|
||||
/* first */
|
||||
nextone = f->next;
|
||||
f->pile->first = nextone;
|
||||
free(f);
|
||||
} else {
|
||||
lastone = f->prev;
|
||||
free (lastone->next );
|
||||
lastone->next = nextone;
|
||||
}
|
||||
}
|
||||
|
||||
void killflagpile(flagpile_t *fp) {
|
||||
while (fp->first) {
|
||||
killflag(fp->first);
|
||||
}
|
||||
free(fp);
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
#include "defs.h"
|
||||
|
||||
|
||||
// functions
|
||||
flag_t *addflag(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text);
|
||||
flagpile_t *addflagpile(void);
|
||||
flag_t *hasflag(flagpile_t *fp, int id);
|
||||
flag_t *hasflagval(flagpile_t *fp, int id, int val1, int val2, int val3, char *text);
|
||||
void killflag(flag_t *f);
|
||||
void killflagpile(flagpile_t *fp);
|
|
@ -0,0 +1,921 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ncurses.h>
|
||||
#include "defs.h"
|
||||
#include "io.h"
|
||||
#include "map.h"
|
||||
#include "move.h"
|
||||
#include "nexus.h"
|
||||
#include "objects.h"
|
||||
|
||||
WINDOW *mainwin;
|
||||
WINDOW *gamewin;
|
||||
WINDOW *msgwin;
|
||||
WINDOW *statwin;
|
||||
|
||||
extern enum ERROR reason;
|
||||
|
||||
extern FILE *logfile;
|
||||
extern enum OBCLASS sortorder[];
|
||||
|
||||
extern int gamestarted;
|
||||
|
||||
char msgbuf[HUGEBUFLEN];
|
||||
|
||||
extern lifeform_t *player;
|
||||
|
||||
extern map_t *firstmap;
|
||||
|
||||
int viewx = -9999,viewy = -9999;
|
||||
|
||||
int vieww,viewh;
|
||||
|
||||
void anim(cell_t *src, cell_t *dst, char ch) {
|
||||
int deltax, deltay;
|
||||
int numpixels;
|
||||
int d;
|
||||
int dinc1,dinc2,xinc1,xinc2,yinc1,yinc2;
|
||||
int xinc,yinc,dinc;
|
||||
int i;
|
||||
int x1,y1,dir;
|
||||
int x;
|
||||
int y;
|
||||
int maxvisrange;
|
||||
int modmaxvisrange;
|
||||
int xray = B_FALSE;
|
||||
int wentuphill = B_FALSE;
|
||||
int origheight;
|
||||
int shopwall;
|
||||
|
||||
int x2,y2;
|
||||
|
||||
// just in case
|
||||
if (src->map != dst->map) return;
|
||||
|
||||
x1 = src->x;
|
||||
y1 = src->y;
|
||||
x2 = dst->x;
|
||||
y2 = dst->y;
|
||||
|
||||
deltax = (x2 - x1);
|
||||
if (deltax < 0) deltax = -deltax;
|
||||
deltay = (y2 - y1);
|
||||
if (deltay < 0) deltay = -deltay;
|
||||
|
||||
// going nowhere
|
||||
if ((deltax == 0) && (deltay == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (deltax >= deltay) {
|
||||
numpixels = deltax + 1;
|
||||
d = (deltay*2) - deltax;
|
||||
dinc1 = deltay << 1;
|
||||
dinc2 = (deltay-deltax) << 1;
|
||||
xinc1 = 1;
|
||||
xinc2 = 1;
|
||||
yinc1 = 0;
|
||||
yinc2 = 1;
|
||||
} else {
|
||||
numpixels = deltay + 1;
|
||||
d = (deltax*2) - deltay;
|
||||
dinc1 = deltax << 1;
|
||||
dinc2 = (deltax - deltay) << 1;
|
||||
xinc1 = 0;
|
||||
xinc2 = 1;
|
||||
yinc1 = 1;
|
||||
yinc2 = 1;
|
||||
}
|
||||
|
||||
if (x1 > x2) {
|
||||
xinc1 = - xinc1;
|
||||
xinc2 = - xinc2;
|
||||
}
|
||||
if (y1 > y2) {
|
||||
yinc1 = - yinc1;
|
||||
yinc2 = - yinc2;
|
||||
}
|
||||
|
||||
x = x1; y = y1;
|
||||
|
||||
for (i = 0; i < numpixels ; i++) {
|
||||
cell_t *cell;
|
||||
|
||||
// get current cell
|
||||
cell = getcellat(src->map, x, y);
|
||||
|
||||
// update screen
|
||||
updateviewfor(cell);
|
||||
drawlevelfor(player);
|
||||
// draw char & cursor at its current pos...
|
||||
mvwprintw(gamewin, cell->y - viewy, cell->x - viewx, "%c", ch);
|
||||
wmove(gamewin, cell->y - viewy, cell->x - viewx);
|
||||
wrefresh(gamewin);
|
||||
usleep(ANIMDELAY);
|
||||
|
||||
// move to next cell
|
||||
if (d < 0) {
|
||||
xinc = xinc1;
|
||||
yinc = yinc1;
|
||||
dinc = dinc1;
|
||||
} else {
|
||||
xinc = xinc2;
|
||||
yinc = yinc2;
|
||||
dinc = dinc2;
|
||||
}
|
||||
|
||||
d += dinc;
|
||||
x += xinc;
|
||||
y += yinc;
|
||||
}
|
||||
}
|
||||
|
||||
cell_t *askcoords(char *prompt) {
|
||||
int finished = B_FALSE;
|
||||
cell_t *c,*newcell;
|
||||
|
||||
c = player->cell;
|
||||
|
||||
wclear(msgwin);
|
||||
mvwprintw(msgwin, 0, 0, "%s", prompt);
|
||||
wrefresh(msgwin);
|
||||
|
||||
while (!finished) {
|
||||
int dir;
|
||||
char ch;
|
||||
|
||||
drawstatus();
|
||||
updateviewfor(c);
|
||||
drawlevelfor(player);
|
||||
// move cursor selected position
|
||||
wmove(gamewin, c->y - viewy, c->x - viewx);
|
||||
redraw();
|
||||
|
||||
// get input
|
||||
ch = getch();
|
||||
if (ch == '.') {
|
||||
return c;
|
||||
} else if (ch == 27) { // ESC - cancel
|
||||
finished = B_TRUE;
|
||||
} else {
|
||||
dir = chartodir(ch);
|
||||
if (dir != D_NONE) {
|
||||
newcell = getcellindir(c, dir);
|
||||
if (newcell) c = newcell;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
object_t *askobject(obpile_t *op, char *prompt, int *count) {
|
||||
int c,i;
|
||||
object_t *mylist[MAXPILEOBS+1];
|
||||
char myletters[MAXPILEOBS+1];
|
||||
char numstring[BUFLEN];
|
||||
int firstob = 0;
|
||||
int nextpage = -1;
|
||||
int lastline = SCREENH-2;
|
||||
char buf[BUFLEN];
|
||||
int finished;
|
||||
char nextlet = 'a';
|
||||
int useobletters;
|
||||
|
||||
// if picking form a player's pack, use the object's letters.
|
||||
// otherwise just label them a, b, c, etc.
|
||||
if (op->owner && (op->owner->controller == C_PLAYER)) {
|
||||
useobletters = B_TRUE;
|
||||
} else {
|
||||
useobletters = B_FALSE;
|
||||
}
|
||||
|
||||
// construct a list of objects
|
||||
c = 0;
|
||||
i = 0;
|
||||
while (sortorder[c] != OC_NULL) {
|
||||
object_t *o;
|
||||
// add all objects of this class
|
||||
for (o = op->first ; o ; o = o->next) {
|
||||
if (o->type->obclass->id == sortorder[c]) {
|
||||
mylist[i] = o;
|
||||
myletters[i] = nextlet;
|
||||
if (++nextlet > 'z') nextlet = 'A';
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
c++;
|
||||
}
|
||||
mylist[i] = NULL;
|
||||
|
||||
// start displaying from the first one
|
||||
firstob = 0;
|
||||
nextpage = -1;
|
||||
finished = B_FALSE;
|
||||
strcpy(numstring, "");
|
||||
while (!finished) {
|
||||
int lastclass = OC_NULL;
|
||||
int y;
|
||||
int ch;
|
||||
|
||||
wclear(mainwin);
|
||||
// list the objects
|
||||
y = 2;
|
||||
for (i = firstob ; (mylist[i] != NULL) && (y < lastline); i++) {
|
||||
if (mylist[i]->type->obclass->id != lastclass) {
|
||||
objectclass_t *oc;
|
||||
// print class heading
|
||||
mvwprintw(mainwin, y, 0, "%s", mylist[i]->type->obclass->name);
|
||||
|
||||
lastclass = mylist[i]->type->obclass->id;
|
||||
|
||||
y++;
|
||||
}
|
||||
getobname(mylist[i], buf,mylist[i]->amt);
|
||||
mvwprintw(mainwin, y, 0, " %c - %s",
|
||||
useobletters ? mylist[i]->letter : myletters[i],
|
||||
buf);
|
||||
y++;
|
||||
}
|
||||
if (mylist[i] == NULL) {
|
||||
nextpage = -1;
|
||||
} else {
|
||||
nextpage = i;
|
||||
}
|
||||
// draw prompt
|
||||
if (strlen(numstring) > 0) {
|
||||
mvwprintw(mainwin, 0, 0, "%s (ESC to quit) [%s]: ",prompt, numstring);
|
||||
} else {
|
||||
mvwprintw(mainwin, 0, 0, "%s (ESC to quit): ", prompt);
|
||||
}
|
||||
if (nextpage != -1) {
|
||||
mvwprintw(mainwin, y, 0, "-- More --");
|
||||
}
|
||||
// update screen
|
||||
wrefresh(mainwin);
|
||||
// wait for keypess
|
||||
ch = getch();
|
||||
if (ch == 27) { // ESCAPE
|
||||
finished = B_TRUE;
|
||||
break;
|
||||
}
|
||||
// otherwise look for shift key etc..
|
||||
ch = keycodetokey(ch);
|
||||
// then handle input
|
||||
if (ch == ' ') { // next page
|
||||
if (nextpage == -1) { // go to first page
|
||||
firstob = 0;
|
||||
} else {
|
||||
firstob = nextpage;
|
||||
}
|
||||
} else if (isalpha(ch)) {
|
||||
object_t *o;
|
||||
// describe that object
|
||||
if (useobletters) {
|
||||
o = findobl(op, ch);
|
||||
} else {
|
||||
o = NULL;
|
||||
for (i = firstob ; (mylist[i] != NULL) && (y < lastline); i++) {
|
||||
if (myletters[i] == ch) {
|
||||
o = mylist[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (o) {
|
||||
// make sure count is okay...
|
||||
if (count && *count > o->amt) {
|
||||
*count = o->amt;
|
||||
}
|
||||
if (count && (*count == ALL)) {
|
||||
*count = o->amt;
|
||||
}
|
||||
// display game windows again
|
||||
drawscreen();
|
||||
return o;
|
||||
}
|
||||
} else if (isdigit(ch)) {
|
||||
char temp[2];
|
||||
temp[0] = ch;
|
||||
temp[1] = '\0';
|
||||
strcat(numstring, temp);
|
||||
*count = atoi(numstring);
|
||||
} else if (ch == 8) { // backspace
|
||||
if (strlen(numstring) > 0) {
|
||||
// remove last letter of number string
|
||||
numstring[strlen(numstring)-1] = '\0';
|
||||
*count = atoi(numstring);
|
||||
}
|
||||
}
|
||||
|
||||
// sanity check count...
|
||||
if (count && (*count == 0)) {
|
||||
strcpy(numstring, "");
|
||||
}
|
||||
}
|
||||
|
||||
// display game windows again
|
||||
drawscreen();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void centre(WINDOW *win, int y, char *format, ... ) {
|
||||
int w;
|
||||
char buf[BUFLEN];
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
vsprintf( buf, format, args );
|
||||
va_end(args);
|
||||
|
||||
w = getmaxx(win);
|
||||
mvwprintw(win, y, (w/2) - (strlen(buf)/2), buf);
|
||||
}
|
||||
|
||||
|
||||
int chartodir(char c) {
|
||||
switch (tolower(c)) {
|
||||
case 'h': return D_W;
|
||||
case 'j': return D_S;
|
||||
case 'k': return D_N;
|
||||
case 'l': return D_E;
|
||||
case 'y': return DC_NW;
|
||||
case 'u': return DC_NE;
|
||||
case 'b': return DC_SW;
|
||||
case 'n': return DC_SE;
|
||||
}
|
||||
return D_NONE;
|
||||
}
|
||||
|
||||
void clearmsg(void) {
|
||||
wclear(msgwin);
|
||||
wrefresh(msgwin);
|
||||
}
|
||||
|
||||
int cleanupgfx(void) {
|
||||
curs_set(1);
|
||||
endwin();
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
|
||||
void updateviewfor(cell_t *cell) {
|
||||
// calculate viewport if required
|
||||
if ((viewx == -9999) || (viewy == -9999)) {
|
||||
// try to centre player
|
||||
viewx = cell->x - (SCREENW/2);
|
||||
viewy = cell->y - (SCREENH/2);
|
||||
}
|
||||
|
||||
while ((cell->x - viewx) >= ((SCREENW / 3)*2)) {
|
||||
viewx++;
|
||||
}
|
||||
while ((cell->y - viewy) >= ((SCREENH / 3)*2)) {
|
||||
viewy++;
|
||||
}
|
||||
while ((cell->x - viewx) <= (SCREENW/3)) {
|
||||
viewx--;
|
||||
}
|
||||
while ((cell->y - viewy) <= (SCREENH/3)) {
|
||||
viewy--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void drawscreen(void) {
|
||||
drawstatus();
|
||||
|
||||
updateviewfor(player->cell);
|
||||
drawlevelfor(player);
|
||||
drawcursor();
|
||||
redraw();
|
||||
}
|
||||
|
||||
|
||||
void describeob(object_t *o) {
|
||||
char buf[BUFLEN];
|
||||
int y;
|
||||
material_t *m;
|
||||
|
||||
wclear(mainwin);
|
||||
|
||||
// title
|
||||
getobname(o, buf,o->amt);
|
||||
mvwprintw(mainwin, 0, 0, buf);
|
||||
mvwprintw(mainwin, 2, 0, o->type->desc);
|
||||
|
||||
// properties
|
||||
y = 4;
|
||||
mvwprintw(mainwin, y, 0, "%s made from %s.",(o->amt == 1) ? "It is" : "They are", o->material->name); y++;
|
||||
|
||||
if (o->amt == 1) {
|
||||
mvwprintw(mainwin, y, 0, "It weighs %0.1fkg.",o->weight);
|
||||
} else {
|
||||
mvwprintw(mainwin, y, 0, "They weigh %0.1fkg (%0.1f each).",(o->weight * o->amt), o->weight);
|
||||
}
|
||||
|
||||
wrefresh(mainwin);
|
||||
|
||||
// wait for key
|
||||
getch();
|
||||
}
|
||||
|
||||
void dodrop(obpile_t *op) {
|
||||
object_t *o;
|
||||
char buf[BUFLEN];
|
||||
int count = ALL;
|
||||
o = askobject(op, "Drop what", &count);
|
||||
if (o) {
|
||||
getobname(o, buf, count);
|
||||
o = moveob(o, op->owner->cell->obpile, count);
|
||||
if (o) { // if drop was successful...
|
||||
if (op->owner) {
|
||||
if (op->owner->controller == C_PLAYER) {
|
||||
msg("You drop %s.",buf);
|
||||
}
|
||||
taketime(op->owner, (SPEED_DROP * count));
|
||||
}
|
||||
} else {
|
||||
// tell the player why!
|
||||
if (op->owner->controller == C_PLAYER) {
|
||||
switch (reason) {
|
||||
case E_NOSPACE:
|
||||
msg("There is no space here for any more objects!");
|
||||
break;
|
||||
default:
|
||||
msg("For some reason, you cannot drop %s!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dopickup(lifeform_t *lf, obpile_t *op) {
|
||||
int obcount;
|
||||
object_t *o = NULL;
|
||||
int howmany = ALL;
|
||||
char buf[BUFLEN];
|
||||
|
||||
obcount = countobs(op);
|
||||
// anything here?
|
||||
if (obcount == 0) {
|
||||
if (lf->controller == C_PLAYER) {
|
||||
msg("There is nothing here to pick up!");
|
||||
}
|
||||
return;
|
||||
} else if (obcount == 1) {
|
||||
// just get it
|
||||
o = op->first;
|
||||
howmany = ALL;
|
||||
} else {
|
||||
// prompt which one to pick up
|
||||
o = askobject(op, "Pick up what", &howmany);
|
||||
}
|
||||
|
||||
if (!o) {
|
||||
return;
|
||||
}
|
||||
|
||||
getobname(o, buf, howmany);
|
||||
|
||||
// try to move whatever was selected
|
||||
o = moveob(o, lf->pack, howmany);
|
||||
if (o) { // if pickup was successful...
|
||||
if (lf->controller == C_PLAYER) {
|
||||
msg("You pick up %s.",buf);
|
||||
}
|
||||
taketime(lf, (SPEED_PICKUP * howmany));
|
||||
} else {
|
||||
// tell the player why!
|
||||
if (lf->controller == C_PLAYER) {
|
||||
switch (reason) {
|
||||
case E_NOSPACE:
|
||||
msg("Your pack is too full to fit any more objects.");
|
||||
break;
|
||||
default:
|
||||
msg("For some reason, you cannot pick up %s!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void doinventory(obpile_t *op) {
|
||||
object_t *o;
|
||||
o = askobject(op, "Select object to describe", NULL);
|
||||
while (o) {
|
||||
// describe it
|
||||
describeob(o);
|
||||
// ask for another one
|
||||
o = askobject(op, "Select object to describe", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void dothrow(obpile_t *op) {
|
||||
object_t *o;
|
||||
char buf[BUFLEN],buf2[BUFLEN];
|
||||
|
||||
// ask which object to throw
|
||||
o = askobject(op, "Throw what", NULL);
|
||||
if (o) {
|
||||
cell_t *where;
|
||||
getobname(o, buf, 1);
|
||||
|
||||
// TODO: calculate throw range
|
||||
|
||||
// ask where to throw it
|
||||
sprintf(buf2, "Throw %s where?",buf);
|
||||
where = askcoords(buf2);
|
||||
|
||||
if (where) {
|
||||
if (haslof(player, where)) {
|
||||
throwat(player, o, where);
|
||||
} else {
|
||||
msg("You don't have a clear line of fire to there.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void drawcell(cell_t *cell, int x, int y) {
|
||||
if (cell->lf) { // lifeform here?
|
||||
// TODO: draw the lf's race glyph
|
||||
mvwprintw(gamewin, y, x, "%c", cell->lf->race->glyph);
|
||||
} else if (countobs(cell->obpile) > 0) {
|
||||
object_t *o;
|
||||
int c;
|
||||
int drawn = B_FALSE;
|
||||
// draw highest object in sort order
|
||||
c = 0;
|
||||
while ((sortorder[c] != OC_NULL) && (!drawn)) {
|
||||
// check each object against this ob class
|
||||
// count backwards so more recently dropped objects
|
||||
// appear first.
|
||||
for (o = cell->obpile->last ; o ; o = o->prev) {
|
||||
if (o->type->obclass->id == sortorder[c]) {
|
||||
// draw it
|
||||
mvwprintw(gamewin, y, x, "%c", o->type->obclass->glyph);
|
||||
drawn = B_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
c++;
|
||||
}
|
||||
if (!drawn) {
|
||||
// should never happen. if it does, just show the
|
||||
// first object
|
||||
dblog("Warn: sorted object glyph drawing matching nothing!");
|
||||
mvwprintw(gamewin, y, x, "%c", cell->obpile->first->type->obclass->glyph);
|
||||
}
|
||||
} else {
|
||||
// draw ground
|
||||
mvwprintw(gamewin, y, x, "%c", cell->type->glyph);
|
||||
}
|
||||
}
|
||||
|
||||
void drawcursor(void) {
|
||||
// move cursor to player position
|
||||
wmove(gamewin, player->cell->y - viewy, player->cell->x - viewx);
|
||||
wrefresh(gamewin);
|
||||
}
|
||||
|
||||
void drawlevelfor(lifeform_t *lf) {
|
||||
int x,y;
|
||||
int cx,cy;
|
||||
cell_t *cell;
|
||||
map_t *map;
|
||||
map = lf->cell->map;
|
||||
|
||||
wclear(gamewin);
|
||||
for (y = viewy; y < viewy + viewh; y++) {
|
||||
for (x = viewx; x < viewx + vieww; x++) {
|
||||
cell = getcellat(map, x, y);
|
||||
if (cell) {
|
||||
if (haslos(lf, cell)) {
|
||||
drawcell(cell, x-viewx, y-viewy);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void initgfx(void) {
|
||||
mainwin = initscr();
|
||||
if (!has_colors()) {
|
||||
printf("Terminal does not support colour.\n");
|
||||
exit(1);
|
||||
}
|
||||
start_color();
|
||||
noecho();
|
||||
cbreak();
|
||||
nodelay(mainwin, FALSE);
|
||||
|
||||
// determine window sizes
|
||||
vieww = SCREENW;
|
||||
viewh = SCREENH - 4;
|
||||
|
||||
// create windows
|
||||
msgwin = newwin(1, vieww, 0, 0);
|
||||
gamewin = newwin(viewh, vieww, 1, 0);
|
||||
statwin = newwin(2, vieww, 2 + viewh,0);
|
||||
|
||||
redraw();
|
||||
refresh();
|
||||
|
||||
// init message buffer
|
||||
strcpy(msgbuf, "");
|
||||
}
|
||||
|
||||
int getkey(void) {
|
||||
int key_code=0;
|
||||
|
||||
key_code = getch();
|
||||
|
||||
return keycodetokey(key_code);
|
||||
}
|
||||
|
||||
void handleinput(void) {
|
||||
int ch;
|
||||
ch = getkey();
|
||||
|
||||
switch (ch) {
|
||||
// movement
|
||||
case 'h':
|
||||
case 'j':
|
||||
case 'k':
|
||||
case 'l':
|
||||
case 'y':
|
||||
case 'u':
|
||||
case 'b':
|
||||
case 'n':
|
||||
trymove(player, chartodir(ch));
|
||||
break;
|
||||
case 'H':
|
||||
case 'J':
|
||||
case 'K':
|
||||
case 'L':
|
||||
case 'Y':
|
||||
case 'U':
|
||||
case 'B':
|
||||
case 'N':
|
||||
tryrun(player, chartodir(ch));
|
||||
break;
|
||||
case '.': // wait
|
||||
dowait(player);
|
||||
break;
|
||||
// testing
|
||||
case '1':
|
||||
msg("Something happens.");
|
||||
msg("Something else happens.");
|
||||
msg("Another thing is about to happen now.");
|
||||
msg("Too many things are happening!");
|
||||
break;
|
||||
// object functions
|
||||
case 'd': // drop
|
||||
dodrop(player->pack);
|
||||
break;
|
||||
case 'i': // inventory
|
||||
doinventory(player->pack);
|
||||
break;
|
||||
case ',': // pickup
|
||||
dopickup(player, player->cell->obpile);
|
||||
break;
|
||||
case 't': // throw
|
||||
dothrow(player->pack);
|
||||
break;
|
||||
// GAME FUNCTIONS
|
||||
case 'S': // save + quit
|
||||
if (savegame()) {
|
||||
msg("Save failed.");
|
||||
drawmsg();
|
||||
} else {
|
||||
msg("Saved successfully. See you later...");
|
||||
more();
|
||||
drawmsg();
|
||||
exit(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int keycodetokey(int keycode) {
|
||||
int keystroke = 0;
|
||||
|
||||
if (keycode == -1) return -1;
|
||||
|
||||
if (keycode == 27) { // an esc sequence
|
||||
keycode=getch();
|
||||
keystroke=keycode;
|
||||
keycode=getch();
|
||||
keystroke=keystroke | (keycode<<8);
|
||||
keycode=getch();
|
||||
keystroke=keystroke | (keycode<<16);
|
||||
} else {
|
||||
// regular keypress
|
||||
return (int)keycode;
|
||||
}
|
||||
|
||||
return keystroke;
|
||||
}
|
||||
|
||||
void dblog(char *format, ... ) {
|
||||
char buf[HUGEBUFLEN];
|
||||
va_list args;
|
||||
char *p;
|
||||
|
||||
va_start(args, format);
|
||||
vsprintf( buf, format, args );
|
||||
va_end(args);
|
||||
|
||||
/*
|
||||
if (gamestarted) {
|
||||
fprintf(logfile, "%s\n", buf);
|
||||
fflush(logfile);
|
||||
} else {
|
||||
printf("%s\n", buf);
|
||||
fflush(stdout);
|
||||
}
|
||||
*/
|
||||
fprintf(logfile, "%s\n", buf);
|
||||
fflush(logfile);
|
||||
}
|
||||
|
||||
// force a '--more--' prompt
|
||||
void more(void) {
|
||||
msg("%100s"," ");
|
||||
}
|
||||
|
||||
void msg(char *format, ... ) {
|
||||
char buf[BUFLEN];
|
||||
va_list args;
|
||||
char *p;
|
||||
int db = B_FALSE;
|
||||
|
||||
va_start(args, format);
|
||||
vsprintf( buf, format, args );
|
||||
va_end(args);
|
||||
|
||||
if (db) dblog("adding to msgbuf: [%s]",buf);
|
||||
|
||||
// Move to just after the last '^' in the message buffer...
|
||||
p = strrchr(msgbuf, '^');
|
||||
if (p) {
|
||||
p++;
|
||||
} else {
|
||||
p = msgbuf;
|
||||
}
|
||||
|
||||
// ie. can we fit the new text + '--more--' ?
|
||||
if (strlen(p) + strlen(buf) + strlen(MORESTRING) >= SCREENW) {
|
||||
strcat(msgbuf, "^");
|
||||
} else {
|
||||
if (strlen(msgbuf) > 0) {
|
||||
strcat(msgbuf, " ");
|
||||
}
|
||||
}
|
||||
strcat(msgbuf, buf);
|
||||
|
||||
if (db) dblog(" msgbuf is now: [%s]",msgbuf);
|
||||
|
||||
}
|
||||
|
||||
void drawstatus(void) {
|
||||
char buf[BUFLEN];
|
||||
wclear(statwin);
|
||||
sprintf(buf, "[%-12s] HP: %d/%d","Player", player->hp,player->maxhp);
|
||||
mvwprintw(statwin, 0, 0, buf);
|
||||
//redraw();
|
||||
}
|
||||
|
||||
|
||||
void drawmsg(void) {
|
||||
char *tok,*nexttok;
|
||||
int db = B_FALSE;
|
||||
|
||||
// no messages to display?
|
||||
if (!strcmp(msgbuf, "")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: if it's a monster's turn, always do a more?
|
||||
nexttok = strstr(msgbuf, "^");
|
||||
if (!nexttok) {
|
||||
// just update msg with current text
|
||||
wclear(msgwin);
|
||||
mvwprintw(msgwin, 0, 0, "%s", msgbuf);
|
||||
wrefresh(msgwin);
|
||||
} else {
|
||||
while (nexttok) {
|
||||
char thistok[BUFLEN];
|
||||
int thistoklen;
|
||||
// print up to just before the "^" current token
|
||||
|
||||
// remember this token
|
||||
|
||||
thistoklen = nexttok - msgbuf;
|
||||
strncpy(thistok, msgbuf, thistoklen);
|
||||
thistok[thistoklen] = '\0';
|
||||
if (db) dblog("drawmsg: thistok is [%s]",thistok);
|
||||
|
||||
// is there another token?
|
||||
nexttok = strstr(msgbuf, "^");
|
||||
|
||||
if (nexttok) {
|
||||
char *p;
|
||||
nexttok++; // go forward past the ^
|
||||
if (db) dblog("drawmsg: nexttok is [%s]",nexttok);
|
||||
// print with '--more--' added to the end
|
||||
if (db) dblog("drawmsg: displaying thistok [%s]",thistok);
|
||||
wclear(msgwin);
|
||||
mvwprintw(msgwin, 0, 0, "%s%s", thistok,MORESTRING);
|
||||
wrefresh(msgwin);
|
||||
|
||||
// ...wait for spacebar before showing next bit...
|
||||
while (getch() != ' ');
|
||||
if (db) dblog("prompting for --more--");
|
||||
|
||||
// now clear msgstring up to end of where
|
||||
// 'thistok' appears!
|
||||
strcpy(msgbuf, nexttok);
|
||||
if (db) dblog(" reduced msgbuf to: [%s]",msgbuf);
|
||||
} else {
|
||||
if (db) dblog("drawmsg: no nexttok");
|
||||
// just print this bit
|
||||
wclear(msgwin);
|
||||
mvwprintw(msgwin, 0, 0, "%s", thistok);
|
||||
wrefresh(msgwin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// clear message buffer
|
||||
if (isplayerturn()) {
|
||||
strcpy(msgbuf, "");
|
||||
if (db) dblog("clearing msg buf");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void redraw(void) {
|
||||
//wrefresh(msgwin);
|
||||
wrefresh(statwin);
|
||||
wrefresh(gamewin);
|
||||
}
|
||||
|
||||
int savegame(void) {
|
||||
map_t *m;
|
||||
FILE *f;
|
||||
char buf[BUFLEN];
|
||||
int rv;
|
||||
for (m = firstmap; m ; m = m->next) {
|
||||
// save world
|
||||
rv = savemap(m);
|
||||
if (rv) {
|
||||
msg("Could not save map '%s'",m->name);
|
||||
return B_TRUE;
|
||||
}
|
||||
// save player + their objects
|
||||
sprintf(buf, "%s/game.sav",SAVEDIR);
|
||||
f = fopen(buf, "wt");
|
||||
if (!f) {
|
||||
msg("Could not open save file!");
|
||||
return B_TRUE;
|
||||
}
|
||||
savelf(f, player);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
void tombstone(lifeform_t *lf) {
|
||||
// clear screen
|
||||
wclear(mainwin);
|
||||
|
||||
centre(mainwin, 1, "R.I.P.\n");
|
||||
//printf("%s\n",lf->name);
|
||||
centre(mainwin, 2, "Player\n");// TODO: use player name here
|
||||
centre(mainwin, 3, "Killed by %s.\n",lf->lastdam);
|
||||
|
||||
wrefresh(mainwin);
|
||||
// wait for key...
|
||||
getch();
|
||||
|
||||
// close down graphics ready to quit
|
||||
// clear windows
|
||||
delwin(gamewin);
|
||||
delwin(statwin);
|
||||
delwin(msgwin);
|
||||
// clear screen
|
||||
wclear(mainwin);
|
||||
// close down curses
|
||||
curs_set(1);
|
||||
endwin();
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
#include <ncurses.h>
|
||||
#include "defs.h"
|
||||
|
||||
void anim(cell_t *src, cell_t *dst, char ch);
|
||||
object_t *askobject(obpile_t *op, char *title, int *count);
|
||||
cell_t *askcoords(char *prompt);
|
||||
void centre(WINDOW *win, int y, char *format, ... );
|
||||
int chartodir(char ch);
|
||||
void clearmsg(void);
|
||||
void describeob(object_t *o);
|
||||
void dodrop(obpile_t *op);
|
||||
void doinventory(obpile_t *op);
|
||||
void dopickup(lifeform_t *lf, obpile_t *op);
|
||||
void dothrow(obpile_t *op);
|
||||
void drawcell(cell_t *cell, int x, int y);
|
||||
void drawcursor(void);
|
||||
void drawlevelfor(lifeform_t *lf);
|
||||
void drawmsg(void);
|
||||
void drawscreen(void);
|
||||
void drawstatus(void);
|
||||
int getkey(void);
|
||||
void handleinput(void);
|
||||
int keycodetokey(int keycode);
|
||||
void more(void);
|
||||
void msg(char *format, ... );
|
||||
void dblog(char *format, ... );
|
||||
void redraw(void);
|
||||
int savequit(void);
|
||||
void tombstone(lifeform_t *lf);
|
||||
void updateviewfor(cell_t *cell);
|
|
@ -0,0 +1,639 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "defs.h"
|
||||
#include "flag.h"
|
||||
#include "lf.h"
|
||||
#include "map.h"
|
||||
#include "objects.h"
|
||||
|
||||
extern race_t *firstrace, *lastrace;
|
||||
extern lifeform_t *player;
|
||||
|
||||
|
||||
lifeform_t *addlf(cell_t *cell, enum RACE rid) {
|
||||
map_t *m;
|
||||
lifeform_t *a;
|
||||
int i;
|
||||
flag_t *f;
|
||||
|
||||
m = cell->map;
|
||||
|
||||
// add to the end of the list
|
||||
if (m->lf == NULL) {
|
||||
m->lf = malloc(sizeof(lifeform_t));
|
||||
a = m->lf;
|
||||
a->prev = NULL;
|
||||
} else {
|
||||
// go to end of list
|
||||
a = m->lastlf;
|
||||
a->next = malloc(sizeof(lifeform_t));
|
||||
a->next->prev = a;
|
||||
a = a->next;
|
||||
}
|
||||
m->lastlf = a;
|
||||
a->next = NULL;
|
||||
|
||||
// props
|
||||
a->id = m->nextlfid; m->nextlfid++;
|
||||
a->controller = C_AI;
|
||||
a->race = findrace(rid);
|
||||
a->hp = 10; // TODO: fix
|
||||
a->maxhp = 10; // TODO: fix
|
||||
a->cell = cell; // TODO: fix
|
||||
a->alive = B_TRUE;
|
||||
a->lastdam = strdup("nothing");
|
||||
a->timespent = 0;
|
||||
a->sorted = B_FALSE;
|
||||
|
||||
a->pack = addobpile(a, NOLOC);
|
||||
|
||||
// clear laoding variables
|
||||
for (i = 0; i < MAXPILEOBS; i++) {
|
||||
a->oblist[i] = -1;
|
||||
}
|
||||
a->x = -1;
|
||||
a->y = -1;
|
||||
|
||||
// inherit flags from race
|
||||
a->flags = addflagpile();
|
||||
for (f = a->race->flags->first ; f ; f = f->next) {
|
||||
addflag(a->flags, f->id, f->val[0], f->val[1], f->val[2], f->text);
|
||||
}
|
||||
|
||||
// update other things
|
||||
cell->lf = a;
|
||||
}
|
||||
|
||||
race_t *addrace(enum RACE id, char *name, char glyph) {
|
||||
race_t *a;
|
||||
|
||||
// add to the end of the list
|
||||
if (firstrace == NULL) {
|
||||
firstrace = malloc(sizeof(race_t));
|
||||
a = firstrace;
|
||||
a->prev = NULL;
|
||||
} else {
|
||||
// go to end of list
|
||||
a = lastrace;
|
||||
a->next = malloc(sizeof(race_t));
|
||||
a->next->prev = a;
|
||||
a = a->next;
|
||||
}
|
||||
lastrace = a;
|
||||
a->next = NULL;
|
||||
|
||||
// props
|
||||
a->id = id;
|
||||
a->name = strdup(name);
|
||||
a->glyph = glyph;
|
||||
|
||||
a->flags = addflagpile();
|
||||
}
|
||||
|
||||
void die(lifeform_t *lf) {
|
||||
char buf[BUFLEN];
|
||||
object_t *o, *nexto;
|
||||
flag_t *f;
|
||||
|
||||
lf->alive = B_FALSE;
|
||||
if (lf->controller == C_PLAYER) {
|
||||
// forec screen redraw so you see your hp = 0
|
||||
drawscreen();
|
||||
msg("You die.");
|
||||
more();
|
||||
// force msg redraw!
|
||||
drawmsg();
|
||||
} else {
|
||||
if (!hasflag(lf->flags, F_NODEATHANNOUNCE)) {
|
||||
if (haslos(player, lf->cell)) {
|
||||
getlfname(lf, buf);
|
||||
capitalise(buf);
|
||||
msg("%s dies.",buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// drop all objects
|
||||
while (lf->pack->first) {
|
||||
if (!moveob(lf->pack->first, lf->cell->obpile, ALL)) {
|
||||
killob(lf->pack->first);
|
||||
}
|
||||
}
|
||||
|
||||
// drop corpse
|
||||
f = hasflag(lf->flags, F_CORPSETYPE);
|
||||
if (f) {
|
||||
addob(lf->cell->obpile, f->text);
|
||||
}
|
||||
|
||||
if (lf->controller != C_PLAYER) {
|
||||
// kill lifeform
|
||||
killlf(lf);
|
||||
}
|
||||
}
|
||||
|
||||
lifeform_t *findlf(map_t *m, int lfid) {
|
||||
lifeform_t *lf;
|
||||
for (lf = m->lf ; lf ; lf = lf->next) {
|
||||
if (lf->id == lfid) return lf;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
race_t *findrace(enum RACE id) {
|
||||
race_t *r;
|
||||
for (r = firstrace; r ; r = r->next) {
|
||||
if (r->id == id) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int getattackspeed(lifeform_t *lf) {
|
||||
int speed = SPEED_ATTACK;
|
||||
flag_t *f;
|
||||
f = hasflag(lf->flags, F_ATTACKSPEED);
|
||||
if (f) {
|
||||
speed = f->val[0];
|
||||
}
|
||||
return speed;
|
||||
}
|
||||
|
||||
int getmovespeed(lifeform_t *lf) {
|
||||
int speed = SPEED_MOVE;
|
||||
flag_t *f;
|
||||
f = hasflag(lf->flags, F_MOVESPEED);
|
||||
if (f) {
|
||||
speed = f->val[0];
|
||||
}
|
||||
return speed;
|
||||
}
|
||||
|
||||
|
||||
char *getlfname(lifeform_t *lf, char *buf) {
|
||||
if (lf == player) {
|
||||
sprintf(buf, "you");
|
||||
} else {
|
||||
sprintf(buf, "the %s",lf->race->name);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
int haslof(lifeform_t *viewer, cell_t *dest) {
|
||||
int deltax, deltay;
|
||||
int numpixels;
|
||||
int d;
|
||||
int dinc1,dinc2,xinc1,xinc2,yinc1,yinc2;
|
||||
int xinc,yinc,dinc;
|
||||
int i;
|
||||
int x1,y1,dir;
|
||||
int x;
|
||||
int y;
|
||||
int maxvisrange;
|
||||
int modmaxvisrange;
|
||||
int xray = B_FALSE;
|
||||
int wentuphill = B_FALSE;
|
||||
int origheight;
|
||||
int shopwall;
|
||||
|
||||
int x2,y2;
|
||||
map_t *map;
|
||||
|
||||
// must have line of sight to fire...
|
||||
if (!haslos(viewer, dest)) return B_FALSE;
|
||||
|
||||
if (viewer->cell->map != dest->map) return B_FALSE;
|
||||
map = dest->map;
|
||||
|
||||
|
||||
x1 = viewer->cell->x;
|
||||
y1 = viewer->cell->y;
|
||||
x2 = dest->x;
|
||||
y2 = dest->y;
|
||||
|
||||
deltax = (x2 - x1);
|
||||
if (deltax < 0) deltax = -deltax;
|
||||
deltay = (y2 - y1);
|
||||
if (deltay < 0) deltay = -deltay;
|
||||
|
||||
// can always fire at your own cell
|
||||
if ((deltax == 0) && (deltay == 0)) {
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
if (deltax >= deltay) {
|
||||
numpixels = deltax + 1;
|
||||
d = (deltay*2) - deltax;
|
||||
dinc1 = deltay << 1;
|
||||
dinc2 = (deltay-deltax) << 1;
|
||||
xinc1 = 1;
|
||||
xinc2 = 1;
|
||||
yinc1 = 0;
|
||||
yinc2 = 1;
|
||||
} else {
|
||||
numpixels = deltay + 1;
|
||||
d = (deltax*2) - deltay;
|
||||
dinc1 = deltax << 1;
|
||||
dinc2 = (deltax - deltay) << 1;
|
||||
xinc1 = 0;
|
||||
xinc2 = 1;
|
||||
yinc1 = 1;
|
||||
yinc2 = 1;
|
||||
}
|
||||
|
||||
if (x1 > x2) {
|
||||
xinc1 = - xinc1;
|
||||
xinc2 = - xinc2;
|
||||
}
|
||||
if (y1 > y2) {
|
||||
yinc1 = - yinc1;
|
||||
yinc2 = - yinc2;
|
||||
}
|
||||
|
||||
x = x1; y = y1;
|
||||
|
||||
for (i = 0; i < numpixels ; i++) {
|
||||
cell_t *cell;
|
||||
|
||||
// don't need to move out of the last one
|
||||
if ((x == x2) && (y == y2)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (d < 0) {
|
||||
xinc = xinc1;
|
||||
yinc = yinc1;
|
||||
dinc = dinc1;
|
||||
} else {
|
||||
xinc = xinc2;
|
||||
yinc = yinc2;
|
||||
dinc = dinc2;
|
||||
}
|
||||
|
||||
// solid cells stop lof
|
||||
cell = getcellat(map, x, y);
|
||||
if (cell->type->solid) {
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
// move to next cell
|
||||
d += dinc;
|
||||
x += xinc;
|
||||
y += yinc;
|
||||
}
|
||||
|
||||
// made it to the target cell!
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
int haslos(lifeform_t *viewer, cell_t *dest) {
|
||||
int deltax, deltay;
|
||||
int numpixels;
|
||||
int d;
|
||||
int dinc1,dinc2,xinc1,xinc2,yinc1,yinc2;
|
||||
int xinc,yinc,dinc;
|
||||
int i;
|
||||
int x1,y1,dir;
|
||||
int x;
|
||||
int y;
|
||||
int maxvisrange;
|
||||
int modmaxvisrange;
|
||||
int xray = B_FALSE;
|
||||
int wentuphill = B_FALSE;
|
||||
int origheight;
|
||||
int shopwall;
|
||||
|
||||
int x2,y2;
|
||||
map_t *map;
|
||||
|
||||
if (viewer->cell->map != dest->map) return B_FALSE;
|
||||
map = dest->map;
|
||||
|
||||
|
||||
x1 = viewer->cell->x;
|
||||
y1 = viewer->cell->y;
|
||||
x2 = dest->x;
|
||||
y2 = dest->y;
|
||||
|
||||
|
||||
/*
|
||||
if (hasproplf(viewer, P_XRAYVISION)) {
|
||||
xray = getproplf(viewer, P_XRAYVISION);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
deltax = (x2 - x1);
|
||||
if (deltax < 0) deltax = -deltax;
|
||||
deltay = (y2 - y1);
|
||||
if (deltay < 0) deltay = -deltay;
|
||||
|
||||
// can always see your own cell
|
||||
if ((deltax == 0) && (deltay == 0)) {
|
||||
//if (viewer->controller == C_HUMAN) wreck->mazelev[z].maze[y2*MAZEW+x2].known = B_PERM;
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
if (hasproplf(viewer, P_BLINDED)) {
|
||||
return B_FALSE;
|
||||
}
|
||||
*/
|
||||
|
||||
if (deltax >= deltay) {
|
||||
numpixels = deltax + 1;
|
||||
d = (deltay*2) - deltax;
|
||||
dinc1 = deltay << 1;
|
||||
dinc2 = (deltay-deltax) << 1;
|
||||
xinc1 = 1;
|
||||
xinc2 = 1;
|
||||
yinc1 = 0;
|
||||
yinc2 = 1;
|
||||
} else {
|
||||
numpixels = deltay + 1;
|
||||
d = (deltax*2) - deltay;
|
||||
dinc1 = deltax << 1;
|
||||
dinc2 = (deltax - deltay) << 1;
|
||||
xinc1 = 0;
|
||||
xinc2 = 1;
|
||||
yinc1 = 1;
|
||||
yinc2 = 1;
|
||||
}
|
||||
|
||||
if (x1 > x2) {
|
||||
xinc1 = - xinc1;
|
||||
xinc2 = - xinc2;
|
||||
}
|
||||
if (y1 > y2) {
|
||||
yinc1 = - yinc1;
|
||||
yinc2 = - yinc2;
|
||||
}
|
||||
|
||||
x = x1; y = y1;
|
||||
|
||||
//maxvisrange = getvisrange(viewer, B_LIGHTDOESNTMATTER);
|
||||
maxvisrange = UNLIMITED;
|
||||
|
||||
/*
|
||||
if (hasproplf(viewer, P_SEEINDARK) || wreck->mazelev[viewer->z].lightlevel >= 100) {
|
||||
modmaxvisrange = maxvisrange;
|
||||
} else {
|
||||
modmaxvisrange = getvisrange(viewer, B_LIGHTMATTERS);
|
||||
}
|
||||
*/
|
||||
|
||||
//origheight = getheight(x1,y1,z);
|
||||
|
||||
// too far away
|
||||
if (maxvisrange != UNLIMITED) {
|
||||
if (getcelldist(viewer->cell, dest) > maxvisrange) {
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// outside our modified vision range, and not lit
|
||||
/*
|
||||
if (modmaxvisrange != UNLIMITED) {
|
||||
if (getdistance(x1,y1,x2,y2) > modmaxvisrange) {
|
||||
if (!xyislit(x2,y2,viewer->z)) {
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
//shopwall = B_FALSE;
|
||||
|
||||
for (i = 0; i < numpixels ; i++) {
|
||||
cell_t *cell;
|
||||
|
||||
// if we went uphill, stop here
|
||||
/*
|
||||
if (wentuphill) {
|
||||
return B_FALSE;
|
||||
}
|
||||
*/
|
||||
|
||||
// don't need to move out of the last one
|
||||
if ((x == x2) && (y == y2)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (d < 0) {
|
||||
xinc = xinc1;
|
||||
yinc = yinc1;
|
||||
dinc = dinc1;
|
||||
} else {
|
||||
xinc = xinc2;
|
||||
yinc = yinc2;
|
||||
dinc = dinc2;
|
||||
}
|
||||
|
||||
/*
|
||||
if (debug) {
|
||||
printf("checking LOS at %d,%d going (%d,%d)\n",x,y,xinc,yinc);
|
||||
fflush(stdout);
|
||||
}
|
||||
*/
|
||||
|
||||
// solid cells stop los
|
||||
cell = getcellat(map, x, y);
|
||||
if (!cell->type->transparent) {
|
||||
if (xray) xray--;
|
||||
else return B_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
// check for smoke
|
||||
if ((x != x1) || (y != y1)) { // if not in first cell
|
||||
if (hasopaqueobject(viewer, x,y,z) && (getheight(x,y,z) >= origheight)) {
|
||||
if (!hasproplf(viewer, P_SEEINSMOKE)) {
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// xray vision decreases by one
|
||||
if (xray) xray--;
|
||||
|
||||
// if you went uphill, can't see any further
|
||||
/*
|
||||
if (getheight(x,y,z) > origheight) {
|
||||
wentuphill = B_TRUE;
|
||||
}
|
||||
*/
|
||||
|
||||
// move to next cell
|
||||
d += dinc;
|
||||
x += xinc;
|
||||
y += yinc;
|
||||
}
|
||||
|
||||
// made it to the target cell!
|
||||
/*
|
||||
if (viewer->controller == C_HUMAN) wreck->mazelev[z].maze[y2*MAZEW+x2].known = B_PERM;
|
||||
if (viewer->controller == C_HUMAN) wreck->mazelev[z].maze[y2*MAZEW+x2].known = B_PERM;
|
||||
*/
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
|
||||
void initrace(void) {
|
||||
addrace(R_HUMAN, "human", '@');
|
||||
addflag(lastrace->flags, F_CORPSETYPE, -1, -1, -1, "human corpse");
|
||||
addflag(lastrace->flags, F_RARITY, H_DUNGEON, RR_RARE, -1, "");
|
||||
addrace(R_GOBLIN, "goblin", 'g');
|
||||
addflag(lastrace->flags, F_CORPSETYPE, -1, -1, -1, "goblin corpse");
|
||||
addflag(lastrace->flags, F_HOSTILE, B_TRUE, -1, -1, "");
|
||||
addflag(lastrace->flags, F_RARITY, H_DUNGEON, RR_COMMON, -1, "");
|
||||
addrace(R_BAT, "bat", 'B');
|
||||
addflag(lastrace->flags, F_CORPSETYPE, -1, -1, -1, "bat corpse");
|
||||
addflag(lastrace->flags, F_ATTACKSPEED, 5, -1, -1, "");
|
||||
addflag(lastrace->flags, F_MOVESPEED, 5, -1, -1, "");
|
||||
addflag(lastrace->flags, F_FLYING, B_TRUE, -1, -1, "");
|
||||
addflag(lastrace->flags, F_RARITY, H_DUNGEON, RR_COMMON, -1, "");
|
||||
addrace(R_GIANTFLY, "giant fly", 'I');
|
||||
addflag(lastrace->flags, F_CORPSETYPE, -1, -1, -1, "giant fly corpse");
|
||||
addflag(lastrace->flags, F_MOVESPEED, 2, -1, -1, "");
|
||||
addflag(lastrace->flags, F_FLYING, B_TRUE, -1, -1, "");
|
||||
addflag(lastrace->flags, F_RARITY, H_DUNGEON, RR_COMMON, -1, "");
|
||||
addrace(R_GIANTBLOWFLY, "giant blowfly", 'I');
|
||||
addflag(lastrace->flags, F_CORPSETYPE, -1, -1, -1, "giant fly corpse");
|
||||
addflag(lastrace->flags, F_MOVESPEED, 2, -1, -1, "");
|
||||
addflag(lastrace->flags, F_FLYING, B_TRUE, -1, -1, "");
|
||||
addflag(lastrace->flags, F_RARITY, H_DUNGEON, RR_UNCOMMON, -1, "");
|
||||
}
|
||||
|
||||
int isdead(lifeform_t *lf) {
|
||||
if (!lf->alive) return B_TRUE;
|
||||
if (lf->hp <= 0) return B_TRUE;
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
void killlf(lifeform_t *lf) {
|
||||
int i;
|
||||
lifeform_t *nextone, *lastone;
|
||||
map_t *m;
|
||||
|
||||
m = lf->cell->map;
|
||||
|
||||
// remove references
|
||||
lf->cell->lf = NULL;
|
||||
|
||||
// free mem
|
||||
if (lf->lastdam) free(lf->lastdam);
|
||||
|
||||
// kill any remaining obs
|
||||
while (lf->pack->first) {
|
||||
killob(lf->pack->first);
|
||||
}
|
||||
// kill object pile
|
||||
free(lf->pack);
|
||||
|
||||
// kill flags
|
||||
while (lf->flags->first) {
|
||||
killflag(lf->flags->first);
|
||||
}
|
||||
killflagpile(lf->flags);
|
||||
|
||||
// remove from list
|
||||
nextone = lf->next;
|
||||
if (nextone != NULL) {
|
||||
nextone->prev = lf->prev;
|
||||
} else { /* last */
|
||||
m->lastlf = lf->prev;
|
||||
}
|
||||
|
||||
if (lf->prev == NULL) {
|
||||
/* first */
|
||||
nextone = lf->next;
|
||||
free(m->lf);
|
||||
m->lf = nextone;
|
||||
} else {
|
||||
lastone = lf->prev;
|
||||
free (lastone->next );
|
||||
lastone->next = nextone;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void killrace(race_t *race) {
|
||||
int i;
|
||||
race_t *nextone, *lastone;
|
||||
|
||||
// free mem
|
||||
free(race->name);
|
||||
|
||||
// remove from list
|
||||
nextone = race->next;
|
||||
if (nextone != NULL) {
|
||||
nextone->prev = race->prev;
|
||||
} else { /* last */
|
||||
lastrace = race->prev;
|
||||
}
|
||||
|
||||
if (race->prev == NULL) {
|
||||
/* first */
|
||||
nextone = race->next;
|
||||
free(race);
|
||||
race = nextone;
|
||||
} else {
|
||||
lastone = race->prev;
|
||||
free (lastone->next );
|
||||
lastone->next = nextone;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void losehp(lifeform_t *lf, int amt, lifeform_t *fromlf, char *damsrc) {
|
||||
char buf[BUFLEN];
|
||||
lf->hp -= amt;
|
||||
if (lf->lastdam) {
|
||||
free(lf->lastdam);
|
||||
}
|
||||
|
||||
// replace 'the' at start of damsrc with 'a'
|
||||
if (strstr(damsrc, "the ") == damsrc) {
|
||||
sprintf(buf, "a %s", (damsrc+4));
|
||||
} else {
|
||||
strcpy(buf, damsrc);
|
||||
}
|
||||
lf->lastdam = strdup(buf);
|
||||
|
||||
// they will now fight back!
|
||||
if (fromlf && !isdead(lf)) {
|
||||
if (lf->controller != C_PLAYER) {
|
||||
if (!hasflagval(lf->flags, F_TARGET, fromlf->id, -1, -1, "")) {
|
||||
addflag(lf->flags, F_TARGET, fromlf->id, -1, -1, "");
|
||||
// announce
|
||||
if (haslos(player, lf->cell)) {
|
||||
char fromlfname[BUFLEN];
|
||||
char lfname[BUFLEN];
|
||||
getlfname(fromlf, fromlfname);
|
||||
getlfname(lf, lfname);
|
||||
capitalise(lfname);
|
||||
msg("%s turns to attack %s!", lfname,
|
||||
haslos(player, fromlf->cell) ? fromlfname : "something");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// give initial equiment to a lifeform
|
||||
void outfitlf(lifeform_t *lf) {
|
||||
if (lf->controller == C_PLAYER) {
|
||||
addob(lf->pack, "10 gold");
|
||||
}
|
||||
}
|
||||
|
||||
void taketime(lifeform_t *lf, int howlong) {
|
||||
// inc timespent
|
||||
lf->timespent += howlong;
|
||||
// TODO: decrement lifeform's (or their object's) temporary flags
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#include "defs.h"
|
||||
|
||||
|
||||
lifeform_t *addlf(cell_t *cell, enum RACE rid);
|
||||
race_t *addrace(enum RACE id, char *name, char glyph);
|
||||
void die(lifeform_t *lf);
|
||||
lifeform_t *findlf(map_t *m, int lfid);
|
||||
race_t *findrace(enum RACE id);
|
||||
int getattackspeed(lifeform_t *lf);
|
||||
int getmovespeed(lifeform_t *lf);
|
||||
char *getlfname(lifeform_t *lf, char *buf);
|
||||
int haslof(lifeform_t *viewer, cell_t *dest);
|
||||
int haslos(lifeform_t *viewer, cell_t *dest);
|
||||
void initrace(void);
|
||||
int isdead(lifeform_t *lf);
|
||||
void killlf(lifeform_t *lf);
|
||||
void killrace(race_t *race);
|
||||
void losehp(lifeform_t *lf, int amt, lifeform_t *fromlf, char *damsrc);
|
||||
void taketime(lifeform_t *lf, int howlong);
|
|
@ -0,0 +1,939 @@
|
|||
|
||||
|
||||
|
||||
====== NEW LOGFILE ====
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 9 stone to cell 38,2
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 3 stone to cell 25,3
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 9 stone to cell 51,4
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 21 gold coin to cell 5,5
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 56 gold coin to cell 5,6
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 79 gold coin to cell 23,6
|
||||
adding random object of rarity 3
|
||||
|
||||
no possible objects like this. trying again with rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 2 stone to cell 50,6
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 8 stone to cell 39,7
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 4 stone to cell 9,8
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 65 gold coin to cell 12,9
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 16 gold coin to cell 12,10
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 99 gold coin to cell 37,10
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 17 gold coin to cell 49,11
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 79 gold coin to cell 51,11
|
||||
adding random object of rarity 3
|
||||
|
||||
no possible objects like this. trying again with rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 31 gold coin to cell 2,12
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 8 stone to cell 31,12
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 4 stone to cell 35,15
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 22 gold coin to cell 60,15
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 42 gold coin to cell 39,17
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 7 stone to cell 10,18
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 37 gold coin to cell 14,18
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 3 stone to cell 34,18
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 95 gold coin to cell 55,18
|
||||
adding random object of rarity 3
|
||||
|
||||
no possible objects like this. trying again with rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 2 stone to cell 23,20
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 46 gold coin to cell 39,20
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 4 stone to cell 52,21
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 92 gold coin to cell 21,24
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 10 stone to cell 20,25
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 54 gold coin to cell 6,26
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 29 gold coin to cell 44,26
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 77 gold coin to cell 52,27
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 40 gold coin to cell 48,31
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 44 gold coin to cell 24,33
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 6 stone to cell 3,35
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 62 gold coin to cell 24,35
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 14 gold coin to cell 21,36
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 1 stone to cell 46,38
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 3 stone to cell 2,39
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 7 stone to cell 44,40
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 71 gold coin to cell 11,41
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 11 gold coin to cell 12,41
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 5 stone to cell 28,41
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 1 stone to cell 10,42
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 28 gold coin to cell 30,46
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 13 gold coin to cell 7,47
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 44 gold coin to cell 15,47
|
||||
--> Will add 9 objects to room 0 (of 23)
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 7 stone to cell 21,17
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 17 gold coin to cell 24,3
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 88 gold coin to cell 12,27
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 2 stone to cell 25,21
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 33 gold coin to cell 25,26
|
||||
adding random object of rarity 3
|
||||
|
||||
no possible objects like this. trying again with rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 86 gold coin to cell 20,9
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 90 gold coin to cell 1,47
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 31 gold coin to cell 48,9
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 91 gold coin to cell 7,1
|
||||
--> Will add 12 objects to room 1 (of 23)
|
||||
adding random object of rarity 4
|
||||
|
||||
no possible objects like this. trying again with rarity 3
|
||||
|
||||
no possible objects like this. trying again with rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 94 gold coin to cell 53,16
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 6 stone to cell 57,19
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 2 stone to cell 54,16
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 5 stone to cell 49,16
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 1 stone to cell 61,16
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 8 stone to cell 52,20
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 4 stone to cell 50,20
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 5 stone to cell 55,19
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 10 stone to cell 58,21
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 3 stone to cell 60,14
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 6 stone to cell 59,20
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 3 stone to cell 50,16
|
||||
--> Will add 3 pillars
|
||||
--> Will add 10 objects to room 2 (of 23)
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 7 stone to cell 6,7
|
||||
adding random object of rarity 3
|
||||
|
||||
no possible objects like this. trying again with rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 9 stone to cell 3,5
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 94 gold coin to cell 6,1
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 3 stone to cell 3,8
|
||||
adding random object of rarity 3
|
||||
|
||||
no possible objects like this. trying again with rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 5 stone to cell 3,7
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 5 stone to cell 4,2
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 71 gold coin to cell 2,4
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 31 gold coin to cell 1,9
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 4 stone to cell 5,1
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 10 stone to cell 6,2
|
||||
--> Will add 4 objects to room 3 (of 23)
|
||||
adding random object of rarity 3
|
||||
|
||||
no possible objects like this. trying again with rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 53 gold coin to cell 24,29
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 6 stone to cell 27,30
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 58 gold coin to cell 30,28
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 35 gold coin to cell 35,29
|
||||
--> Will add 5 objects to room 4 (of 23)
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 7 stone to cell 4,37
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 8 stone to cell 2,35
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 5 stone to cell 1,37
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 35 gold coin to cell 5,38
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 10 stone to cell 3,38
|
||||
--> Will add 3 objects to room 5 (of 23)
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 9 stone to cell 50,41
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 21 gold coin to cell 50,39
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 1 stone to cell 42,40
|
||||
--> Will add 5 objects to room 6 (of 23)
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 2 stone to cell 50,29
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 6 stone to cell 43,25
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 10 stone to cell 45,32
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 56 gold coin to cell 47,29
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 1 stone to cell 46,29
|
||||
--> Will add 1 objects to room 7 (of 23)
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 9 stone to cell 38,4
|
||||
--> Will add 9 objects to room 8 (of 23)
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 37 gold coin to cell 14,43
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 1 stone to cell 17,44
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 73 gold coin to cell 11,42
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 4 stone to cell 18,47
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 3 stone to cell 20,46
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 10 stone to cell 15,40
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 84 gold coin to cell 11,46
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 3 stone to cell 19,48
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 9 stone to cell 9,44
|
||||
--> Will add 7 objects to room 9 (of 23)
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 3 stone to cell 42,46
|
||||
adding random object of rarity 3
|
||||
|
||||
no possible objects like this. trying again with rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 5 stone to cell 37,47
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 99 gold coin to cell 44,43
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 9 stone to cell 45,43
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 1 gold coin to cell 37,45
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 3 stone to cell 35,43
|
||||
adding random object of rarity 3
|
||||
|
||||
no possible objects like this. trying again with rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 5 stone to cell 43,47
|
||||
--> Will add 2 objects to room 10 (of 23)
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 7 stone to cell 41,8
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 8 gold coin to cell 40,9
|
||||
--> Will add 4 objects to room 11 (of 23)
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 3 stone to cell 18,7
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 13 gold coin to cell 30,4
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 6 stone to cell 32,5
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 1 gold coin to cell 29,6
|
||||
--> Will add 5 objects to room 12 (of 23)
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 66 gold coin to cell 18,36
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 7 stone to cell 17,39
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 14 gold coin to cell 17,37
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 9 stone to cell 14,37
|
||||
adding random object of rarity 4
|
||||
|
||||
no possible objects like this. trying again with rarity 3
|
||||
|
||||
no possible objects like this. trying again with rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 25 gold coin to cell 18,38
|
||||
--> Will add 7 objects to room 13 (of 23)
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 50 gold coin to cell 28,46
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 7 gold coin to cell 27,45
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 4 stone to cell 29,43
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 26 gold coin to cell 26,46
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 34 gold coin to cell 25,47
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 1 stone to cell 26,42
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 4 stone to cell 22,45
|
||||
--> Will add 5 objects to room 14 (of 23)
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 32 gold coin to cell 9,23
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 7 stone to cell 19,20
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 1 stone to cell 17,17
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 2 stone to cell 17,18
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 24 gold coin to cell 14,19
|
||||
--> Will add 11 objects to room 15 (of 23)
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 57 gold coin to cell 33,38
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 2 stone to cell 39,38
|
||||
adding random object of rarity 3
|
||||
|
||||
no possible objects like this. trying again with rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 30 gold coin to cell 40,41
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 16 gold coin to cell 34,39
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 71 gold coin to cell 31,39
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 10 stone to cell 41,39
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 39 gold coin to cell 39,39
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 7 stone to cell 40,40
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 2 stone to cell 30,41
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 2 stone to cell 31,40
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 3 stone to cell 34,41
|
||||
--> Will add 0 objects to room 16 (of 23)
|
||||
--> Will add 2 pillars
|
||||
--> Will add 10 objects to room 17 (of 23)
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 50 gold coin to cell 1,31
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 1 stone to cell 2,30
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 74 gold coin to cell 4,24
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 96 gold coin to cell 4,25
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 84 gold coin to cell 1,23
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 5 stone to cell 2,29
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 4 stone to cell 2,23
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 52 gold coin to cell 4,31
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 32 gold coin to cell 3,22
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 7 stone to cell 1,28
|
||||
--> Will add 7 objects to room 18 (of 23)
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 41 gold coin to cell 7,8
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 55 gold coin to cell 17,10
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 7 stone to cell 15,10
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 2 stone to cell 15,13
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 87 gold coin to cell 17,7
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 9 stone to cell 14,6
|
||||
adding random object of rarity 3
|
||||
|
||||
no possible objects like this. trying again with rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 46 gold coin to cell 8,12
|
||||
--> Will add 2 objects to room 19 (of 23)
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 28 gold coin to cell 23,12
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 65 gold coin to cell 28,13
|
||||
--> Will add 7 objects to room 20 (of 23)
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 5 gold coin to cell 1,17
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 57 gold coin to cell 3,16
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 1 stone to cell 2,19
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 28 gold coin to cell 2,16
|
||||
adding random object of rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 32 gold coin to cell 4,14
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 5 gold coin to cell 4,16
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 51 gold coin to cell 3,15
|
||||
--> Will add 1 objects to room 21 (of 23)
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 56 gold coin to cell 43,21
|
||||
--> Will add 15 objects to room 22 (of 23)
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 44 gold coin to cell 22,3
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 57 gold coin to cell 12,2
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 86 gold coin to cell 18,3
|
||||
adding random object of rarity 3
|
||||
|
||||
no possible objects like this. trying again with rarity 2
|
||||
|
||||
no possible objects like this. trying again with rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 7 stone to cell 15,1
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 39 gold coin to cell 10,3
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 9 stone to cell 18,1
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 60 gold coin to cell 14,1
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 39 gold coin to cell 20,2
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 8 stone to cell 11,1
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 4 stone to cell 15,2
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 93 gold coin to cell 17,3
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 83 gold coin to cell 19,1
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 7 stone to cell 12,1
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 9 stone to cell 23,2
|
||||
adding random object of rarity 1
|
||||
|
||||
got 2 possibilities.
|
||||
adding 18 gold coin to cell 21,2
|
||||
Finished adding objects.
|
||||
AIMOVE: bat
|
||||
AIMOVE: bat
|
||||
AIMOVE: bat
|
||||
AIMOVE: bat
|
||||
AIMOVE: bat
|
||||
AIMOVE: bat
|
||||
AIMOVE: bat
|
||||
AIMOVE: bat
|
||||
AIMOVE: bat
|
||||
AIMOVE: bat
|
||||
AIMOVE: bat
|
||||
AIMOVE: bat
|
||||
AIMOVE: bat
|
||||
AIMOVE: bat
|
||||
AIMOVE: bat
|
|
@ -0,0 +1,29 @@
|
|||
#include "defs.h"
|
||||
|
||||
cell_t *addcell(map_t *map, int x, int y);
|
||||
map_t *addmap(void);
|
||||
void addrandomthing(cell_t *c);
|
||||
cell_t *getcellat(map_t *map, int x, int y);
|
||||
int getcelldist(cell_t *src, cell_t *dst);
|
||||
int calcroompos(map_t *map, int w, int h, int *bx, int *by);
|
||||
int countadjcellsoftype(cell_t *cell, int id);
|
||||
int countcellexits(cell_t *cell);
|
||||
void createmap(map_t *map, int habitat);
|
||||
void createroom(map_t *map, int minx, int miny, int w, int h, int roomid);
|
||||
int dirtox(int dt, int dir);
|
||||
int dirtoy(int dt, int dir);
|
||||
void dumpmap(map_t *map);
|
||||
map_t *findmap(int mid);
|
||||
cell_t *getcellindir(cell_t *cell, int dir);
|
||||
int getnewdigdir(cell_t *cell, int lastdir, int turnpct, int *moved);
|
||||
int getobchance(int habitat);
|
||||
cell_t *getrandomcell(map_t *map);
|
||||
cell_t *getrandomcelloftype(map_t *map, int id);
|
||||
int getrandomdir(int dirtype);
|
||||
cell_t *getrandomroomcell(map_t *map, int roomid);
|
||||
int isloopdirok(cell_t *cell, int dir);
|
||||
int isnewcellok(cell_t *cell, char *err);
|
||||
int isonmap(map_t *map, int x, int y);
|
||||
int iswallindir(cell_t *cell, int dir);
|
||||
void makedoor(cell_t *cell);
|
||||
void setcelltype(cell_t *cell, int id);
|
|
@ -0,0 +1,5 @@
|
|||
When modifying the object_t structure:
|
||||
|
||||
- update obpropsmatch()
|
||||
- update isplainob()
|
||||
- update addobject()
|
|
@ -0,0 +1,146 @@
|
|||
#include <stdio.h>
|
||||
#include "attack.h"
|
||||
#include "defs.h"
|
||||
#include "map.h"
|
||||
|
||||
extern lifeform_t *player;
|
||||
|
||||
int canmove(lifeform_t *lf, int dir, enum ERROR *error) {
|
||||
cell_t *cell;
|
||||
|
||||
cell = getcellindir(lf->cell, dir);
|
||||
|
||||
if (cell->type->solid) {
|
||||
if (error) *error = E_WALLINWAY;
|
||||
return B_FALSE;
|
||||
}
|
||||
if (cell->lf) {
|
||||
if (error) *error = E_LFINWAY;
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
void dorandommove(lifeform_t *lf) {
|
||||
int dir;
|
||||
int tries = 0;
|
||||
dir = getrandomdir(DT_COMPASS);
|
||||
while (trymove(lf, dir)) {
|
||||
if (++dir > DC_NW) dir = DC_N;
|
||||
if (++tries >= MAXDIR_COMPASS) {
|
||||
dowait(lf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int dowait(lifeform_t *lf) {
|
||||
taketime(lf, SPEED_WAIT);
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
void movelf(lifeform_t *lf, cell_t *newcell) {
|
||||
// update current cell
|
||||
lf->cell->lf = NULL;
|
||||
|
||||
// update lifeform
|
||||
lf->cell = newcell;
|
||||
|
||||
// update new cell
|
||||
newcell->lf = lf;
|
||||
|
||||
}
|
||||
|
||||
// basically this is a warpper for 'movelf' which
|
||||
// does other game things like telling the player
|
||||
// what is here.
|
||||
int moveto(lifeform_t *lf, cell_t *newcell) {
|
||||
|
||||
// actually do the move
|
||||
movelf(lf, newcell);
|
||||
|
||||
// tell player about things
|
||||
if (lf->controller == C_PLAYER) {
|
||||
int numobs;
|
||||
char buf[BUFLEN];
|
||||
numobs = countobs(newcell->obpile);
|
||||
if (numobs == 1) {
|
||||
getobname(newcell->obpile->first, buf, newcell->obpile->first->amt);
|
||||
msg("You see %s here.", buf);
|
||||
} else if ((numobs > 1) && (numobs <= 3)) {
|
||||
msg("You see a few objects here.");
|
||||
} else if ((numobs > 3) && (numobs <= 6)) {
|
||||
msg("You see some objects here.");
|
||||
} else if (numobs > 6) {
|
||||
msg("You see many objects here.");
|
||||
} else {
|
||||
// just clear the message buffer
|
||||
clearmsg();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int opendoor(lifeform_t *lf, cell_t *cell) {
|
||||
char buf[BUFLEN];
|
||||
if (cell->type->id == CT_DOORCLOSED) {
|
||||
// open it
|
||||
setcelltype(cell, CT_DOOROPEN);
|
||||
if (lf->controller == C_PLAYER) {
|
||||
msg("You open a door.");
|
||||
} else {
|
||||
// TODO: only announce if player can see it
|
||||
if (haslos(player, cell)) {
|
||||
getlfname(lf, buf);
|
||||
capitalise(buf);
|
||||
msg("%s opens a door.",buf);
|
||||
}
|
||||
}
|
||||
taketime(lf, getmovespeed(lf));
|
||||
} else {
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
int tryrun(lifeform_t *lf, int dir) {
|
||||
// continue moving until we fail
|
||||
while (canmove(lf, dir, NULL)) {
|
||||
trymove(lf,dir);
|
||||
}
|
||||
}
|
||||
|
||||
int trymove(lifeform_t *lf, int dir) {
|
||||
cell_t *cell;
|
||||
enum ERROR errcode;
|
||||
char buf[BUFLEN], buf2[BUFLEN];
|
||||
|
||||
cell = getcellindir(lf->cell, dir);
|
||||
if (canmove(lf, dir, &errcode)) {
|
||||
moveto(lf, cell);
|
||||
taketime(lf, getmovespeed(lf));
|
||||
} else {
|
||||
switch (errcode) {
|
||||
case E_WALLINWAY:
|
||||
// is it a door in the way?
|
||||
if (cell->type->id == CT_DOORCLOSED) {
|
||||
// try to open it
|
||||
opendoor(lf, cell);
|
||||
} else {
|
||||
if (lf->controller == C_PLAYER) {
|
||||
msg("Ouch! You walk into a wall.");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case E_LFINWAY:
|
||||
// attack!
|
||||
doattack(lf, cell->lf);
|
||||
break;
|
||||
}
|
||||
return B_TRUE;
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
#include "defs.h"
|
||||
|
||||
int canmove(lifeform_t *lf, int dir, enum ERROR *error);
|
||||
void dorandommove(lifeform_t *lf);
|
||||
int dowait(lifeform_t *lf);
|
||||
void movelf(lifeform_t *lf, cell_t *newcell);
|
||||
int moveto(lifeform_t *lf, cell_t *newcell);
|
||||
int trymove(lifeform_t *lf, int dir);
|
|
@ -0,0 +1,297 @@
|
|||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "io.h"
|
||||
#include "lf.h"
|
||||
#include "map.h"
|
||||
#include "nexus.h"
|
||||
#include "objects.h"
|
||||
#include "save.h"
|
||||
|
||||
material_t *material = NULL,*lastmaterial = NULL;
|
||||
objectclass_t *objectclass = NULL,*lastobjectclass = NULL;
|
||||
objecttype_t *objecttype = NULL,*lastobjecttype = NULL;
|
||||
celltype_t *firstcelltype = NULL,*lastcelltype = NULL;
|
||||
race_t *firstrace = NULL,*lastrace = NULL;
|
||||
map_t *firstmap = NULL,*lastmap = NULL;
|
||||
|
||||
FILE *logfile;
|
||||
|
||||
enum ERROR reason; // global for returning errors
|
||||
|
||||
lifeform_t *player = NULL;
|
||||
int gameover;
|
||||
|
||||
int gamestarted = B_FALSE;
|
||||
|
||||
int main(char **argv, int argc) {
|
||||
int newworld = B_FALSE;
|
||||
|
||||
atexit(cleanup);
|
||||
|
||||
// init params
|
||||
init();
|
||||
|
||||
// load whatever maps are available
|
||||
loadall();
|
||||
|
||||
// init graphics
|
||||
initgfx();
|
||||
|
||||
// if no maps, make the initial level
|
||||
if (!firstmap) {
|
||||
newworld = B_TRUE;
|
||||
addmap();
|
||||
createmap(firstmap, H_DUNGEON);
|
||||
}
|
||||
|
||||
// if no player, add them
|
||||
if (!player) {
|
||||
msg("Welcome to %snexus!", newworld ? "the new " : "");
|
||||
more();
|
||||
player = addlf(getrandomcelloftype(firstmap, CT_ROOM), R_HUMAN);
|
||||
player->controller = C_PLAYER;
|
||||
outfitlf(player);
|
||||
addlf(getcellindir(player->cell, D_N), R_BAT);
|
||||
} else {
|
||||
msg("Welcome back!");
|
||||
more();
|
||||
}
|
||||
|
||||
|
||||
// start game - this will cause debug messages to now
|
||||
// go to the log file instead of stdout.
|
||||
gamestarted = B_TRUE;
|
||||
|
||||
|
||||
// show level
|
||||
drawscreen();
|
||||
|
||||
// MAIN LOOP
|
||||
gameover = B_FALSE;
|
||||
while (!gameover) {
|
||||
|
||||
// someone has a turn
|
||||
donextturn(player->cell->map);
|
||||
// update lifeform structue to figure out who goes next
|
||||
sortlf(player->cell->map);
|
||||
|
||||
// TODO: monsters move etc
|
||||
|
||||
// check for death etc
|
||||
doeffects();
|
||||
|
||||
// show level
|
||||
drawscreen();
|
||||
|
||||
// check end of game
|
||||
checkendgame();
|
||||
|
||||
}
|
||||
|
||||
// print tombstone
|
||||
tombstone(player);
|
||||
}
|
||||
|
||||
celltype_t *addcelltype(int id, char glyph, int solid, int transparent) {
|
||||
celltype_t *a;
|
||||
|
||||
// add to the end of the list
|
||||
if (firstcelltype == NULL) {
|
||||
firstcelltype = malloc(sizeof(celltype_t));
|
||||
a = firstcelltype;
|
||||
a->prev = NULL;
|
||||
} else {
|
||||
// go to end of list
|
||||
a = lastcelltype;
|
||||
a->next = malloc(sizeof(celltype_t));
|
||||
a->next->prev = a;
|
||||
a = a->next;
|
||||
}
|
||||
lastcelltype = a;
|
||||
a->next = NULL;
|
||||
|
||||
// set props
|
||||
a->id = id;
|
||||
a->glyph = glyph;
|
||||
a->solid = solid;
|
||||
a->transparent = transparent;
|
||||
}
|
||||
|
||||
void checkendgame(void) {
|
||||
if (!player->alive) {
|
||||
gameover = B_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
void cleanup(void) {
|
||||
fclose(logfile);
|
||||
cleanupgfx();
|
||||
}
|
||||
|
||||
|
||||
void doeffects(void) {
|
||||
lifeform_t *lf;
|
||||
// check for death
|
||||
for (lf = player->cell->map->lf; lf ; lf = lf->next) {
|
||||
if (lf->hp <= 0) {
|
||||
// die!
|
||||
die(lf);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void donextturn(map_t *map) {
|
||||
lifeform_t *who;
|
||||
|
||||
// show messages to plaeyr
|
||||
drawmsg();
|
||||
|
||||
who = map->lf;
|
||||
if (who->controller == C_PLAYER) {
|
||||
drawcursor();
|
||||
// find out what player wants to do
|
||||
handleinput();
|
||||
} else {
|
||||
// TODO: do ai move
|
||||
aimove(who);
|
||||
}
|
||||
|
||||
// everyone else's time goes down by 1
|
||||
for (who = map->lf->next ; who ; who = who->next ){
|
||||
if (who->timespent > 0) who->timespent--;
|
||||
}
|
||||
}
|
||||
|
||||
celltype_t *findcelltype(int id) {
|
||||
celltype_t *ct;
|
||||
for (ct = firstcelltype; ct ; ct = ct->next) {
|
||||
if (ct->id == id) {
|
||||
return ct;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *getdirname(int dir) {
|
||||
switch (dir) {
|
||||
case D_N:
|
||||
return "North";
|
||||
case D_E:
|
||||
return "East";
|
||||
case D_S:
|
||||
return "South";
|
||||
case D_W:
|
||||
return "West";
|
||||
case D_UNKNOWN:
|
||||
return "D_UNKNOWN";
|
||||
case D_NONE:
|
||||
return "D_NONE";
|
||||
}
|
||||
return "?errordir?";
|
||||
}
|
||||
|
||||
int init(void) {
|
||||
// random numbers
|
||||
srand(time(NULL));
|
||||
|
||||
// open log file
|
||||
logfile = fopen("log.txt","wt");
|
||||
fprintf(logfile, "\n\n\n====== NEW LOGFILE ====\n");
|
||||
|
||||
// cell types
|
||||
addcelltype(CT_WALL, '#', B_SOLID, B_OPAQUE);
|
||||
addcelltype(CT_ROOMWALL, '#', B_SOLID, B_OPAQUE);
|
||||
addcelltype(CT_CORRIDOR, '.', B_EMPTY, B_TRANS);
|
||||
addcelltype(CT_LOOPCORRIDOR, 'L', B_EMPTY, B_TRANS);
|
||||
addcelltype(CT_ROOM, '.', B_EMPTY, B_TRANS);
|
||||
addcelltype(CT_DOOROPEN, '-', B_EMPTY, B_TRANS);
|
||||
addcelltype(CT_DOORCLOSED, '+', B_SOLID, B_OPAQUE);
|
||||
|
||||
initobjects();
|
||||
|
||||
initrace();
|
||||
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
int isplayerturn(void) {
|
||||
if (player->cell->map->lf->controller == C_PLAYER) {
|
||||
return B_TRUE;
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
// get a random number
|
||||
int rnd(int min, int max) {
|
||||
int res;
|
||||
res = (rand() % (max - min + 1)) + min;
|
||||
return res;
|
||||
}
|
||||
|
||||
// sort map's lifeform list by time spent
|
||||
void sortlf(map_t *map) {
|
||||
int donesomething;
|
||||
lifeform_t *l;
|
||||
int adjustby;
|
||||
int db = B_FALSE;
|
||||
|
||||
// bubblesort
|
||||
if (db) {
|
||||
dblog("BEFORE sortlf():");
|
||||
for (l = map->lf ; l ; l = l->next) {
|
||||
dblog("- %s (timespent= %d) (sorted=%d)", (l == player) ? "player" : l->race->name, l->timespent,l->sorted);
|
||||
}
|
||||
}
|
||||
|
||||
donesomething = B_TRUE;
|
||||
while (donesomething) {
|
||||
donesomething = B_FALSE;
|
||||
for (l = map->lf ; l ; l = l->next) {
|
||||
if (!l->sorted && l->next && (l->timespent > l->next->timespent) ) {
|
||||
lifeform_t *temp;
|
||||
// remember next element
|
||||
temp = l->next;
|
||||
|
||||
// remove this element from list
|
||||
if (l->prev == NULL) {
|
||||
// first
|
||||
map->lf = l->next;
|
||||
} else {
|
||||
// not first
|
||||
l->prev->next = l->next;
|
||||
}
|
||||
// don't bother checking for next - we know ther eis one.
|
||||
l->next->prev = l->prev;
|
||||
|
||||
// re-add element afterwards
|
||||
l->next = temp->next;
|
||||
l->prev = temp;
|
||||
temp->next = l;
|
||||
if (l->next == NULL) map->lastlf = l;
|
||||
|
||||
donesomething = B_TRUE;
|
||||
} else {
|
||||
l->sorted = B_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (db) {
|
||||
dblog("AFTER SORT:");
|
||||
for (l = map->lf ; l ; l = l->next) {
|
||||
dblog("- %s (timespent= %d) (sorted=%d)", (l == player) ? "player" : l->race->name, l->timespent,l->sorted);
|
||||
}
|
||||
}
|
||||
|
||||
// now go through the list and make the first element be 0
|
||||
adjustby = map->lf->timespent;
|
||||
for (l = map->lf ; l ; l = l->next) {
|
||||
l->timespent -= adjustby;
|
||||
l->sorted = B_FALSE;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
#include "defs.h"
|
||||
|
||||
celltype_t *addcelltype(int id, char glyph, int solid, int transparent);
|
||||
void checkendgame(void);
|
||||
void cleanup(void);
|
||||
void doeffects(void);
|
||||
void donextturn(map_t *map);
|
||||
celltype_t *findcelltype(int id);
|
||||
char *getdirname(int dir);
|
||||
int init(void);
|
||||
int isplayerturn(void);
|
||||
int rnd(int min, int max);
|
||||
void sortlf(map_t *map);
|
|
@ -0,0 +1,940 @@
|
|||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "defs.h"
|
||||
#include "flag.h"
|
||||
#include "objects.h"
|
||||
#include "text.h"
|
||||
|
||||
extern objecttype_t *objecttype,*lastobjecttype;
|
||||
extern objectclass_t *objectclass,*lastobjectclass;
|
||||
extern material_t *material,*lastmaterial;
|
||||
|
||||
extern lifeform_t *player;
|
||||
|
||||
extern int reason;
|
||||
|
||||
char letorder[MAXPILEOBS] = {
|
||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
|
||||
};
|
||||
|
||||
objecttype_t *lastot = NULL;
|
||||
|
||||
enum OBCLASS sortorder[] = {
|
||||
OC_MONEY,
|
||||
OC_WEAPON,
|
||||
OC_ARMOUR,
|
||||
OC_SCROLL,
|
||||
OC_POTION,
|
||||
OC_FOOD,
|
||||
OC_ROCK,
|
||||
OC_MISC,
|
||||
OC_NULL
|
||||
};
|
||||
|
||||
long nextoid = 0;
|
||||
|
||||
|
||||
material_t *addmaterial(enum MATERIAL id, char *name) {
|
||||
material_t *a;
|
||||
|
||||
// add to the end of the list
|
||||
if (material == NULL) {
|
||||
material = malloc(sizeof(material_t));
|
||||
a = material;
|
||||
a->prev = NULL;
|
||||
} else {
|
||||
// go to end of list
|
||||
a = lastmaterial;
|
||||
a->next = malloc(sizeof(material_t));
|
||||
a->next->prev = a;
|
||||
a = a->next;
|
||||
}
|
||||
lastmaterial = a;
|
||||
a->next = NULL;
|
||||
|
||||
// props
|
||||
a->id = id;
|
||||
a->name = strdup(name);
|
||||
}
|
||||
|
||||
objectclass_t *addoc(enum OBCLASS id, char *name, char glyph) {
|
||||
objectclass_t *a;
|
||||
|
||||
// add to the end of the list
|
||||
if (objectclass == NULL) {
|
||||
objectclass = malloc(sizeof(objectclass_t));
|
||||
a = objectclass;
|
||||
a->prev = NULL;
|
||||
} else {
|
||||
// go to end of list
|
||||
a = lastobjectclass;
|
||||
a->next = malloc(sizeof(objectclass_t));
|
||||
a->next->prev = a;
|
||||
a = a->next;
|
||||
}
|
||||
lastobjectclass = a;
|
||||
a->next = NULL;
|
||||
|
||||
// props
|
||||
a->id = id;
|
||||
a->name = strdup(name);
|
||||
a->glyph = glyph;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// create a new obkejct, stacking ok
|
||||
object_t *addob(obpile_t *where, char *name) {
|
||||
addobject(where, name, B_TRUE);
|
||||
}
|
||||
|
||||
// create a new object
|
||||
// if canstack is true, we are allwoed
|
||||
// to join similar objects together instead of
|
||||
// creating new obejct entries.
|
||||
object_t *addobject(obpile_t *where, char *name, int canstack) {
|
||||
objecttype_t *ot;
|
||||
object_t *o;
|
||||
char *p,*nsp;
|
||||
char numstring[BUFLEN];
|
||||
int howmany = 1;
|
||||
int i;
|
||||
int db = B_FALSE;
|
||||
flag_t *f;
|
||||
|
||||
// parse name string
|
||||
nsp = numstring;
|
||||
for (p = name ; isdigit(*p) ; p++) {
|
||||
*nsp = *p;
|
||||
nsp++;
|
||||
}
|
||||
*nsp = '\0';
|
||||
|
||||
|
||||
// are we giving multiple objects?
|
||||
if (strlen(numstring) > 0) {
|
||||
// first increment name string pointer
|
||||
// past any spaces
|
||||
while (!isalpha(*p)) p++;
|
||||
// now figure out how many
|
||||
howmany = atoi(numstring);
|
||||
} else {
|
||||
howmany = 1;
|
||||
}
|
||||
|
||||
|
||||
// make sure we can find the requested object type
|
||||
ot = findotn(p);
|
||||
if (!ot) {
|
||||
if (db) dblog("DB: No match for object name '%s'", p );
|
||||
return NULL;
|
||||
}
|
||||
if (db) dblog("DB: '%s' -> adding %d x %s",name, howmany, ot->name);
|
||||
|
||||
for (i = 0; i < howmany; i++) {
|
||||
int added = B_FALSE;
|
||||
if (canstack) {
|
||||
object_t *existob;
|
||||
if (db) dblog("DB: Looking for stacks...");
|
||||
// TODO: if object is stackable
|
||||
// TODO: if (hasflag(ob,stackable) && hasobject(where, ot)) {
|
||||
// does the pile already contain one?
|
||||
existob = canstacknewot(where, ot);
|
||||
if (existob) {
|
||||
if (db) dblog("DB: STACK FOUND. Adding %d obs to existing stack.",howmany);
|
||||
existob->amt++;
|
||||
added = B_TRUE;
|
||||
}
|
||||
if (db) dblog("DB: No stacks found.");
|
||||
}
|
||||
|
||||
if (!added) {
|
||||
if (db) dblog("DB: Creating new object.");
|
||||
|
||||
// otherwise add to list
|
||||
if (where->first == NULL) {
|
||||
where->first = malloc(sizeof(object_t));
|
||||
o = where->first;
|
||||
o->prev = NULL;
|
||||
} else {
|
||||
// go to end of list
|
||||
o = where->last;
|
||||
o->next = malloc(sizeof(object_t));
|
||||
o->next->prev = o;
|
||||
o = o->next;
|
||||
}
|
||||
where->last = o;
|
||||
|
||||
o->next = NULL;
|
||||
|
||||
// fill in props
|
||||
o->id = nextoid++; // increment next ob id
|
||||
o->type = ot;
|
||||
o->pile = where;
|
||||
// inherit from objecttype
|
||||
o->material = ot->material;
|
||||
o->weight = ot->weight;
|
||||
o->flags = addflagpile();
|
||||
for (f = ot->flags->first ; f ; f = f->next) {
|
||||
addflag(o->flags, f->id, f->val[0], f->val[1], f->val[2], f->text);
|
||||
}
|
||||
|
||||
// non-inherited:
|
||||
o->inscription = NULL;
|
||||
// if adding to a player...
|
||||
if (where->owner) {
|
||||
o->letter = getnextletter(where, NULL);
|
||||
} else {
|
||||
// new object - has no letter yet.
|
||||
o->letter = ' ';
|
||||
}
|
||||
o->amt = 1;
|
||||
o->blessed = B_UNCURSED;
|
||||
o->blessknown = B_FALSE; // TODO: change to false
|
||||
}
|
||||
}
|
||||
|
||||
// return the last object given
|
||||
return o;
|
||||
}
|
||||
|
||||
obpile_t *addobpile(lifeform_t *owner, cell_t *where) {
|
||||
obpile_t *op;
|
||||
op = malloc(sizeof(obpile_t));
|
||||
op->first = NULL;
|
||||
op->last = NULL;
|
||||
op->owner = owner;
|
||||
op->where = where;
|
||||
|
||||
return op;
|
||||
}
|
||||
|
||||
|
||||
objecttype_t *addot(int id, char *name, char *description, int material, float weight, int obclassid) {
|
||||
objecttype_t *a;
|
||||
|
||||
// add to the end of the list
|
||||
if (objecttype == NULL) {
|
||||
objecttype = malloc(sizeof(objecttype_t));
|
||||
a = objecttype;
|
||||
a->prev = NULL;
|
||||
} else {
|
||||
// go to end of list
|
||||
a = lastobjecttype;
|
||||
a->next = malloc(sizeof(objecttype_t));
|
||||
a->next->prev = a;
|
||||
a = a->next;
|
||||
}
|
||||
lastobjecttype = a;
|
||||
a->next = NULL;
|
||||
|
||||
// props
|
||||
a->id = id;
|
||||
a->name = strdup(name);
|
||||
a->desc = strdup(description);
|
||||
a->material = findmaterial(material);
|
||||
a->weight = weight;
|
||||
a->obclass = findoc(obclassid);
|
||||
a->flags = addflagpile();
|
||||
|
||||
// for easy addition of flags
|
||||
lastot = a;
|
||||
}
|
||||
|
||||
// does the pile "op" have an object we can
|
||||
// stack "o" with
|
||||
object_t *canstackob(obpile_t *op, object_t *match) {
|
||||
object_t *o;
|
||||
if (!hasflag(match->flags, F_STACKABLE)) {
|
||||
return NULL;
|
||||
}
|
||||
for (o = op->first ; o ; o = o->next) {
|
||||
if (obpropsmatch(o, match)) return o;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// does the pile "op" have an object we can
|
||||
// stack a new object of type "ot" with
|
||||
object_t *canstacknewot(obpile_t *op, objecttype_t *match) {
|
||||
object_t *o;
|
||||
if (!hasflag(match->flags, F_STACKABLE)) {
|
||||
return NULL;
|
||||
}
|
||||
for (o = op->first ; o ; o = o->next) {
|
||||
if (o->type == match) {
|
||||
if (isplainob(o)) return o;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void copyobprops(object_t *dst, object_t *src) {
|
||||
dst->material = src->material;
|
||||
dst->weight = src->weight;
|
||||
// TODO: copy flags
|
||||
if (src->inscription) {
|
||||
dst->inscription = strdup(src->inscription);
|
||||
}
|
||||
}
|
||||
|
||||
int countobs(obpile_t *op) {
|
||||
object_t *o;
|
||||
int count = 0;
|
||||
for (o = op->first ; o ; o = o->next) {
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
material_t *findmaterial(int id) {
|
||||
material_t *m;
|
||||
for (m = material ; m ; m = m->next) {
|
||||
if (m->id == id) return m;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
objectclass_t *findoc(int id) {
|
||||
objectclass_t *oc;
|
||||
for (oc = objectclass ; oc ; oc = oc->next) {
|
||||
if (oc->id == id) return oc;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
object_t *findobl(obpile_t *op, char let) {
|
||||
object_t *o;
|
||||
for (o = op->first; o ; o = o->next) {
|
||||
if (o->letter == let) return o;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
objecttype_t *findot(int id) {
|
||||
objecttype_t *ot;
|
||||
for (ot = objecttype ; ot ; ot = ot->next) {
|
||||
if (ot->id == id) return ot;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
objecttype_t *findotn(char *name) {
|
||||
objecttype_t *ot;
|
||||
char *searchfor;
|
||||
searchfor = strdup(name);
|
||||
for (ot = objecttype ; ot ; ot = ot->next) {
|
||||
if (strstr(ot->name, searchfor)) {
|
||||
free(searchfor);
|
||||
return ot;
|
||||
}
|
||||
}
|
||||
|
||||
// haven't found it yet - check for plurals
|
||||
// search for words ending in "es" (eg. tomatoes)
|
||||
if ((searchfor[strlen(searchfor)-1] == 's') &&
|
||||
(searchfor[strlen(searchfor)-2] == 'e') ) {
|
||||
// remove trailing 'es'
|
||||
searchfor[strlen(searchfor)-1] = '\0';
|
||||
searchfor[strlen(searchfor)-2] = '\0';
|
||||
// search again
|
||||
for (ot = objecttype ; ot ; ot = ot->next) {
|
||||
if (strstr(ot->name, searchfor)) {
|
||||
free(searchfor);
|
||||
return ot;
|
||||
}
|
||||
}
|
||||
}
|
||||
// reset back to inital word
|
||||
free(searchfor);
|
||||
searchfor = strdup(name);
|
||||
|
||||
// search for words ending in "s" (eg. "swords")
|
||||
if (searchfor[strlen(searchfor)-1] == 's') {
|
||||
// remove trailing 's'
|
||||
searchfor[strlen(searchfor)-1] = '\0';
|
||||
searchfor[strlen(searchfor)-2] = '\0';
|
||||
// search again
|
||||
for (ot = objecttype ; ot ; ot = ot->next) {
|
||||
if (strstr(ot->name, searchfor)) {
|
||||
free(searchfor);
|
||||
return ot;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int getletidx(char let) {
|
||||
int i;
|
||||
for (i = 0; i < MAXPILEOBS; i++) {
|
||||
if (letorder[i] == let) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// select lowest possible letter
|
||||
char getnextletter(obpile_t *op, char *wantletter) {
|
||||
object_t *o;
|
||||
int curidx = -1, thisidx;
|
||||
char let;
|
||||
int db = B_FALSE;
|
||||
|
||||
// try 'wantletter' first
|
||||
if (wantletter) {
|
||||
if (!pilehasletter(op, *wantletter)) {
|
||||
return *wantletter;
|
||||
}
|
||||
}
|
||||
|
||||
curidx = 0; // ie 'a'
|
||||
|
||||
for (curidx = 0; curidx < MAXPILEOBS; curidx++) {
|
||||
// does any other object in the pile have this letter?
|
||||
let = letorder[curidx];
|
||||
if (!pilehasletter(op, let)) {
|
||||
// if we didn't find it, this letter is okay.
|
||||
return let;
|
||||
}
|
||||
}
|
||||
|
||||
return '-';
|
||||
}
|
||||
|
||||
// buf must already be allocated
|
||||
char *getobname(object_t *o, char *buf, int count) {
|
||||
char *pluralname;
|
||||
char prefix[BUFLEN];
|
||||
|
||||
// handle ALL
|
||||
if (count == ALL) {
|
||||
count = o->amt;
|
||||
}
|
||||
|
||||
// figure out prefix
|
||||
if ((count == 1) && !hasflag(o->flags, F_NO_A)) {
|
||||
pluralname = strdup(o->type->name);
|
||||
|
||||
if (o->blessknown) {
|
||||
if (o->blessed == B_UNCURSED) {
|
||||
strcpy(prefix, "an");
|
||||
} else {
|
||||
strcpy(prefix, "a");
|
||||
}
|
||||
} else {
|
||||
if (isvowel(o->type->name[0])) {
|
||||
strcpy(prefix, "an");
|
||||
} else {
|
||||
strcpy(prefix, "a");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// multiple objects?
|
||||
if (hasflag(o->flags, F_NO_PLURAL)) {
|
||||
pluralname = strdup(o->type->name);
|
||||
} else {
|
||||
pluralname = makeplural(o->type->name);
|
||||
}
|
||||
sprintf(prefix, "%d",count);
|
||||
}
|
||||
|
||||
sprintf(buf, "%s ", prefix);
|
||||
|
||||
|
||||
// blessed status
|
||||
if (o->blessknown) {
|
||||
switch (o->blessed) {
|
||||
case B_BLESSED:
|
||||
strcat(buf, "blessed ");
|
||||
break;
|
||||
case B_UNCURSED:
|
||||
strcat(buf, "uncursed ");
|
||||
break;
|
||||
case B_CURSED:
|
||||
strcat(buf, "cursed ");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// object name
|
||||
strcat(buf, pluralname);
|
||||
free(pluralname);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
char *getrandomob(map_t *map, char *buf) {
|
||||
enum RARITY rarity;
|
||||
objecttype_t *ot;
|
||||
int roll;
|
||||
objecttype_t *poss[MAXRANDOMOBCANDIDATES];
|
||||
int nposs = 0;
|
||||
int selidx;
|
||||
int amt;
|
||||
flag_t *f;
|
||||
int db = B_FALSE;
|
||||
|
||||
// determine rarity of object to generate
|
||||
rarity = RR_FREQUENT;
|
||||
|
||||
// start with 'frequent'ly appearing items
|
||||
// roll a die. 30% chance of getting rarer.
|
||||
// stop when we fail the die roll.
|
||||
roll = rnd(1,100);
|
||||
while (roll < 30) {
|
||||
rarity++;
|
||||
if (rarity == RR_VERYRARE) break;
|
||||
roll = rnd(1,100);
|
||||
}
|
||||
if (db) dblog("adding random object of rarity %d\n",rarity);
|
||||
|
||||
|
||||
// try to find an object of this type which will
|
||||
// fit in the map's habitat
|
||||
nposs = 0;
|
||||
while (nposs == 0) {
|
||||
for (ot = objecttype ; ot ; ot = ot->next) {
|
||||
if (hasflagval(ot->flags, F_RARITY, map->habitat, rarity, -1, "") ||
|
||||
hasflagval(ot->flags, F_RARITY, H_ALL, rarity, -1, "") ) {
|
||||
poss[nposs] = ot;
|
||||
nposs++;
|
||||
if (nposs >= MAXRANDOMOBCANDIDATES) break;
|
||||
}
|
||||
}
|
||||
|
||||
// nothing found?
|
||||
if (nposs == 0) {
|
||||
// already at lowest rarity?
|
||||
if (rarity == RR_FREQUENT) {
|
||||
// give up
|
||||
sprintf(buf, "");
|
||||
if (db) dblog("no possible objects at all! giving up.");
|
||||
return NULL;
|
||||
} else {
|
||||
// lower rarity and try again
|
||||
rarity--;
|
||||
if (db) dblog("no possible objects like this. trying again with rarity %d\n",rarity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (db) dblog("got %d possibilities.",nposs);
|
||||
// pick a random object from our possiblities
|
||||
selidx = rnd(0,nposs-1);
|
||||
ot = poss[selidx];
|
||||
// handle objects which appear in multiples (ie. rocks)
|
||||
f = hasflag(ot->flags, F_NUMAPPEAR);
|
||||
if (f) {
|
||||
amt = rnd(f->val[0], f->val[1]);
|
||||
} else {
|
||||
amt = 1;
|
||||
}
|
||||
if (db) sprintf(buf, "%d %s", amt, ot->name);
|
||||
return buf;
|
||||
}
|
||||
|
||||
object_t *hasob(obpile_t *op, enum OBTYPE oid) {
|
||||
object_t *o;
|
||||
for (o = op->first ; o ; o = o->next) {
|
||||
if (o->type->id == oid) return o;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void initobjects(void) {
|
||||
// materials
|
||||
addmaterial(MT_STONE, "stone");
|
||||
addmaterial(MT_FIRE, "fire");
|
||||
addmaterial(MT_PLASTIC, "plastic");
|
||||
addmaterial(MT_METAL, "metal");
|
||||
addmaterial(MT_WOOD, "wood");
|
||||
addmaterial(MT_FLESH, "flesh");
|
||||
addmaterial(MT_GOLD, "gold");
|
||||
|
||||
// object classes
|
||||
addoc(OC_MONEY, "Money", '$');
|
||||
addoc(OC_SCROLL, "Scrolls", '?');
|
||||
addoc(OC_POTION, "Potions", '!');
|
||||
addoc(OC_WEAPON, "Weapons", '\\');
|
||||
addoc(OC_ARMOUR, "Armour", ']');
|
||||
addoc(OC_ROCK, "Rocks/Gems", '*');
|
||||
addoc(OC_FOOD, "Food", '%');
|
||||
addoc(OC_MISC, "Miscellaneous", '"');
|
||||
|
||||
// object types
|
||||
addot(OT_GOLD, "gold coin", "Sparkling nuggets of gold, the standard currency of Nexus.", MT_GOLD, 0.1, OC_MONEY);
|
||||
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
|
||||
addflag(lastot->flags, F_RARITY, H_ALL, RR_COMMON, -1, "");
|
||||
addflag(lastot->flags, F_NUMAPPEAR, 1, 100, -1, "");
|
||||
addot(OT_STONE, "stone", "A medium-sized roundish stone.", MT_STONE, 0.5, OC_ROCK);
|
||||
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
|
||||
addflag(lastot->flags, F_RARITY, H_DUNGEON, RR_FREQUENT, -1, "");
|
||||
addflag(lastot->flags, F_NUMAPPEAR, 1, 10, -1, "");
|
||||
|
||||
// corpses
|
||||
addot(OT_CORPSEHUMAN, "human corpse", "The dead body of a human.", MT_FLESH, 50, OC_FOOD);
|
||||
addflag(lastot->flags, F_EDIBLE, B_TRUE, 5, NA, "");
|
||||
addot(OT_CORPSEGOBLIN, "goblin corpse", "The dead body of a goblin.", MT_FLESH, 20, OC_FOOD);
|
||||
addflag(lastot->flags, F_EDIBLE, B_TRUE, 5, NA, "");
|
||||
addot(OT_CORPSEBAT, "bat corpse", "The dead body of a bat.", MT_FLESH, 5, OC_FOOD);
|
||||
addflag(lastot->flags, F_EDIBLE, B_TRUE, 5, NA, "");
|
||||
addot(OT_CORPSEBAT, "fly corpse", "The dead body of a giant flying insect.", MT_FLESH, 5, OC_FOOD);
|
||||
addflag(lastot->flags, F_EDIBLE, B_TRUE, 5, NA, "");
|
||||
}
|
||||
|
||||
// has this object changed proerties from its
|
||||
// parent objecttype?
|
||||
int isplainob(object_t *o) {
|
||||
if (o->material != o->type->material) return B_FALSE;
|
||||
if (o->weight != o->type->weight) return B_FALSE;
|
||||
if (o->inscription) return B_FALSE;
|
||||
if (o->blessed != B_UNCURSED) return B_FALSE;
|
||||
if (o->blessknown) return B_FALSE;
|
||||
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
|
||||
void killmaterial(material_t *m) {
|
||||
int i;
|
||||
material_t *nextone, *lastone;
|
||||
|
||||
// free mem
|
||||
free(m->name);
|
||||
|
||||
// remove from list
|
||||
nextone = m->next;
|
||||
if (nextone != NULL) {
|
||||
nextone->prev = m->prev;
|
||||
} else { /* last */
|
||||
lastmaterial = m->prev;
|
||||
}
|
||||
|
||||
if (m->prev == NULL) {
|
||||
/* first */
|
||||
nextone = m->next;
|
||||
free(material);
|
||||
material = nextone;
|
||||
} else {
|
||||
lastone = m->prev;
|
||||
free (lastone->next );
|
||||
lastone->next = nextone;
|
||||
}
|
||||
}
|
||||
|
||||
void killob(object_t *o) {
|
||||
int i;
|
||||
object_t *nextone, *lastone;
|
||||
|
||||
// free mem
|
||||
if (o->inscription) free(o->inscription);
|
||||
|
||||
// remove from list
|
||||
nextone = o->next;
|
||||
if (nextone != NULL) {
|
||||
nextone->prev = o->prev;
|
||||
} else { /* last */
|
||||
o->pile->last = o->prev;
|
||||
}
|
||||
|
||||
if (o->prev == NULL) {
|
||||
/* first */
|
||||
nextone = o->next;
|
||||
o->pile->first = nextone;
|
||||
free(o);
|
||||
} else {
|
||||
lastone = o->prev;
|
||||
free (lastone->next );
|
||||
lastone->next = nextone;
|
||||
}
|
||||
}
|
||||
|
||||
void killoc(objectclass_t *oc) {
|
||||
int i;
|
||||
objectclass_t *nextone, *lastone;
|
||||
|
||||
// free mem
|
||||
free(oc->name);
|
||||
|
||||
// remove from list
|
||||
nextone = oc->next;
|
||||
if (nextone != NULL) {
|
||||
nextone->prev = oc->prev;
|
||||
} else { /* last */
|
||||
lastobjectclass = oc->prev;
|
||||
}
|
||||
|
||||
if (oc->prev == NULL) {
|
||||
/* first */
|
||||
nextone = oc->next;
|
||||
free(objectclass);
|
||||
objectclass = nextone;
|
||||
} else {
|
||||
lastone = oc->prev;
|
||||
free (lastone->next );
|
||||
lastone->next = nextone;
|
||||
}
|
||||
}
|
||||
|
||||
void killot(objecttype_t *ot) {
|
||||
int i;
|
||||
objecttype_t *nextone, *lastone;
|
||||
|
||||
// free mem
|
||||
free(ot->name);
|
||||
free(ot->desc);
|
||||
if (ot->flags) killflagpile(ot->flags);
|
||||
|
||||
// remove from list
|
||||
nextone = ot->next;
|
||||
if (nextone != NULL) {
|
||||
nextone->prev = ot->prev;
|
||||
} else { /* last */
|
||||
lastobjecttype = ot->prev;
|
||||
}
|
||||
|
||||
if (ot->prev == NULL) {
|
||||
/* first */
|
||||
nextone = ot->next;
|
||||
free(objecttype);
|
||||
objecttype = nextone;
|
||||
} else {
|
||||
lastone = ot->prev;
|
||||
free (lastone->next );
|
||||
lastone->next = nextone;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
object_t *moveob(object_t *src, obpile_t *dst, int howmany) {
|
||||
object_t *o, *oo, *existob;
|
||||
int i;
|
||||
int db = B_FALSE;
|
||||
|
||||
reason = E_OK;
|
||||
|
||||
if (db) dblog("DB: moveob() - moving %d x %s",howmany, src->type->name);
|
||||
existob = canstackob(dst, src);
|
||||
if (existob) {
|
||||
if (db) dblog("DB: moveob() - found stack to join");
|
||||
if (howmany == ALL) howmany = src->amt;
|
||||
existob->amt += howmany;
|
||||
src->amt -= howmany;
|
||||
if (src->amt == 0) {
|
||||
killob(src);
|
||||
}
|
||||
return existob;
|
||||
} else {
|
||||
if (db) dblog("DB: moveob() - no stack to join");
|
||||
|
||||
// space in destination pile?
|
||||
if (getnextletter(dst, NULL) == '-') {
|
||||
reason = E_NOSPACE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// no similar objects in the dest pile.
|
||||
if ((howmany == ALL) || (howmany == src->amt)) {
|
||||
if (db) dblog("DB: dropping ALL - relinking object to new pile");
|
||||
// just move the whole object to the new pile
|
||||
o = relinkob(src, dst);
|
||||
} else {
|
||||
obpile_t *tempop;
|
||||
if (db) dblog("DB: moving only some of a stack.");
|
||||
|
||||
|
||||
// create temporary object pile
|
||||
tempop = addobpile(NULL, NULL);
|
||||
// add new object to the temporary pile
|
||||
o = addob(tempop, src->type->name);
|
||||
// copy props from original object
|
||||
copyobprops(o, src);
|
||||
|
||||
// just move some of them
|
||||
for (i = 0; i < howmany; i++ ) {
|
||||
// the first one is already there!
|
||||
if (i != 0) {
|
||||
// inc counter in temp pile
|
||||
o->amt++;
|
||||
}
|
||||
// dec counter on original
|
||||
src->amt--;
|
||||
}
|
||||
if (src->amt <= 0) {
|
||||
killob(src);
|
||||
}
|
||||
// now move the object entry from the temporary pile to the
|
||||
// real destination pile.
|
||||
while (tempop->first) {
|
||||
o = relinkob(tempop->first, dst);
|
||||
}
|
||||
free(tempop);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
int obfits(object_t *o, obpile_t *op) {
|
||||
if (countobs(op) >= MAXPILEOBS) {
|
||||
return B_FALSE;
|
||||
}
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
// has this object changed proerties from its
|
||||
// parent objecttype?
|
||||
int obpropsmatch(object_t *a, object_t *b) {
|
||||
if (a->type != b->type) return B_FALSE;
|
||||
if (a->material != b->material) return B_FALSE;
|
||||
if (a->weight != b->weight) return B_FALSE;
|
||||
if (a->inscription || b->inscription) return B_FALSE;
|
||||
if (a->blessed != b->blessed) return B_FALSE;
|
||||
if (a->blessknown != b->blessknown) return B_FALSE;
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
|
||||
int pilehasletter(obpile_t *op, char let) {
|
||||
object_t *o;
|
||||
int found = B_FALSE;
|
||||
|
||||
for (o = op->first ; o ; o = o->next) {
|
||||
if (o->letter == let) {
|
||||
found = B_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
object_t *relinkob(object_t *src, obpile_t *dst) {
|
||||
if (!obfits(src, dst)) return NULL;
|
||||
|
||||
// unlink this object from the current list
|
||||
if (src->prev == NULL) {
|
||||
// first
|
||||
src->pile->first = src->next;
|
||||
} else {
|
||||
// not first
|
||||
src->prev->next = src->next;
|
||||
}
|
||||
if (src->next == NULL) {
|
||||
// last
|
||||
src->pile->last = src->prev;
|
||||
} else {
|
||||
// not last
|
||||
src->next->prev = src->prev;
|
||||
}
|
||||
|
||||
// add this object to the end of the list for the new pile
|
||||
if (dst->first == NULL) {
|
||||
// first element in new list
|
||||
dst->first = src;
|
||||
src->prev = NULL;
|
||||
} else {
|
||||
object_t *aa;
|
||||
// go to end of list
|
||||
aa = dst->last;
|
||||
// not first in new list
|
||||
src->prev = aa;
|
||||
aa->next = src;
|
||||
}
|
||||
|
||||
|
||||
dst->last = src;
|
||||
src->pile = dst;
|
||||
src->next = NULL;
|
||||
|
||||
// adjust letter if going to player
|
||||
if (dst->owner && (dst->owner->controller == C_PLAYER)) {
|
||||
src->letter = getnextletter(dst, &src->letter);
|
||||
}
|
||||
|
||||
return src;
|
||||
}
|
||||
|
||||
void throwat(lifeform_t *thrower, object_t *o, cell_t *where) {
|
||||
char throwername[BUFLEN];
|
||||
char obname[BUFLEN];
|
||||
char targetname[BUFLEN];
|
||||
char buf[BUFLEN];
|
||||
lifeform_t *target;
|
||||
|
||||
|
||||
getlfname(thrower, throwername);
|
||||
|
||||
target = where->lf;
|
||||
if (target) {
|
||||
getlfname(target, targetname);
|
||||
}
|
||||
|
||||
// announce it ("xx throws xx" "at yy")
|
||||
getobname(o, obname, 1);
|
||||
if (thrower->controller == C_PLAYER) {
|
||||
if (target) {
|
||||
msg("You throw %s at %s.", obname, targetname);
|
||||
} else {
|
||||
msg("You throw %s.",obname);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
if (haslos(player, thrower->cell)) {
|
||||
char throwstring[BUFLEN];
|
||||
char *throwercaps;
|
||||
throwercaps = strdup(throwername);
|
||||
capitalise(throwercaps);
|
||||
sprintf(throwstring, "%s throw%s %s",throwercaps,
|
||||
(thrower->controller == C_PLAYER) ? "" : "s",
|
||||
obname);
|
||||
|
||||
if (target && haslos(player, where)) {
|
||||
strcat(throwstring, " at");
|
||||
strcat(throwstring, targetname);
|
||||
}
|
||||
strcat(throwstring, ".");
|
||||
|
||||
free(throwercaps);
|
||||
}
|
||||
|
||||
taketime(thrower, SPEED_THROW);
|
||||
|
||||
// TODO: figure out if you miss or not, based on distance
|
||||
|
||||
// do throw animation
|
||||
anim(thrower->cell, where, o->type->obclass->glyph);
|
||||
|
||||
// if someone is there, they take damage and the object might die
|
||||
if (target) {
|
||||
int dam;
|
||||
char damstring[BUFLEN];
|
||||
// damage is kilograms / 5.
|
||||
// ie. 5 kg object does 1 damage
|
||||
// ie. 100 kg object does 20 damage (person)
|
||||
// ie. 1 tonne object does 200 damage (car)
|
||||
dam = (int)ceil((double)o->weight / 5.0);
|
||||
|
||||
// announce
|
||||
if (haslos(player, where)) {
|
||||
char *obcaps;
|
||||
obcaps = strdup(obname);
|
||||
capitalise(obcaps);
|
||||
|
||||
msg("%s hits %s.",obcaps,targetname);
|
||||
free(obcaps);
|
||||
}
|
||||
sprintf(damstring, "%s (thrown by %s)",obname,throwername);
|
||||
losehp(target, dam, thrower, damstring);
|
||||
}
|
||||
|
||||
// either remove or move the object
|
||||
moveob(o, where->obpile, 1);
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
#ifndef __OBJECTS_H
|
||||
#define __OBJECTS_H
|
||||
#include "defs.h"
|
||||
|
||||
material_t *addmaterial(enum MATERIAL id, char *name);
|
||||
objectclass_t *addoc(enum OBCLASS id, char *name, char glyph);
|
||||
object_t *addob(obpile_t *where, char *name);
|
||||
object_t *addobject(obpile_t *where, char *name, int canstack);
|
||||
obpile_t *addobpile(lifeform_t *owner, cell_t *where);
|
||||
objecttype_t *addot(int id, char *name, char *description, int material, float weight, int obclassid);
|
||||
object_t *canstackob(obpile_t *op, object_t *match);
|
||||
object_t *canstacknewot(obpile_t *op, objecttype_t *match);
|
||||
void copyobprops(object_t *dst, object_t *src);
|
||||
int countobs(obpile_t *op);
|
||||
material_t *findmaterial(int id);
|
||||
objectclass_t *findoc(int id);
|
||||
object_t *findobl(obpile_t *op, char let); // find object by letter
|
||||
objecttype_t *findot(int id);
|
||||
objecttype_t *findotn(char *name); // find objecttype by name
|
||||
int getletindex(char let);
|
||||
char getnextletter(obpile_t *op, char *wantletter);
|
||||
char *getobname(object_t *o, char *buf, int count);
|
||||
char *getrandomob(map_t *map, char *buf);
|
||||
object_t *hasob(obpile_t *op, enum OBTYPE oid);
|
||||
void initobjects(void);
|
||||
int isplainob(object_t *o);
|
||||
void killmaterial(material_t *m);
|
||||
void killob(object_t *o);
|
||||
void killoc(objectclass_t *oc);
|
||||
void killot(objecttype_t *ot);
|
||||
object_t *moveob(object_t *src, obpile_t *dst, int howmany);
|
||||
int obfits(object_t *o, obpile_t *op);
|
||||
int obpropsmatch(object_t *a, object_t *b);
|
||||
int pilehasletter(obpile_t *op, char let);
|
||||
object_t *relinkob(object_t *src, obpile_t *dst);
|
||||
void throwat(lifeform_t *thrower, object_t *o, cell_t *where);
|
||||
#endif
|
|
@ -0,0 +1,594 @@
|
|||
#include <dirent.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "defs.h"
|
||||
#include "lf.h"
|
||||
#include "map.h"
|
||||
#include "move.h"
|
||||
#include "nexus.h"
|
||||
#include "objects.h"
|
||||
#include "save.h"
|
||||
|
||||
extern lifeform_t *player;
|
||||
extern map_t *firstmap;
|
||||
|
||||
int loadall(void) {
|
||||
DIR *dir;
|
||||
struct dirent *ent;
|
||||
char *filename;
|
||||
FILE *f;
|
||||
|
||||
dir = opendir(MAPDIR);
|
||||
if (!dir) {
|
||||
dblog("Could not open map directory '%s'",MAPDIR);
|
||||
return B_TRUE;
|
||||
}
|
||||
// for each map file in directory
|
||||
while ((ent = readdir(dir)) != NULL) {
|
||||
char *p;
|
||||
// ie. start of 4 char prefix
|
||||
p = ent->d_name + strlen(ent->d_name) - 4;
|
||||
// load this map
|
||||
if (!strcmp(p, ".map") ) {
|
||||
if (!loadmap(ent->d_name)) {
|
||||
printf("Error loading map from file '%s'",ent->d_name);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
|
||||
loadsavegame();
|
||||
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// load and allocate one lifeform from given file
|
||||
lifeform_t *loadlf(FILE *f, cell_t *where) {
|
||||
lifeform_t *l;
|
||||
int lfid, lfraceid;
|
||||
long obid;
|
||||
int rv;
|
||||
int i;
|
||||
char buf[BUFLEN];
|
||||
int obcount;
|
||||
int mapid;
|
||||
map_t *m;
|
||||
int x,y;
|
||||
int db = B_TRUE;
|
||||
|
||||
if (db) dblog("--> Loading lifeform...\n");
|
||||
|
||||
fscanf(f, "startlf\n");
|
||||
fscanf(f, "lfid: %d\n",&lfid);
|
||||
fscanf(f, "race: %d\n",&lfraceid);
|
||||
fscanf(f, "map: %d\n",&mapid);
|
||||
fscanf(f, "pos: %d,%d\n",&x, &y);
|
||||
|
||||
// find the map
|
||||
m = findmap(mapid);
|
||||
if (!m) {
|
||||
dblog("ERROR loading lf id %d: can't find map id %d\n",lfid,mapid);
|
||||
exit(1);
|
||||
}
|
||||
if (where == NULL) {
|
||||
where = getcellat(m, x, y);
|
||||
}
|
||||
if (!m) {
|
||||
dblog("ERROR loading lf id %d: can't find cell at %d,%d on map id %d\n",lfid,x,y,mapid);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
l = addlf(where, lfraceid);
|
||||
l->id = lfid;
|
||||
l->x = x;
|
||||
l->y = y;
|
||||
|
||||
// load rest of this lf
|
||||
fscanf(f, "contr: %d\n",&l->controller);
|
||||
fscanf(f, "hp: %d/%d\n",&l->hp, &l->maxhp);
|
||||
fscanf(f, "alive: %d\n",&l->alive);
|
||||
|
||||
fgets(buf, BUFLEN, f); // lastdam
|
||||
buf[strlen(buf)-1] = '\0'; // strip newline
|
||||
l->lastdam = strdup(buf + 9); // after 'lastdam: '
|
||||
|
||||
fscanf(f, "timespent: %d\n",&l->timespent);
|
||||
|
||||
fscanf(f, "sorted: %d\n",&l->sorted);
|
||||
|
||||
if (db) dblog("--> Got hp=%d/%d. timespend=%d. sorted=%d. Now loading ob list.",l->hp,l->maxhp,l->timespent,l->sorted);
|
||||
|
||||
// load object list
|
||||
obcount = 0;
|
||||
obid = 9999; // for testing
|
||||
rv = fscanf(f, "ob:%ld\n",&obid);
|
||||
while (obid != -1) {
|
||||
if (db) dblog("--> Load ob id %d into list...",obid);
|
||||
l->pack->oblist[obcount] = obid;
|
||||
obcount++;
|
||||
fscanf(f, "ob:%ld\n",&obid);
|
||||
}
|
||||
// terminate with -1s!
|
||||
for (i = obcount ; i < MAXPILEOBS; i++) {
|
||||
l->pack->oblist[i] = -1;
|
||||
}
|
||||
if (db) dblog("--> Finished oblist. Found %d objects.",obcount);
|
||||
|
||||
// now load load object defs!
|
||||
fscanf(f, "obdefs\n");
|
||||
for (i = 0; i < obcount; i++) {
|
||||
//if (db) dblog("-----> ob %d/%d...\n",i+1,obcount);
|
||||
if (loadob(f, l->pack)) {
|
||||
dblog("Error - can't create object %d/%d!\n",i+1,obcount);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// is this the player?
|
||||
if (l->controller == C_PLAYER) {
|
||||
player = l;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
map_t *loadmap(char *basefile) {
|
||||
FILE *f;
|
||||
char filename[BUFLEN];
|
||||
char buf[BUFLEN];
|
||||
char buf2[BUFLEN];
|
||||
int obcount;
|
||||
int i;
|
||||
int x,y;
|
||||
int db = B_TRUE;
|
||||
lifeform_t *l;
|
||||
object_t *o,*nexto;
|
||||
map_t *m;
|
||||
cell_t *dummycell;
|
||||
|
||||
if (db) dblog("Loading map from %s...",basefile);
|
||||
sprintf(filename, "%s/%s",MAPDIR,basefile);
|
||||
f = fopen(filename, "rt");
|
||||
|
||||
|
||||
|
||||
// create map
|
||||
m = addmap();
|
||||
dummycell = malloc(sizeof(cell_t));
|
||||
dummycell->obpile = addobpile(NULL, dummycell);
|
||||
dummycell->map = m;
|
||||
dummycell->type = (celltype_t *)0xabcde; // for debugging
|
||||
|
||||
if (!m) {
|
||||
dblog("Error creating map while loading file '%s'",filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// load map info
|
||||
if (db) dblog("--> Loading map info...\n");
|
||||
fscanf(f, "id:%d\n",&m->id); // map id
|
||||
fgets(buf, BUFLEN, f); // map name
|
||||
buf[strlen(buf)-1] = '\0'; // strip newline
|
||||
m->name = strdup(buf + 5); // after 'name:'
|
||||
fscanf(f, "habitat:%d\n",(int *)&m->habitat); // habitat
|
||||
fscanf(f, "seed:%d\n",&m->seed); // seed
|
||||
fscanf(f, "dims:%d,%d\n",&m->w, &m->h); // map dimensons
|
||||
fscanf(f, "nextlfid:%ld\n",&m->nextlfid);
|
||||
fscanf(f, "nextmaps:\n");
|
||||
for (i = 0; i < MAXDIR_ORTH; i++) {
|
||||
fscanf(f, "%d\n",&m->nextmap[i]); // map dimensons
|
||||
}
|
||||
if (db) dblog("--> Finished map info. name='%s', dims=%d x %d\n",m->name, m->w, m->h);
|
||||
fscanf(f, "id:%d\n",&m->id); // map id
|
||||
|
||||
// load lifeforms
|
||||
if (db) dblog("--> Loading lifeforms...\n");
|
||||
fscanf(f, "lifeforms:\n");
|
||||
|
||||
fscanf(f, "%s\n",buf);
|
||||
while (!strcmp(buf ,"startlf")) {
|
||||
loadlf(f, dummycell);
|
||||
|
||||
// check for more lifeforms...
|
||||
fscanf(f, "%s\n",buf);
|
||||
}
|
||||
|
||||
// load cells
|
||||
if (db) dblog("--> Loading map cells...\n");
|
||||
fscanf(f, "cells:\n");
|
||||
for (y = 0; y < m->h; y++) {
|
||||
for (x = 0; x < m->w; x++) {
|
||||
cell_t *c;
|
||||
celltype_t *ct;
|
||||
int celltypeid;
|
||||
long obid;
|
||||
|
||||
//if (db) dblog("cell %d,%d...",x,y);
|
||||
|
||||
// allocate this cell
|
||||
c = addcell(m, x, y);
|
||||
/*
|
||||
c = m->cell[y * m->w + x];
|
||||
c->map = m;
|
||||
c->obpile = addobpile(NULL, c);
|
||||
c->lf = NULL;
|
||||
c->x = x;
|
||||
c->y = y;
|
||||
c->roomid = -1;
|
||||
*/
|
||||
|
||||
// cell info
|
||||
fscanf(f, "%d,%d,%d,%d\n",
|
||||
&c->roomid, &celltypeid, &c->known, &c->visited);
|
||||
|
||||
|
||||
ct = findcelltype(celltypeid);
|
||||
if (ct) {
|
||||
c->type = ct;
|
||||
} else {
|
||||
dblog("ERROR loading map cells - can't find celltype id %ld\n",celltypeid);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// cell objects
|
||||
obcount = 0;
|
||||
fscanf(f, "ob:%ld\n",&obid);
|
||||
while (obid != -1) {
|
||||
c->obpile->oblist[obcount] = obid;
|
||||
obcount++;
|
||||
fscanf(f, "ob:%ld\n",&obid);
|
||||
}
|
||||
// terminate with -1s!
|
||||
for (i = obcount ; i < MAXPILEOBS; i++) {
|
||||
c->obpile->oblist[i] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// load object definitions
|
||||
if (db) dblog("--> Loading object definitions for map obs...\n");
|
||||
fscanf(f, "MAPOBS:%d\n",&obcount); // how many obs?
|
||||
|
||||
// create all objects in a dummy cell
|
||||
for (i = 0; i < obcount; i++) {
|
||||
if (db) dblog("-----> ob %d/%d...\n",i+1,obcount);
|
||||
if (loadob(f, dummycell->obpile)) {
|
||||
dblog("Error - can't create object %d/%d!\n",i+1,obcount);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// hand out the objects to lifeforms...
|
||||
for (l = m->lf ; l ; l = l->next) {
|
||||
int curob = 0;
|
||||
long obid;
|
||||
obid = l->pack->oblist[curob];
|
||||
while (obid != -1) {
|
||||
int found = B_FALSE;
|
||||
// find this ob id in the dummycell
|
||||
for (o = dummycell->obpile->first ; o ; o = nexto) {
|
||||
nexto = o->next;
|
||||
if (o->id == obid) {
|
||||
relinkob(o, l->pack);
|
||||
found = B_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
dblog("Error loading obs - lf %d should have obid %ld but can't find it.\n",l->id, obid);
|
||||
exit(1);
|
||||
}
|
||||
// next one
|
||||
curob++;
|
||||
obid = l->pack->oblist[curob];
|
||||
|
||||
}
|
||||
// clear the oblist
|
||||
for (i = 0; i < MAXPILEOBS; i++) {
|
||||
l->pack->oblist[i] = -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// hand out objects to cells
|
||||
for (y = 0; y < m->h; y++) {
|
||||
for (x = 0; x < m->w; x++) {
|
||||
cell_t *c;
|
||||
long obid;
|
||||
int curob = 0;
|
||||
c = m->cell[y * m->w + x];
|
||||
|
||||
obid = c->obpile->oblist[curob];
|
||||
while (obid != -1) {
|
||||
int found = B_FALSE;
|
||||
// find this ob id in the dummycell
|
||||
for (o = dummycell->obpile->first ; o ; o = nexto) {
|
||||
nexto = o->next;
|
||||
if (o->id == obid) {
|
||||
relinkob(o, c->obpile);
|
||||
found = B_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
dblog("Error loading obs - cell %d,%d should have obid %ld but can't find it.\n",x,y, obid);
|
||||
exit(1);
|
||||
}
|
||||
// next one
|
||||
curob++;
|
||||
}
|
||||
// clear the oblist
|
||||
for (i = 0; i < MAXPILEOBS; i++) {
|
||||
c->obpile->oblist[i] = -1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
// move lifeforms to their proper locations
|
||||
for (l = m->lf ; l ; l = l->next) {
|
||||
cell_t *c;
|
||||
c = getcellat(m, l->x, l->y);
|
||||
if (!c) {
|
||||
dblog("Error loading map - Can't find cell at %d,%d to place lifeform id %d.\n",
|
||||
l->x, l->y, l->id);
|
||||
exit(1);
|
||||
}
|
||||
movelf(l, c);
|
||||
//dblog("Moving lf %d to %d,%d\n",l->id, l->x, l->y);
|
||||
}
|
||||
|
||||
free(dummycell);
|
||||
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
int loadob(FILE *f, obpile_t *op) {
|
||||
objecttype_t *ot;
|
||||
object_t *o;
|
||||
material_t *mat;
|
||||
long obid;
|
||||
int otid,matid;
|
||||
char buf[BUFLEN];
|
||||
int flagid;
|
||||
flag_t tempflag;
|
||||
int rv;
|
||||
|
||||
fscanf(f, "id:%ld\n",&obid);
|
||||
fscanf(f, "type:%d\n",&otid);
|
||||
|
||||
ot = findot(otid);
|
||||
if (!ot) {
|
||||
dblog("ERROR loading objects - can't find obtype id %ld\n",obid);
|
||||
return B_TRUE;
|
||||
}
|
||||
// create the object
|
||||
o = addob(op, ot->name);
|
||||
|
||||
// overwrite ob parameters
|
||||
o->id = obid;
|
||||
fscanf(f, "material:%d\n",&matid);
|
||||
mat = findmaterial(matid);
|
||||
if (!mat) {
|
||||
dblog("ERROR loading objects - can't find material %d\n",matid);
|
||||
return B_TRUE;
|
||||
}
|
||||
o->material = mat;
|
||||
|
||||
fscanf(f, "weight:%f\n",&o->weight);
|
||||
|
||||
fgets(buf, BUFLEN, f); // inscription
|
||||
buf[strlen(buf)-1] = '\0'; // strip newline
|
||||
o->inscription = strdup(buf + 6); // after 'inscr:'
|
||||
if (!strcmp(o->inscription, "^^^")) { // ie. if equal to ^^^...
|
||||
free(o->inscription);
|
||||
o->inscription = NULL;
|
||||
}
|
||||
fscanf(f, "letter:%c\n",&o->letter);
|
||||
fscanf(f, "bless:%d\n",&o->blessed);
|
||||
fscanf(f, "blessknown:%d\n",&o->blessknown);
|
||||
fscanf(f, "amt:%d\n",&o->amt);
|
||||
|
||||
fscanf(f, "flags:\n");
|
||||
|
||||
rv = fscanf(f, "%d,%d,%d,%d,%d\n",
|
||||
&tempflag.id, &tempflag.nvals, &tempflag.val[0], &tempflag.val[1], &tempflag.val[2]);
|
||||
|
||||
// get flag text
|
||||
fgets(buf, BUFLEN, f);
|
||||
buf[strlen(buf)-1] = '\0'; // strip newline
|
||||
|
||||
while (tempflag.id != -1) {
|
||||
dblog("got flag id=%d\n",tempflag.id);
|
||||
|
||||
addflag(o->flags, tempflag.id,
|
||||
tempflag.val[0],
|
||||
tempflag.val[1],
|
||||
tempflag.val[2], strcmp(buf, "^^^") ? buf : NULL);
|
||||
// load next one
|
||||
rv = fscanf(f, "%d,%d,%d,%d,%d\n",
|
||||
&tempflag.id, &tempflag.nvals, &tempflag.val[0], &tempflag.val[1], &tempflag.val[2]);
|
||||
//dblog("fscanf returned %d\n",rv);
|
||||
}
|
||||
fscanf(f, "endob\n");
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
int loadsavegame(void) {
|
||||
DIR *dir;
|
||||
struct dirent *ent;
|
||||
char filename[BUFLEN];
|
||||
FILE *f;
|
||||
|
||||
// now see if there is a savegame...
|
||||
dir = opendir(SAVEDIR);
|
||||
if (!dir) {
|
||||
dblog("Could not open savegame directory '%s'",SAVEDIR);
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
ent = readdir(dir);
|
||||
while ((ent = readdir(dir)) != NULL) {
|
||||
char *p;
|
||||
// ie. start of 4 char prefix
|
||||
p = ent->d_name + strlen(ent->d_name) - 4;
|
||||
// load this savegame
|
||||
if (!strcmp(p, ".sav") ) {
|
||||
sprintf(filename, "%s/%s",SAVEDIR,ent->d_name);
|
||||
dblog("Trying to load from %s\n",filename);
|
||||
f = fopen(filename, "rt");
|
||||
if (!f) {
|
||||
printf("Error opening savegame file '%s'",ent->d_name);
|
||||
exit(1);
|
||||
}
|
||||
if (!loadlf(f, NULL)) {
|
||||
printf("Error loading savegame from file '%s'",ent->d_name);
|
||||
exit(1);
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
// successful load - kill the savegame now
|
||||
unlink(filename);
|
||||
break;
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
int savelf(FILE *f, lifeform_t *l) {
|
||||
object_t *o;
|
||||
int obcount = 0;
|
||||
// save this lf
|
||||
fprintf(f, "startlf\n");
|
||||
fprintf(f, "lfid: %d\n",l->id);
|
||||
fprintf(f, "race: %d\n",l->race->id);
|
||||
fprintf(f, "map: %d\n",l->cell->map->id);
|
||||
fprintf(f, "pos: %d,%d\n",l->cell->x, l->cell->y);
|
||||
fprintf(f, "contr: %d\n",l->controller);
|
||||
fprintf(f, "hp: %d/%d\n",l->hp, l->maxhp);
|
||||
fprintf(f, "alive: %d\n",l->alive);
|
||||
fprintf(f, "lastdam: %s\n",l->lastdam);
|
||||
fprintf(f, "timespent: %d\n",l->timespent);
|
||||
fprintf(f, "sorted: %d\n",l->sorted);
|
||||
// lifeform objects
|
||||
obcount = 0;
|
||||
for (o = l->pack->first ; o ; o = o->next) {
|
||||
fprintf(f, "ob:%ld\n",o->id);
|
||||
obcount++;
|
||||
}
|
||||
fprintf(f, "ob:-1\n");
|
||||
|
||||
fprintf(f, "obdefs\n");
|
||||
|
||||
// now save our object definitions
|
||||
for (o = l->pack->first ; o ; o = o->next) {
|
||||
saveob(f, o);
|
||||
}
|
||||
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
|
||||
int savemap(map_t *m) {
|
||||
FILE *f;
|
||||
char filename[BUFLEN];
|
||||
int i;
|
||||
object_t *o;
|
||||
lifeform_t *l;
|
||||
int x,y;
|
||||
int obcount = 0;
|
||||
|
||||
// TODO: check that map dir exists
|
||||
sprintf(filename, "%s/map%d.map",MAPDIR, m->id);
|
||||
f = fopen(filename, "wt");
|
||||
|
||||
// save map info
|
||||
fprintf(f, "id:%d\n",m->id); // map id
|
||||
fprintf(f, "name:%s\n",m->name); // map name
|
||||
fprintf(f, "habitat:%d\n",m->habitat); // habitat
|
||||
fprintf(f, "seed:%d\n",m->seed); // seed
|
||||
fprintf(f, "dims:%d,%d\n",m->w, m->h); // map dimensons
|
||||
fprintf(f, "nextlfid:%ld\n",m->nextlfid);
|
||||
fprintf(f, "nextmaps:\n");
|
||||
for (i = 0; i < MAXDIR_ORTH; i++) {
|
||||
fprintf(f, "%d\n",m->nextmap[i] ); // map dimensons
|
||||
}
|
||||
|
||||
// save all non-player lifeforms (includes their objects)
|
||||
fprintf(f, "lifeforms:\n");
|
||||
for (l = m->lf ; l ; l = l->next) {
|
||||
if (l->controller != C_PLAYER) { // don't save the player!
|
||||
savelf(f, l);
|
||||
}
|
||||
}
|
||||
fprintf(f, "endlifeforms\n");
|
||||
|
||||
// cells
|
||||
fprintf(f, "cells:\n");
|
||||
for (y = 0; y < m->h; y++) {
|
||||
for (x = 0; x < m->w; x++) {
|
||||
cell_t *c;
|
||||
c = getcellat(m, x, y);
|
||||
// cell info
|
||||
fprintf(f, "%d,%d,%d,%d\n",
|
||||
c->roomid, c->type->id, c->known, c->visited);
|
||||
// cell objects
|
||||
for (o = c->obpile->first ; o ; o = o->next) {
|
||||
fprintf(f, "ob:%ld\n",o->id);
|
||||
obcount++;
|
||||
}
|
||||
fprintf(f, "ob:-1\n");
|
||||
}
|
||||
}
|
||||
|
||||
// save object definitions from map cells
|
||||
fprintf(f, "MAPOBS:%d\n",obcount);
|
||||
for (y = 0; y < m->h; y++) {
|
||||
for (x = 0; x < m->w; x++) {
|
||||
cell_t *c;
|
||||
c = getcellat(m, x, y);
|
||||
// cell objects
|
||||
for (o = c->obpile->first ; o ; o = o->next) {
|
||||
saveob(f, o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
|
||||
int saveob(FILE *f, object_t *o) {
|
||||
flag_t *fl;
|
||||
fprintf(f, "id:%ld\n",o->id);
|
||||
fprintf(f, "type:%d\n",o->type->id);
|
||||
fprintf(f, "material:%d\n",o->material->id);
|
||||
fprintf(f, "weight:%f\n",o->weight);
|
||||
fprintf(f, "inscr:%s\n",o->inscription ? o->inscription : "^^^");
|
||||
fprintf(f, "letter:%c\n",o->letter);
|
||||
fprintf(f, "bless:%d\n",o->blessed);
|
||||
fprintf(f, "blessknown:%d\n",o->blessknown);
|
||||
fprintf(f, "amt:%d\n",o->amt);
|
||||
fprintf(f, "flags:\n");
|
||||
for (fl = o->flags->first ; fl ; fl = fl->next) {
|
||||
fprintf(f, "%d,%d,%d,%d,%d\n",
|
||||
fl->id, fl->nvals, fl->val[0], fl->val[1], fl->val[2]);
|
||||
if (!fl->text || !strcmp(fl->text, "")) {
|
||||
fprintf(f, "%s\n","^^^");
|
||||
} else {
|
||||
fprintf(f, "%s\n",fl->text);
|
||||
}
|
||||
}
|
||||
fprintf(f, "-1,-1,-1,-1,-1\n");
|
||||
fprintf(f, "endob\n");
|
||||
return B_FALSE;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
#include "defs.h"
|
||||
|
||||
int loadall(void);
|
||||
lifeform_t *loadlf(FILE *f, cell_t *where);
|
||||
map_t *loadmap(char *basefile);
|
||||
int loadob(FILE *f, obpile_t *op);
|
||||
int loadsavegame(void);
|
||||
int savelf(FILE *f, lifeform_t *l);
|
||||
int savemap(map_t *m);
|
||||
int saveob(FILE *f, object_t *o);
|
|
@ -0,0 +1,37 @@
|
|||
Initial checkin
|
||||
|
||||
--This line, and those below, will be ignored--
|
||||
|
||||
A objects.h
|
||||
A ai.h
|
||||
A save.c
|
||||
A lf.c
|
||||
A nexus.c
|
||||
A save.h
|
||||
A move.c
|
||||
A lf.h
|
||||
A attack.c
|
||||
A io.c
|
||||
A nexus.h
|
||||
A flag.c
|
||||
A object.h
|
||||
A move.h
|
||||
A io.h
|
||||
A attack.h
|
||||
A map.c
|
||||
A log.txt
|
||||
A flag.h
|
||||
A map.h
|
||||
A doc
|
||||
A doc/add_race.txt
|
||||
A doc/add_obclass.txt
|
||||
A text.c
|
||||
A defs.h
|
||||
A data
|
||||
A data/maps
|
||||
A data/save
|
||||
A ai.c
|
||||
A objects.c
|
||||
A text.h
|
||||
A Makefile
|
||||
A mod_ob.txt
|
|
@ -0,0 +1,41 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "defs.h"
|
||||
#include "objects.h"
|
||||
|
||||
char *capitalise(char *text) {
|
||||
text[0] = toupper(text[0]);
|
||||
return text;
|
||||
}
|
||||
|
||||
int isvowel (char c) {
|
||||
switch (c) {
|
||||
case 'a':
|
||||
case 'e':
|
||||
case 'i':
|
||||
case 'o':
|
||||
case 'u':
|
||||
return B_TRUE;
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
// allocates and returns new string
|
||||
char *makeplural(char *text) {
|
||||
int newlen;
|
||||
char *newtext;
|
||||
char lastlet;
|
||||
|
||||
lastlet = text[strlen(text)-1];
|
||||
switch (lastlet) {
|
||||
case 's':
|
||||
case 'o': // append "es"
|
||||
asprintf(&newtext, "%ses",text);
|
||||
break;
|
||||
default: // append "s"
|
||||
asprintf(&newtext, "%ss",text);
|
||||
break;
|
||||
}
|
||||
return newtext;
|
||||
}
|
Loading…
Reference in New Issue