diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | field.c | 20 | ||||
-rw-r--r-- | field.h | 3 | ||||
-rw-r--r-- | ghosts.c | 89 | ||||
-rw-r--r-- | ghosts.h | 72 | ||||
-rw-r--r-- | pac.c | 3 | ||||
-rw-r--r-- | pacman.c | 139 |
7 files changed, 294 insertions, 34 deletions
@@ -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 @@ -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; +} @@ -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 @@ -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; } @@ -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 @@ -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); @@ -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); |