123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404 |
- #include "Map.h"
- game CreateGame() {
- game G = NULL;
- G = malloc(sizeof(Game));
- if(G) {
- G->print = CursesPrint;
- G->pc = NULL;
- G->ZombieListHead = NULL;
- G->win = NULL;
- int y, x;
- getmaxyx(stdscr, y, x );
- G->win = newwin( y, x, 0, 0 );
- G->arena = NULL;
- int status_height = 0;
- G->arena = CreateSubwindow(G->win, y-status_height, x, 0, 0 );
- G->status = NULL;
- G->status = CreateSubwindow(G->win, status_height, x, y-status_height, 0 );
- G->gameMap = CreateMap(G);
- InitMap(G->gameMap);
- return G;
- } else {
- fprintf( L, "Fatal error: failed to assign memory in CreateGame().\n" );
- exit(EXIT_FAILURE);
- }
- }
- game NewGame() {
- game g = CreateGame();
- if( g == NULL ) return NULL;
- RandomMap(g->gameMap);
- g->pc = CreateCharacter(g);
- wrefresh(g->win);
- init_pc(g->pc);
- box(g->arena, 0, 0);
- wrefresh(g->arena);
- int nzombies = NumZombies(g->arena);
- g->ZombieListHead = CreateCreature(g);
- init_npc(g->ZombieListHead->Character);
- wrefresh(g->arena);
- int n = 1;
- while( n < nzombies ) {
- wrefresh(g->arena);
- creature Z = CreateCreature(g);
- init_npc(Z->Character);
- InsertCreatureNode( g->ZombieListHead, Z );
- ++n;
- }
- return g;
- }
- void RunGame( int load) {
- game g = NULL;
- if(load) {
- g = LoadGame();
- } else {
- g = NewGame();
- }
- if(g==NULL) {
- return;
- }
- wrefresh(g->arena);
- wrefresh(g->status);
- if(g!=NULL) {
- if(g->pc) g->print(g->pc);
- creature G = CreateCreature(g);
- G = g->ZombieListHead;
- while(G) {
- g->print(G->Character);
- G = G->Next;
- }
- PrintAllBuildings(g->gameMap, g->pc->pos);
- PlayLoop(g);
- if(G) {
- PurgeCreatureNode(G);
- DESTROY(G);
- }
- PurgeGame(g);
- DESTROY(g);
- }
- }
- void PlayLoop( game g ) {
- while(pc_play(g)) {
- PrintAllBuildings(g->gameMap, g->pc->pos);
- move_zombies(g);
- update_alertness(g);
- bite_check(g);
- }
- char ch;
- while( ( g->pc->win || g->pc->health <= 0 ) && ! (( ch = getch() ) == 'q') ){
- // Let the player revel in their victory or failure.
- }
- wrefresh(g->arena);
- wrefresh(g->status);
- }
- /*! Waits for player input. */
- int pc_play( game g ) {
- if( g->pc->health <= 0 ) {
- wattron( g->win, COLOR_PAIR(ACTIVE) | A_BOLD );
- int max_y, max_x;
- getmaxyx( g->win, max_y, max_x );
- mvwprintw( g->win, max_y/2, max_x/2, "YOU LOSE!!" );
- wstandend(g->win);
- wrefresh(g->win);
- return FALSE;
- }
- if( g->pc->fatigue > 0 ) {
- g->pc->fatigue--;
- }
- g->pc->exhausted = (!g->pc->exhausted && g->pc->fatigue >= max_fatigue -1) || (g->pc->exhausted && g->pc->fatigue > 0 );
- int ch = getch();
- int i;
- switch( ch ) {
- case 'K':
- for( i=0; i<= !g->pc->exhausted; i++ ) {
- mvrel( g->pc, -1, 0 );
- g->pc->fatigue += !g->pc->exhausted;
- }
- break;
- case 'k':
- mvrel( g->pc, -1, 0);
- break;
- case 'J':
- for( i=0; i<= !g->pc->exhausted; i++ ) {
- mvrel( g->pc, 1, 0 );
- g->pc->fatigue += !g->pc->exhausted;
- }
- break;
- case 'j':
- mvrel( g->pc, 1, 0);
- break;
- case 'H':
- for( i=0; i<=!g->pc->exhausted; i++ ) {
- mvrel( g->pc, 0, -1 );
- g->pc->fatigue += !g->pc->exhausted;
- }
- break;
- case 'h':
- mvrel( g->pc, 0, -1);
- break;
- case 'L':
- for( i=0; i<=!g->pc->exhausted; i++ ) {
- mvrel( g->pc, 0, 1 );
- g->pc->fatigue += !g->pc->exhausted;
- }
- break;
- case 'l':
- mvrel( g->pc, 0, 1);
- break;
- case 'w':
- SaveGame(g);
- break;
- case 'q': // ESC
- return FALSE;
- }
- if( g->pc->win ) {
- wattron( g->win, COLOR_PAIR(WINNING_GREEN) | A_BOLD );
- int max_y, max_x;
- getmaxyx( g->win, max_y, max_x );
- mvwprintw( g->win, max_y/2, max_x/2, "YOU WIN!!" );
- wstandend(g->win);
- wrefresh(g->win);
- return FALSE;
- }
- return TRUE;
- }
- void PurgeGame( game g ) {
- DestroyZombies( g );
- if( g->pc != NULL ) {
- PurgeCharacter( g->pc );
- free( g->pc );
- }
- g->print= NULL;
- g->pc = NULL;
- DestroyMap(g->gameMap);
- DestroyWindow(g->arena);
- DestroyWindow(g->status);
- DestroyWindow(g->win);
- }
- void DestroyZombies( game g ) {
- if( g == NULL ) return;
- if( g->ZombieListHead == NULL ) return;
- while( g->ZombieListHead->Next != NULL ) {
- creature G = g->ZombieListHead->Next;
- CutCreatureNode( g->ZombieListHead, G );
- if(G != NULL) {
- PurgeCreatureNode( G );
- DESTROY(G);
- }
- }
- if( g->ZombieListHead != NULL ) {
- PurgeCreatureNode( g->ZombieListHead );
- DESTROY( g->ZombieListHead );
- }
- }
- void LoadCharacter( game g, chr c ) {
- if( g == NULL || c == NULL ) return;
- if( c->ispc ) {
- LoadPlayerCharacter( g, c );
- } else {
- LoadZombie( g, c );
- }
- }
- void LoadPlayerCharacter( game g, chr c ) {
- if( g == NULL || c == NULL ) return;
- if( g->pc ) { // Start from scratch ...
- PurgeCharacter( g->pc );
- DESTROY(g->pc);
- }
- g->pc = CreateCharacter(g);
- CopyCharacter( g->pc, c );
- wrefresh(g->arena);
- }
- void LoadZombie( game g, chr z ) {
- if( g == NULL || z == NULL ) return;
- if( g->ZombieListHead != NULL ) {
- creature Z = CreateCreature(g);
- CopyCharacter( Z->Character, z );
- InsertCreatureNode( g->ZombieListHead, Z );
- } else {
- g->ZombieListHead = CreateCreature(g);
- CopyCharacter( g->ZombieListHead->Character, z );
- }
- wrefresh(g->arena);
- }
- /*! First increase or decrease zombie's alertness depending
- on player proximity. Then use alertness to check whether
- the zombie starts actively hunting. */
- void update_alertness( game g ) {
- creature Z = g->ZombieListHead;
- int d;
- while( Z != NULL ) {
- chr z = Z->Character;
- // If a zombie sees another zombie hunting, it increases
- // alertness.
- creature Z1 = g->ZombieListHead;
- int num_alert = 0;
- while(Z1 != NULL) {
- chr z1 = Z1->Character;
- d = distance(z1->pos, z->pos);
- num_alert += z1->alert && d <= zombie_sight_range && d > 0;
- Z1 = Z1->Next;
- }
- if(!z->alert) z->alertness += (randint(0, num_alert) != 0);
- d = distance( g->pc->pos, z->pos );
- if( d <= zombie_sight_range ) {
- if( z->alertness < max_alertness ) {
- z->alertness++;
- }
- } else if( z->alertness > 0 ) {
- if(randint(0, (d - z->alert)/(zombie_sight_range + z->alertness))) z->alertness--;
- }
- int check = randint( 0, max_alertness );
- if( ( z->alert && d > zombie_sight_range ) || ! z->alert ) {
- z->alert = ( check < z->alertness );
- }
- Z = Z->Next;
- }
- }
- void move_zombies( game g ) {
- creature Z = g->ZombieListHead;
- while( Z != NULL ) {
- chr z = Z->Character;
- if( ! z->alert ) {
- int check = randint(-1,1);
- if( check == 0 ) {
- mvrel( z, randint( -1, 1 ), 0 );
- } else if( check ==1 ) {
- mvrel( z, 0, randint( -1, 1 ) );
- }
- } else {
- int dx = g->pc->pos->x - z->pos->x;
- int dy = g->pc->pos->y - z->pos->y;
- // Axis 0 will be horizontal, axis 1 is vertical.
- int axis = randint( 0, 1 );
- if( abs( dx ) > abs( dy ) ) {
- axis = 0;
- } else if( abs( dx ) < abs( dy ) ) {
- axis = 1;
- }
- int h_blocked = blocked(g->arena, z->pos->y, z->pos->x + 2*(dx >= 0) - 1);
- int v_blocked = blocked(g->arena, z->pos->y + 2*(dy >= 0) - 1, z->pos->x);
- if(h_blocked && !v_blocked) axis = 1;
- if(v_blocked && !h_blocked) axis = 0;
- int dir = 0;
- if( axis == 0 ) { // move along x-axis.
- if( dx >= 0 ) {
- dir = 1;
- } else {
- dir = -1;
- }
- mvrel( z, 0, dir );
- } else {
- if( dy >= 0 ) {
- dir = 1;
- } else {
- dir = -1;
- }
- mvrel( z, dir, 0 );
- }
- }
- Z = Z->Next;
- }
- }
- void bite_check( game g ) {
- creature Z = g->ZombieListHead;
- while( Z != NULL ) {
- chr z = Z->Character;
- int d = distance( g->pc->pos, z->pos );
- if( d == 1 ) {
- g->pc->health -= randint( 0, 1 );
- }
- Z = Z->Next;
- }
- }
- void SaveGame( game g ) {
- FILE* sf = fopen( "game.save", "w+" );
- SaveCharacter( sf, g->pc );
- creature Z = g->ZombieListHead;
- while( Z != NULL ) {
- chr z = Z->Character;
- SaveCharacter( sf, z );
- Z = Z->Next;
- }
- SaveMap(sf, g->gameMap);
- fclose( sf );
- }
- void SaveCharacter( FILE* sf, chr c ) {
- if( ! c->ispc ) fprintf( sf, "n" ); // Put "n" on "npc"
- fprintf( sf, "pc { pos = ( %d, %d )", GetStat( c, "y" ), GetStat( c, "x" ) );
- int i;
- for( i=0; i < nattrs; ++i ) {
- attr* attr_pair = Attrs + i;
- if( strcmp( attr_pair->str, "x" ) != 0 && strcmp( attr_pair->str, "y" ) != 0 ) {
- fprintf( sf, ", %s = %d", attr_pair->str, GetStat( c, attr_pair->str ) );
- }
- }
- fprintf( sf, "}\n" );
- }
- void SaveMap( FILE* sf, map m ) {
- if(!m) return;
- fprintf(sf, "map { ");
- building B = m->BuildingListHead;
- block b = B->contents;
- if(b) fprintf(sf, "(%d, %d, %d, %d)", b->h, b->w, b->y, b->x);
- B = B->Next;
- while(B) {
- block b = B->contents;
- if(b) fprintf(sf, ", (%d, %d, %d, %d)", b->h, b->w, b->y, b->x);
- B = B->Next;
- }
- fprintf(sf, " }");
- }
- int InLineOfSight(coords c, coords z, map m) {
- if(!c || !z || !m) return FALSE;
- if(c->x == z->x && c->y == z->y) return TRUE;
- if(!m->BuildingListHead) return FALSE;
- building B = m->BuildingListHead;
- block b = NULL;
- coords u = CreateCoords(), v = CreateCoords();
- while(B) {
- b = B->contents;
- int x;
- for(x = b->x; x <= b->x + b->w - 1; x += b->w - 1) {
- u->x = x;
- u->y = b->y;
- v->x = x;
- v->y = b->y + b->h - 1;
- if(Intersects(c, z, u, v)) {
- return FALSE;
- }
- }
- int y;
- for(y = b->y; y <= b->y + b->h - 1; y += b->h - 1) {
- u->x = b->x;
- u->y = y;
- v->x = b->x + b->w - 1;
- v->y = y;
- if(Intersects(c, z, u, v)) {
- return FALSE;
- }
- }
- B = B->Next;
- }
- return TRUE;
- }
|