float point exception, waiting for debugging
This commit is contained in:
33
src/Makefile
Normal file
33
src/Makefile
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# Universal makefile for single C++ program
|
||||||
|
#
|
||||||
|
# Use gcc flag -MMD (user) or -MD (user/system) to generate dependencies among source files.
|
||||||
|
# Use make default rules for commonly used file-name suffixes and make variables names.
|
||||||
|
#
|
||||||
|
# % make [ a.out ]
|
||||||
|
|
||||||
|
########## Variables ##########
|
||||||
|
|
||||||
|
CXX = g++ # compiler
|
||||||
|
CXXFLAGS = -std=c++20 -g -Wall -MMD -lncurses # compiler flags
|
||||||
|
MAKEFILE_NAME = ${firstword ${MAKEFILE_LIST}} # makefile name
|
||||||
|
|
||||||
|
SOURCES = $(wildcard *.cc) # source files (*.cc)
|
||||||
|
OBJECTS = ${SOURCES:.cc=.o} # object files forming executable
|
||||||
|
DEPENDS = ${OBJECTS:.o=.d} # substitute ".o" with ".d"
|
||||||
|
EXEC = cc3k # executable name
|
||||||
|
|
||||||
|
########## Targets ##########
|
||||||
|
|
||||||
|
.PHONY : clean # not file names
|
||||||
|
|
||||||
|
${EXEC} : ${OBJECTS} # link step
|
||||||
|
${CXX} ${CXXFLAGS} $^ -o $@ # additional object files before $^
|
||||||
|
|
||||||
|
${OBJECTS} : ${MAKEFILE_NAME} # OPTIONAL : changes to this file => recompile
|
||||||
|
|
||||||
|
# make implicitly generates rules to compile C++ files that generate .o files
|
||||||
|
|
||||||
|
-include ${DEPENDS} # include *.d files containing program dependences
|
||||||
|
|
||||||
|
clean : # remove files that can be regenerated
|
||||||
|
rm -f ${DEPENDS} ${OBJECTS} ${EXEC}
|
152
src/characters.cc
Normal file
152
src/characters.cc
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
#include "characters.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
character::character(const enum race &nrace):
|
||||||
|
race{nrace}, HP{STARTING_HP[race]},
|
||||||
|
ATK{STARTING_ATK[race]}, DEF{STARTING_DEF[race]} {}
|
||||||
|
|
||||||
|
character::~character() {}
|
||||||
|
|
||||||
|
enum race character::get_race() const {
|
||||||
|
return race;
|
||||||
|
}
|
||||||
|
|
||||||
|
position character::get_position() const {
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
int character::get_HP() const {
|
||||||
|
return HP;
|
||||||
|
}
|
||||||
|
|
||||||
|
int character::get_ATK() const {
|
||||||
|
return ATK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int character::get_DEF() const {
|
||||||
|
return DEF;
|
||||||
|
}
|
||||||
|
|
||||||
|
int character::get_gold() const {
|
||||||
|
return gold;
|
||||||
|
}
|
||||||
|
|
||||||
|
float character::get_hitrate() const {
|
||||||
|
return base_hitrate;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool character::is_hostile() const {
|
||||||
|
return hostile;
|
||||||
|
}
|
||||||
|
|
||||||
|
void character::set_position(const position &npos) {
|
||||||
|
pos = npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
void character::set_HP(const int nHP) {
|
||||||
|
HP = nHP;
|
||||||
|
}
|
||||||
|
|
||||||
|
void character::set_ATK(const int nATK) {
|
||||||
|
ATK = nATK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void character::set_DEF(const int nDEF) {
|
||||||
|
DEF = nDEF;
|
||||||
|
}
|
||||||
|
|
||||||
|
void character::set_gold(const int ngold) {
|
||||||
|
gold = ngold;
|
||||||
|
}
|
||||||
|
|
||||||
|
void character::set_hitrate(const float nhitrate) {
|
||||||
|
base_hitrate = nhitrate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void character::set_hostile(const bool is_hostile) {
|
||||||
|
hostile = is_hostile;
|
||||||
|
}
|
||||||
|
|
||||||
|
void character::apply_buff(const stat_name statn, const int amount) {
|
||||||
|
switch (statn) {
|
||||||
|
case stat_name::HP:
|
||||||
|
HP += amount;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case stat_name::ATK:
|
||||||
|
ATK += amount;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case stat_name::DEF:
|
||||||
|
DEF += amount;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case stat_name::hostile: {
|
||||||
|
if (amount > 0)
|
||||||
|
hostile = true;
|
||||||
|
else
|
||||||
|
hostile = false;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
character_list::character_list():
|
||||||
|
layer{layer_num::characters} {}
|
||||||
|
|
||||||
|
void character_list::print() const {
|
||||||
|
// TODO: implement it using ncurses
|
||||||
|
}
|
||||||
|
|
||||||
|
void character_list::print(display &display) const {
|
||||||
|
for (auto &ch : characters)
|
||||||
|
display.print_position(ch->get_position(),
|
||||||
|
CHARACTER_REP[ch->get_race()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<character>>::const_iterator character_list::begin()
|
||||||
|
const {
|
||||||
|
return characters.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<character>>::const_iterator character_list::end()
|
||||||
|
const {
|
||||||
|
return characters.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
direction_list character::moveable(const position_list &available_positions)
|
||||||
|
const {
|
||||||
|
direction_list result;
|
||||||
|
|
||||||
|
for (int i = 0; i < DIRECTION_CNT; ++i)
|
||||||
|
if (find(available_positions, pos + MOVE[i])
|
||||||
|
!= available_positions.size())
|
||||||
|
result.push_back((direction)i);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
result character::apply(direction &dir, const potion_list &potions) {
|
||||||
|
// TODO: implement this after implementing potions
|
||||||
|
return result::fine;
|
||||||
|
}
|
||||||
|
|
||||||
|
position_list remove_from_list(const position_list &sorted_positions,
|
||||||
|
position_list excluded) {
|
||||||
|
std::sort(excluded.begin(), excluded.end());
|
||||||
|
|
||||||
|
position_list result{sorted_positions.size() - excluded.size()};
|
||||||
|
|
||||||
|
auto exc = excluded.begin();
|
||||||
|
|
||||||
|
for (auto src : sorted_positions) {
|
||||||
|
if (exc != excluded.end() && src == *exc)
|
||||||
|
++exc;
|
||||||
|
else
|
||||||
|
result.push_back(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
2
src/characters.d
Normal file
2
src/characters.d
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
characters.o: characters.cc characters.h constants.h position.h layer.h \
|
||||||
|
display.h objects.h rng.h
|
99
src/characters.h
Normal file
99
src/characters.h
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* CS 246 Final Project
|
||||||
|
* File: map.h
|
||||||
|
* Purpose: handles all characters
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CHARACTERS_H__
|
||||||
|
#define __CHARACTERS_H__
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
#include "constants.h"
|
||||||
|
#include "position.h"
|
||||||
|
#include "layer.h"
|
||||||
|
#include "objects.h"
|
||||||
|
#include "rng.h"
|
||||||
|
// #include "inventory.h" // Reserved for later
|
||||||
|
|
||||||
|
class character; // forward declaration
|
||||||
|
extern RNG rng;
|
||||||
|
|
||||||
|
// Note: player should not be in the character list
|
||||||
|
class character_list final: public layer {
|
||||||
|
private:
|
||||||
|
std::vector<std::unique_ptr<character>> characters;
|
||||||
|
public:
|
||||||
|
character_list();
|
||||||
|
void print() const;
|
||||||
|
void print(display &display) const;
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<character>>::const_iterator begin() const;
|
||||||
|
std::vector<std::unique_ptr<character>>::const_iterator end() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class character {
|
||||||
|
public:
|
||||||
|
character(const race &nrace); // fills out the starting stats
|
||||||
|
|
||||||
|
~character(); // placeholder
|
||||||
|
|
||||||
|
// usually I wouldn't do this but considering that the map has
|
||||||
|
// a super small size an O(n) solution is acceptable
|
||||||
|
// IMPORTANT: available_positions do NOT have characters in them
|
||||||
|
direction_list moveable(const position_list &available_positions) const;
|
||||||
|
virtual result move(const direction dir,
|
||||||
|
const position_list &available_positions) = 0;
|
||||||
|
virtual result attack(const direction dir,
|
||||||
|
const character_list &chlist) = 0;
|
||||||
|
virtual result move_or_attack(const direction dir,
|
||||||
|
const position_list &available_positions,
|
||||||
|
const character_list &chlist) = 0;
|
||||||
|
virtual result apply(direction &dir,
|
||||||
|
const potion_list &potions);
|
||||||
|
virtual result get_hit(const enum race &race, const int atk,
|
||||||
|
const float hitrate) = 0;
|
||||||
|
enum race get_race() const;
|
||||||
|
position get_position() const;
|
||||||
|
int get_HP() const;
|
||||||
|
int get_ATK() const;
|
||||||
|
int get_DEF() const;
|
||||||
|
int get_gold() const;
|
||||||
|
float get_hitrate() const;
|
||||||
|
bool is_hostile() const;
|
||||||
|
|
||||||
|
void set_position(const position &npos);
|
||||||
|
void set_HP(const int nHP);
|
||||||
|
void set_ATK(const int nATK);
|
||||||
|
void set_DEF(const int nDEF);
|
||||||
|
void set_gold(const int ngold);
|
||||||
|
void set_hitrate(const float nhitrate);
|
||||||
|
void set_hostile(const bool is_hostile);
|
||||||
|
|
||||||
|
// if stat is hostile, positive to set it to hostile,
|
||||||
|
// negative to set it to peaceful
|
||||||
|
void apply_buff(const stat_name statn, const int amount);
|
||||||
|
// void apply_buff(const stat_name statn, const float mul);
|
||||||
|
// reserved for later
|
||||||
|
protected:
|
||||||
|
const enum race race;
|
||||||
|
|
||||||
|
int HP;
|
||||||
|
int ATK;
|
||||||
|
int DEF;
|
||||||
|
|
||||||
|
position pos;
|
||||||
|
|
||||||
|
int gold; // characters spawn with gold
|
||||||
|
// inventory inventory; // Reserved
|
||||||
|
|
||||||
|
float base_hitrate; // requires: between [0,1]
|
||||||
|
|
||||||
|
bool hostile;
|
||||||
|
};
|
||||||
|
|
||||||
|
// requires: all elements of excluded are in sorted_positions
|
||||||
|
position_list remove_from_list(const position_list &sorted_positions,
|
||||||
|
position_list excluded);
|
||||||
|
|
||||||
|
#endif
|
BIN
src/characters.o
Normal file
BIN
src/characters.o
Normal file
Binary file not shown.
67
src/constants.h
Normal file
67
src/constants.h
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
// TODO: Consider moving the contents of this header to their relevant
|
||||||
|
// headers
|
||||||
|
|
||||||
|
#ifndef __CONSTANTS_H__
|
||||||
|
#define __CONSTANTS_H__
|
||||||
|
#include <vector>
|
||||||
|
#include "position.h"
|
||||||
|
|
||||||
|
// IMPORTANT: added END to the end of all valued enums so that you can
|
||||||
|
// iterate over them
|
||||||
|
|
||||||
|
enum error {none};
|
||||||
|
|
||||||
|
// TODO: update result to include subject
|
||||||
|
enum result {fine, died, go_down, hit, moved};
|
||||||
|
|
||||||
|
enum stat_name {HP, ATK, DEF, hostile};
|
||||||
|
|
||||||
|
const int LAYER_CNT = 4; // TODO: update as you go
|
||||||
|
enum layer_num {map = 0, objects, characters, shop};
|
||||||
|
|
||||||
|
const int RACE_CNT = 2; // TODO: update as you go
|
||||||
|
|
||||||
|
enum race {unknown = 0, rshade /* TODO: fill out the other races (including enemies) */};
|
||||||
|
|
||||||
|
// TODO: fill out the other races (including enemies)
|
||||||
|
const int MAX_HP[RACE_CNT] = {0, 125};
|
||||||
|
const int STARTING_HP[RACE_CNT] = {0, 125};
|
||||||
|
const int STARTING_ATK[RACE_CNT] = {0, 25};
|
||||||
|
const int STARTING_DEF[RACE_CNT] = {0, 25};
|
||||||
|
const char CHARACTER_REP[RACE_CNT] = {'@', 'S'};
|
||||||
|
|
||||||
|
const int DIRECTION_CNT = 8;
|
||||||
|
// IMPORTANT: east is positive for x and SOUTH is positive for y
|
||||||
|
// initializes all directions to an int
|
||||||
|
enum direction {east = 0, west, north, south, northeast,
|
||||||
|
northwest, southeast, southest
|
||||||
|
};
|
||||||
|
|
||||||
|
const position MOVE[DIRECTION_CNT] = {
|
||||||
|
{1, 0}, {-1, 0}, {0, -1}, {0, 1},
|
||||||
|
{1, -1}, {-1, -1}, {1, 1}, {-1, 1}
|
||||||
|
};
|
||||||
|
|
||||||
|
const int MAP_HEIGHT = 25;
|
||||||
|
const int MAP_WIDTH = 79;
|
||||||
|
const int DISPLAY_HEIGHT = 30;
|
||||||
|
const int DISPLAY_WIDTH = 79;
|
||||||
|
|
||||||
|
// TODO: list all extra features
|
||||||
|
// using constants to keep track of features
|
||||||
|
// method: features: FEATURE_XXX | FEATURE_YYY
|
||||||
|
// That is: use bit manipulation
|
||||||
|
// check if feature is enabled:
|
||||||
|
// features & FEATURE_XXX
|
||||||
|
typedef unsigned int feature; // can extend to unsigned long (long) if needed
|
||||||
|
const feature FEATURE_NCURSES = 1 << 0;
|
||||||
|
const feature FEATURE_RAND_MAP = 1 << 1;
|
||||||
|
const feature FEATURE_ENEMIES_CHASE = 1 << 2;
|
||||||
|
const feature FEATURE_INVENTORY = 1 << 3;
|
||||||
|
const feature FEATURE_THROW = 1 << 4;
|
||||||
|
const feature FEATURE_REVISIT = 1 << 5;
|
||||||
|
|
||||||
|
typedef std::vector<position> position_list;
|
||||||
|
typedef std::vector<direction> direction_list;
|
||||||
|
|
||||||
|
#endif
|
21
src/display.cc
Normal file
21
src/display.cc
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#include "display.h"
|
||||||
|
|
||||||
|
display::display(): contents{DISPLAY_HEIGHT} {}
|
||||||
|
|
||||||
|
void display::clear() {
|
||||||
|
for (auto line : contents)
|
||||||
|
line.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void display::print(std::ostream &out) const {
|
||||||
|
for (auto line : contents)
|
||||||
|
out << line << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void display::print_line(const std::string &line, const int linenum) {
|
||||||
|
contents[linenum] = line;
|
||||||
|
}
|
||||||
|
|
||||||
|
void display::print_position(const position &pos, const char ch) {
|
||||||
|
contents[pos.y][pos.x] = ch;
|
||||||
|
}
|
1
src/display.d
Normal file
1
src/display.d
Normal file
@ -0,0 +1 @@
|
|||||||
|
display.o: display.cc display.h position.h constants.h
|
30
src/display.h
Normal file
30
src/display.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* CS 246 Final Project
|
||||||
|
* File: display.h
|
||||||
|
* Purpose: handles map functionality
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __DISPLAY_H__
|
||||||
|
#define __DISPLAY_H__
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include "position.h"
|
||||||
|
#include "constants.h"
|
||||||
|
|
||||||
|
class display final {
|
||||||
|
private:
|
||||||
|
std::vector<std::string> contents;
|
||||||
|
public:
|
||||||
|
display();
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
// use this instead of overloading for clarity
|
||||||
|
void print(std::ostream &out) const;
|
||||||
|
void print_line(const std::string &line, const int linenum);
|
||||||
|
|
||||||
|
// will override any character that was there
|
||||||
|
void print_position(const position &pos, const char ch);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
BIN
src/display.o
Normal file
BIN
src/display.o
Normal file
Binary file not shown.
22
src/layer.h
Normal file
22
src/layer.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* CS 246 Final Project
|
||||||
|
* File: map.h
|
||||||
|
* Purpose: handles map functionality
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LAYER_H__
|
||||||
|
#define __LAYER_H__
|
||||||
|
#include "constants.h"
|
||||||
|
#include "display.h"
|
||||||
|
|
||||||
|
class layer {
|
||||||
|
public:
|
||||||
|
const layer_num num;
|
||||||
|
|
||||||
|
layer(const layer_num ln): num{ln} {}
|
||||||
|
|
||||||
|
virtual void print() const = 0;
|
||||||
|
virtual void print(display &display) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
47
src/main.cc
Normal file
47
src/main.cc
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include "map.h"
|
||||||
|
#include "races.h"
|
||||||
|
#include "display.h"
|
||||||
|
#include "rng.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
RNG rng;//{(unsigned int)time(0)};
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
display display;
|
||||||
|
unique_ptr<game_map> mmap(new game_map{default_map, 0});
|
||||||
|
unique_ptr<class shade>
|
||||||
|
player(new shade{mmap->get_available_positions()});
|
||||||
|
|
||||||
|
for (char ch = ' '; ch != 'q'; ch = getchar()) {
|
||||||
|
display.clear();
|
||||||
|
mmap->print(display);
|
||||||
|
display.print_position(player->get_position(), '@');
|
||||||
|
|
||||||
|
auto available_positions = mmap->get_available_positions();
|
||||||
|
|
||||||
|
switch (ch) {
|
||||||
|
case 'j':
|
||||||
|
player->move(direction::south, available_positions);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'k':
|
||||||
|
player->move(direction::north, available_positions);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'h':
|
||||||
|
player->move(direction::west, available_positions);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'l':
|
||||||
|
player->move(direction::east, available_positions);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
2
src/main.d
Normal file
2
src/main.d
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
main.o: main.cc map.h objects.h layer.h constants.h position.h display.h \
|
||||||
|
characters.h rng.h races.h
|
BIN
src/main.o
Normal file
BIN
src/main.o
Normal file
Binary file not shown.
65
src/map.cc
Normal file
65
src/map.cc
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#include "map.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
game_map::game_map(int lvl):
|
||||||
|
layer{layer_num::map}, map{MAP_HEIGHT}, level{lvl} {
|
||||||
|
// TODO: randomly generate a map
|
||||||
|
}
|
||||||
|
|
||||||
|
game_map::game_map(const std::string &map_data, int lvl):
|
||||||
|
layer{layer_num::map}, map{MAP_HEIGHT}, level{lvl} {
|
||||||
|
std::istringstream iss{map_data};
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
|
||||||
|
for (int i = 0; i < MAP_HEIGHT; ++i) {
|
||||||
|
getline(iss, line);
|
||||||
|
map.push_back(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
game_map::~game_map() {}
|
||||||
|
|
||||||
|
int game_map::get_level() const {
|
||||||
|
return this->level;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<position> game_map::get_available_positions() const {
|
||||||
|
std::vector<position> result;
|
||||||
|
|
||||||
|
for (int line = 0; line < MAP_HEIGHT; ++line)
|
||||||
|
for (int x = 0; x < MAP_WIDTH; ++x)
|
||||||
|
if (map[line][x] == '.')
|
||||||
|
result.push_back(position{x, line});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void game_map::print() const {
|
||||||
|
|
||||||
|
// TODO: write a print function using ncurses
|
||||||
|
}
|
||||||
|
|
||||||
|
void game_map::print(display &display) const {
|
||||||
|
for (int i = 0; i < MAP_HEIGHT; ++i)
|
||||||
|
display.print_line(map[i] + "\n", i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void game_map::apply_potion(character *who, const stat_name statn,
|
||||||
|
const int amount) {
|
||||||
|
effects.push_back(effect{who, statn, amount});
|
||||||
|
who->apply_buff(statn, amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
void game_map::enter_level(character *who) {
|
||||||
|
for (auto eff : effects)
|
||||||
|
if (eff.who == who)
|
||||||
|
who->apply_buff(eff.statn, eff.amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
void game_map::leave_level(character *who) {
|
||||||
|
who->set_ATK(STARTING_ATK[who->get_race()]);
|
||||||
|
who->set_DEF(STARTING_DEF[who->get_race()]);
|
||||||
|
}
|
2
src/map.d
Normal file
2
src/map.d
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
map.o: map.cc map.h objects.h layer.h constants.h position.h display.h \
|
||||||
|
characters.h rng.h
|
87
src/map.h
Normal file
87
src/map.h
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* CS 246 Final Project
|
||||||
|
* File: map.h
|
||||||
|
* Purpose: handles map functionality
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MAP_H__
|
||||||
|
#define __MAP_H__
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include "objects.h"
|
||||||
|
#include "constants.h"
|
||||||
|
#include "display.h"
|
||||||
|
#include "position.h"
|
||||||
|
#include "layer.h"
|
||||||
|
#include "characters.h"
|
||||||
|
|
||||||
|
class game_map final: public layer {
|
||||||
|
public:
|
||||||
|
game_map(int lvl = 0); // randomly generate one
|
||||||
|
// initialize using stored data
|
||||||
|
game_map(const std::string &map_data, int lvl);
|
||||||
|
~game_map(); // placeholder
|
||||||
|
|
||||||
|
int get_level() const;
|
||||||
|
|
||||||
|
position_list get_available_positions() const;
|
||||||
|
|
||||||
|
// IMPORTANT: always print a map before anything else
|
||||||
|
|
||||||
|
// prints using ncurses
|
||||||
|
void print() const;
|
||||||
|
|
||||||
|
// prints to a string
|
||||||
|
void print(display &display) const;
|
||||||
|
|
||||||
|
// This is implemented this way to do two things:
|
||||||
|
// 1. avoid directly accessing heap memory (bonus points)
|
||||||
|
// 2. make a level revisitable
|
||||||
|
void apply_potion(character *who, const stat_name statn, const int amount);
|
||||||
|
|
||||||
|
// just in case you want to retain the potion effects
|
||||||
|
void enter_level(character *who);
|
||||||
|
void leave_level(character *who);
|
||||||
|
private:
|
||||||
|
struct effect {
|
||||||
|
character *who;
|
||||||
|
stat_name statn;
|
||||||
|
int amount;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<std::string> map;
|
||||||
|
int level;
|
||||||
|
|
||||||
|
// use this to remember every applied potion
|
||||||
|
std::vector<effect> effects;
|
||||||
|
};
|
||||||
|
|
||||||
|
const std::string default_map =
|
||||||
|
"|-----------------------------------------------------------------------------|\
|
||||||
|
| |\
|
||||||
|
| |--------------------------| |-----------------------| |\
|
||||||
|
| |..........................| |.......................| |\
|
||||||
|
| |..........................+########+.......................|-------| |\
|
||||||
|
| |..........................| # |...............................|--| |\
|
||||||
|
| |..........................| # |..................................|--| |\
|
||||||
|
| |----------+---------------| # |----+----------------|...............| |\
|
||||||
|
| # ############# |...............| |\
|
||||||
|
| # # |-----+------| |...............| |\
|
||||||
|
| # # |............| |...............| |\
|
||||||
|
| ################### |............| ######+...............| |\
|
||||||
|
| # # |............| # |...............| |\
|
||||||
|
| # # |-----+------| # |--------+------| |\
|
||||||
|
| |---------+-----------| # # # # |\
|
||||||
|
| |.....................| # # # |----+------| |\
|
||||||
|
| |.....................| ######################## |...........| |\
|
||||||
|
| |.....................| # # |...........| |\
|
||||||
|
| |.....................| # |------+--------------------|...........| |\
|
||||||
|
| |.....................| # |.......................................| |\
|
||||||
|
| |.....................+##########+.......................................| |\
|
||||||
|
| |.....................| |.......................................| |\
|
||||||
|
| |---------------------| |---------------------------------------| |\
|
||||||
|
| |\
|
||||||
|
|-----------------------------------------------------------------------------|\
|
||||||
|
";
|
||||||
|
|
||||||
|
#endif
|
33
src/objects.h
Normal file
33
src/objects.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* CS 246 Final Project
|
||||||
|
* File: map.h
|
||||||
|
* Purpose: handles map functionality
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __OBJECTS_H__
|
||||||
|
#define __OBJECTS_H__
|
||||||
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
#include "layer.h"
|
||||||
|
#include "display.h"
|
||||||
|
|
||||||
|
class object {
|
||||||
|
// TODO: design the entire class
|
||||||
|
public:
|
||||||
|
void print() {} // use ncurses
|
||||||
|
void print(display &display) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: throw potion into another header
|
||||||
|
|
||||||
|
class potion final: public object {
|
||||||
|
// TODO: design the entire class
|
||||||
|
};
|
||||||
|
|
||||||
|
class potion_list final: public layer {
|
||||||
|
private:
|
||||||
|
std::vector<std::unique_ptr<potion>> potions;
|
||||||
|
// TODO: design the entire class
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
52
src/position.cc
Normal file
52
src/position.cc
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#include "position.h"
|
||||||
|
|
||||||
|
position::position(): x{0}, y{0} {}
|
||||||
|
|
||||||
|
position::position(int nx, int ny): x{nx}, y{ny} {}
|
||||||
|
|
||||||
|
position position::operator+(const position &other) const {
|
||||||
|
position result{x + other.x, y + other.y};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
position &position::operator=(const position &other) {
|
||||||
|
x = other.x;
|
||||||
|
y = other.y;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
position &position::operator+=(const position &other) {
|
||||||
|
return *this = *this + other;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool position::operator==(const position &other) const {
|
||||||
|
return x == other.x && y == other.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool position::operator!=(const position &other) const {
|
||||||
|
return x != other.x || y != other.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool position::operator<(const position &other) const {
|
||||||
|
return y < other.y || x < other.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t find(const std::vector<position> &sorted_list,
|
||||||
|
const position &target) {
|
||||||
|
int l = 0;
|
||||||
|
int r = sorted_list.size() - 1;
|
||||||
|
|
||||||
|
while (l <= r) {
|
||||||
|
int mid = l + (l + r) / 2;
|
||||||
|
|
||||||
|
if (target == sorted_list[mid])
|
||||||
|
return mid;
|
||||||
|
|
||||||
|
if (target < sorted_list[mid])
|
||||||
|
l = mid + 1;
|
||||||
|
else
|
||||||
|
r = mid - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sorted_list.size();
|
||||||
|
}
|
1
src/position.d
Normal file
1
src/position.d
Normal file
@ -0,0 +1 @@
|
|||||||
|
position.o: position.cc position.h
|
29
src/position.h
Normal file
29
src/position.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* CS 246 Final Project
|
||||||
|
* File: map.h
|
||||||
|
* Purpose: handles map functionality
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __POSITION_H__
|
||||||
|
#define __POSITION_H__
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
typedef struct position {
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
|
||||||
|
position();
|
||||||
|
position(int nx, int ny);
|
||||||
|
|
||||||
|
position operator+(const position &other) const;
|
||||||
|
position &operator=(const position &other);
|
||||||
|
position &operator+=(const position &other);
|
||||||
|
bool operator==(const position &other) const;
|
||||||
|
bool operator!=(const position &other) const;
|
||||||
|
bool operator<(const position &other) const;
|
||||||
|
} position;
|
||||||
|
|
||||||
|
size_t find(const std::vector<position> &sorted_list,
|
||||||
|
const position &target);
|
||||||
|
|
||||||
|
#endif
|
BIN
src/position.o
Normal file
BIN
src/position.o
Normal file
Binary file not shown.
68
src/races.cc
Normal file
68
src/races.cc
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#include "races.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
shade::shade(const position_list &available_positions):
|
||||||
|
character{race::rshade} {
|
||||||
|
pos = available_positions[rng.rand_under(available_positions.size())];
|
||||||
|
gold = 0;
|
||||||
|
hostile = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IMPORTANT: remember to check if player is on the stairs
|
||||||
|
result shade::move(const direction dir,
|
||||||
|
const position_list &available_positions) {
|
||||||
|
if (find(available_positions, pos + MOVE[dir])
|
||||||
|
!= available_positions.size()) {
|
||||||
|
pos += MOVE[dir];
|
||||||
|
return result::moved;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result::fine;
|
||||||
|
}
|
||||||
|
|
||||||
|
result shade::attack(const direction dir, const character_list &chlist) {
|
||||||
|
position tmp{pos + MOVE[dir]};
|
||||||
|
|
||||||
|
for (auto &ch : chlist)
|
||||||
|
if (tmp == ch->get_position()) {
|
||||||
|
return ch->get_hit(race, ATK, base_hitrate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result::fine;
|
||||||
|
}
|
||||||
|
|
||||||
|
result shade::move_or_attack(const direction dir,
|
||||||
|
const position_list &available_positions,
|
||||||
|
const character_list &chlist) {
|
||||||
|
position tmp{pos + MOVE[dir]};
|
||||||
|
|
||||||
|
if (find(available_positions, tmp)
|
||||||
|
!= available_positions.size()) {
|
||||||
|
pos = tmp;
|
||||||
|
return result::moved;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &ch : chlist)
|
||||||
|
if (tmp == ch->get_position()) {
|
||||||
|
return ch->get_hit(race, ATK, base_hitrate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result::fine;
|
||||||
|
}
|
||||||
|
|
||||||
|
int calc_dmg(const int ATK, const int DEF) {
|
||||||
|
return ceil((100 / (100 + DEF)) * ATK);
|
||||||
|
}
|
||||||
|
|
||||||
|
result shade::get_hit(const enum race &race, const int atk,
|
||||||
|
const float hitrate) {
|
||||||
|
if (rng.rand_num() <= hitrate * (float)RAND_MAX) // This is a hit!
|
||||||
|
HP = std::max(HP - calc_dmg(atk, DEF), 0);
|
||||||
|
|
||||||
|
if (HP == 0)
|
||||||
|
return result::died;
|
||||||
|
|
||||||
|
return result::hit;
|
||||||
|
}
|
2
src/races.d
Normal file
2
src/races.d
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
races.o: races.cc races.h characters.h constants.h position.h layer.h \
|
||||||
|
display.h objects.h rng.h
|
30
src/races.h
Normal file
30
src/races.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* CS 246 Final Project
|
||||||
|
* File: map.h
|
||||||
|
* Purpose: handles map functionality
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __RACES_H__
|
||||||
|
#define __RACES_H__
|
||||||
|
#include "characters.h"
|
||||||
|
|
||||||
|
// IMPORTANT: assumes all available positions have excluded chlist
|
||||||
|
|
||||||
|
class shade final: public character {
|
||||||
|
public:
|
||||||
|
shade(const position_list &available_positions); // spawn at a random place
|
||||||
|
virtual result move(const direction dir,
|
||||||
|
const position_list &available_positions) override;
|
||||||
|
virtual result attack(const direction dir,
|
||||||
|
const character_list &chlist) override;
|
||||||
|
virtual result move_or_attack(const direction dir,
|
||||||
|
const position_list &available_positions,
|
||||||
|
const character_list &chlist) override;
|
||||||
|
virtual result get_hit(const enum race &race, const int atk,
|
||||||
|
const float hitrate) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: fill out the other races
|
||||||
|
// TODO: implement enemie movement
|
||||||
|
|
||||||
|
#endif
|
BIN
src/races.o
Normal file
BIN
src/races.o
Normal file
Binary file not shown.
39
src/rng.cc
Normal file
39
src/rng.cc
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#include "rng.h"
|
||||||
|
|
||||||
|
RNG::RNG(): init_seed(time(0)), curr_rand_num(0) {
|
||||||
|
srand(init_seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
RNG::RNG(const unsigned int seed): init_seed(seed), curr_rand_num(0) {
|
||||||
|
srand(init_seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
int RNG::rand_num() {
|
||||||
|
return curr_rand_num = rand();
|
||||||
|
}
|
||||||
|
|
||||||
|
int RNG::rand_between(const int lower_bound, const int upper_bound) {
|
||||||
|
curr_rand_num = rand();
|
||||||
|
|
||||||
|
return lower_bound + (curr_rand_num % (upper_bound - lower_bound));
|
||||||
|
}
|
||||||
|
|
||||||
|
int RNG::rand_under(const int upper_bound) {
|
||||||
|
curr_rand_num = rand();
|
||||||
|
|
||||||
|
return curr_rand_num % upper_bound;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int RNG::get_init_seed() const {
|
||||||
|
return init_seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RNG::get_curr_rand_num() const {
|
||||||
|
return curr_rand_num;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T> T &RNG::get_rand_in_vector(const std::vector<T> &vec) {
|
||||||
|
curr_rand_num = rand();
|
||||||
|
|
||||||
|
return vec[curr_rand_num % vec.size()];
|
||||||
|
}
|
30
src/rng.h
Normal file
30
src/rng.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#ifndef __RNG_H__
|
||||||
|
#define __RNG_H__
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// Technically, you should ONLY define one rng for the entire program
|
||||||
|
// IMPORTANT: pass all RNG objects as references
|
||||||
|
class RNG final {
|
||||||
|
private:
|
||||||
|
const unsigned int init_seed;
|
||||||
|
int curr_rand_num;
|
||||||
|
public:
|
||||||
|
RNG(); // use time(0) as the seed
|
||||||
|
RNG(const unsigned int seed); // use a seed
|
||||||
|
|
||||||
|
int rand_num(); // returns a random number between 0 and RAND_MAX
|
||||||
|
|
||||||
|
// IMPORTANT: all upper bounds are not included, all lower bounds are
|
||||||
|
int rand_between(const int lower_bound, const int upper_bound);
|
||||||
|
// returns a random number between 0 and upper_bound
|
||||||
|
int rand_under(const int upper_bound);
|
||||||
|
unsigned int get_init_seed() const;
|
||||||
|
int get_curr_rand_num() const;
|
||||||
|
|
||||||
|
template<class T> T &get_rand_in_vector(const std::vector<T> &vec);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
Reference in New Issue
Block a user