From 04a6703fd66a7d34b2556a9c203c4dada3baca38 Mon Sep 17 00:00:00 2001 From: scratko Date: Fri, 12 Apr 2024 03:17:46 +0300 Subject: Added behavior modes Reverse direction Random direction --- pacman.c | 218 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 197 insertions(+), 21 deletions(-) (limited to 'pacman.c') diff --git a/pacman.c b/pacman.c index 95d121d..f9b1278 100644 --- a/pacman.c +++ b/pacman.c @@ -5,14 +5,62 @@ #include #include #include +#include enum { - timeout_duration = 0, - sleep_duration = 190000, - key_escape = 27, - count_get_out_moves = 5 + timeout_duration = 0, + sleep_duration = 190000, + key_escape = 27, + count_get_out_moves = 6, + chase_move_limit = 100, + scatter_move_limit = 35, + frightened_move_limit = 30, + phase_limit = 4 }; +struct mode_type { + enum behavior_mode current_mode; + int chase_count; + int scatter_count; + int frightened_count; + int phase_number; + int reverse_direction; +}; + +static void change_mode(struct mode_type *mode_params) +{ + if(!(mode_params->current_mode == frightened) && + mode_params->phase_number == phase_limit) + return; + switch(mode_params->current_mode) { + case chase: + if(mode_params->chase_count > chase_move_limit) { + mode_params->current_mode = scatter; + mode_params->chase_count = 0; + ++mode_params->phase_number; + if(mode_params->phase_number == phase_limit) + mode_params->current_mode = chase; + ++mode_params->reverse_direction; + } + break; + case scatter: + if(mode_params->scatter_count > scatter_move_limit) { + mode_params->current_mode = chase; + mode_params->scatter_count = 0; + ++mode_params->reverse_direction; + } + break; + case frightened: + if(mode_params->frightened_count > frightened_move_limit) { + mode_params->current_mode = + mode_params->chase_count || mode_params->phase_number == + phase_limit ? chase : scatter; + mode_params->frightened_count = 0; + ++mode_params->reverse_direction; + } + } +} + static int is_up_move_blocked(const struct ghost_type *ghost, enum intersection_type intersection) { @@ -20,7 +68,9 @@ static int is_up_move_blocked(const struct ghost_type *ghost, ghost->direction == right); } -static void pathfinder_stage(game_space field, struct pacman pac, +static void pathfinder_stage(game_space field, + struct mode_type *mode_params, + const struct pacman *pac, struct ghost_type *red_ghost, struct ghost_type *pink_ghost, struct ghost_type *blue_ghost, @@ -30,39 +80,117 @@ static void pathfinder_stage(game_space field, struct pacman pac, enum intersection_type intersection; int color_priority; struct ghost_type *current_ghost; - struct coordinates target_point; + struct coordinates new_target_point; for(color_priority = 0; color_priority <= orange; ++color_priority) { switch(color_priority) { case red: current_ghost = red_ghost; - target_point = pac.position; - search_method = breadth_first_search; + new_target_point = mode_params->current_mode == scatter ? + current_ghost->home_position : pac->position; + search_method = mode_params->current_mode == scatter ? + compute_distance_between_points : breadth_first_search; break; case pink: current_ghost = pink_ghost; - target_point = identify_target_in_front(pac, pink_shift); + new_target_point = mode_params->current_mode == scatter ? + current_ghost->home_position : + identify_target_in_front(*pac, pink_shift); search_method = compute_distance_between_points; break; case blue: current_ghost = blue_ghost; - target_point = identify_blue_target(pac, red_ghost); + new_target_point = mode_params->current_mode == scatter ? + current_ghost->home_position : + identify_blue_target(*pac, red_ghost); search_method = compute_distance_between_points; break; case orange: current_ghost = orange_ghost; - target_point = pac.position; - search_method = breadth_first_search; - break; + new_target_point = mode_params->current_mode == scatter ? + current_ghost->home_position : pac->position; + search_method = mode_params->current_mode == scatter ? + compute_distance_between_points : breadth_first_search; } 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, + redirect(field, intersection, current_ghost, new_target_point, search_method); } } +static void random_pathfinder_stage(game_space field, + struct ghost_type *red_ghost, + struct ghost_type *pink_ghost, + struct ghost_type *blue_ghost, + struct ghost_type *orange_ghost) +{ + enum intersection_type intersection; + int color_priority; + struct ghost_type *current_ghost; + 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; + } + intersection = get_intersection(field, current_ghost); + if(intersection != direct_path) + random_redirect(field, current_ghost); + } +} + +static void chase_mode(game_space field, struct mode_type *mode_params, + const struct pacman *pac, + struct ghost_type *red_ghost, + struct ghost_type *pink_ghost, + struct ghost_type *blue_ghost, + struct ghost_type *orange_ghost) +{ + pathfinder_stage(field, mode_params, pac, red_ghost, pink_ghost, blue_ghost, + orange_ghost); + if(mode_params->phase_number < phase_limit) { + ++mode_params->chase_count; + change_mode(mode_params); + } +} + +static void scatter_mode(game_space field, struct mode_type *mode_params, + struct ghost_type *red_ghost, + struct ghost_type *pink_ghost, + struct ghost_type *blue_ghost, + struct ghost_type *orange_ghost) +{ + pathfinder_stage(field, mode_params, NULL, red_ghost, pink_ghost, + blue_ghost, orange_ghost); + if(mode_params->phase_number < phase_limit) { + ++mode_params->scatter_count; + change_mode(mode_params); + } +} + +static void frightened_mode(game_space field, struct mode_type *mode_params, + struct ghost_type *red_ghost, + struct ghost_type *pink_ghost, + struct ghost_type *blue_ghost, + struct ghost_type *orange_ghost) +{ + random_pathfinder_stage(field, red_ghost, pink_ghost, blue_ghost, + orange_ghost); + ++mode_params->frightened_count; + change_mode(mode_params); +} + static void initialize_ghosts(struct ghost_type *red_ghost, struct ghost_type *pink_ghost, struct ghost_type *blue_ghost, @@ -74,8 +202,20 @@ static void initialize_ghosts(struct ghost_type *red_ghost, initialize_ghost(orange_ghost, orange); } -static void ncurses_params() +static void initialize_modes(struct mode_type *mode_params, int *get_out_stage) +{ + mode_params->current_mode = scatter; + mode_params->chase_count = 0; + mode_params->scatter_count = 0; + mode_params->frightened_count = 0; + mode_params->phase_number = 0; + mode_params->reverse_direction = 0; + *get_out_stage = count_get_out_moves; +} + +static void initialize_params() { + srand(time(NULL)); initscr(); start_color(); cbreak(); @@ -92,38 +232,74 @@ int main() struct ghost_type red_ghost, pink_ghost, blue_ghost, orange_ghost; struct pacman pac; struct queue eaten_coins; + struct mode_type mode_params; int key, get_out_stage; enum movement_direction stored_direction; stored_direction = none; - get_out_stage = count_get_out_moves; - ncurses_params(); + initialize_params(); field = get_new_field(); print_field(field); initialize_ghosts(&red_ghost, &pink_ghost, &blue_ghost, &orange_ghost); initialize_pac(&pac); + initialize_modes(&mode_params, &get_out_stage); queue_init(&eaten_coins); 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); while((key = getch()) != key_escape) { + /* + * pacman + */ if(key != ERR) change_pac_direction(field, &pac, key, &stored_direction); else check_remaining_direction(field, &pac, &stored_direction); + make_pac_move(field, &pac, &eaten_coins); + if(pac.is_energizer_eaten) { + mode_params.current_mode = frightened; + mode_params.reverse_direction = 1; + pac.is_energizer_eaten = 0; + } + /* + * ghosts + */ if(get_out_stage) pull_out_ghosts(&get_out_stage, &red_ghost, &pink_ghost, &blue_ghost, &orange_ghost); - else - pathfinder_stage(field, pac, &red_ghost, &pink_ghost, &blue_ghost, - &orange_ghost); - make_pac_move(field, &pac, &eaten_coins); + else if(mode_params.reverse_direction) { + reverse_all_ghosts(&red_ghost, &pink_ghost, + &blue_ghost, &orange_ghost); + mode_params.reverse_direction = 0; + } + else if(mode_params.current_mode == chase) + chase_mode(field, &mode_params, &pac, &red_ghost, &pink_ghost, + &blue_ghost, &orange_ghost); + else if(mode_params.current_mode == scatter) + scatter_mode(field, &mode_params, &red_ghost, &pink_ghost, + &blue_ghost, &orange_ghost); + else if(mode_params.current_mode == frightened) + frightened_mode(field, &mode_params, &red_ghost, &pink_ghost, + &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); display_ghosts_on_field(&red_ghost, &pink_ghost, &blue_ghost, &orange_ghost); usleep(sleep_duration); +#if 1 + move(0, 50); + if(mode_params.current_mode == chase) + printw("CHASE"); + else if(mode_params.current_mode == scatter) + printw("SCATTER"); + else if(mode_params.current_mode == frightened) + printw("FRIGHTENED"); + refresh(); +#endif } queue_clear(&eaten_coins); endwin(); -- cgit v1.2.3