commit b981ccfa281e40c47ac344de6c05cf273e135fd9
parent 71b57be738098d2761777025ad3286ef6ed86e7a
Author: Christos Margiolis <christos@margiolis.net>
Date: Thu, 20 May 2021 19:26:56 +0300
C+
Diffstat:
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;
}