diff --git a/kernels/snake/snake.c b/kernels/snake/snake.c new file mode 100644 index 0000000..0462a37 --- /dev/null +++ b/kernels/snake/snake.c @@ -0,0 +1,249 @@ +#include +#define _Bool unsigned int /* lcc doesn't define this */ +#include + +#define MAX_LENGTH 100 + +typedef enum { NONE, UP, DOWN, LEFT, RIGHT } dir_t; + +typedef struct { + int x, y; +} point_t; + +typedef struct { + int width, height; +} dim_t; + +typedef struct { + int top, bottom, left, right; +} rect_t; + +typedef struct { + point_t body[MAX_LENGTH]; + int length; + int index; + int dead; +} snake_t; + +point_t create_food(dim_t); +void print_board(rect_t); +void print_food(point_t, rect_t); +void print_head(snake_t*, rect_t); +void clear_tail(snake_t*, rect_t); +dir_t get_dir(int); +void move_snake(snake_t*, dir_t); +int is_dead(snake_t*, dim_t); +int has_food(snake_t*, point_t); + +int main(void) +{ + snake_t snake={0}; + point_t food; + rect_t board; + dim_t screen; + dim_t game_size; + dir_t dir=RIGHT; + dir_t move_dir=NONE; + int c; + + srand(time(0)); + initscr(); + + getmaxyx(stdscr, screen.height, screen.width); + + game_size.width=screen.width/2; + game_size.height=screen.height/2; + + food=create_food(game_size); + + snake.body[0].x=game_size.width/2; + snake.body[0].y=game_size.height/2; + snake.body[1].x=game_size.width/2; + snake.body[1].y=game_size.height/2+1; + snake.length=2; + snake.index=1; + + board.left=screen.width/2-game_size.width/2-1; + board.right=board.left+game_size.width+1; + board.top=screen.height/2-game_size.height/2-1; + board.bottom=board.top+game_size.height+1; + + noecho(); + cbreak(); + timeout(0); + curs_set(0); + + clear(); + do { + print_board(board); + print_food(food,board); + print_head(&snake,board); + clear_tail(&snake,board); + refresh(); + + c=getch(); + move_dir=get_dir(c); + if (move_dir!=NONE) { + dir=move_dir; + } + + move_snake(&snake, dir); + snake.dead=is_dead(&snake,game_size); + + if (has_food(&snake, food)) { + snake.length++; + food=create_food(game_size); + } + + usleep (100000-snake.length*5000<5000?5000:100000-snake.length*5000); + + } while (c!=27 && !snake.dead); + + move( + screen.height/2, + screen.width/2-5 + ); + printw("GAME OVER"); + refresh(); + nocbreak(); + timeout(-1); + c=getch(); + endwin(); + + return 0; +} + +point_t create_food(dim_t game_size) +{ + point_t f; + f.x=rand()%game_size.width; + f.y=rand()%game_size.height; + return f; +} + +void print_board(rect_t board) +{ + int i; + + for (i=board.left; i<=board.right; i++) { + move(board.top, i); + addch(' '|A_REVERSE); + move(board.bottom, i); + addch(' '|A_REVERSE); + } + + for (i=board.top; i<=board.bottom; i++) { + move(i, board.left); + addch(' '|A_REVERSE); + move(i, board.right); + addch(' '|A_REVERSE); + } +} + +void print_food(point_t food, rect_t board) +{ + move( + food.y+board.top+1, + food.x+board.left+1 + ); + printw("@"); +} + +void print_head(snake_t* snake, rect_t board) +{ + move( + snake->body[snake->index].y+board.top+1, + snake->body[snake->index].x+board.left+1 + ); + printw("o"); +} + +void clear_tail(snake_t* snake, rect_t board) +{ + int t=snake->index-snake->length; + if (t<0) { + t+=MAX_LENGTH; + } + move( + snake->body[t].y+board.top+1, + snake->body[t].x+board.left+1 + ); + printw(" "); +} + +dir_t get_dir(int c) +{ + if (c=='a') { + return LEFT; + } + else if (c=='w') { + return UP; + } + else if (c=='d') { + return RIGHT; + } + else if (c=='s') { + return DOWN; + } + else { + return NONE; + } +} + +void move_snake(snake_t* snake, dir_t dir) +{ + point_t p; + p=snake->body[snake->index]; + + if (dir==LEFT) { + p.x--; + } + else if (dir==DOWN) { + p.y++; + } + else if (dir==RIGHT) { + p.x++; + } + else if (dir==UP) { + p.y--; + } + + snake->index++; + if (snake->index==MAX_LENGTH) { + snake->index=0; + } + + snake->body[snake->index]=p; +} + +int is_dead(snake_t* snake, dim_t game_size) +{ + int i, j; + point_t head=snake->body[snake->index]; + + if (head.x==-1) return 1; + if (head.x==game_size.width) return 1; + if (head.y==-1) return 1; + if (head.y==game_size.height) return 1; + + i=1; + while (i!=snake->length) { + j=snake->index-i; + if (j<0) { + j+=MAX_LENGTH; + } + if (head.x==snake->body[j].x && head.y==snake->body[j].y) { + return 1; + } + i++; + } + + return 0; +} + +int has_food(snake_t* snake, point_t food) +{ + return + snake->body[snake->index].x==food.x && + snake->body[snake->index].y==food.y; +}