back to scratko.xyz
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorscratko <m@scratko.xyz>2024-04-14 21:18:36 +0300
committerscratko <m@scratko.xyz>2024-04-14 21:18:36 +0300
commit0cf5dfed3e492608d044a5fc90c1815fab506fd7 (patch)
treed1efa942e89ab4f064324fcee4c623173abc5298
parent91583d5699503e981105beecc51d37b59dc1842e (diff)
downloadpacman-0cf5dfed3e492608d044a5fc90c1815fab506fd7.tar.gz
pacman-0cf5dfed3e492608d044a5fc90c1815fab506fd7.tar.bz2
pacman-0cf5dfed3e492608d044a5fc90c1815fab506fd7.zip
Capture and liberation of ghosts
Fixed coordinate in field_has_coin. Added marks on the field for the liberation zone (1 in front of #). Prison parameters for the ghost are set. Fixed condition in BFS search (additionally exclude the current point in the loop, dx == 0 && dy == 0).
-rw-r--r--Makefile2
-rw-r--r--field.c20
-rw-r--r--field.h3
-rw-r--r--ghosts.c89
-rw-r--r--ghosts.h72
-rw-r--r--pac.c3
-rw-r--r--pacman.c139
7 files changed, 294 insertions, 34 deletions
diff --git a/Makefile b/Makefile
index aefc9fa..334b90d 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
SRCMODULES = field.c ghosts.c pac.c queue.c pacman.c
OBJMODULES = $(SRCMODULES:.c=.o)
CC = gcc
-CFLAGS = -Wall -g -c
+CFLAGS = -Wall -g -c -D DEBUG
LIBS = -lncurses -lm
diff --git a/field.c b/field.c
index 2dcd783..340e380 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 y y 1//./ "},
+ {" /.//1 y11y 1//./ "},
{" /.// ///##/// //./ "},
{"//////.// / /2 2//////"},
{" 3 2/ / //2 "},
@@ -55,9 +55,10 @@ game_space get_new_field()
int field_has_coin(int x, int y)
{
- return !((x == 12 && y == 9) || (x == 12 && y == 18) ||
- (x == 14 && y == 18) || (x == 15 && y == 9) ||
- (x == 17 && y == 9) || (x == 17 && y == 18));
+ return !((x == 9 && y == 12)|| (x == 18 && y == 12) ||
+ (x == 18 && y == 14) || (x == 9 && y == 15) ||
+ (x == 9 && y == 17) || (x == 18 && y == 17) ||
+ (x == 13 && y == 12) || (x == 14 && y == 12));
}
int field_has_energizer(const game_space field, int x, int y)
@@ -242,3 +243,14 @@ void clear_energizer(game_space field, struct coordinates point)
y = point.y;
field[y][x] = ' ';
}
+
+int is_equal_points(struct coordinates first_point, struct coordinates
+ second_point)
+{
+ int x1, y1, x2, y2;
+ x1 = first_point.x;
+ y1 = first_point.y;
+ x2 = second_point.x;
+ y2 = second_point.y;
+ return x1 == x2 && y1 == y2;
+}
diff --git a/field.h b/field.h
index ecf8c9a..56921d6 100644
--- a/field.h
+++ b/field.h
@@ -64,4 +64,7 @@ void change_point_if_outside_tunnel(struct coordinates *point);
void clear_energizer(game_space field, struct coordinates point);
+int is_equal_points(struct coordinates first_point, struct coordinates
+ second_point);
+
#endif
diff --git a/ghosts.c b/ghosts.c
index f8edfa2..20d19dd 100644
--- a/ghosts.c
+++ b/ghosts.c
@@ -19,6 +19,11 @@ void initialize_ghost(struct ghost_type *ghost, enum ghost_color color)
ghost->color = red;
ghost->frightened_status = 0;
ghost->direction = none;
+ ghost->prison_params.position.x = red_home_x;
+ ghost->prison_params.position.y = red_home_y;
+ ghost->prison_params.prison_counter = 0;
+ ghost->prison_params.active = 0;
+ ghost->capture_info.status = 0;
break;
case pink:
ghost->position.y = pink_y;
@@ -28,6 +33,11 @@ void initialize_ghost(struct ghost_type *ghost, enum ghost_color color)
ghost->color = pink;
ghost->frightened_status = 0;
ghost->direction = none;
+ ghost->prison_params.position.x = pink_home_x;
+ ghost->prison_params.position.y = pink_home_y;
+ ghost->prison_params.prison_counter = 0;
+ ghost->prison_params.active = 0;
+ ghost->capture_info.status = 0;
break;
case blue:
ghost->position.y = blue_y;
@@ -37,6 +47,11 @@ void initialize_ghost(struct ghost_type *ghost, enum ghost_color color)
ghost->color = blue;
ghost->frightened_status = 0;
ghost->direction = none;
+ ghost->prison_params.position.x = blue_home_x;
+ ghost->prison_params.position.y = blue_home_y;
+ ghost->prison_params.prison_counter = 0;
+ ghost->prison_params.active = 0;
+ ghost->capture_info.status = 0;
break;
case orange:
ghost->position.y = orange_y;
@@ -46,6 +61,11 @@ void initialize_ghost(struct ghost_type *ghost, enum ghost_color color)
ghost->color = orange;
ghost->frightened_status = 0;
ghost->direction = none;
+ ghost->prison_params.position.x = orange_home_x;
+ ghost->prison_params.position.y = orange_home_y;
+ ghost->prison_params.prison_counter = 0;
+ ghost->prison_params.active = 0;
+ ghost->capture_info.status = 0;
break;
}
}
@@ -256,7 +276,7 @@ void breadth_first_search(game_space field, struct ghost_type *ghost,
for(dx = -1; dx <= 1; ++dx) {
int dy;
for(dy = -1; dy <= 1; ++dy) {
- if(dx != 0 && dy != 0)
+ if((dx != 0 && dy != 0) || (dx == 0 && dy == 0))
continue;
near_point = get_near_point(consider_point, dx, dy);
change_point_if_outside_tunnel(&near_point);
@@ -406,14 +426,73 @@ void random_redirect(game_space field, struct ghost_type *ghost)
ghost->direction = random_direction;
}
+static int is_liberation_zone(const struct ghost_type *ghost)
+{
+ return ghost->position.y == liberation_y &&
+ (ghost->position.x == 14 || ghost->position.x == 15) &&
+ ghost->direction == up;
+}
void reverse_all_ghosts(struct ghost_type *red_ghost,
struct ghost_type *pink_ghost,
struct ghost_type *blue_ghost,
struct ghost_type *orange_ghost)
{
- red_ghost->direction ^= 1;
- pink_ghost->direction ^= 1;
- blue_ghost->direction ^= 1;
- orange_ghost->direction ^= 1;
+ if(!red_ghost->prison_params.active)
+ red_ghost->direction = is_liberation_zone(red_ghost) ?
+ left : red_ghost->direction ^ 1;
+ if(!pink_ghost->prison_params.active)
+ pink_ghost->direction = is_liberation_zone(pink_ghost) ?
+ left : pink_ghost->direction ^ 1;
+ if(!blue_ghost->prison_params.active)
+ blue_ghost->direction = is_liberation_zone(blue_ghost) ?
+ left : blue_ghost->direction ^ 1;
+ if(!orange_ghost->prison_params.active)
+ orange_ghost->direction = is_liberation_zone(orange_ghost) ?
+ left : orange_ghost->direction ^ 1;
+}
+
+void set_frightened_status(int status, struct ghost_type *red_ghost,
+ struct ghost_type *pink_ghost,
+ struct ghost_type *blue_ghost,
+ struct ghost_type *orange_ghost)
+{
+ red_ghost->frightened_status = status;
+ pink_ghost->frightened_status = status;
+ blue_ghost->frightened_status = status;
+ orange_ghost->frightened_status = status;
+}
+
+int is_pac_nearby(struct pacman pac, struct ghost_type ghost)
+{
+ if(ghost.capture_info.status)
+ return 0;
+ struct coordinates near_point;
+ int dx;
+ for(dx = -1; dx <= 1; ++dx) {
+ int dy;
+ for(dy = -1; dy <= 1; ++dy) {
+ if((dx != 0 && dy != 0) || (dx == 0 && dy == 0))
+ continue;
+ near_point = get_near_point(ghost.position, dx, dy);
+ if(equal_points(near_point, pac.position))
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void set_capture_info(struct ghost_type *ghost, const struct pacman *pac)
+{
+ ghost->capture_info.previous_pac_position = pac->position;
+ ghost->capture_info.previous_ghost_position = ghost->position;
+ ghost->capture_info.status = 1;
+}
+
+void catch_ghost(const game_space field, struct ghost_type *ghost)
+{
+ ghost->prison_params.active = 1;
+ ghost->direction = none;
+ ghost->position.x = ghost->prison_params.position.x;
+ ghost->position.y = ghost->prison_params.position.y;
}
diff --git a/ghosts.h b/ghosts.h
index d55da6a..3eb58f7 100644
--- a/ghosts.h
+++ b/ghosts.h
@@ -4,25 +4,34 @@
#include "field.h"
enum {
- red_y = 14,
- red_x = 15,
- red_home_y = -1,
- red_home_x = 25,
- pink_y = red_y + 1,
- pink_x = red_x - 2,
- pink_home_y = red_home_y,
- pink_home_x = 2,
- blue_y = red_y,
- blue_x = red_x-1,
- blue_home_y = 29,
- blue_home_x = 27,
- orange_y = red_y + 1,
- orange_x = red_x - 3,
- orange_home_y = blue_home_y,
- orange_home_x = 0,
- pink_shift = 4,
- blue_shift = 2,
- orange_search_limit = 8
+ red_y = 14,
+ red_x = 15,
+ red_home_y = -1,
+ red_home_x = 25,
+ pink_y = red_y + 1,
+ pink_x = red_x - 2,
+ pink_home_y = red_home_y,
+ pink_home_x = 2,
+ blue_y = red_y,
+ blue_x = red_x-1,
+ blue_home_y = 29,
+ blue_home_x = 27,
+ orange_y = red_y + 1,
+ orange_x = red_x - 3,
+ orange_home_y = blue_home_y,
+ orange_home_x = 0,
+ pink_shift = 4,
+ blue_shift = 2,
+ orange_search_limit = 8,
+ red_prison_y = 14,
+ red_prison_x = 14,
+ pink_prison_y = red_prison_y + 1,
+ pink_prison_x = red_prison_x,
+ blue_prison_y = red_prison_y,
+ blue_prison_x = red_prison_x - 1,
+ orange_prison_y = red_prison_y + 1,
+ orange_prison_x = red_prison_x - 1,
+ liberation_y = 12
};
enum ghost_color { red, pink, blue, orange };
@@ -34,12 +43,26 @@ struct coordinates {
int x;
};
+struct prison {
+ int prison_counter;
+ struct coordinates position;
+ int active;
+};
+
+struct capture {
+ struct coordinates previous_pac_position;
+ struct coordinates previous_ghost_position;
+ int status;
+};
+
struct ghost_type {
struct coordinates position;
struct coordinates home_position;
enum ghost_color color;
int frightened_status;
enum movement_direction direction;
+ struct prison prison_params;
+ struct capture capture_info;
};
void initialize_ghost(struct ghost_type *ghost, enum ghost_color color);
@@ -81,4 +104,15 @@ void reverse_all_ghosts(struct ghost_type *red_ghost,
struct ghost_type *blue_ghost,
struct ghost_type *orange_ghost);
+void set_frightened_status(int status, struct ghost_type *red_ghost,
+ struct ghost_type *pink_ghost,
+ struct ghost_type *blue_ghost,
+ struct ghost_type *orange_ghost);
+
+int is_pac_nearby(struct pacman pac, struct ghost_type ghost);
+
+void set_capture_info(struct ghost_type *ghost, const struct pacman *pac);
+
+void catch_ghost(const game_space field, struct ghost_type *ghost);
+
#endif
diff --git a/pac.c b/pac.c
index a3cae71..6579e14 100644
--- a/pac.c
+++ b/pac.c
@@ -14,8 +14,7 @@ void initialize_pac(struct pacman *pac)
static enum movement_direction get_matching_for_directions(game_space field,
struct pacman *pac,
- enum movement_direction
- direction)
+ enum movement_direction direction)
{
struct free_directions free_paths =
find_free_directions(field, pac->position.x, pac->position.y);
diff --git a/pacman.c b/pacman.c
index f03941c..1fb296c 100644
--- a/pacman.c
+++ b/pacman.c
@@ -15,7 +15,8 @@ enum {
chase_move_limit = 70,
scatter_move_limit = 35,
frightened_move_limit = 30,
- phase_limit = 4
+ phase_limit = 4,
+ prison_limit = 30
};
struct mode_type {
@@ -85,6 +86,8 @@ static void pathfinder_stage(game_space field,
for(color_priority = 0; color_priority <= orange; ++color_priority) {
switch(color_priority) {
case red:
+ if(red_ghost->prison_params.active)
+ continue;
current_ghost = red_ghost;
new_target_point = mode_params->current_mode == scatter ?
current_ghost->home_position : pac->position;
@@ -92,6 +95,8 @@ static void pathfinder_stage(game_space field,
compute_distance_between_points : breadth_first_search;
break;
case pink:
+ if(pink_ghost->prison_params.active)
+ continue;
current_ghost = pink_ghost;
new_target_point = mode_params->current_mode == scatter ?
current_ghost->home_position :
@@ -99,6 +104,8 @@ static void pathfinder_stage(game_space field,
search_method = compute_distance_between_points;
break;
case blue:
+ if(blue_ghost->prison_params.active)
+ continue;
current_ghost = blue_ghost;
new_target_point = mode_params->current_mode == scatter ?
current_ghost->home_position :
@@ -106,6 +113,8 @@ static void pathfinder_stage(game_space field,
search_method = compute_distance_between_points;
break;
case orange:
+ if(orange_ghost->prison_params.active)
+ continue;
current_ghost = orange_ghost;
new_target_point = mode_params->current_mode == scatter ?
current_ghost->home_position : pac->position;
@@ -133,15 +142,23 @@ static void random_pathfinder_stage(game_space field,
for(color_priority = 0; color_priority <= orange; ++color_priority) {
switch(color_priority) {
case red:
+ if(red_ghost->prison_params.active)
+ continue;
current_ghost = red_ghost;
break;
case pink:
+ if(pink_ghost->prison_params.active)
+ continue;
current_ghost = pink_ghost;
break;
case blue:
+ if(blue_ghost->prison_params.active)
+ continue;
current_ghost = blue_ghost;
break;
case orange:
+ if(orange_ghost->prison_params.active)
+ continue;
current_ghost = orange_ghost;
break;
}
@@ -151,6 +168,114 @@ static void random_pathfinder_stage(game_space field,
}
}
+static int is_outside_prison(struct ghost_type ghost)
+{
+ return ghost.prison_params.active && ghost.direction == up;
+}
+
+static int is_ghost_prisoner(struct ghost_type ghost)
+{
+ return ghost.prison_params.active && ghost.direction == none;
+}
+
+static void prison_leaving_stage(game_space field, struct ghost_type *red_ghost,
+ struct ghost_type *pink_ghost,
+ struct ghost_type *blue_ghost,
+ struct ghost_type *orange_ghost)
+{
+ struct ghost_type *current_ghost;
+ int color_priority;
+ for(color_priority = 0; color_priority <= orange; ++color_priority) {
+ switch(color_priority) {
+ case red:
+ current_ghost = red_ghost;
+ break;
+ case pink:
+ current_ghost = pink_ghost;
+ break;
+ case blue:
+ current_ghost = blue_ghost;
+ break;
+ case orange:
+ current_ghost = orange_ghost;
+ break;
+ }
+ if(is_ghost_prisoner(*current_ghost)) {
+ ++current_ghost->prison_params.prison_counter;
+ /*
+ * liberation
+ */
+ if(current_ghost->prison_params.prison_counter == prison_limit) {
+ current_ghost->prison_params.prison_counter = 0;
+ current_ghost->direction = up;
+ }
+ } else if(is_outside_prison(*current_ghost))
+ current_ghost->prison_params.active =
+ current_ghost->position.y == liberation_y ? 0 : 1;
+ }
+}
+
+static int is_castling(struct pacman pac, struct ghost_type ghost)
+{
+ return ghost.capture_info.status &&
+ pac.position.x == ghost.capture_info.previous_ghost_position.x &&
+ pac.position.y == ghost.capture_info.previous_ghost_position.y &&
+ ghost.position.x == ghost.capture_info.previous_pac_position.x &&
+ ghost.position.y == ghost.capture_info.previous_pac_position.y;
+}
+
+static void caughting_stage(game_space field,
+ const struct mode_type *mode_params,
+ struct pacman *pac, struct ghost_type *red_ghost,
+ struct ghost_type *pink_ghost,
+ struct ghost_type *blue_ghost,
+ struct ghost_type *orange_ghost)
+{
+ struct ghost_type *current_ghost;
+ current_ghost = red_ghost;
+ int color_priority;
+ for(color_priority = 0; color_priority <= orange; ++color_priority) {
+ switch(color_priority) {
+ case red:
+ if(is_pac_nearby(*pac, *red_ghost)) {
+ set_capture_info(red_ghost, pac);
+ continue;
+ }
+ current_ghost = red_ghost;
+ break;
+ case pink:
+ if(is_pac_nearby(*pac, *pink_ghost)) {
+ set_capture_info(pink_ghost, pac);
+ continue;
+ }
+ current_ghost = pink_ghost;
+ break;
+ case blue:
+ if(is_pac_nearby(*pac, *blue_ghost)) {
+ set_capture_info(blue_ghost, pac);
+ continue;
+ }
+ current_ghost = blue_ghost;
+ break;
+ case orange:
+ if(is_pac_nearby(*pac, *orange_ghost)) {
+ set_capture_info(orange_ghost, pac);
+ continue;
+ }
+ current_ghost = orange_ghost;
+ break;
+ }
+ if(is_equal_points(pac->position, current_ghost->position) ||
+ is_castling(*pac, *current_ghost)) {
+ if(mode_params->current_mode == frightened)
+ catch_ghost(field, current_ghost);
+ else
+ --pac->lives;
+ }
+ current_ghost->capture_info.status = 0;
+ }
+}
+
static void chase_mode(game_space field, struct mode_type *mode_params,
const struct pacman *pac,
struct ghost_type *red_ghost,
@@ -190,6 +315,8 @@ static void frightened_mode(game_space field, struct mode_type *mode_params,
orange_ghost);
++mode_params->frightened_count;
change_mode(mode_params);
+ set_frightened_status(mode_params->current_mode == frightened ? 1 : 0,
+ red_ghost, pink_ghost, blue_ghost, orange_ghost);
}
static void initialize_ghosts(struct ghost_type *red_ghost,
@@ -284,14 +411,20 @@ int main()
&blue_ghost, &orange_ghost);
make_ghost_moves(field, &red_ghost, &pink_ghost, &blue_ghost,
&orange_ghost, &eaten_coins);
+
/*
* displaying characters
*/
- display_character(pac.position.y, pac.position.x, pac_char);
+ caughting_stage(field, &mode_params, &pac, &red_ghost, &pink_ghost,
+ &blue_ghost, &orange_ghost);
display_ghosts_on_field(&red_ghost, &pink_ghost, &blue_ghost,
&orange_ghost);
+ display_character(pac.position.y, pac.position.x, pac_char);
usleep(sleep_duration);
-#if 1
+ prison_leaving_stage(field, &red_ghost, &pink_ghost, &blue_ghost,
+ &orange_ghost);
+
+#ifdef DEBUG
move(0, 50);
if(mode_params.current_mode == chase)
printw("CHASE %d ", mode_params.chase_count);