Skip to content

Commit c91de2e

Browse files
author
Angel Jumbo
committed
Fixed bug of --try-hard + screensaver mode .
1 parent 9c447dd commit c91de2e

File tree

8 files changed

+102
-106
lines changed

8 files changed

+102
-106
lines changed

README.md

+25-12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# sssnake
2-
The classic snake game for the terminal that can play itself and be use like a screensaver.
2+
The classic snake game for the terminal that can play itself and be used like a screensaver.
33
[![asciicast](https://asciinema.org/a/477685.svg)](https://asciinema.org/a/477685)
44
## Installation
55

@@ -24,23 +24,29 @@ make install
2424

2525
## Usage
2626

27-
(The options are different than the options on the released versions. If you installed this program from the released page please check "sssnake -h")
28-
29-
By default it will run like a normal snake game that you can control with wasd, hjkl(vi keys) or the arrow keys.
30-
But try this
27+
You can see the manpage or use the -h option to see the details of what this program can do.
28+
So instead would like to show you a few things that I like to run.
3129

3230
```
33-
sssnake -m screensaver -s 15
31+
sssnake -m autopilot -s 15 -j 10
3432
```
3533

36-
or
34+
[![Watch the video](https://img.youtube.com/vi/qNDcn5tdyno/maxresdefault.jpg)](https://youtu.be/qNDcn5tdyno)
3735

3836
```
39-
sssnake -l full -m screensaver -s 15 -j 5
37+
sssnake -m autopilot -s 15 -z -t -l ascii
38+
```
39+
40+
[![Watch the video](https://img.youtube.com/vi/XTS2CXHzBjA/maxresdefault.jpg)](https://youtu.be/XTS2CXHzBjA)
4041

42+
43+
```
44+
sssnake -m screensaver -s 15 -z -x 8 -y 8 --try-hard 1
4145
```
4246

43-
Use the -h options to see the option details.
47+
[![Watch the video](https://img.youtube.com/vi/oh4CK8wPU-4/maxresdefault.jpg)](https://youtu.be/oh4CK8wPU-4)
48+
49+
4450

4551
## Planned features
4652

@@ -56,11 +62,17 @@ Use the -h options to see the option details.
5662

5763
### Does the snake fills the entire screen/terminal with the autopilot?
5864
If you use the "--try-hard" options the snake will get pretty close and sometimes it will fill the terminal.
59-
(This is experimental and it does not work well in the screensaver mode because it refuses to die, but I'll fix that soon.)
60-
I recommend you to run it in small terminals or limit the game field like this:
65+
I implemented two algorithms "--try-hard 1" is good for big terminals/boards. You can test it running:
66+
```
67+
sssnake -m autopilot -s 15 --try-hard 1
6168
```
62-
sssnake -m screensaver -s 10 -x 10 -y 10 --try-hard 1
69+
70+
"--try-hard 2" uses more cpu and it can get laggy with big boards but it has more chances to fill the board. Try:
6371
```
72+
sssnake -m autopilot -s 10 -x 10 -y 10 --try-hard 2
73+
```
74+
Neither of the two algorithms work well with junk.
75+
6476
### Why the name "sssnake"?
6577
All the snake games in the terminal that I found use ascii characters and lets be honest, they are kinda ugly.
6678
I try to do something more visually appealing, something "sexy" and it can play itself so it is "smart".
@@ -74,3 +86,4 @@ Use the -h options to see the option details.
7486

7587
- Min heap implementation base on Martin Broadhurst min-heap ( http://www.martinbroadhurst.com/min-heap-in-c.html )
7688
- A\* base on (https://www.geeksforgeeks.org/a-search-algorithm/)
89+
- The two "--try-hard" algorithms that I implemented were inspired by chuyangliu's greedy solver ( https://github.com/chuyangliu/snake/blob/master/docs/algorithms.md#greedy-solver )

docs/sssnake.1

+3-3
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,10 @@ Makes the snake (almost) unkillable in the autopilot/screensaver mode.
8282
For now there are two options (algorithms):
8383
.RS
8484
.IP \[bu] 2
85-
\[lq]\[en]try-hard 1\[rq] is cpu efficient.
85+
\[lq]\[en]try-hard 1\[rq] is cpu efficient, good for big boards.
8686
.IP \[bu] 2
87-
\[lq]\[en]try-hard 2\[rq] uses more cpu but it reaches the food faster
88-
and produces a cleaner board.
87+
\[lq]\[en]try-hard 2\[rq] uses more cpu, it reaches the food faster and
88+
produces a cleaner board.
8989
.RE
9090
.TP
9191
\f[B]-h, \[en]help\f[R]

docs/sssnake.1.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ sssnake - Classic snake game on the terminal that can run in autopilot.
5252
**--try-hard N**
5353
: Makes the snake (almost) unkillable in the autopilot/screensaver mode. For now there are two options (algorithms):
5454

55-
* "--try-hard 1" is cpu efficient.
56-
* "--try-hard 2" uses more cpu but it reaches the food faster and produces a cleaner board.
55+
* "--try-hard 1" is cpu efficient, good for big boards.
56+
* "--try-hard 2" uses more cpu, it reaches the food faster and produces a cleaner board.
5757

5858
**-h, --help**
5959
: Print help message..

gede2.ini

-15
This file was deleted.

main.c

+52-74
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ Point foodLastPoint;
5151
Point tailLastPoint;
5252
int snakeSize = 0;
5353

54+
Point controlLastPoint = {-1, -1};
55+
int controlSnakeSize = 0;
56+
int loops = 0;
57+
5458
void init_options(int argc, char *argv[]);
5559
void init_game(void);
5660
// void init_score();
@@ -61,7 +65,6 @@ void draw_point(int x, int y, short color, int type);
6165
void draw_score(Snake *snake);
6266
void draw_walls();
6367

64-
int get_time(); // usleep() makes this fuction useless
6568
int get_direction(int c);
6669
int check_junk_pos(int x, int y);
6770
void print_help();
@@ -162,7 +165,6 @@ int main(int argc, char *argv[]) {
162165
while (1) {
163166
// Get a new path to follow if the autopilot or the screensaver are active
164167
if ((selectedMode == AUTOPILOT || selectedMode == SCREENSAVER) &&
165-
//(foodLastPoint.x != food.x || foodLastPoint.y != food.y)&&
166168
!check_path()) {
167169

168170
switch (selectedAlgorithm) {
@@ -199,13 +201,6 @@ int main(int argc, char *argv[]) {
199201

200202
if (path != NULL) {
201203

202-
// if (selectedAlgorithm == GREEDY && !snake->onWayToFood) {
203-
// Point *p = point_create(snake->head->x, snake->head->y);
204-
// stack_push(path, p);
205-
// long_step(blocksTaken, path, snake->teleport);
206-
// free(stack_pop(path));
207-
// }
208-
209204
Point *point = stack_pop(path);
210205
update_position_autopilot(snake, blocksTaken, &food, point->x, point->y,
211206
maxX, maxY);
@@ -218,24 +213,30 @@ int main(int argc, char *argv[]) {
218213
update_position(snake, blocksTaken, &food, direction, maxX, maxY);
219214
}
220215

221-
// ignore this, is just a debug block
222-
// xymap_print_log(blocksTaken, snake->head->x, snake->head->y,
223-
// snake->tail->x, snake->tail->y);
224-
225-
// FILE *fp;
226-
// fp = fopen("log.txt", "a+");
227-
228-
// fprintf(fp, "Food (%i,%i) \n", food.x, food.y);
229-
// fclose(fp);
230-
216+
if (selectedMode == SCREENSAVER) {
217+
if (controlLastPoint.x == snake->head->x &&
218+
controlLastPoint.y == snake->head->y &&
219+
snake->length == controlSnakeSize) {
220+
loops++;
221+
if (loops >= 2) {
222+
stack_free(path);
223+
path = a_star_search(blocksTaken, snake, maxX, maxY, food, 1);
224+
}
225+
}
226+
if (snake->length == maxBlocks)
227+
break;
228+
}
231229
if (snake->head->x == food.x && snake->head->y == food.y) {
232230
if (junkCount + snake->length < maxBlocks) {
231+
controlLastPoint = food;
232+
controlSnakeSize = snake->length;
233+
loops = 0;
233234
rand_pos_food(&food, blocksTaken, maxX, maxY);
235+
234236
} else {
235237
food.x = -1;
236238
food.y = -1;
237239
}
238-
// snake->onWayToFood = 0;
239240

240241
if (selectedMode == ARCADE)
241242
speed = speed - 2000;
@@ -289,8 +290,8 @@ int main(int argc, char *argv[]) {
289290
2 | ▀ ▀ | ▀▀▀
290291
3 | ▀ ▀ ▀ | ▀▀▀▀▀
291292
292-
so from this two characters ▀ and █ we have this extra combination to fill the
293-
gaps in the snake body ▀▀ and █▀
293+
so from this two characters ▀ and █ we have this two extra combination to fill
294+
the gaps in the snake body ▀▀ and █▀
294295
295296
And like this we can have a really cool snake.
296297
@@ -369,31 +370,9 @@ void draw_point(int x, int y, short color, int type) {
369370
addwstr(L"▚▀");
370371
break;
371372
case 18:
372-
addwstr(L"━━");
373-
break;
374-
case 19:
375-
addwstr(L"┃ ");
376-
break;
377-
case 20:
378-
addwstr(L"┛ ");
379-
break;
380-
case 21:
381-
addwstr(L"┓ ");
382-
break;
383-
case 22:
384-
addwstr(L"┏━");
385-
break;
386-
case 23:
387-
addwstr(L"┗━");
388-
break;
389-
case 24:
390-
addwstr(L"╹ ");
391-
break;
392-
case 25:
393-
addwstr(L"━ ");
394-
break;
395-
case 26:
396-
addwstr(L"▀━");
373+
attron(A_BOLD);
374+
addstr(". ");
375+
attroff(A_BOLD);
397376
break;
398377
}
399378
attroff(COLOR_PAIR(color));
@@ -502,6 +481,8 @@ void draw_snake(Snake *snake) {
502481
draw_point(sPart->x, sPart->y, 0, 9);
503482
// draw the second section of the body
504483
draw_point(sPart->next->x, sPart->next->y, 0, 8);
484+
// draw tail
485+
draw_point(sPart2->x, sPart2->y, 0, 18);
505486
break;
506487
case FANCY:
507488
// draw the head
@@ -831,11 +812,6 @@ void init_options(int argc, char *argv[]) {
831812
}
832813
}
833814

834-
int get_time() {
835-
clock_t difference = clock() - initTime;
836-
return difference * 1000 / CLOCKS_PER_SEC;
837-
}
838-
839815
void draw_score(Snake *snake) {
840816

841817
move(minY + maxY + 1, minX);
@@ -852,6 +828,7 @@ void draw_score(Snake *snake) {
852828
void draw_walls() {
853829
switch (selectedStyle) {
854830
case DOTS:
831+
case FULL:
855832
case FANCY:
856833
if (score || walls) {
857834
for (int i = 0; i < maxX; i++)
@@ -873,26 +850,26 @@ void draw_walls() {
873850
draw_point(-1, -1, 4, 17);
874851
draw_point(-1, maxY, 4, 17);
875852
}
876-
break;
877-
case FULL:
878-
if (score || walls) {
879-
for (int i = 0; i < maxX; i++)
880-
draw_point(i, maxY, 4, 0);
881-
}
882-
if (walls) {
883-
for (int i = -1; i < maxX + 1; i++) {
884-
draw_point(i, -1, 4, 0);
885-
}
886-
887-
for (int i = -1; i < maxY + 1; i++) {
888-
draw_point(-1, i, 4, 0);
889-
}
890-
891-
for (int i = -1; i < maxY + 1; i++) {
892-
draw_point(maxX, i, 4, 0);
893-
}
894-
}
895-
break;
853+
break; /*
854+
case FULL:
855+
if (score || walls) {
856+
for (int i = 0; i < maxX; i++)
857+
draw_point(i, maxY, 4, 0);
858+
}
859+
if (walls) {
860+
for (int i = -1; i < maxX + 1; i++) {
861+
draw_point(i, -1, 4, 0);
862+
}
863+
864+
for (int i = -1; i < maxY + 1; i++) {
865+
draw_point(-1, i, 4, 0);
866+
}
867+
868+
for (int i = -1; i < maxY + 1; i++) {
869+
draw_point(maxX, i, 4, 0);
870+
}
871+
}
872+
break;*/
896873
case ASCII:
897874
if (score || walls) {
898875
for (int i = 0; i < maxX; i++)
@@ -949,8 +926,9 @@ void print_help() {
949926
"autopilot/screensaver mode\n."
950927

951928
" For now there are two options (algorithms):\n"
952-
" \"--try-hard 1\" is cpu efficient.\n"
953-
" \"--try-hard 2\" uses more cpu but it reaches the "
929+
" \"--try-hard 1\" is cpu efficient, good for big "
930+
"boards.\n"
931+
" \"--try-hard 2\" uses more cpu, it reaches the "
954932
"food faster and produces a cleaner board.\n"
955933
" Neither of the two works well with junk in the "
956934
"board.\n"

makefile

+5
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ sssnake: main.c autopilot.c xymap.c essentials.c snake.c
66
#autopilot.o: autopilot.c xymap.c essentials.c snake.c
77
# gcc -c autopilot.c xymap.c essentials.c snake.c
88

9+
10+
.PHONY: genman
11+
genman:
12+
pandoc ./docs/sssnake.1.md -s -t man -o ./docs/sssnake.1
13+
914
.PHONY: clean
1015
clean:
1116
$(RM) sssnake

snake.c

+13
Original file line numberDiff line numberDiff line change
@@ -214,3 +214,16 @@ Point *point_create(int x, int y) {
214214
tmp->y = y;
215215
return tmp;
216216
}
217+
218+
int snake_cmp(Snake *sn1, Snake *sn2) {
219+
if (sn1->length != sn2->length)
220+
return 0;
221+
SnakePart *snp1;
222+
SnakePart *snp2;
223+
for (snp1 = sn1->head, snp2 = sn2->head; snp1 != NULL;
224+
snp1 = snp1->next, snp2 = snp2->next)
225+
if (snp1->x != snp2->x || snp1->y != snp2->y)
226+
return 0;
227+
228+
return 1;
229+
}

snake.h

+2
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ void update_position_autopilot(Snake *snake, XYMap *blocksTaken, Point *food,
4646
void check_collision(Snake *sn, XYMap *blocksTaken, int x, int y, int maxX,
4747
int maxY);
4848

49+
int snake_cmp(Snake *sn1, Snake *sn2);
50+
4951
void rand_pos_food(Point *food, XYMap *blocksTaken, int maxX, int maxY);
5052
Point *point_create(int x, int y);
5153
#endif

0 commit comments

Comments
 (0)