148 lines
4.5 KiB
Python
148 lines
4.5 KiB
Python
#
|
|
# Copyright © 2023 adithyagenie
|
|
#
|
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
#
|
|
|
|
import curses
|
|
import random
|
|
import time
|
|
from curses import textpad
|
|
|
|
import maze.menu
|
|
import maze.modules.maze as m
|
|
|
|
OPPOSITE_DIRECTION_DICT = {
|
|
curses.KEY_UP: curses.KEY_DOWN,
|
|
curses.KEY_DOWN: curses.KEY_UP,
|
|
curses.KEY_RIGHT: curses.KEY_LEFT,
|
|
curses.KEY_LEFT: curses.KEY_RIGHT,
|
|
}
|
|
|
|
DIRECTIONS_LIST = [curses.KEY_RIGHT, curses.KEY_LEFT, curses.KEY_DOWN, curses.KEY_UP]
|
|
|
|
|
|
def create_food(snake, box):
|
|
"""Simple function to find coordinates of food which is inside box and not on snake body"""
|
|
food = None
|
|
while food is None:
|
|
food = [
|
|
random.randint(box[0][0] + 1, box[1][0] - 1),
|
|
random.randint(box[0][1] + 1, box[1][1] - 1),
|
|
]
|
|
if food in snake:
|
|
food = None
|
|
return food
|
|
|
|
|
|
def main(stdscr):
|
|
# initial settings
|
|
curses.curs_set(0)
|
|
stdscr.nodelay(1)
|
|
curses.init_pair(1, curses.COLOR_RED, curses.COLOR_BLACK)
|
|
curses.init_pair(2, curses.COLOR_GREEN, curses.COLOR_BLACK)
|
|
curses.init_pair(3, curses.COLOR_YELLOW, curses.COLOR_BLACK)
|
|
curses.init_pair(6, curses.COLOR_CYAN, curses.COLOR_BLACK)
|
|
stdscr.timeout(100)
|
|
stdscr.clear()
|
|
stdscr.refresh()
|
|
|
|
# create a game box
|
|
sh, sw = stdscr.getmaxyx()
|
|
box = [[3, 3], [sh - 3, sw - 3]] # [[ul_y, ul_x], [dr_y, dr_x]]
|
|
textpad.rectangle(stdscr, box[0][0], box[0][1], box[1][0], box[1][1])
|
|
|
|
# create snake and set initial direction
|
|
snake = [[sh // 2, sw // 2 + 1], [sh // 2, sw // 2], [sh // 2, sw // 2 - 1]]
|
|
direction = curses.KEY_RIGHT
|
|
|
|
# draw snake
|
|
for y, x in snake:
|
|
stdscr.addstr(y, x, "█", curses.color_pair(3) | curses.A_BOLD)
|
|
|
|
# create food
|
|
food = create_food(snake, box)
|
|
stdscr.addstr(food[0], food[1], "🍎")
|
|
|
|
# print score
|
|
score = 0
|
|
score_text = "Score: {}".format(score)
|
|
stdscr.addstr(1, sw // 2 - len(score_text) // 2, score_text)
|
|
|
|
while 1:
|
|
# non-blocking input
|
|
key = stdscr.getch()
|
|
|
|
if key == 27:
|
|
stdscr.clear()
|
|
stdscr.refresh()
|
|
time.sleep(1)
|
|
maze.menu.menu(stdscr)
|
|
return
|
|
# set direction if user pressed any arrow key and that key is not opposite of current direction
|
|
if key in DIRECTIONS_LIST and key != OPPOSITE_DIRECTION_DICT[direction]:
|
|
direction = key
|
|
|
|
# find next position of snake head
|
|
head = snake[0]
|
|
if direction == curses.KEY_RIGHT:
|
|
new_head = [head[0], head[1] + 1]
|
|
elif direction == curses.KEY_LEFT:
|
|
new_head = [head[0], head[1] - 1]
|
|
elif direction == curses.KEY_DOWN:
|
|
new_head = [head[0] + 1, head[1]]
|
|
elif direction == curses.KEY_UP:
|
|
new_head = [head[0] - 1, head[1]]
|
|
|
|
# insert and print new head
|
|
stdscr.addstr(
|
|
new_head[0], new_head[1], "█", curses.color_pair(3) | curses.A_BOLD
|
|
)
|
|
snake.insert(0, new_head)
|
|
|
|
# if sanke head is on food
|
|
if snake[0] == food:
|
|
# update score
|
|
score += 1
|
|
score_text = "Score: {}".format(score)
|
|
stdscr.addstr(1, sw // 2 - len(score_text) // 2, score_text)
|
|
|
|
# create new food
|
|
food = create_food(snake, box)
|
|
stdscr.addstr(food[0], food[1], "🍎", curses.color_pair(1) | curses.A_BOLD)
|
|
|
|
# increase speed of game
|
|
stdscr.timeout(100 - (len(snake) // 3) % 90)
|
|
else:
|
|
# shift snake's tail
|
|
stdscr.addstr(snake[-1][0], snake[-1][1], " ")
|
|
snake.pop()
|
|
|
|
# conditions for game over
|
|
if (
|
|
snake[0][0] in [box[0][0], box[1][0]]
|
|
or snake[0][1] in [box[0][1], box[1][1]]
|
|
or snake[0] in snake[1:]
|
|
):
|
|
msg = "Game Over!"
|
|
stdscr.addstr(
|
|
sh // 2,
|
|
sw // 2 - len(msg) // 2,
|
|
msg,
|
|
curses.color_pair(1) | curses.A_BOLD,
|
|
)
|
|
stdscr.addstr(
|
|
sh // 2 + 1,
|
|
sw // 2 - 8,
|
|
"The Score is: " + str(score),
|
|
curses.color_pair(3) | curses.A_BOLD,
|
|
)
|
|
while stdscr.getch() == -1:
|
|
pass
|
|
time.sleep(2)
|
|
m.play(stdscr, executeguest=True, outerscore=score, outergame="snake")
|
|
# Call play with guestcheck to update scores
|
|
stdscr.clear()
|
|
stdscr.refresh()
|
|
maze.menu.menu(stdscr)
|
|
return score
|