-
Notifications
You must be signed in to change notification settings - Fork 0
/
lib.cpp
177 lines (168 loc) · 7.17 KB
/
lib.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#include "stdcpp.h"
#include <ncurses.h>
#include "lib.h"
using namespace std;
void update_leaderboard(string player_name, double seconds, string level_string) {
system("test -f leaderboard.txt || touch leaderboard.txt"); // Create leaderboard.txt if it does not exist
ofstream fout;
fout.open("leaderboard.txt", ios::app); // Open leaderboard.txt
if (fout.fail()) {
clear();
mvaddstr(0, 0, "Cannot open leaderboard.txt");
} else {
fout << fixed << setprecision(2);
fout << player_name << " " << seconds << " " << level_string << endl; // Append latest player and score
fout.close();
system("sort leaderboard.txt -o leaderboard.txt"); // Sort leaderboard by name and then by score
system("sort -t ' ' -k 1,1 -u leaderboard.txt -o leaderboard.txt"); // Remove entries with duplicate names, leaving unique name entries and their best scores
system("sort -t ' ' -k 2,2 -n leaderboard.txt -o leaderboard.txt"); // Sort leaderboard by score
}
}
string get_player_name() { // Returns the player's name by capturing input
string player_name = "";
int keypress = getch();
while (keypress != 10) {
switch (keypress) {
case KEY_BACKSPACE:
if (player_name.length()==0) {break;}
else {player_name.pop_back();}
break;
default:
if (isalnum(keypress)) { // Spaces are ignored because they will be delimiters of the columns in the file
player_name.push_back(keypress);
}
break;
}
keypress = getch();
}
if (player_name.length()==0) {player_name = "Anonymous";}
return player_name;
}
void w(double seconds, string level_string) {
clear();
string str = "You win!";
mvaddstr(NUM_ROWS/2, NUM_COLS/2-4, str.c_str());
refresh();
this_thread::sleep_for(chrono::milliseconds(2000)); // Pause a couple of seconds to let that sink in
clear();
string message = "You have eliminated the invaders in "; // Report game duration
message += to_string(seconds);
message += " seconds!";
mvaddstr(NUM_ROWS/2-1, 0, message.c_str());
mvaddstr(NUM_ROWS/2+1, 0, "Enter your name: ");
move(NUM_ROWS/2+1, 17); // Move cursor to appropriate position for player to input name
curs_set(1); // Re-enable cursor
echo(); // So player can see what they're typing
refresh();
string player_name = get_player_name();
update_leaderboard(player_name, seconds, level_string);
};
void l() {
clear();
string str = "Your starship is destroyed!";
mvaddstr(NUM_ROWS/2, NUM_COLS/2-13, str.c_str());
refresh();
this_thread::sleep_for(chrono::milliseconds(2000));
}
void greet() {
// Prints an ASCII art and game rules
clear();
int y = NUM_ROWS/2-6;
mvaddstr(y, 0, " __ .__ __. ____ ____ ___ _______ _______ .______ _______.");
mvaddstr(y+1, 0, "| | | \\ | | \\ \\ / / / \\ | \\ | ____|| _ \\ / |");
mvaddstr(y+2, 0, "| | | \\| | \\ \\/ / / ^ \\ | .--. || |__ | |_) | | (----`");
mvaddstr(y+3, 0, "| | | . ` | \\ / / /_\\ \\ | | | || __| | / \\ \\ ");
mvaddstr(y+4, 0, "| | | |\\ | \\ / / _____ \\ | '--' || |____ | |\\ \\----.----) | ");
mvaddstr(y+5, 0, "|__| |__| \\__| \\__/ /__/ \\__\\ |_______/ |_______|| _| `._____|_______/ ");
mvaddstr(y+7, 0, "Shoot down the horde of intergalatic invaders threatening your spaceship!");
mvaddstr(y+8, 0, "Press SPACE to shoot, LEFT/RIGHT to move, P to pause, any key to resume, Q to quit");
mvaddstr(y+9, 0, "You can fire three bullets at the same time. You cannot fire while you move.");
mvaddstr(y+10, 0, "You LOSE if the invaders reach you -- beware: the closer they are the faster they move!");
mvaddstr(y+12, 0, "Press any key to continue");
refresh();
getch();
}
void present_options(int y) {
// Add a border around the frame
string top_and_bottom = "+";
for (int i=0; i<NUM_COLS; i++) {
top_and_bottom.push_back('-');
}
top_and_bottom.push_back('+');
mvaddstr(0, 0, top_and_bottom.c_str());
for (int iter_row=1; iter_row<NUM_ROWS+1; iter_row++) {
mvaddstr(iter_row, 0, "|");
mvaddstr(iter_row, NUM_COLS+1, "|");
}
mvaddstr(NUM_ROWS+1, 0, top_and_bottom.c_str());
mvaddstr(y, NUM_COLS/2-2+1, "Easy");
mvaddstr(y+1, NUM_COLS/2-3+1, "Medium");
mvaddstr(y+2, NUM_COLS/2-2+1, "Hard");
mvaddstr(y+3, NUM_COLS/2-3+1, "Extreme");
}
Level cursor_to_level(int y, int cursor_at_level) {
if (cursor_at_level==y) {
return Level::easy;
} else if (cursor_at_level==y+1) {
return Level::medium;
} else if (cursor_at_level==y+2) {
return Level::hard;
} else if (cursor_at_level==y+3) {
return Level::extreme;
}
return Level::easy;
}
Level choose_difficulty() {
clear();
int y = NUM_ROWS/2-2; // Make sure it's vertically centered
Level level = Level::easy; // Default level is easy
int cursor_at_level = y; // Tracks the > < cursor
present_options(y);
mvaddstr(y, NUM_COLS/2-5+1, ">");
mvaddstr(y, NUM_COLS/2+5+1, "<");
refresh();
int keypress = getch();
if (keypress=='t') {return Level::test;} // Secret test level for development purposes
while (keypress != 10) {
switch (keypress) {
case KEY_UP:
switch (level) {
case Level::easy:
break;
default:
present_options(y);
mvaddstr(cursor_at_level, NUM_COLS/2-5+1, " ");
mvaddstr(cursor_at_level, NUM_COLS/2+5+1, " ");
mvaddstr(cursor_at_level-1, NUM_COLS/2-5+1, ">");
mvaddstr(cursor_at_level-1, NUM_COLS/2+5+1, "<");
cursor_at_level -= 1;
level = cursor_to_level(y, cursor_at_level);
refresh();
break;
}
break;
case KEY_DOWN:
switch (level) {
case Level::extreme:
break;
default:
present_options(y);
mvaddstr(cursor_at_level, NUM_COLS/2-5+1, " ");
mvaddstr(cursor_at_level, NUM_COLS/2+5+1, " ");
mvaddstr(cursor_at_level+1, NUM_COLS/2-5+1, ">");
mvaddstr(cursor_at_level+1, NUM_COLS/2+5+1, "<");
cursor_at_level += 1;
level = cursor_to_level(y, cursor_at_level);
refresh();
break;
}
break;
case 10: // 10 is the key code for enter (KEY_ENTER is only for numpad enter)
return level;
default:
break;
}
keypress = getch();
}
return level;
}