#include #include #include #include #define SWIDTH 10 /* segment width */ typedef enum { UP, DOWN, LEFT, RIGHT } Direction; typedef struct Snake { Point p[50]; int length; int head; int tail; Direction d; } Snake; Image *dots, *back, *snakecolor, *foodcolor; struct Snake s; /* our hero */ Point food; void newfood(void) { Point newfood; Rectangle r = screen->r; newfood.x = r.min.x + ntruerand(29)*10; newfood.y = r.min.y + ntruerand(29)*10; food = newfood; } void redraw(Image *screen) { static Rectangle r; Point pt; Rectangle foo; int i; r = screen->r; draw(screen, screen->r, back, nil, ZP); foo = Rect(food.x, food.y, food.x + SWIDTH, food.y + SWIDTH); draw(screen, foo, foodcolor, nil, ZP); for (i = 0; i < s.length; i++) { pt = s.p[s.head - i]; if (s.head - i < 0) pt = s.p[50 + (s.head - i)]; foo = Rect(pt.x, pt.y, pt.x + SWIDTH, pt.y + SWIDTH); draw(screen, foo, snakecolor, nil, ZP); } flushimage(display, 1); } void movesnake(void) { Rectangle r = screen->r; Point head, pt; int i; if (s.length < 50) { if (s.p[s.head].x == food.x && s.p[s.head].y == food.y) { s.length++; newfood(); } else { s.tail++; if (s.tail == 50) s.tail = 0; } s.head++; if (s.head == 50) s.head = 0; switch (s.d) { case UP: s.p[s.head] = subpt(s.p[s.head-1], Pt(0,SWIDTH)); if (s.head == 0) s.p[0] = subpt(s.p[49], Pt(0,SWIDTH)); break; case DOWN: s.p[s.head] = addpt(s.p[s.head-1], Pt(0,SWIDTH)); if (s.head == 0) s.p[0] = addpt(s.p[49], Pt(0,SWIDTH)); break; case LEFT: s.p[s.head] = subpt(s.p[s.head-1], Pt(SWIDTH,0)); if (s.head == 0) s.p[0] = subpt(s.p[49], Pt(SWIDTH,0)); break; case RIGHT: s.p[s.head] = addpt(s.p[s.head-1], Pt(SWIDTH,0)); if (s.head == 0) s.p[0] = addpt(s.p[49], Pt(SWIDTH,0)); break; default: print("wtf mate\n"); break; } head = s.p[s.head]; for (i = 1; i < s.length; i++) { pt = s.p[s.head - i]; if (s.head - i < 0) pt = s.p[50 + (s.head - i)]; if (head.x == pt.x && head.y == pt.y) { print("You hit yourself! Score: %d\n", s.length); exits(nil); } } if ((head.x < r.min.x) || (head.x > r.max.x - 10) || (head.y < r.min.y) || (head.y > r.max.y - 10)) { print("You hit a wall! Score: %d\n", s.length); exits(nil); } } redraw(screen); } void eresized(int new) { if(new && getwindow(display, Refnone) < 0) fprint(2,"can't reattach to window"); redraw(screen); } void resize(int x, int y) { int fd; fd = open("/dev/wctl", OWRITE); if(fd >= 0){ fprint(fd, "resize -dx %d -dy %d", x, y); close(fd); } } void main(int, char**) { Event e; Mouse m; Menu menu; char *mstr[] = {"exit", 0}; int key, timer, inputk; int t; resize(300,300); initdraw(0,0,"snake"); back = allocimagemix(display, DPalebluegreen, DWhite); snakecolor = allocimage(display, Rect(0, 0, 1, 1), RGB24, 1, DGreen); foodcolor = allocimage(display, Rect(0,0,1,1), RGB24, 1, DBlack); food = addpt(screen->r.min, Pt(150, 60)); s.p[0] = addpt(screen->r.min, Pt(150,150)); s.length = 1; s.d = UP; s.head = 0; s.tail = 0; redraw(screen); einit(Emouse | Ekeyboard); t = (150); timer = etimer(0, t); menu.item = mstr; menu.lasthit = 0; for(;;) { key = event(&e); if(key == Emouse) { m = e.mouse; if(m.buttons & 4) { if(emenuhit(3, &m, &menu) == 0) { print("mouse exit\n"); exits(0); } } } else if (key == Ekeyboard) { inputk = e.kbdc; switch (inputk) { case 'h': if (s.d != RIGHT) s.d = LEFT; break; case 'j': if (s.d != UP) s.d = DOWN; break; case 'k': if (s.d != DOWN) s.d = UP; break; case 'l': if (s.d != LEFT) s.d = RIGHT; break; case 'q': print("Quitter... your score: %d\n", s.length); exits(nil); break; default: break; } } else if(key == timer) { movesnake(); } } }