uni

University stuff
git clone git://git.christosmarg.xyz/uni-assignments.git
Log | Files | Refs | README | LICENSE

commit b981ccfa281e40c47ac344de6c05cf273e135fd9
parent 71b57be738098d2761777025ad3286ef6ed86e7a
Author: Christos Margiolis <christos@margiolis.net>
Date:   Thu, 20 May 2021 19:26:56 +0300

C+

Diffstat:
Mc-os2/ex2/ex3_server.c | 10+++++-----
Mcpp-oop/game/Engine.cc | 274+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
Mcpp-oop/game/Engine.hpp | 13++++++++++---
Mcpp-oop/game/Movable.cc | 12++++--------
Mcpp-oop/game/Movable.hpp | 3+--
Mcpp-oop/game/Score.hpp | 2+-
Mcpp-oop/game/main.cc | 26+++++++++++++++-----------
7 files changed, 200 insertions(+), 140 deletions(-)

diff --git a/c-os2/ex2/ex3_server.c b/c-os2/ex2/ex3_server.c @@ -56,10 +56,10 @@ srv(struct foo *foo) f = (struct foo *)foo; while (cont != 'n') { if (recv(f->cfd, &n, sizeof(int), 0) == -1) - goto exit; + goto fail; arr = emalloc(n * sizeof(int)); if (recv(f->cfd, arr, n * sizeof(int), 0) == -1) - goto exit; + goto fail; res = emalloc(sizeof(struct pack_res)); printf("cfd: %d\tn: %d\n", f->cfd, n); for (i = 0, sum = 0; i < n; i++) { @@ -75,18 +75,18 @@ srv(struct foo *foo) (void)strncpy(res->str, "sequence: failed", sizeof(res->str) - 1); if (send(f->cfd, res, sizeof(struct pack_res), 0) == -1) - goto exit; + goto fail; f->ntotal++; printf("[%s] success: %d: total: %d\n", argv0, f->nsucc, f->ntotal); if (recv(f->cfd, &cont, 1, 0) == -1) - goto exit; + goto fail; free(arr); } rc = 0; -exit: +fail: printf("[%s] connection with client %d closed\n", argv0, f->cfd); (void)close(f->cfd); if (arr != NULL) diff --git a/cpp-oop/game/Engine.cc b/cpp-oop/game/Engine.cc @@ -9,20 +9,7 @@ enum Color { LAST }; -Engine::Engine() -{ -} - -Engine::~Engine() -{ - for (auto&& e : entities) - if (e != NULL) - delete e; - (void)endwin(); -} - -void -Engine::init(const char *mapfile, const char *scorefile) +Engine::Engine(const char *mapfile, const char *scorefile) { if (!load_map(mapfile)) throw "load_map failed: " + std::string(mapfile); @@ -32,94 +19,20 @@ Engine::init(const char *mapfile, const char *scorefile) throw "init_entities failed"; if (!init_score(scorefile)) throw "init_score failed: " + std::string(scorefile); - f_running = 1; -} - -void -Engine::kbd_input() -{ - int key, dir; - - switch (key = getch()) { - case KEY_LEFT: - dir = Movable::Direction::LEFT; - break; - case KEY_RIGHT: - dir = Movable::Direction::RIGHT; - break; - case KEY_UP: - dir = Movable::Direction::UP; - break; - case KEY_DOWN: - dir = Movable::Direction::DOWN; - break; - case 'c': - menuopts(); - return; - case ESC: /* FALLTHROUGH */ - f_running = 0; - default: - return; - } - - player->set_newpos(dir, xmax, ymax); -} -void -Engine::collisions() -{ + f_running = 1; } -void -Engine::upd_score() -{ -} -void -Engine::redraw() -{ - char msg_opts[] = "c Controls"; - int color; - - erase(); - /* TODO: add scores and stuff */ - printw("(%d, %d)", player->get_x(), player->get_y()); - mvprintw(0, xmax - strlen(msg_opts), msg_opts); - mvhline(1, 0, ACS_HLINE, xmax); - move (2, 0); - attron(A_REVERSE); - for (const auto& row : map) { - for (const auto& c : row) { - if (c == '*') - color = COLOR_PAIR(Color::WALL); - else if (c == ' ') - color = COLOR_PAIR(Color::PATH); - attron(color); - addch(c); - attroff(color); - } - } - for (const auto& entity : entities) { - if (dynamic_cast<Potter *>(entity) != nullptr) - color = COLOR_PAIR(Color::POTTER); - else if (dynamic_cast<Gnome *>(entity) != nullptr) - color = COLOR_PAIR(Color::GNOME); - else if (dynamic_cast<Traal *>(entity) != nullptr) - color = COLOR_PAIR(Color::TRAAL); - - attron(color); - mvaddch(entity->get_y(), entity->get_x(), - entity->get_sym()); - attroff(color); - } - attroff(A_REVERSE); - refresh(); -} - -bool -Engine::is_running() +Engine::~Engine() { - return f_running; + for (auto&& e : entities) + if (e != NULL) + delete e; + colors.clear(); + map.clear(); + (void)delwin(gw); + (void)endwin(); } bool @@ -138,11 +51,14 @@ Engine::load_map(const char *mapfile) break; row.push_back(c); if (c == '\n') { + /* XXX: h != hprev */ + h = row.size(); map.push_back(row); row.clear(); } } f.close(); + w = map.size(); return true; } @@ -151,6 +67,8 @@ Engine::load_map(const char *mapfile) bool Engine::init_curses() { + int wr, wc, wy, wx; + if (!initscr()) return false; noecho(); @@ -162,10 +80,20 @@ Engine::init_curses() xmax = getmaxx(stdscr); ymax = getmaxy(stdscr); + wr = w; + wc = h; + wy = CENTER(ymax, wr); + wx = CENTER(xmax, wc); + if ((gw = newwin(wr, wc, wy, wx)) == NULL) + return false; + box(gw, 0, 0); + wxmax = getmaxx(gw); + wymax = getmaxy(gw); + colors.push_back(COLOR_BLUE); /* Wall */ - colors.push_back(COLOR_GREEN); /* Path */ - colors.push_back(COLOR_MAGENTA);/* Potter */ - colors.push_back(COLOR_CYAN); /* Gnome */ + colors.push_back(COLOR_RED); /* Path */ + colors.push_back(COLOR_CYAN); /* Potter */ + colors.push_back(COLOR_GREEN); /* Gnome */ colors.push_back(COLOR_YELLOW); /* Traal */ start_color(); @@ -176,15 +104,53 @@ Engine::init_curses() return true; } +void +Engine::calc_pos(int *x, int *y) +{ + do { + *x = rand() % w; + *y = rand() % h; + /* + * Don't spawn an enemy at the same coordinates with + * another entity. + */ + for (const auto& e : entities) + if (*x == e->get_x() && *y == e->get_y()) + continue; + } while (map[*x][*y] != ' '); +} + bool Engine::init_entities() { - srand(time(nullptr)); + int i, type, x, y; - entities.push_back(new Potter(15, 10, Movable::Direction::DOWN, 'P')); - entities.push_back(new Gnome(30, 20, Movable::Direction::DOWN, 'G')); - entities.push_back(new Traal(50, 26, Movable::Direction::DOWN, 'T')); + srand(time(nullptr)); + calc_pos(&x, &y); + /* + * Passing the parameters in reverse order (i.e `y, x` instead of + * `x, y`) so that mvwaddch(3) doesn't print the entity on the + * wrong coordinates. + */ + entities.push_back(new Potter(y, x, Movable::Direction::DOWN, 'P')); + for (i = 0; i < nenemies; i++) { + calc_pos(&x, &y); + /* + * Randomly choose whether we'll create a `Gnome` or + * `Traal` enemy. + */ + switch (type = rand() % 2) { + case 0: + entities.push_back(new Gnome(y, x, + Movable::Direction::DOWN, 'G')); + break; + case 1: + entities.push_back(new Traal(y, x, + Movable::Direction::DOWN, 'T')); + break; + } + } player = (Potter *)entities[0]; return true; @@ -197,16 +163,104 @@ Engine::init_score(const char *scorefile) } void +Engine::kbd_input() +{ + int key, dir; + + switch (key = getch()) { + case KEY_LEFT: + dir = Movable::Direction::LEFT; + break; + case KEY_RIGHT: + dir = Movable::Direction::RIGHT; + break; + case KEY_UP: + dir = Movable::Direction::UP; + break; + case KEY_DOWN: + dir = Movable::Direction::DOWN; + break; + case 'c': + menuopts(); + return; + case ESC: /* FALLTHROUGH */ + /* FIXME: what? */ + f_running = 0; + default: + return; + } + + player->set_newpos(dir, wxmax, wymax); +} + +void +Engine::collisions() +{ +} + +void +Engine::upd_score() +{ +} + +void +Engine::redraw() +{ + char msg_score[] = "Score: %d"; + char msg_opts[] = "c Controls"; + int color; + + werase(gw); + erase(); + mvprintw(0, 0, "Potter: (%d, %d)", player->get_x(), player->get_y()); + mvprintw(0, CENTER(xmax, strlen(msg_score)), msg_score, 10); + mvprintw(0, xmax - strlen(msg_opts), msg_opts); + mvhline(1, 0, ACS_HLINE, xmax); + wattron(gw, A_REVERSE); + for (const auto& row : map) { + for (const auto& c : row) { + if (c == '*') + color = COLOR_PAIR(Color::WALL); + else if (c == ' ') + color = COLOR_PAIR(Color::PATH); + wattron(gw, color); + waddch(gw, c); + wattroff(gw, color); + } + } + for (const auto& e : entities) { + if (dynamic_cast<Potter *>(e) != nullptr) + color = COLOR_PAIR(Color::POTTER); + else if (dynamic_cast<Gnome *>(e) != nullptr) + color = COLOR_PAIR(Color::GNOME); + else if (dynamic_cast<Traal *>(e) != nullptr) + color = COLOR_PAIR(Color::TRAAL); + wattron(gw, color); + mvwaddch(gw, e->get_y(), e->get_x(), e->get_sym()); + wattroff(gw, color); + } + wattroff(gw, A_REVERSE); + refresh(); + wrefresh(gw); +} + +bool +Engine::is_running() +{ + return f_running; +} + +void Engine::menuopts() { WINDOW *opts; - int w, h, wy, wx; + int wr, wc, wy, wx; - w = 32; - h = 9; - wy = CENTER(ymax, h); - wx = CENTER(xmax, w); - if ((opts = newwin(h, w, wy, wx)) == NULL) + wc = 32; + wr = 9; + wx = CENTER(xmax, wc); + wy = CENTER(ymax, wr); + if ((opts = newwin(wr, wc, wy, wx)) == NULL) return; werase(opts); box(opts, 0, 0); diff --git a/cpp-oop/game/Engine.hpp b/cpp-oop/game/Engine.hpp @@ -1,6 +1,7 @@ #ifndef _ENGINE_HPP_ #define _ENGINE_HPP_ +#include <csignal> #include <cstdlib> #include <ctime> #include <iostream> @@ -29,15 +30,20 @@ private: std::vector<int> colors; Potter *player; Score score; + WINDOW *gw; int xmax; int ymax; - int f_running; + int wxmax; + int wymax; + int w; + int h; + int nenemies = 5; + volatile sig_atomic_t f_running; public: - Engine(); + explicit Engine(const char *mapfile, const char *scorefile); ~Engine(); - void init(const char *mapfile, const char *scorefile); void kbd_input(); void collisions(); void upd_score(); @@ -49,6 +55,7 @@ private: bool init_curses(); bool init_entities(); bool init_score(const char *scorefile); + void calc_pos(int *x, int *y); void menuopts(); }; diff --git a/cpp-oop/game/Movable.cc b/cpp-oop/game/Movable.cc @@ -1,9 +1,5 @@ #include "Movable.hpp" -Movable::Movable() -{ -} - Movable::Movable(int x, int y, int dir, char sym) :x(x), y(y), dir(dir), sym(sym) { @@ -22,12 +18,12 @@ Movable::set_newpos(int dir, int xmax, int ymax) x = 0; break; case Direction::RIGHT: - if (++x > xmax - 1) - x = xmax - 1; + if (++x > xmax - 2) + x = xmax - 2; break; case Direction::UP: - if (--y < 2) - y = 2; + if (--y < 0) + y = 0; break; case Direction::DOWN: if (++y > ymax - 1) diff --git a/cpp-oop/game/Movable.hpp b/cpp-oop/game/Movable.hpp @@ -12,8 +12,7 @@ public: enum Direction { LEFT, RIGHT, UP, DOWN }; public: - Movable(); - Movable(int x, int y, int dir, char sym); + explicit Movable(int x, int y, int dir, char sym); virtual ~Movable(); void set_newpos(int dir, int xmax, int ymax); diff --git a/cpp-oop/game/Score.hpp b/cpp-oop/game/Score.hpp @@ -3,7 +3,7 @@ class Score { private: - struct HighScores { + struct HighScore { char name[10]; int score; } hiscores[5]; diff --git a/cpp-oop/game/main.cc b/cpp-oop/game/main.cc @@ -18,39 +18,43 @@ die(const std::string& str) static void usage() { - std::cerr << "usage: " << argv0 << " map_file score_file" << std::endl; + std::cerr << "usage: " << argv0 << " <map_file> <score_file>" << std::endl; exit(1); } int main(int argc, char *argv[]) { - Engine eng; + Engine *eng; char *mapfile, *scorefile; argv0 = *argv++; - if (argc < 3) usage(); mapfile = *argv++; scorefile = *argv; + if (!strcmp(mapfile, scorefile)) - die("input files must not be the same"); + die("input files cannot be the same"); + /* + * We're linking with `lncursesw` so we need to have UTF-8 enabled, + * otherwise colors and certain characters might not show up properly. + */ if (!setlocale(LC_ALL, "")) die("setlocale"); try { - eng.init(mapfile, scorefile); + eng = new Engine(mapfile, scorefile); } catch (std::string e) { die(e); } - - while (eng.is_running()) { - eng.kbd_input(); - eng.collisions(); - eng.upd_score(); - eng.redraw(); + while (eng->is_running()) { + eng->kbd_input(); + eng->collisions(); + eng->upd_score(); + eng->redraw(); } + delete eng; return 0; }