From 235f8481502263fcdb4823ff0bc4e8f831bc934d Mon Sep 17 00:00:00 2001 From: scratko Date: Thu, 11 Apr 2024 15:04:37 +0300 Subject: Removed the reverse motion for ghosts Yellow intersections added. --- field.c | 28 ++++++++++++++++++++++++---- field.h | 22 ++++++++++++++-------- ghosts.c | 43 +++++++++++++++++++++++++++++++------------ pac.c | 1 + pacman.c | 9 +++++++++ 5 files changed, 79 insertions(+), 24 deletions(-) diff --git a/field.c b/field.c index a795f8e..add43d1 100644 --- a/field.c +++ b/field.c @@ -17,7 +17,7 @@ static const char field_sample[field_height][field_width] = { {"/1....2//1..1//1..1//2....1/"}, {"//////.///// // /////.//////"}, {" /.///// // /////./ "}, - {" /.//1 1//./ "}, + {" /.//1 y y 1//./ "}, {" /.// ///##/// //./ "}, {"//////.// / /2 2//////"}, {" 3 2/ / //2 "}, @@ -27,7 +27,7 @@ static const char field_sample[field_height][field_width] = { {"/1....3..2..1//1..2..3....1/"}, {"/.////./////.//./////.////./"}, {"/.////./////.//./////.////./"}, - {"/1.1//2..2..2..2..2..2//1.1/"}, + {"/1.1//2..2..y..y..2..2//1.1/"}, {"///.//.//.////////.//.//.///"}, {"///.//.//.////////.//.//.///"}, {"/1.2..1//1..1//1..1//1..2.1/"}, @@ -128,6 +128,7 @@ void clear_or_revert_symbol(game_space field, struct coordinates position, case one_path: case two_paths: case three_paths: + case yellow_block: if(field_has_coin(y, x)) queue_consists_point(eaten_coins, position) ? addch(' ') : addch('.'); @@ -165,17 +166,26 @@ enum intersection_type get_intersection(const game_space field, return two_paths; case three_paths: return three_paths; + case yellow_block: + return yellow_block; default: return direct_path; } } +/* + * last conditions x-1 == left_outside_tunnel_x and + * x+1 == right_outside_tunnel_x are used by only pacman (while + * cheking remaining direction) + */ struct free_directions find_free_directions(const game_space field, int y, int x) { struct free_directions found_paths; - found_paths.left = field[y][x-1] != '/' && field[y][x-1] != '#' ? 1 : 0; - found_paths.right = field[y][x+1] != '/' && field[y][x+1] != '#' ? 1 : 0; + found_paths.left = (field[y][x-1] != '/' && field[y][x-1] != '#') || + x-1 == left_outside_tunnel_x ? 1 : 0; + found_paths.right = (field[y][x+1] != '/' && field[y][x+1] != '#') || + x+1 == right_outside_tunnel_x ? 1 : 0; found_paths.up = field[y-1][x] != '/' && field[y-1][x] != '#' ? 1 : 0; found_paths.down = field[y+1][x] != '/' && field[y+1][x] != '#' ? 1 : 0; return found_paths; @@ -186,3 +196,13 @@ int is_obstacle(const game_space field, int x, int y) int symbol = field[y][x]; return symbol == door || symbol == block; } + +void change_point_if_outside_tunnel(struct coordinates *point) +{ + if(point->x == left_outside_tunnel_x) { + point->x = right_outside_tunnel_x - 1; + return; + } + if(point->x == right_outside_tunnel_x) + point->x = left_outside_tunnel_x + 1; +} diff --git a/field.h b/field.h index 4681267..977a3d9 100644 --- a/field.h +++ b/field.h @@ -2,17 +2,20 @@ #define FIELD_H_SENTRY enum { - field_width = 28, - field_height = 29, - door = '#', - block = '/', - coin = '.' + field_width = 28, + field_height = 29, + left_outside_tunnel_x = -1, + right_outside_tunnel_x = field_width, + door = '#', + block = '/', + coin = '.' }; enum intersection_type { - one_path = '1', - two_paths = '2', - three_paths = '3', + one_path = '1', + two_paths = '2', + three_paths = '3', + yellow_block = 'y', direct_path }; @@ -53,6 +56,9 @@ enum intersection_type get_intersection(const game_space field, struct free_directions find_free_directions(game_space field, int y, int x); int is_obstacle(game_space field, int x, int y); + int field_has_coin(int x, int y); +void change_point_if_outside_tunnel(struct coordinates *point); + #endif diff --git a/ghosts.c b/ghosts.c index 61c1bb1..fe1a51f 100644 --- a/ghosts.c +++ b/ghosts.c @@ -77,19 +77,20 @@ static void change_position(struct ghost_type *ghost, switch(direction) { case left: --ghost->position.x; - return; + break; case right: ++ghost->position.x; - return; + break; case up: --ghost->position.y; - return; + break; case down: ++ghost->position.y; - return; + break; default: return; } + change_point_if_outside_tunnel(&ghost->position); } void make_ghost_moves(game_space field, @@ -215,12 +216,14 @@ static void clear_both_queues(struct queue *next_points, queue_clear(reviewed_points); } -static int is_bfs_search_for_orange(enum search_flag current_width, - int move_count) +static int is_bfs_search_for_orange(enum search_flag *current_width, + int *move_count) { - if(current_width == not_viewed) - ++move_count; - return move_count > orange_search_limit; + if(*current_width == not_viewed) { + ++*move_count; + *current_width = viewed; + } + return *move_count > orange_search_limit; } void breadth_first_search(game_space field, struct ghost_type *ghost, @@ -228,15 +231,23 @@ void breadth_first_search(game_space field, struct ghost_type *ghost, { int move_count; enum search_flag current_width = not_viewed; + enum movement_direction reverse_direction; struct coordinates consider_point, near_point; struct coordinates start_point = { ghost->position.y, ghost->position.x }; struct queue next_points, reviewed_points; move_count = 0; + reverse_direction = ghost->direction; + reverse_direction ^= 1; queue_init(&next_points); queue_init(&reviewed_points); queue_push(&next_points, &target_point); queue_push(&reviewed_points, &target_point); while(!empty(&next_points)) { + if(ghost->position.x == target_point.x && + ghost->position.y == target_point.y) { + ghost->direction=none; + break; + } consider_point = queue_front(&next_points); pop(&next_points); int dx; @@ -246,22 +257,30 @@ void breadth_first_search(game_space field, struct ghost_type *ghost, if(dx != 0 && dy != 0) continue; near_point = get_near_point(consider_point, dx, dy); + change_point_if_outside_tunnel(&near_point); if(is_obstacle(field, near_point.x, near_point.y)) continue; if(queue_consists_point(&reviewed_points, near_point)) continue; if(equal_points(start_point, near_point)) { - if(ghost->color == orange) - if(!is_bfs_search_for_orange(current_width, - move_count)) { + if(ghost->color == orange) { + if(!is_bfs_search_for_orange(¤t_width, + &move_count)) { redirect(field, two_paths, ghost, ghost->home_position, compute_distance_between_points); clear_both_queues(&next_points, &reviewed_points); return; } + } ghost->direction = find_direction(consider_point, start_point); +#if 1 + if(ghost->direction == reverse_direction) { + queue_push(&reviewed_points, &consider_point); + continue; + } +#endif clear_both_queues(&next_points, &reviewed_points); return; } diff --git a/pac.c b/pac.c index 241609b..ed929ae 100644 --- a/pac.c +++ b/pac.c @@ -161,4 +161,5 @@ void make_pac_move(game_space field, struct pacman *pac, } if(check_coin(field, pac->position, eaten_coins)) queue_push(eaten_coins, &pac->position); + change_point_if_outside_tunnel(&pac->position); } diff --git a/pacman.c b/pacman.c index f2e0161..95d121d 100644 --- a/pacman.c +++ b/pacman.c @@ -13,6 +13,13 @@ enum { count_get_out_moves = 5 }; +static int is_up_move_blocked(const struct ghost_type *ghost, + enum intersection_type intersection) +{ + return intersection == yellow_block && (ghost->direction == left || + ghost->direction == right); +} + static void pathfinder_stage(game_space field, struct pacman pac, struct ghost_type *red_ghost, struct ghost_type *pink_ghost, @@ -48,6 +55,8 @@ static void pathfinder_stage(game_space field, struct pacman pac, break; } intersection = get_intersection(field, current_ghost); + if(is_up_move_blocked(current_ghost, intersection)) + continue; if(intersection != direct_path) redirect(field, intersection, current_ghost, target_point, search_method); -- cgit v1.2.3