Advertisement
Bmorr

Untitled

Oct 28th, 2019
203
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Go 11.87 KB | None | 0 0
  1. import pygame, time
  2. from random import randint, shuffle
  3. from copy import deepcopy
  4. from uuid import uuid1 as ranuuid
  5.  
  6.  
  7. scale = 10
  8. width, height = 64, 64
  9. scoreboard_width, scoreboard_border = 320, 6
  10. pygame.init()
  11. win = pygame.display.set_mode((width * 10 + scoreboard_width, height * 10))
  12. pygame.display.set_caption("Snek")
  13.  
  14. class Snake:
  15.     def __init__(self, x, y, color=None, controller=None, name=None):
  16.         self.body = [(x, y)]
  17.         self.direction = randint(0, 3)
  18.         self.alive = True
  19.         self.length = 3
  20.         self.uuid = ranuuid()
  21.         self.name = name
  22.  
  23.         if color is None:
  24.             color = [(255, 0, 0)]
  25.         self.color = color
  26.  
  27.         self.is_player = controller is None
  28.         self.controller = controller
  29.  
  30.         self.ticks = 0
  31.         self.kills = 0.0
  32.  
  33.     def tick(self):
  34.         if len(self.body) == 0:
  35.             return
  36.         last_x, last_y = self.body[-1]
  37.         # Dead
  38.         if not self.alive:
  39.             self.body.pop(0)
  40.         # Right
  41.         elif self.direction == 0:
  42.             self.body.append((last_x + 1, last_y))
  43.         # Up
  44.         elif self.direction == 1:
  45.             self.body.append((last_x, last_y - 1))
  46.         # Left
  47.         elif self.direction == 2:
  48.             self.body.append((last_x - 1, last_y))
  49.         # Down
  50.         elif self.direction == 3:
  51.             self.body.append((last_x, last_y + 1))
  52.         else:
  53.             print("Direction does not exist.")
  54.         # Removes the oldest segments until it has reached the proper length
  55.         while self.length < len(self.body):
  56.             self.body.pop(0)
  57.         self.ticks += 1
  58.  
  59.     def collision(self, snakes, apples):
  60.         if len(self.body) == 0:
  61.             return
  62.         x, y = head = self.body[-1]
  63.         # Collision with our own body
  64.         if head in self.body[0:-1]:
  65.             self.body.pop(len(self.body) - 1)
  66.             self.alive = False
  67.         # Collision with other snakes
  68.         closest_snakes, closest_snake_dist = [], 0
  69.         for snake in snakes:
  70.             if snake != self:
  71.                 if head in snake.body:
  72.                     self.body.pop(len(self.body) - 1)
  73.                     self.alive = False
  74.                     snake.kills += 1.0
  75.                     snake.length += self.length // 2
  76.                 # Finds the closest snake by each segment to tell who killed it.
  77.                 for body in snake.body:
  78.                     dist = abs(body[0] - head[0]) + abs(body[1] - head[1])
  79.                     if closest_snake_dist == 0 or dist < closest_snake_dist:
  80.                         closest_snakes = [snake]
  81.                         closest_snake_dist = dist
  82.                     elif dist == closest_snake_dist:
  83.                         closest_snakes.append(snake)
  84.         # Collisions with food
  85.         for food in apples:
  86.             if head == food:
  87.                 apples.remove(food)
  88.                 self.length += 1
  89.         # Outside the map
  90.         # TODO: Detect when snakes run other snakes off the map or trap them.
  91.         if not (0 <= x < width and 0 <= y < height):
  92.             print("Dist to closeset:", closest_snake_dist)
  93.             if closest_snake_dist <= 2:
  94.                 for snake in closest_snakes:
  95.                     snake.kills += 1 / len(closest_snakes)
  96.                     snake.length += (self.length / 2) // len(closest_snakes)
  97.             self.body.pop(len(self.body) - 1)
  98.             self.alive = False
  99.  
  100.     def set_direction(self, direction):
  101.         if direction % 2 != self.direction % 2:
  102.             self.direction = direction % 4
  103.             return True
  104.         return False
  105.  
  106.     def get_head(self):
  107.         return self.body[-1]
  108.  
  109.     def score(self):
  110.         return int(self.kills / 3 * self.length)
  111.  
  112. def default_think(snake: Snake, snakes: list, apples: list):
  113.     if not snake.alive:
  114.         return snake.direction
  115.     x, y = head = snake.get_head()
  116.     dir = snake.direction
  117.  
  118.     filled_tiles = [] + snake.body
  119.     for snek in snakes:
  120.         if snek != snake and snek.uuid != snake.uuid:
  121.             filled_tiles += snek.body
  122.             if snek.alive:
  123.                 head_x, head_y = snek.get_head()
  124.                 if snek.direction == 0:
  125.                     filled_tiles.append((head_x + 1, head_y))
  126.                 elif snek.direction == 1:
  127.                     filled_tiles.append((head_x, head_y - 1))
  128.                 elif snek.direction == 2:
  129.                     filled_tiles.append((head_x - 1, head_y))
  130.                 elif snek.direction == 3:
  131.                     filled_tiles.append((head_x, head_y + 1))
  132.  
  133.     for num in range(-1, 65):
  134.         filled_tiles += [(-1, num), (64, num), (num, -1), (num, 64)]
  135.  
  136.     # for spot in filled_tiles:
  137.     #     pygame.draw.rect(win, (255, 0, 0), (spot[0] * scale, spot[1] * scale, scale, scale))
  138.  
  139.     # The four possible directions
  140.     head_up, head_down = (x, y - 1), (x, y + 1)
  141.     head_left, head_right = (x - 1, y), (x + 1, y)
  142.  
  143.     if dir == 0:
  144.         x += 1
  145.     if dir == 1:
  146.         y -= 1
  147.     if dir == 2:
  148.         x -= 1
  149.     if dir == 3:
  150.         y += 1
  151.  
  152.     if (x, y) in filled_tiles or ((x == width // 2 or y == height // 2) and randint(1, 2) == 1):
  153.         possible_directions = []
  154.         if head_up not in filled_tiles:
  155.             possible_directions.append(1)
  156.         if head_down not in filled_tiles:
  157.             possible_directions.append(3)
  158.         if head_left not in filled_tiles:
  159.             possible_directions.append(2)
  160.         if head_right not in filled_tiles:
  161.             possible_directions.append(0)
  162.  
  163.         shuffle(possible_directions)
  164.         if len(possible_directions):
  165.             return possible_directions[0]
  166.  
  167.     return dir
  168.  
  169. def ben_think(snake: Snake, snakes: list, apples: list):
  170.     # Hahahahaa you THOUGHT you would get to see my code!
  171.     return snake.direction
  172.  
  173. def draw_tile(x, y, color, translate=True):
  174.     if translate:
  175.         pygame.draw.rect(win, color, (x * scale + 1 + scoreboard_width, y * scale + 1, scale - 2, scale - 2))
  176.     else:
  177.         pygame.draw.rect(win, color, (x * scale + 1, y * scale + 1, scale - 2, scale - 2))
  178.  
  179. def ran_color(min_avg=0):
  180.     r, g, b = randint(0, 255), randint(0, 255), randint(0, 255)
  181.     while r + g + b / 3 < min_avg:
  182.         r, g, b = randint(0, 255), randint(0, 255), randint(0, 255)
  183.     return r, g, b
  184.  
  185. def draw_text(win, text, c_x, c_y, size=10, color=(0, 0, 0), x_left=False, y_up=False):
  186.     text = str(text)
  187.     basic_font = pygame.font.SysFont(None, size)
  188.     text = basic_font.render(text, True, color)
  189.     text_rect = text.get_rect()
  190.     text_rect.centerx = c_x
  191.     text_rect.centery = c_y
  192.     if x_left:
  193.         text_rect.x = c_x
  194.     if y_up:
  195.         text_rect.y = c_y
  196.     win.blit(text, text_rect)
  197.  
  198. def main():
  199.     ticks = 0
  200.     snakes, dead_snakes, foods = [], [], []
  201.     def random_open_spot():
  202.         filled = [] + [bod for bod in [snake.body for snake in snakes]] + foods
  203.         ran = (randint(0, 64), randint(0, 64))
  204.         while ran in filled:
  205.             ran = (randint(0, width - 1), randint(0, width - 1))
  206.         return ran
  207.  
  208.     # snakes.append(Snake(32, 32, [(100, 0, 200), (0, 0, 200)]))
  209.     for i in range(25):
  210.         ran = random_open_spot()
  211.         snakes.append(Snake(ran[0], ran[1], [ran_color(150) for _ in range(0, randint(0, 2) + 1)], default_think))
  212.  
  213.     max_foods = 1
  214.     movement_events = []
  215.     clock = pygame.time.Clock()
  216.     running, paused = True, False
  217.  
  218.     tps = 10
  219.     # Game loop
  220.     while running:
  221.         keys = pygame.key.get_pressed()
  222.         # Events
  223.         for event in pygame.event.get():
  224.             if event.type == pygame.QUIT:
  225.                 running = False
  226.             elif event.type == pygame.KEYDOWN:
  227.                 if event.key == pygame.K_ESCAPE:
  228.                     running = False
  229.                 if event.key == pygame.K_r:
  230.                     return True
  231.                 if event.key == pygame.K_c:
  232.                     foods.clear()
  233.                 if event.key == pygame.K_p:
  234.                     paused = not paused
  235.                 if not paused and event.key in [pygame.K_w, pygame.K_a, pygame.K_s, pygame.K_d,
  236.                                  pygame.K_LEFT, pygame.K_RIGHT, pygame.K_UP, pygame.K_DOWN]:
  237.                     movement_events.append(event)
  238.  
  239.         # Movement
  240.         if not paused:
  241.             if len(movement_events) > 0:
  242.                 event = movement_events.pop(0)
  243.                 key = event.key
  244.                 player_controlled = list(filter(lambda x: x.is_player, snakes))
  245.                 for snake in player_controlled:
  246.                     if key == pygame.K_d or key == pygame.K_RIGHT:
  247.                         snake.set_direction(0)
  248.                     elif key == pygame.K_w or key == pygame.K_UP:
  249.                         snake.set_direction(1)
  250.                     elif key == pygame.K_a or key == pygame.K_LEFT:
  251.                         snake.set_direction(2)
  252.                     elif key == pygame.K_s or key == pygame.K_DOWN:
  253.                         snake.set_direction(3)
  254.             last_snakes = deepcopy(snakes)
  255.             for snake in snakes:
  256.                 if snake.controller is not None:
  257.                     snake.set_direction(snake.controller(snake, last_snakes, foods))
  258.                 snake.tick()
  259.  
  260.             for snake in snakes:
  261.                 if not snake.alive and len(snake.body) == 0:
  262.                     snakes.remove(snake)
  263.                     dead_snakes.insert(0, snake)
  264.                 snake.collision(snakes, foods)
  265.  
  266.             while len(foods) < max_foods:
  267.                 foods.append(random_open_spot())
  268.  
  269.         win.fill((50, 50, 50))
  270.         # Game Drawing
  271.         for snake in snakes:
  272.             body, color = snake.body, snake.color
  273.             for body_index, segment in enumerate(list(reversed(body))):
  274.                 draw_tile(segment[0], segment[1], color[body_index % len(color)])
  275.         for food in foods:
  276.             food_x, food_y = food
  277.             draw_tile(food_x, food_y, (222, 0, 0))
  278.         # Scoreboard Drawing
  279.         # TODO: Make it so if the mouse is hovering over a snake on the scoreboard, the snake gets highlighted
  280.         # Do this by filling the squares behind it with a rainbow color (shifting through the rainbow)
  281.         pygame.draw.rect(win, (200, 200, 200), (0, 0, scoreboard_width, height * scale))
  282.         pygame.draw.rect(win, (50, 50, 50), (scoreboard_border // 2, scoreboard_border // 2,
  283.                                              scoreboard_width - scoreboard_border, height * scale - scoreboard_border))
  284.  
  285.         def draw_scoreboard(sneks):
  286.             index, ret = 0, 0
  287.             for snake in sneks:
  288.                 x, y = 0, (2 * index) + 9
  289.                 for i in range(4):
  290.                     x = 1 + i
  291.                     draw_tile(x, y, snake.color[i % len(snake.color)], translate=False)
  292.                 text_color = (255, 255, 255)
  293.                 if not snake.alive:
  294.                     text_color = (255, 0, 0)
  295.                 draw_text(win, "Kills: " + str(snake.kills) + " Length: " + str(snake.length), x * scale + 15, (y + .5) * scale, color=text_color, size=30, x_left=True)
  296.                 ret = (y + .5) * scale
  297.                 index += 1
  298.             return ret
  299.         sorted_snakes = list(sorted(snakes, key=lambda s: s.score(), reverse=True))
  300.         draw_scoreboard(sorted_snakes + dead_snakes)
  301.  
  302.  
  303.         # Updates the window
  304.         pygame.display.flip()
  305.  
  306.         # Food amount management
  307.         if not paused:
  308.             ticks += 1
  309.             if ticks % 100 == 0:
  310.                 max_foods += 1
  311.                 # Makes the snakes longer
  312.                 for snake in snakes:
  313.                     if snake.alive:
  314.                         snake.length += 1
  315.         # Speed up the game
  316.         if keys[pygame.K_SPACE]:
  317.             clock.tick(tps * 5)
  318.         else:
  319.             clock.tick(tps)
  320.  
  321.  
  322. if __name__ == '__main__':
  323.     while True:
  324.         if not main():
  325.             break
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement