added completly static build to meson, added line-of-sight test for aggro and map drawing
MCMakeLists.txt
| @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0) | |||
|---|---|---|---|
| 2 | 2 | ||
| 3 | 3 | project(orcsmasher LANGUAGES C) | |
| 4 | 4 | ||
| 5 | - | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wpedantic") | |
| 5 | + | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wpedantic -Wno-type-limits") | |
| 6 | 6 | ||
| 7 | 7 | if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") | |
| 8 | 8 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Og -g -fsanitize=address") | |
Minclude/algorithm.h
| @@ -2,6 +2,7 @@ | |||
|---|---|---|---|
| 2 | 2 | #define ALGORITHM_H | |
| 3 | 3 | #include <stddef.h> | |
| 4 | 4 | #include <game.h> | |
| 5 | + | #include <config.h> | |
| 5 | 6 | ||
| 6 | 7 | //creates a game, fills it with walls and empty fields | |
| 7 | 8 | struct game make_maze(size_t y, size_t x); | |
| @@ -10,7 +11,22 @@ typedef darray(struct point) pointarr; | |||
|---|---|---|---|
| 10 | 11 | //algorithm terminates with no path if target is not found within maxdist | |
| 11 | 12 | //result contains target as well as the source point | |
| 12 | 13 | //so even if next to the target, the result arr is at least 2 items big | |
| 13 | - | pointarr astar(struct game *g, struct point start, struct point target, size_t maxdist); | |
| 14 | - | ||
| 14 | + | pointarr astar(struct game *g, struct point start, struct point target, size_t maxdist); | |
| 15 | + | #define insight(g,p1,p2) (insight_(g,p1,p2) || insight_(g,p2,p1)) | |
| 16 | + | static inline bool insight_(const struct game *g, struct point p1, struct point p2) | |
| 17 | + | { | |
| 18 | + | size_t view_left = SIGHT_RANGE; //FIXME: range seems too long ingame | |
| 19 | + | while(!pointeq(p1,p2)) | |
| 20 | + | { | |
| 21 | + | if(p1.x != p2.x) | |
| 22 | + | p2.x += sign(p1.x - p2.x); | |
| 23 | + | if(p1.y != p2.y) | |
| 24 | + | p2.y += sign(p1.y - p2.y); | |
| 25 | + | if(!(view_left--) || game_at(g, p2)->u->ground.type == WALL) | |
| 26 | + | return false; | |
| 27 | + | } | |
| 28 | + | ||
| 29 | + | return true; | |
| 30 | + | } | |
| 15 | 31 | ||
| 16 | 32 | #endif //ALGORITHM_H | |
Minclude/config.h
| @@ -1,7 +1,9 @@ | |||
|---|---|---|---|
| 1 | 1 | #ifndef CONFIG_H | |
| 2 | 2 | #define CONFIG_H | |
| 3 | 3 | ||
| 4 | - | #define AGGRO_RANGE 4 | |
| 4 | + | #define AGGRO_RANGE 6 | |
| 5 | + | #define SIGHT_RANGE ((size_t)-1) | |
| 6 | + | #define SIGHT_EMPTY true | |
| 5 | 7 | #define GAME_MIN_Y 10 | |
| 6 | 8 | #define GAME_MIN_X 10 | |
| 7 | 9 | #define GAME_MAX_Y 30 | |
| @@ -14,4 +16,5 @@ | |||
|---|---|---|---|
| 14 | 16 | #define MAX_LOOT 15 | |
| 15 | 17 | ||
| 16 | 18 | ||
| 19 | + | ||
| 17 | 20 | #endif //COFNIG_H | |
Minclude/helper.h
| @@ -21,6 +21,13 @@ static inline unsigned int iabs(int i) | |||
|---|---|---|---|
| 21 | 21 | return i < 0 ? -i : i; | |
| 22 | 22 | } | |
| 23 | 23 | ||
| 24 | + | static inline int sign(int m) | |
| 25 | + | { | |
| 26 | + | return m < 0 ? -1: | |
| 27 | + | m > 0 ? 1: | |
| 28 | + | 0; | |
| 29 | + | } | |
| 30 | + | ||
| 24 | 31 | static inline int ipow(int base, int exp) | |
| 25 | 32 | { | |
| 26 | 33 | int result = 1; | |
Mmeson.build
| @@ -5,8 +5,10 @@ project('orcsmasher', 'c', | |||
|---|---|---|---|
| 5 | 5 | inc = include_directories('include') | |
| 6 | 6 | ||
| 7 | 7 | cc = meson.get_compiler('c') | |
| 8 | + | static_build = get_option('default_library') == 'static' | |
| 9 | + | ||
| 8 | 10 | ||
| 9 | - | CFLAGS = [] | |
| 11 | + | CFLAGS = ['-Wno-type-limits'] | |
| 10 | 12 | LDFLAGS = [] | |
| 11 | 13 | ||
| 12 | 14 | if get_option('buildtype') == 'debug' | |
| @@ -16,9 +18,11 @@ endif | |||
|---|---|---|---|
| 16 | 18 | ||
| 17 | 19 | if get_option('buildtype') == 'release' | |
| 18 | 20 | CFLAGS += ['-O3', '-march=native', '-g'] | |
| 21 | + | if static_build | |
| 22 | + | LDFLAGS += ['-static'] | |
| 23 | + | endif | |
| 19 | 24 | endif | |
| 20 | 25 | ||
| 21 | - | static_build = get_option('default_library') == 'static' | |
| 22 | 26 | ||
| 23 | 27 | if static_build | |
| 24 | 28 | LDFLAGS += ['-l:libgpm.a'] | |
Msrc/loop.c
| @@ -205,21 +205,23 @@ static void run_ai(struct game *g, struct point player) | |||
|---|---|---|---|
| 205 | 205 | goto next; | |
| 206 | 206 | } | |
| 207 | 207 | darray_append(checked, game_at(g, (struct point){y,x})->m.id); | |
| 208 | - | ||
| 209 | - | res = astar(g, (struct point){y,x}, player, AGGRO_RANGE); | |
| 210 | - | if(res.size >= 2) { | |
| 211 | - | attack_move(g, (struct point){y,x}, darray_item(res, res.size-2)); | |
| 212 | - | } else { | |
| 213 | - | struct point ps[4] = | |
| 214 | - | { | |
| 215 | - | {y, x-1}, | |
| 216 | - | {y, x+1}, | |
| 217 | - | {y-1, x}, | |
| 218 | - | {y+1, x} | |
| 219 | - | }; | |
| 220 | - | move_object(g, (struct point){y,x}, ps[randrange(0,3)]); | |
| 208 | + | ||
| 209 | + | if(insight(g, ((struct point){y,x}), player)) { | |
| 210 | + | res = astar(g, (struct point){y,x}, player, 20); | |
| 211 | + | if(res.size >= 2) { | |
| 212 | + | attack_move(g, (struct point){y,x}, darray_item(res, res.size-2)); | |
| 213 | + | } else { | |
| 214 | + | struct point ps[4] = | |
| 215 | + | { | |
| 216 | + | {y, x-1}, | |
| 217 | + | {y, x+1}, | |
| 218 | + | {y-1, x}, | |
| 219 | + | {y+1, x} | |
| 220 | + | }; | |
| 221 | + | move_object(g, (struct point){y,x}, ps[randrange(0,3)]); | |
| 222 | + | } | |
| 223 | + | darray_free(res); | |
| 221 | 224 | } | |
| 222 | - | darray_free(res); | |
| 223 | 225 | ||
| 224 | 226 | } | |
| 225 | 227 | next:; | |
| @@ -291,6 +293,7 @@ void loop() | |||
|---|---|---|---|
| 291 | 293 | delete_game(&g); | |
| 292 | 294 | return; | |
| 293 | 295 | case MOVE:; | |
| 296 | + | struct point oldpos = player; | |
| 294 | 297 | struct point targetpos = relative(player, c.u.d); | |
| 295 | 298 | ||
| 296 | 299 | if(!in_bounds(&g, targetpos)) { | |
| @@ -305,7 +308,7 @@ void loop() | |||
|---|---|---|---|
| 305 | 308 | loop(); | |
| 306 | 309 | return; | |
| 307 | 310 | } | |
| 308 | - | run_ai(&g, player); | |
| 311 | + | run_ai(&g, oldpos); | |
| 309 | 312 | break; | |
| 310 | 313 | case SPAWN: | |
| 311 | 314 | spawn_enemy(&g); | |
Msrc/tui.c
| @@ -11,6 +11,8 @@ | |||
|---|---|---|---|
| 11 | 11 | #include <string.h> | |
| 12 | 12 | ||
| 13 | 13 | #include <helper.h> | |
| 14 | + | #include <config.h> | |
| 15 | + | #include <algorithm.h> | |
| 14 | 16 | ||
| 15 | 17 | static PANEL *stdpanel = NULL; | |
| 16 | 18 | static WINDOW *logbox = NULL; | |
| @@ -240,10 +242,23 @@ void draw_map(const struct game *g, struct point p) | |||
|---|---|---|---|
| 240 | 242 | for(size_t j = startx; j < endx; j++) | |
| 241 | 243 | { | |
| 242 | 244 | struct field *f = game_at(g, (struct point){.y = i, .x = j}); | |
| 243 | - | if(f->has_monster) | |
| 244 | - | waddch(mapwin, f->m.symbol); | |
| 245 | - | else | |
| 246 | - | waddch(mapwin, f->u->ground.symbol); | |
| 245 | + | bool sight = insight(g, p, ((struct point){.y = i, .x = j})); | |
| 246 | + | if(SIGHT_EMPTY || sight) { //TODO: add colors to unkown but sighted areas | |
| 247 | + | if(!sight) | |
| 248 | + | wattron(mapwin, A_DIM); | |
| 249 | + | ||
| 250 | + | if(f->has_monster && sight) { | |
| 251 | + | waddch(mapwin, f->m.symbol); | |
| 252 | + | } else if(f->u->ground.type == ITEM && !sight) { | |
| 253 | + | waddch(mapwin, ' '); | |
| 254 | + | } else { | |
| 255 | + | waddch(mapwin, f->u->ground.symbol); | |
| 256 | + | } | |
| 257 | + | if(!sight) | |
| 258 | + | wattroff(mapwin, A_DIM); | |
| 259 | + | } else { | |
| 260 | + | waddch(mapwin, '.'); | |
| 261 | + | } | |
| 247 | 262 | } | |
| 248 | 263 | } | |
| 249 | 264 | ||