#include "field.h" #include "ghosts.h" #include "pac.h" #include "queue.h" #include #include #include #include enum { 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) { return intersection == yellow_block && (ghost->direction == left || ghost->direction == right); } 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, struct ghost_type *orange_ghost) { void (*search_method)(game_space, struct ghost_type*, struct coordinates); enum intersection_type intersection; int color_priority; struct ghost_type *current_ghost; struct coordinates new_target_point; for(color_priority = 0; color_priority <= orange; ++color_priority) { switch(color_priority) { case red: current_ghost = red_ghost; 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; 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; 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; 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, 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, struct ghost_type *orange_ghost) { initialize_ghost(red_ghost, red); initialize_ghost(pink_ghost, pink); initialize_ghost(blue_ghost, blue); initialize_ghost(orange_ghost, orange); } 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(); noecho(); curs_set(0); keypad(stdscr, 1); timeout(timeout_duration); start_color(); } int main() { game_space field = NULL; 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; 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 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(); return 0; }