snek.py

Created by fedyna-kevin

Created on April 14, 2022

2.13 KB

sneki boi


from kandinsky import fill_rect, draw_string
from random import randint
from ion import keydown


WIDTH = 320
HEIGHT = 222
SIZE = 16
# Available dirs ordered by keycode
DIRS = (-10, -1, 1, 10)


def get_f(snake_part):
    return snake_part >> 9


def get_x(snake_part):
    return snake_part & (2**5 - 1)


def get_y(snake_part):
    return snake_part >> 5 & (2**4 - 1)


def set_snake(x, y, f):
    return x | y << 5 | f << 9


def is_coords_equal(obj1, obj2):
    return obj1 & (2**9 - 1) == obj2 & (2**9 - 1)


def generate_fruit(snake):
    available = tuple(x | y << 5
        for x in range(20) for y in range(13) if not x | y << 5 in snake
    )
    return available[randint(0, len(available) - 1)]


def move(snake, facing, fruit):
    """ Move the snake and collision detection (new fruit also) """
    next_x = get_x(snake[-1]) + DIRS[facing] // 10
    next_y = get_y(snake[-1]) + DIRS[facing] %  10

    next_head = set_snake(next_x, next_y, facing)

    if next_x == 20 or next_x == -1 or next_y == 13 or next_y == -1:
        return False, fruit

    for snake_part in snake:
        if is_coords_equal(snake_part, next_head):
            return False, fruit
    
    if is_coords_equal(next_head, fruit):
        fruit = generate_fruit(tuple(i & (2**9 - 1) for i in snake))
    else:
        snake = snake[1:]
    
    return snake + (next_head,), fruit


def solo_game():
    snake = (1536, 1537, 1538)
    facing = 3
    fruit = generate_fruit((0, 1, 2))

    fill_rect(0, 0, SIZE, 3*SIZE, (0, 255, 0))
    fill_rect(get_x(fruit) * SIZE, get_y(fruit) * SIZE, SIZE, SIZE, (255, 0, 0))

    while 1:
        for i in range(4):
            if keydown(i):
                facing = i
        
        last_x = get_x(snake[0]) * SIZE
        last_y = get_y(snake[0]) * SIZE
        fill_rect(last_x, last_y, SIZE, SIZE, (255,)*3)

        snake, fruit = move(snake, facing, fruit)
        if not snake:
            break
        
        new_x = get_x(snake[-1]) * SIZE
        new_y = get_y(snake[-1]) * SIZE
        fill_rect(new_x, new_y, SIZE, SIZE, (0, 255, 0))
        fill_rect(get_x(fruit) * SIZE, get_y(fruit) * SIZE, SIZE, SIZE, (255, 0, 0))