#include "field.h" #include "ghosts.h" #include "queue.h" #include #include #include "color_palette.h" enum { frightened_limit = 50 }; static const char field_sample[field_height][field_width] = { {"////////////////////////////"}, {"/1....2.....1//1.....2....1/"}, {"/.////./////.//./////.////./"}, {"/*/ /./ /.//./ /./ /*/"}, {"/./ /./ /.//./ /./ /./"}, {"/.////./////.//./////.////./"}, {"/2....3..2..2..2..2..3....2/"}, {"/.////.//.////////.//.////./"}, {"/.////.//.////////.//.////./"}, {"/1....2//1..1//1..1//2....1/"}, {"//////.///// // /////.//////"}, {" /.///// // /////./ "}, {" /.//1 y11y 1//./ "}, {" /.// ///##/// //./ "}, {"//////.// / /2 2//////"}, {" 3 2/ / //2 "}, {"//////.// //////// //.//////"}, {" /.//2 2//./ "}, {"//////.// //////// //.//////"}, {"/1....3..2..1//1..2..3....1/"}, {"/.////./////.//./////.////./"}, {"/*////./////.//./////.////*/"}, {"/1.1//2..2..y. y..2..2//1.1/"}, {"///.//.//.////////.//.//.///"}, {"///.//.//.////////.//.//.///"}, {"/1.2..1//1..1//1..1//1..2.1/"}, {"/.//////////.//.//////////./"}, {"/1..........2..2..........1/"}, {"////////////////////////////"}, {" C C Score: /243"} }; static void copy_field(game_space field) { int i; for(i = 0; i < field_height; ++i) { int j; for(j = 0; j < field_width; ++j) field[i][j] = field_sample[i][j]; } } game_space get_new_field() { game_space field = malloc(field_width * field_height); copy_field(field); return field; } void clear_field(game_space *field) { free(*field); *field = NULL; } static int field_has_coin(int x, int y) { 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)); } static int yellow_block_contains_coin(int x, int y) { return (x == 12 && y == 22) || (x == 15 && y == 22); } static int is_coin_symbol(int symbol, int x, int y) { return symbol == coin || symbol == energizer || symbol == one_path || symbol == two_paths || symbol == three_paths || (symbol == yellow_block && yellow_block_contains_coin(x, y)); } int check_coin_for_pac(game_space field, struct coordinates position, struct queue *eaten_coins) { int x, y; x = position.x; y = position.y; return is_coin_symbol(field[y][x], x, y) && field_has_coin(x, y) && !queue_consists_point(eaten_coins, position); } int field_has_energizer(const game_space field, int x, int y) { return field[y][x] == energizer; } void print_field(game_space field) { int i; char symbol; for(i = 0; i < field_height; ++i) { int j; for(j = 0; j < field_width; ++j) { symbol = field[i][j]; move(i, j); if(i == field_height-1) { symbol != ' ' ? paint_stats() : reset_attr(); addch(symbol); continue; } if(is_coin_symbol(symbol, j, i) && field_has_coin(j, i)) { paint_field_element(coin); symbol == energizer ? addch('*') : addch('.'); continue; } switch(symbol) { case one_path: case two_paths: case yellow_block: reset_attr(); addch(' '); break; case block: paint_field_element(block); addch(' '); break; case door: paint_field_element(door); addch(' '); break; case ' ': reset_attr(); addch(' '); break; } if(i == field_height-1) { symbol != ' ' ? paint_stats() : reset_attr(); addch(symbol); } refresh(); } } } static int is_countdown(int timer, int prison_status) { return (timer <= frightened_limit && timer > frightened_limit-10) && !prison_status; } void display_character(int y, int x, int symbol, int prison_status) { move(y, x); if((enum select_character) symbol == pac_char) { paint_pac(); addch(symbol); refresh(); return; } if((enum select_character) symbol != ghost_char) is_countdown(symbol, prison_status) ? printw("%d", frightened_limit - symbol) : addch(ghost_char); else addch(ghost_char); refresh(); } void display_ghosts_on_field(struct ghost_type *red_ghost, struct ghost_type *pink_ghost, struct ghost_type *blue_ghost, struct ghost_type *orange_ghost, int frightened_counter) { paint_ghost(red_ghost->color, frightened_counter, red_ghost->prison_params.active); display_character(red_ghost->position.y, red_ghost->position.x, frightened_counter ? frightened_counter : ghost_char, red_ghost->prison_params.active); paint_ghost(pink_ghost->color, frightened_counter, pink_ghost->prison_params.active); display_character(pink_ghost->position.y, pink_ghost->position.x, frightened_counter ? frightened_counter : ghost_char, pink_ghost->prison_params.active); paint_ghost(blue_ghost->color, frightened_counter, blue_ghost->prison_params.active); display_character(blue_ghost->position.y, blue_ghost->position.x, frightened_counter ? frightened_counter : ghost_char, blue_ghost->prison_params.active); paint_ghost(orange_ghost->color, frightened_counter, orange_ghost->prison_params.active); display_character(orange_ghost->position.y, orange_ghost->position.x, frightened_counter ? frightened_counter : ghost_char, orange_ghost->prison_params.active); } void display_score(int value) { move(field_height-1, 21); paint_stats(); printw("%d", value); refresh(); } void display_ready() { move(17, 11); /* * the same color as pacman */ paint_pac(); printw("READY!"); refresh(); } void clear_or_revert_symbol(const game_space field, struct coordinates position, enum select_character character, const struct queue *eaten_coins) { int x, y; x = position.x; y = position.y; int symbol = field[y][x]; move(y, x); if(character == ghost_char) { if(is_coin_symbol(symbol, x, y) && field_has_coin(x, y) && !queue_consists_point(eaten_coins, position)) { if(symbol == energizer) { paint_field_element(coin); addch('*'); } else { paint_field_element(coin); addch('.'); } refresh(); return; } switch(symbol) { case one_path: case two_paths: case three_paths: case yellow_block: reset_attr(); addch(' '); break; case coin: reset_attr(); addch(' '); break; case door: paint_field_element(door); addch('#'); break; case ' ': reset_attr(); addch(' '); break; } } else if(character == pac_char) { reset_attr(); addch(' '); } refresh(); } enum intersection_type get_intersection(const game_space field, struct ghost_type *ghost) { int y, x, symbol; y = ghost->position.y; x = ghost->position.x; symbol = field[y][x]; switch(symbol) { case one_path: return one_path; case two_paths: 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 x, int y) { struct free_directions found_paths; 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; } 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; } void clear_energizer(game_space field, struct coordinates point) { int x, y; x = point.x; y = point.y; field[y][x] = ' '; } void clear_ready() { move(17, 11); reset_attr(); printw(" "); refresh(); } 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; } void erase_life(int value) { enum { one_life_left = 1, no_lives_left = 0, gap = 2, two_lives_x = 3 }; int x, y; y = field_height - 1; switch(value) { case one_life_left: x = two_lives_x; break; case no_lives_left: x = two_lives_x - gap; } move(y, x); reset_attr(); addch(' '); refresh(); } void display_hit(struct coordinates pac_position, const struct ghost_type *red_ghost, const struct ghost_type *pink_ghost, const struct ghost_type *blue_ghost, const struct ghost_type *orange_ghost) { struct coordinates ghost_position; if(red_ghost->reached_pacman) ghost_position = red_ghost->position; else if(pink_ghost->reached_pacman) ghost_position = pink_ghost->position; else if(blue_ghost->reached_pacman) ghost_position = blue_ghost->position; else ghost_position = orange_ghost->position; reset_attr(); move(ghost_position.y, ghost_position.x); addch(' '); paint_hit(); move(pac_position.y, pac_position.x); addch('X'); refresh(); } void erase_hit(struct coordinates point) { move(point.y, point.x); reset_attr(); addch(' '); refresh(); }