Signed-off-by: Skylar "The Cobra" Widulski <cobra@vern.cc>
This commit is contained in:
Skylar "The Cobra" Widulski 2023-06-16 21:39:48 -04:00
commit 9a58087684
Signed by: cobra
GPG Key ID: 4FD8F812083FF6F9
2 changed files with 366 additions and 0 deletions

3
README.md Normal file
View File

@ -0,0 +1,3 @@
# snake.py
I made this a long time ago and thought it was lost, but when i was searching through my old phone's files, I found it.

363
snake.py Normal file
View File

@ -0,0 +1,363 @@
#!/usr/bin/env python3
import sys
import os
import curses
from select import select, error
from getopt import getopt, GetoptError
from math import floor
from subprocess import check_call
from random import randint, choice
from shlex import split
from struct import unpack
from time import sleep
STDIN_FILENO = sys.stdin.fileno()
body=[]
cherries=[]
paused=False
snake_col=(255, 255, 255)
cherry_col=(255, 0, 0)
bg_col=(0, 0, 0)
arg_cherry=1
interval=0.1
rainbow_snake=False
rainbow_cherry=False
rainbow_bg=False
length=1
grow=1
growths=0
should_grow = False
die_to_self=True
die_to_wall=True
score = 0
def hex_to_rgb(hexa):
try:
return tuple(int(hexa.lstrip('#')[i:i+2], 16) for i in (0, 2, 4))
except:
_help()
def get_args():
global arg_cherry
global snake_col
global bg_col
global cherry_col
global interval
global rainbow_snake
global rainbow_cherry
global rainbow_bg
global length
global grow
global die_to_self
global die_to_wall
try:
opts, args = getopt(sys.argv[1:], 'hnwc:b:s:r:i:l:g:', ['cherries=', 'background=', 'background-color=', 'cherry-color=', 'snake=', 'snake-color=', 'interval=', 'length=', 'grow=', 'no-self-collision', 'no-wall-collision', 'help'])
except GetoptError:
_help()
for opt, arg in opts:
try:
if opt in ("-c", "--cherries"):
arg_cherry = int(arg)
elif opt in ("-b", "--background", "--background-color"):
if int(arg) == -1:
rainbow_bg=True
else:
bg_col = hex_to_rgb(arg)
elif opt in ("-r", "--cherry-color"):
if int(arg) == -1:
rainbow_cherry=True
else:
cherry_col = hex_to_rgb(arg)
elif opt in ("-s", "--snake", "--snake-color"):
if int(arg) == -1:
rainbow_snake=True
else:
snake_col = hex_to_rgb(arg)
elif opt in ("-i", "--interval"):
interval = float(arg)
elif opt in ("-l", "--length"):
length = int(arg)
elif opt in ("-g", "--grow"):
grow = int(arg)
elif opt in ("-n", "--no-self-collision"):
die_to_self=False
elif opt in ("-w", "--no-wall-collision"):
die_to_wall=False
elif opt in ('-h', '--help'):
big_help()
except ValueError:
_help()
def cherry():
global body
global cherries
used_spaces = body.copy()
used_spaces.extend(cherries)
lst = list(set(all_tuples)-set(used_spaces))
if len(lst) > 0:
return choice(lst)
else:
return (-1, -1)
def _help():
try:
curses.endwin()
except:
pass
print("snake [OPTIONS...]", end='\r\n')
exit()
def big_help():
try:
curses.endwin()
except:
pass
print(
"""python snake.py [OPTIONS...]
OPTIONS:
-c INTEGER How many cherries will exist at once
--cherries=
-b HEX Color of the background
--background= --background-color=
-s HEX Color of the snake (-1 for random)
--snake= --snake-color=
-r HEX Color of the cherry
--cherry-color=
-i INTEGER How many seconds between movements
--interval=
-l INTEGER Initial length of snake
--length=
-g INTEGER How much to grow from cherries
--grow=
-n Turn off collision with the snake's body
--no-self-collision
-w Turn off collision with the walls
--no-wall-collision
-h --help Show this page and quit
""", end='\r\n')
exit()
def stop():
print('\033[0m', end='')
curses.curs_set(1)
curses.endwin()
print(f'Score: {score}', end='\r\n')
exit()
def win():
print('\033[0m', end='')
curses.endwin()
print('You win!', end='\r\n')
exit()
def get_terminal_size():
from platform import system
current_os = system()
tuple_xy = None
if current_os == 'Windows':
tuple_xy = _get_terminal_size_windows()
if tuple_xy is None:
tuple_xy = _get_terminal_size_tput()
if current_os in ['Linux', 'Darwin'] or current_os.startswith('CYGWIN'):
tuple_xy = _get_terminal_size_linux()
if tuple_xy is None:
print("default")
tuple_xy = (80, 25)
return tuple_xy
def _get_terminal_size_windows():
try:
from ctypes import windll, create_string_buffer
h = windll.kernel32.GetStdHandle(-12)
csbi = create_string_buffer(22)
res = windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)
if res:
(bufx, bufy, curx, cury, wattr,
left, top, right, bottom,
maxx, maxy) = unpack("hhhhHhhhhhh", csbi.raw)
sizex = right - left + 1
sizey = bottom - top + 1
return sizex, sizey
except:
pass
def _get_terminal_size_tput():
try:
cols = int(check_call(['tput', 'cols']))
rows = int(check_call(['tput', 'lines']))
return (cols, rows)
except:
pass
def _get_terminal_size_linux():
def ioctl_GWINSZ(fd):
try:
from fcntl import ioctl
from termios import TIOCGWINSZ
cr = unpack('hh', ioctl(fd, TIOCGWINSZ, '1234'))
return cr
except:
pass
cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
if not cr:
try:
fd = os.open(os.ctermid(), os.O_RDONLY)
cr = ioctl_GWINSZ(fd)
os.close(fd)
except:
pass
if not cr:
try:
cr = (os.environ['LINES'], os.environ['COLUMNS'])
except:
return None
return int(cr[1]), int(cr[0])
def __select(iwtd, owtd, ewtd):
while True:
try:
return select(iwtd, owtd, ewtd, 0)
except error:
err = sys.exc_info()[1]
if err.args[0] == errno.EINTR:
return([], [], [])
else:
raise
try:
sx, sy = get_terminal_size()
all_tuples = []
for i in range(sx):
for j in range(sy):
all_tuples.append((i, j))
direction = 0
curses.initscr()
curses.curs_set(0)
get_args()
for i in range(length):
x,y = floor(sx/2), floor(sy/2)+i
body.append((x,y))
for i in range(arg_cherry):
cherries.append((-1,-1))
for i in range(len(cherries)):
cherries[i] = cherry()
while True:
r, w, e = __select([STDIN_FILENO], [], [])
if STDIN_FILENO in r:
data=os.read(STDIN_FILENO, 1)
if len(data) == 0:
stop()
if data[0] == 27:
data=os.read(STDIN_FILENO, 1)
if len(data) == 0:
stop()
if data[0] == 91:
data=os.read(STDIN_FILENO, 1)
if len(data) == 0:
stop()
if data[0] == 65 and (direction != 1 or len(body) == 1):
direction = 0
elif data[0] == 66 and (direction != 0 or len(body) == 1):
direction = 1
elif data[0] == 67 and (direction != 3 or len(body) == 1):
direction = 2
elif data[0] == 68 and (direction != 2 or len(body) == 1):
direction = 3
elif data[0] == 70:
if paused:
stop()
elif data[0] == 72:
paused = not paused
elif data[0] in (119, 87):
direction = 0
elif data[0] in (115, 83):
direction = 1
elif data[0] in (100, 68):
direction = 2
elif data[0] in (97, 65):
direction = 3
elif data[0] in (101, 69):
if paused:
stop()
elif data[0] in (112, 80):
paused = not paused
if not paused:
last = body[0]
if direction == 0:
body[0] = (body[0][0], body[0][1]-1)
elif direction == 1:
body[0] = (body[0][0], body[0][1]+1)
elif direction == 2:
body[0] = (body[0][0]+1, body[0][1])
elif direction == 3:
body[0] = (body[0][0]-1, body[0][1])
for i in range(len(body)-1):
temp = body[i+1]
body[i+1] = last
last = temp
if body[0] in cherries:
cherries[cherries.index(body[0])] = cherry()
should_grow = True
score += 1
if growths == grow:
growths = 0
should_grow = False
elif should_grow:
new = (body[-1][0], body[-1][1])
body.append(new)
growths += 1
if body.count(body[0]) > 1 and len(body) > 2 and die_to_self:
stop()
if body[0][0] >= sx or body[0][0] < 0 or body[0][1] >= sy-1 or body[0][1] < 0:
if die_to_wall:
stop()
else:
body[0] = (body[0][0] % sx, body[0][1] % sy)
for j in range(sy-1):
print(f'\033[{j+1};0H', end='')
for i in range(sx):
if (i, j) in body:
if rainbow_snake:
snake_col = (randint(0,256), randint(0,256), randint(0,256))
print(f'\033[48;2;{snake_col[0]};{snake_col[1]};{snake_col[2]}m ', end='')
elif (i, j) in cherries:
if rainbow_cherry:
cherry_col = (randint(0,256), randint(0,256), randint(0,256))
print(f'\033[48;2;{cherry_col[0]};{cherry_col[1]};{cherry_col[2]}m ', end='')
else:
if rainbow_bg:
bg_col = (randint(0,256), randint(0,256), randint(0,256))
print(f'\033[48;2;{bg_col[0]};{bg_col[1]};{bg_col[2]}m ', end='')
print(f'\033[0mScore: {score}', end='')
if not paused:
print(f'\033[{sy+1};{sx-5}H ', end='')
else:
print(f'\033[{sy+1};{sx-5}HPaused', end='')
if list(set(all_tuples)-set(body)) == []:
win()
if interval > 0:
sleep(interval)
except KeyboardInterrupt:
stop()