Skip to content
Snippets Groups Projects
rlg327.cpp 6.28 KiB
Newer Older
Jake Feddersen's avatar
Jake Feddersen committed
#include <ncurses.h>
#include <cstdlib>
#include <vector>
#include <cstdint>
#include <cstring>

#include "character.h"
#include "dungeon.h"
#include "draw_dungeon.h"
#include "distance_map.h"
#include "line_of_sight.h"
#include "save_load.h"
#include "util.h"

void regen_dungeon(dungeon &d, heap_t *h, int nummon) {
  heap_delete(h);
  
  d.free_data();
  
  d.gen_random_dungeon();
  d.gen_monsters(nummon);
  d.gen_items(randrange(10, ITEMS_PER_LEVEL));
  
  d.init_turn_heap(h);
  calc_line_of_sight(d);
Jake Feddersen's avatar
Jake Feddersen committed
}

int main(int argc, char* argv[]) {  
Jake Feddersen's avatar
Jake Feddersen committed
  
  args args;
  parse_args(argc, argv, &args);
  
  srand(args.seed);
  
  if (args.load) {
    load_dungeon(d);
  } else {
    d.gen_random_dungeon();
  }
Jake Feddersen's avatar
Jake Feddersen committed
  
  d.gen_monsters(args.nummon);
  d.gen_items(randrange(10, ITEMS_PER_LEVEL));

  
  if (args.save) {
    save_dungeon(d);
  }
  
  init_screen();
  
  display_message("Using seed: %d", args.seed);
Jake Feddersen's avatar
Jake Feddersen committed

  heap_t h;
  d.init_turn_heap(&h);
  
  int game_won = 0;
  
  // Initialize line of sight
  calc_line_of_sight(d);
Jake Feddersen's avatar
Jake Feddersen committed
  
  while(1) {
    character *c = (character *) heap_remove_min(&h);
    int clear_message = 1;
Jake Feddersen's avatar
Jake Feddersen committed
    
    // If the character is not alive, then free its memory
    if (!c->alive) {
      if (c->is_player()) {
        delete c;
        game_won = 0;
        break;
      } else {
        ((monster *)c)->die();
Jake Feddersen's avatar
Jake Feddersen committed
        delete c;
        if (h.size == 1) {
          // Only one character left and the game isn't over, the player must have won
          game_won = 1;
          break;
        } else {
          continue;
        }
      }
    }
    
    // The character decides where to move next
    position next_move;
    if (!c->is_player()) {
      next_move = ((monster*)c)->monster_move(d);
    } else {
      d.draw();
      refresh_screen();
      
      int key;
      int handled_move = 0;
      while(!handled_move) {
        key = getch();
        
        if (key == -1) {
          d.draw();
          refresh_screen();
          continue;
        }
        
        if (key == 'Q' || key == 'q') {
          game_won = -1;
          break;
        }
Jake Feddersen's avatar
Jake Feddersen committed

        next_move = c->pos;
Jake Feddersen's avatar
Jake Feddersen committed

        if (key == '7' || key == 'y') {
          next_move.x--;
          next_move.y--;
          handled_move = 1;
        }
Jake Feddersen's avatar
Jake Feddersen committed

        if (key == '8' || key == 'k') {
          next_move.y--;
          handled_move = 1;
        }
Jake Feddersen's avatar
Jake Feddersen committed

        if (key == '9' || key == 'u') {
          next_move.y--;
          next_move.x++;
          handled_move = 1;
        }
Jake Feddersen's avatar
Jake Feddersen committed

        if (key == '6' || key == 'l') {
          next_move.x++;
          handled_move = 1;
        }
Jake Feddersen's avatar
Jake Feddersen committed

        if (key == '3' || key == 'n') {
          next_move.x++;
          next_move.y++;
          handled_move = 1;
        }
Jake Feddersen's avatar
Jake Feddersen committed

        if (key == '2' || key == 'j') {
          next_move.y++;
          handled_move = 1;
        }
Jake Feddersen's avatar
Jake Feddersen committed

        if (key == '1' || key == 'b') {
          next_move.x--;
          next_move.y++;
          handled_move = 1;
        }
Jake Feddersen's avatar
Jake Feddersen committed

        if (key == '4' || key == 'h') {
          next_move.x--;
          handled_move = 1;
        }
Jake Feddersen's avatar
Jake Feddersen committed

        if (key == '5' || key == ' ' || key == '.') {
          handled_move = 1;
        }
        
        if (key == 'm') {
          if (d.display_monster_list()) {
            game_won = -1;
            break;
          }
          d.draw();
          refresh_screen();
        }
        
        if (key == 't') {
          if (d.targeting_mode()) {
            game_won = -1;
            break;
          }
          calc_line_of_sight(d);
          d.draw();
          refresh_screen();
        }
        
        if (key == 'f') {
          d.toggle_fog_of_war();
          d.draw();
          refresh_screen();
        }
        
        if (key == '>') {
          for (i = 0; i < d.downstair_count; i++) {
            if (d.downstair_list[i].x == d.player_pos.x && d.downstair_list[i].y == d.player_pos.y) {
              regen_dungeon(d, &h, args.nummon);
              handled_move = 2;
              d.draw();
              refresh_screen();
            }
          }
          if (!handled_move) {
            display_message("%s", "Can't go downstairs there!");
            refresh_screen();
          }
        }
        
        if (key == '<') {
          for (i = 0; i < d.upstair_count; i++) {
            if (d.upstair_list[i] == d.player_pos) {
              regen_dungeon(d, &h, args.nummon);
              handled_move = 2;
              d.draw();
              refresh_screen();
            }
          }
          if (!handled_move) {
            display_message("%s", "Can't go upstairs there!");
            refresh_screen();
          }
        }
      }
      
      if (handled_move == 2) {
        continue;
      }
    }
    
    if (game_won == -1) {
      break;
    }
Jake Feddersen's avatar
Jake Feddersen committed
        
    // If we killed another character by moving there
    if (d.characters[next_move.y][next_move.x] && d.characters[next_move.y][next_move.x] != c) {
      d.characters[next_move.y][next_move.x]->alive = 0;
    }
    
    // Check for rock and tunneling
    if (d.hardness[next_move.y][next_move.x] && d.hardness[next_move.y][next_move.x] < 255 && c->has_characteristic(NPC_TUNNEL)) {
      if (d.hardness[next_move.y][next_move.x] > 85) {
        d.hardness[next_move.y][next_move.x] -= 85;
      } else if (d.hardness[next_move.y][next_move.x] > 0) {
        d.hardness[next_move.y][next_move.x] = 0;
      }
      
      // Update the line of sight
      calc_line_of_sight(d);
Jake Feddersen's avatar
Jake Feddersen committed
    }
    
    // If the space we want to move to has hardness zero, move there
    if (d.hardness[next_move.y][next_move.x] == 0) {
      d.characters[c->pos.y][c->pos.x] = NULL;
      d.characters[next_move.y][next_move.x] = c;
      c->pos = next_move;
      if (c->is_player()) {
        d.player_pos = next_move;
      }
    } else if (c->is_player()) {
      display_message("%s", "Ouch, that was a wall.");
      clear_message = 0;
    }
Jake Feddersen's avatar
Jake Feddersen committed
    
    // Update the character's turn and reinsert into heap
    c->next_turn = c->next_turn + (1000 / c->speed);
    heap_insert(&h, c);
    
    // If the player moved, update line of sight, redraw, and sleep for the timestep
Jake Feddersen's avatar
Jake Feddersen committed
    if (c->is_player()) {
      calc_line_of_sight(d);
      if (clear_message) {
        display_message("");
      }
    }
Jake Feddersen's avatar
Jake Feddersen committed
  }
  
  if (game_won == 1) {
    display_win();
  } else if (game_won == 0) {
    display_lose();
  }
Jake Feddersen's avatar
Jake Feddersen committed
  heap_delete(&h);
}