nexus/nexus.c

298 lines
5.8 KiB
C
Raw Normal View History

2010-12-02 12:17:54 +11:00
#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;
}
}