298 lines
5.8 KiB
C
298 lines
5.8 KiB
C
#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;
|
|
}
|
|
|
|
}
|