#include "field.h" #include "ghosts.h" #include "queue.h" #include #include 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 C Score: "} }; 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(is_coin_symbol(symbol, j, i) && field_has_coin(j, i)) { symbol == energizer ? addch('*') : addch('.'); continue; } switch(symbol) { case one_path: case two_paths: case yellow_block: addch(' '); break; case block: addch('/'); break; case energizer: addch('*'); break; case door: addch('#'); break; case ' ': addch(' '); break; } if(i == field_height-1) addch(symbol); refresh(); } } } void display_character(int y, int x, enum select_character symbol) { move(y, x); addch(symbol); 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) { display_character(red_ghost->position.y, red_ghost->position.x, ghost_char); display_character(pink_ghost->position.y, pink_ghost->position.x, ghost_char); display_character(blue_ghost->position.y, blue_ghost->position.x, ghost_char); display_character(orange_ghost->position.y, orange_ghost->position.x, ghost_char); } void display_score(int value) { move(field_height-1, 25); printw("%d", value); refresh(); } void clear_or_revert_symbol(const game_space field, struct coordinates position, enum select_character character, 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) { switch(symbol) { case one_path: case two_paths: case three_paths: if(field_has_coin(x, y)) queue_consists_point(eaten_coins, position) ? addch(' ') : addch('.'); else addch(' '); break; case yellow_block: if(yellow_block_contains_coin(x, y)) queue_consists_point(eaten_coins, position) ? addch(' ') : addch('.'); else addch(' '); break; case door: addch('#'); break; case energizer: field_has_energizer(field, x, y) ? addch('*') : addch(' '); break; case coin: queue_consists_point(eaten_coins, position) ? addch(' ') : addch('.'); break; case ' ': addch(' '); break; } } else if(character == pac_char) 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] = ' '; } 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 { two_lives_left = 2, one_life_left = 1, no_lives_left = 0, gap = 2, three_lives_x = 5 }; int x, y; y = field_height - 1; switch(value) { case two_lives_left: x = three_lives_x; break; case one_life_left: x = three_lives_x - gap; break; case no_lives_left: x = three_lives_x - gap * 2; } move(y, x); addch(' '); refresh(); }