back to scratko.xyz
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--field.c28
-rw-r--r--field.h22
-rw-r--r--ghosts.c43
-rw-r--r--pac.c1
-rw-r--r--pacman.c9
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(&current_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);