back to scratko.xyz
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorscratko <m@scratko.xyz>2024-04-16 02:37:12 +0300
committerscratko <m@scratko.xyz>2024-04-16 02:37:12 +0300
commit194f71c150eb9ee696acca17176092e8b0ce6e4f (patch)
treefeff177d5ffca319a71db4848f653b7ea7ae17c6
parente42ac35110b1819bf9762fbb4504ab920a17e207 (diff)
downloadpacman-194f71c150eb9ee696acca17176092e8b0ce6e4f.tar.gz
pacman-194f71c150eb9ee696acca17176092e8b0ce6e4f.tar.bz2
pacman-194f71c150eb9ee696acca17176092e8b0ce6e4f.zip
Scoring system
Pacman's starting position doesn't contain a coin. Fixed an error in field_has_energizer(). The field prints the number of pacman lives and the score. All coin checks are moved to the field.c file. Restart is replaced by initialization of starting parameters. The final stage contains the game results screens. Queue clearing is combined with field clearing. Get_out_stage moved to struct mode_type.
-rw-r--r--field.c85
-rw-r--r--field.h11
-rw-r--r--pac.c51
-rw-r--r--pac.h2
-rw-r--r--pacman.c168
5 files changed, 169 insertions, 148 deletions
diff --git a/field.c b/field.c
index 560cae9..06179c9 100644
--- a/field.c
+++ b/field.c
@@ -27,13 +27,14 @@ static const char field_sample[field_height][field_width] = {
{"/1....3..2..1//1..2..3....1/"},
{"/.////./////.//./////.////./"},
{"/*////./////.//./////.////*/"},
- {"/1.1//2..2..y..y..2..2//1.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)
@@ -59,7 +60,7 @@ void clear_field(game_space field)
field = NULL;
}
-int field_has_coin(int x, int y)
+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) ||
@@ -67,14 +68,33 @@ int field_has_coin(int x, int y)
(x == 13 && y == 12) || (x == 14 && y == 12));
}
-int field_has_energizer(const game_space field, int x, int y)
+static int yellow_block_contains_coin(int x, int y)
{
- return field[y][x] = energizer;
+ return (x == 12 && y == 22) || (x == 15 && y == 22);
}
-static int yellow_block_contains_coin(int x, int y)
+static int is_coin_symbol(int symbol, int x, int y)
{
- return (x == 12 && y == 22) || (x == 15 && y == 22);
+ 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)
@@ -86,27 +106,19 @@ void print_field(game_space field)
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 three_paths:
- if(field_has_coin(j, i))
- addch('.');
- else
- addch(' ');
- break;
case yellow_block:
- if(yellow_block_contains_coin(j, i))
- addch('.');
- else
- addch(' ');
+ addch(' ');
break;
case block:
addch('/');
break;
- case coin:
- addch('.');
- break;
case energizer:
addch('*');
break;
@@ -117,6 +129,8 @@ void print_field(game_space field)
addch(' ');
break;
}
+ if(i == field_height-1)
+ addch(symbol);
refresh();
}
}
@@ -143,6 +157,13 @@ void display_ghosts_on_field(struct ghost_type *red_ghost,
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)
@@ -263,3 +284,29 @@ int is_equal_points(struct coordinates first_point, struct coordinates
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();
+}
diff --git a/field.h b/field.h
index 4f84dc6..1543ea8 100644
--- a/field.h
+++ b/field.h
@@ -3,7 +3,7 @@
enum {
field_width = 28,
- field_height = 29,
+ field_height = 30,
left_outside_tunnel_x = -1,
right_outside_tunnel_x = field_width,
door = '#',
@@ -44,6 +44,7 @@ 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);
+void display_score(int value);
struct queue;
struct coordinates;
@@ -58,7 +59,11 @@ struct free_directions find_free_directions(game_space field, int y, int x);
int is_obstacle(game_space field, int x, int y);
-int field_has_coin(int x, int y);
+
+int check_coin_for_pac(game_space field, struct coordinates position,
+ struct queue *eaten_coins);
+
+int field_has_energizer(const game_space field, int x, int y);
void change_point_if_outside_tunnel(struct coordinates *point);
@@ -69,4 +74,6 @@ int is_equal_points(struct coordinates first_point, struct coordinates
void clear_field(game_space field);
+void erase_life(int value);
+
#endif
diff --git a/pac.c b/pac.c
index 97c3833..c3fcbb7 100644
--- a/pac.c
+++ b/pac.c
@@ -5,7 +5,7 @@
void initialize_pac(struct pacman *pac)
{
pac->lives = max_live;
- pac->coins_eaten = 0;
+ pac->score = 0;
pac->position.y = pac_y;
pac->position.x = pac_x;
pac->direction = none;
@@ -33,27 +33,6 @@ static enum movement_direction get_matching_for_directions(game_space field,
}
-#if 0
-void check_remaining_direction(game_space field, struct pacman *pac,
- enum movement_direction *stored_direction)
-{
- enum movement_direction temp_direction;
- struct free_directions free_path =
- find_free_directions(field, pac->position.x, pac->position.y);
- enum movement_direction current_direction =
- stored_direction ? *stored_direction : pac->direction;
- temp_direction = get_correct_path(pac, free_path, current_direction);
- if(temp_direction != none)
- pac->direction = temp_direction;
- else {
- current_direction = pac->direction;
- pac->direction = get_correct_path(pac, free_path, current_direction);
- }
- if(stored_direction)
- *stored_direction = none;
-}
-#endif
-
void check_remaining_direction(game_space field, struct pacman *pac,
enum movement_direction *stored_direction)
{
@@ -121,30 +100,9 @@ void change_pac_direction(game_space field, struct pacman *pac, int key,
check_remaining_direction_after_pressed_key(field, pac);
}
-static int is_coin_symbol(int symbol)
-{
- return
- symbol == coin || symbol == energizer || symbol == one_path ||
- symbol == two_paths || symbol == three_paths;
-}
-
-static int check_coin(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]) && field_has_coin(x, y) &&
- !queue_consists_point(eaten_coins, position);
-}
-
static void eat_energizer(game_space field, struct pacman *pac)
{
- int x, y;
- x = pac->position.x;
- y = pac->position.y;
- if(field[y][x] == energizer) {
+ if(field_has_energizer(field, pac->position.x, pac->position.y)) {
pac->is_energizer_eaten = 1;
clear_energizer(field, pac->position);
}
@@ -170,9 +128,9 @@ void make_pac_move(game_space field, struct pacman *pac,
default:
return;
}
- if(check_coin(field, pac->position, eaten_coins)) {
+ if(check_coin_for_pac(field, pac->position, eaten_coins)) {
queue_push(eaten_coins, &pac->position);
- ++pac->coins_eaten;
+ ++pac->score;
}
change_point_if_outside_tunnel(&pac->position);
eat_energizer(field, pac);
@@ -181,6 +139,7 @@ void make_pac_move(game_space field, struct pacman *pac,
void catch_pac(struct pacman *pac)
{
--pac->lives;
+ erase_life(pac->lives);
if(pac->lives >= 1) {
pac->position.y = pac_y;
pac->position.x = pac_x;
diff --git a/pac.h b/pac.h
index 29e83a1..ea0825b 100644
--- a/pac.h
+++ b/pac.h
@@ -11,7 +11,7 @@ enum {
struct pacman {
char lives;
- unsigned char coins_eaten;
+ unsigned char score;
struct coordinates position;
enum movement_direction direction;
int is_energizer_eaten;
diff --git a/pacman.c b/pacman.c
index 679fcc2..1468765 100644
--- a/pacman.c
+++ b/pacman.c
@@ -11,12 +11,13 @@ enum {
timeout_duration = 0,
sleep_duration = 190000,
key_escape = 27,
- count_get_out_moves = 6,
+ max_get_out_stage = 6,
chase_move_limit = 70,
scatter_move_limit = 35,
frightened_move_limit = 30,
phase_limit = 4,
- prison_limit = 30
+ prison_limit = 30,
+ max_score = 243
};
struct mode_type {
@@ -26,6 +27,7 @@ struct mode_type {
int frightened_count;
int phase_number;
int reverse_direction;
+ int get_out_stage;
};
struct game_params_type {
@@ -33,21 +35,6 @@ struct game_params_type {
int pause;
};
-static void initialize_params(struct game_params_type *basic_params)
-{
- srand(time(NULL));
- initscr();
- start_color();
- cbreak();
- noecho();
- curs_set(0);
- keypad(stdscr, 1);
- timeout(timeout_duration);
- start_color();
- basic_params->exit = 0;
- basic_params->pause = 0;
-}
-
static void initialize_ghosts(struct ghost_type *red_ghost,
struct ghost_type *pink_ghost,
struct ghost_type *blue_ghost,
@@ -59,7 +46,7 @@ static void initialize_ghosts(struct ghost_type *red_ghost,
initialize_ghost(orange_ghost, orange);
}
-static void initialize_modes(struct mode_type *mode_params, int *get_out_stage)
+static void initialize_modes(struct mode_type *mode_params)
{
mode_params->current_mode = scatter;
mode_params->chase_count = 0;
@@ -67,7 +54,26 @@ static void initialize_modes(struct mode_type *mode_params, int *get_out_stage)
mode_params->frightened_count = 0;
mode_params->phase_number = 0;
mode_params->reverse_direction = 0;
- *get_out_stage = count_get_out_moves;
+ mode_params->get_out_stage = max_get_out_stage;
+}
+
+static void initialize_params(game_space *field, struct queue *eaten_coins,
+ 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)
+{
+ timeout(timeout_duration);
+ *field = get_new_field();
+ print_field(*field);
+ queue_init(eaten_coins);
+ initialize_pac(pac);
+ initialize_ghosts(red_ghost, pink_ghost, blue_ghost, orange_ghost);
+ initialize_modes(mode_params);
+ display_ghosts_on_field(red_ghost, pink_ghost, blue_ghost,
+ orange_ghost);
+ display_character(pac->position.y, pac->position.x, pac_char);
}
static int is_up_move_blocked(const struct ghost_type *ghost,
@@ -310,11 +316,11 @@ static int is_castling(struct pacman pac, struct ghost_type ghost)
}
static void catching_stage(game_space field,
- struct mode_type *mode_params, int *get_out_stage,
- struct pacman *pac, struct ghost_type *red_ghost,
- struct ghost_type *pink_ghost,
- struct ghost_type *blue_ghost,
- struct ghost_type *orange_ghost)
+ 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;
@@ -358,8 +364,8 @@ static void catching_stage(game_space field,
catch_pac(pac);
if(pac->lives)
initialize_ghosts(red_ghost, pink_ghost, blue_ghost,
- orange_ghost);
- initialize_modes(mode_params, get_out_stage);
+ orange_ghost);
+ initialize_modes(mode_params);
usleep(sleep_duration);
return;
}
@@ -368,39 +374,32 @@ static void catching_stage(game_space field,
current_ghost->capture_info.status = 0;
}
}
-static void show_defeat_screen()
+
+static void final_stage(struct game_params_type *game_options, int win)
{
- move(17, 9);
- printw("GAME OVER");
+ int key;
+ if(win) {
+ move(17, 10);
+ printw("YOU WIN");
+ } else {
+ move(17, 9);
+ printw("GAME OVER");
+ }
+ move(14, 11);
+ printw("RETRY?");
+ move(15, 12);
+ printw("Y/N");
refresh();
+ timeout(-1);
+ while((key = getch()) != 'y' && key != 'n')
+ {}
+ game_options->exit = (key == 'y') ? 0 : 1;
}
-static void restart_game(struct game_params_type *basic_params,
- game_space field, struct queue *eaten_coins,
- struct pacman *pac, struct ghost_type *red_ghost,
- struct ghost_type *pink_ghost,
- struct ghost_type *blue_ghost,
- struct ghost_type *orange_ghost)
+static void clear_field_and_queue(game_space field, struct queue *eaten_coins)
{
- initialize_params(basic_params);
- initialize_pac(pac);
- initialize_ghosts(red_ghost, pink_ghost, blue_ghost, orange_ghost);
clear_field(field);
- field = get_new_field();
- print_field(field);
queue_clear(eaten_coins);
- queue_init(eaten_coins);
-}
-
-static void defeat_stage(struct game_params_type *basic_params)
-{
- int key;
- show_defeat_screen();
- timeout(-1);
- while((key = getch()) != 'y' && key != 'n')
- {}
- if(key == 'y')
- basic_params->exit = 0;
}
int main()
@@ -410,20 +409,21 @@ int main()
struct pacman pac;
struct queue eaten_coins;
struct mode_type mode_params;
- struct game_params_type basic_params;
- int key, get_out_stage;
+ struct game_params_type game_options;
+ int key;
enum movement_direction stored_direction;
+ srand(time(NULL));
+ initscr();
+ start_color();
+ cbreak();
+ noecho();
+ curs_set(0);
+ keypad(stdscr, 1);
stored_direction = none;
- initialize_params(&basic_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);
+ game_options.exit = 0;
+ game_options.pause = 0;
+ initialize_params(&field, &eaten_coins, &mode_params, &pac, &red_ghost,
+ &pink_ghost, &blue_ghost, &orange_ghost);
usleep(sleep_duration);
while((key = getch()) != key_escape) {
/*
@@ -442,9 +442,9 @@ int main()
/*
* ghosts
*/
- if(get_out_stage)
- pull_out_ghosts(&get_out_stage, &red_ghost, &pink_ghost,
- &blue_ghost, &orange_ghost);
+ if(mode_params.get_out_stage)
+ pull_out_ghosts(&mode_params.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);
@@ -461,15 +461,19 @@ int main()
&blue_ghost, &orange_ghost);
make_ghost_moves(field, &red_ghost, &pink_ghost, &blue_ghost,
&orange_ghost, &eaten_coins);
-
/*
- * displaying characters
+ * catching
+ */
+ catching_stage(field, &mode_params, &pac, &red_ghost, &pink_ghost,
+ &blue_ghost, &orange_ghost);
+ /*
+ * displaying characters and score
*/
- catching_stage(field, &mode_params, &get_out_stage, &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);
+ display_score(pac.score);
+
usleep(sleep_duration);
prison_leaving_stage(field, &red_ghost, &pink_ghost, &blue_ghost,
&orange_ghost);
@@ -486,17 +490,21 @@ int main()
printw("LIVES: %d", pac.lives);
refresh();
#endif
- if(!pac.lives) {
- defeat_stage(&basic_params);
- if(basic_params.exit)
- return 0;
- else
- restart_game(&basic_params, field, &eaten_coins, &pac,
- &red_ghost, &pink_ghost, &blue_ghost,
- &orange_ghost);
+ if(!pac.lives || pac.score == max_score ) {
+ final_stage(&game_options, !pac.lives ? 0 : 1);
+ if(game_options.exit)
+ break;
+ else {
+ stored_direction = none;
+ clear_field_and_queue(field, &eaten_coins);
+ initialize_params(&field, &eaten_coins, &mode_params, &pac,
+ &red_ghost, &pink_ghost, &blue_ghost,
+ &orange_ghost);
+ usleep(sleep_duration);
+ }
}
}
- queue_clear(&eaten_coins);
+ clear_field_and_queue(field, &eaten_coins);
endwin();
return 0;
}