IcePath/IcePath.c

448 lines
12 KiB
C

#define VERSION "0.20"
#define N 512
#define DELAY 25 // milliseconds
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ncurses.h>
void printm();
void play();
void move_ptr(int direction);
void menu();
void readfiles();
void ranking();
void rules();
void selectlevel();
int checkwin();
int searchlevel();
typedef struct {
int x;
int y;
} point;
struct selctd {
int level;
int world;
int pos; // position in level[]
} selected;
struct dataresult {
int moves;
int world;
int level;
time_t time;
} data[100];
struct infolevel { // level[0] empty
char name[15];
int world;
int num;
int height;
int width;
char matrix[N][N];
point start;
point exit;
} level[100];
int win = 0;
int moves = 0;
int totallevels; // number of levels available
point ptr;
FILE *f_info;
FILE *f_data;
int main() {
initscr();
noecho();
cbreak();
keypad(stdscr, true);
f_info = fopen("icelevels.txt", "r");
f_data = fopen("icedata.txt", "a+");
if (f_info == NULL || f_data == NULL) {
printw("Error opening file. Please put icelevels.txt in the same folder of IcePath.c");
refresh();
getch();
endwin();
return 1;
} else {
readfiles();
menu();
fclose(f_info);
fclose(f_data);
}
endwin();
return 0;
}
void readfiles() {
int u = 1, i = 0, lines = 0, j, k, newline;
char ch, tile;
// read f_data
rewind(f_data);
do { // count lines
ch = fgetc(f_data);
if (ch == '\n')
lines++;
} while (ch != EOF);
if (ch != '\n' && lines != 0)
lines++;
rewind(f_data);
do {
fscanf(f_data, "%li %d %d %d", &data[i].time, &data[i].world, &data[i].level, &data[i].moves);
i++;
} while (i < lines - 1);
selected.world = data[i-1].world;
selected.level = data[i-1].level + 1;
// read f_info
lines = 0;
do { // read from line 5
ch = fgetc(f_info);
if (ch == '\n')
lines++;
} while (lines < 5);
do {
fscanf(f_info, "%d.%d %s", &level[u].world, &level[u].num, level[u].name);
newline = j = k = 0;
if (level[u].world != 999) {
level[u].width = level[u].height = 0;
while (newline < 2) {
if (level[u].width == 0)
level[u].width = k;
k = 0;
while (1) {
tile = fgetc(f_info);
if (tile == '\n') {
newline++;
break;
}
newline = 0;
level[u].matrix[j][k] = tile;
if(level[u].matrix[j][k] == 'A') {
level[u].matrix[j][k] = ' ';
level[u].start.x = k;
level[u].start.y = j;
}
if (level[u].matrix[i][j] == 'B') {
level[u].exit.x = k;
level[u].exit.y = j;
}
k++;
}
j++;
level[u].height++;
}
level[u].height -= 2;
}
u++;
} while (level[u-1].world != 999);
totallevels = u - 1;
selected.pos = searchlevel();
}
void menu() {
while (1) {
clear();
printw("~~~ ICE PATH ~~~\n\n"
"[1] Play\n"
"[2] Select level\n"
"[3] Ranking\n"
//"[4] Settings\n"
"[5] Rules\n"
"[q] Quit\n\nv%s\n\n", VERSION);
switch (getch()) {
case 'q': return;
case '1': play(); break;
case '2': selectlevel(); break;
case '3': ranking(); break;
//case '4': settings(); break;
case '5': rules(); break;
}
}
}
void play() {
int direction;
int win, again = 0;
char *text = malloc(sizeof(text) * N);
do {
selected.pos = searchlevel();
moves = 0;
again = 0;
ptr.x = level[selected.pos].start.x;
ptr.y = level[selected.pos].start.y;
do {
flushinp();
printm();
refresh();
direction = getch();
if (direction == 'q') {
printw ("\nDo you really want to exit? [y/n] ");
refresh ();
if (getch () == 'y') {
return;
} else {
direction = 0;
}
}
if (direction == 'r') {
printw ("\nDo you really want to retry this level? [y/n] ");
refresh ();
if (getch () == 'y') {
again = 1;
} else {
direction = 0;
}
}
if (direction != 0 && direction != 'r') {
move_ptr(direction);
}
win = checkwin();
} while (win == 0 && direction != 'r');
if (win == 1) {
sprintf(text, "%li %d %d %d\n", time(NULL), selected.world, selected.level, moves);
fseek(f_data, 0, SEEK_END);
fputs(text, f_data);
printw("You win! Moves: %d. Retry [r]. Next level? [y/n]\n", moves);
refresh();
char ch = getchar();
if (ch == 'y') {
again = 1;
} else if (ch == 'r') {
again = 1;
selected.level--;
}
selected.level++;
}
} while (again);
free(text);
return;
}
void move_ptr(int direction) {
int temp_x = ptr.x, temp_y = ptr.y, tempmoves = moves;
switch (direction) {
case KEY_LEFT:
moves++;
while (ptr.x != 0 && level[selected.pos].matrix[ptr.y][ptr.x-1] != '+') {
ptr.x--;
printm();
refresh();
if (checkwin() == 1) {
break;
} else {
napms(DELAY);
}
} break;
case KEY_RIGHT:
moves++;
while (ptr.x < level[selected.pos].width - 1 && level[selected.pos].matrix[ptr.y][ptr.x+1] != '+'){
ptr.x++;
printm();
refresh();
if (checkwin() == 1) {
break;
} else {
napms(DELAY);
}
} break;
case KEY_UP:
moves++;
while (ptr.y > 0 && level[selected.pos].matrix[ptr.y-1][ptr.x] != '+') {
ptr.y--;
printm();
refresh();
if (checkwin() == 1) {
break;
} else {
napms(DELAY);
}
} break;
case KEY_DOWN:
moves++;
while (ptr.y < level[selected.pos].height - 1 && level[selected.pos].matrix[ptr.y+1][ptr.x] != '+') {
ptr.y++;
printm();
refresh();
if (checkwin() == 1) {
break;
} else {
napms(DELAY);
}
} break;
default: return;
}
if (temp_x == ptr.x && temp_y == ptr.y)
moves = tempmoves;
}
void printm() {
int i, j, a = 1, b = 1;
int left = 0, right = 0, up = 0, down = 0;
clear();
printw("Level %d.%d: %s. Moves: %d. Use arrows to move.\nRetry [r]. Quit [q]\n\n", level[selected.pos].world, level[selected.pos].num, level[selected.pos].name, moves);
if (level[selected.pos].height > 9 || level[selected.pos].width > 9)
printw("Warning! Keep this window in fullscreen mode please\n\n\n");
while (left + right < 18 && (a == 1 || a == 2)) {
a = 0;
if (ptr.x - left > 0) {
left++;
a++;
}
if (ptr.x + right + 1 < level[selected.pos].width) {
right++;
a++;
}
}
while (up + down < 18 && (b == 1 || b == 2)) {
b = 0;
if (ptr.y - up - 1 > 0) {
up++;
b++;
}
if (ptr.y + down < level[selected.pos].height) {
down++;
b++;
}
}
for (i = ptr.y - up; i <= ptr.y + down; i++) {
for (j = ptr.x - left; j <= ptr.x + right; j++) {
if (i == ptr.y && j == ptr.x) {
printw("YOU");
} else {
switch (level[selected.pos].matrix[i][j]) {
case 'B': printw("()"); break;
default: printw("%c", level[selected.pos].matrix[i][j]); break;
}
}
printw("\t");
}
printw("\n\n");
}
refresh();
}
int searchlevel() {
int i;
for (i = 0; i < totallevels; i++) {
if (level[i].num == selected.level && level[i].world == selected.world)
return i;
}
// else go to level 1 of next world
selected.world++;
selected.level = 1;
for (i = 0; i < totallevels; i++) {
if (level[i].num == selected.level && level[i].world == selected.world)
return i;
}
// else go to level 0.1
selected.world = 0;
selected.level = 1;
return 1;
}
void selectlevel() {
while (1) {
int again;
clear();
printw("> Select level. Menu [q]\n\n");
do {
again = 0;
clear();
printw("World? [1/2] ");
refresh();
switch (getch()) {
case 'q': return;
case '0': selected.world = 0; break;
case '1': selected.world = 1; break;
case '2': selected.world = 2; break;
default: again = 1; break;
}
} while (again);
do {
again = 0;
clear();
printw("> World %d\n\n", selected.world);
printw("Level? ");
refresh();
switch (getch()) {
case 'q': selected.level = 1; return;
case '1': selected.level = 1; return;
case '2': selected.level = 2; return;
case '3': selected.level = 3; return;
case '4': selected.level = 4; return;
case '5': selected.level = 5; return;
case '6': selected.level = 6; return;
case '7': selected.level = 7; return;
default: again = 1; break;
}
} while (again);
}
}
void ranking() {
int i, j, templevel = selected.level, tempworld = selected.world, printed;
struct dataresult temp;
char *time_string[N];
readfiles();
// reord data
for (i = 0; data[i].moves != 0; i++) {
for (j = i + 1; data[j].moves != 0; j++) {
if (data[i].moves > data[j].moves) {
temp = data[i];
data[i] = data[j];
data[j] = temp;
}
}
}
do {
if (templevel == 'w'-'0') {
printw("\nSelect world: [1/2] ");
tempworld = getch() - '0';
templevel = 1;
refresh();
}
clear();
printw("Best results level %d.%d:\n\n", tempworld, templevel);
printed = 0;
for (i = 0; data[i].moves != 0; i++) {
if ((data[i].level == templevel && data[i].world == tempworld) && printed < 5) {
time_string[i] = ctime(&data[i].time);
printw("# %d - %3d moves\t- level %d.%d \t- %s", printed + 1, data[i].moves, tempworld, data[i].level, time_string[i]);
refresh();
printed++;
}
}
if (printed == 0) {
printw("Nothing to show...\n");
refresh();
}
printw("\nMenu [q]; To filter by level [1-?]; Change world [w]");
refresh();
do {
templevel = getch() - '0';
} while ((templevel < 0 || templevel > 9) && templevel != 0 && templevel != 'q'-'0' && templevel != 'w'-'0');
} while (templevel != ('q'-'0'));
}
void rules() {
clear();
printw("> Rules\n\n");
printw("Reach the escape door ( )\n");
refresh();
getch();
}
int checkwin() {
if (level[selected.pos].matrix[ptr.y][ptr.x] == 'B'){
return 1;
}
else return 0;
}