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); | 
