Skip to content

Instantly share code, notes, and snippets.

@qrees
Last active December 27, 2015 22:10
Show Gist options
  • Save qrees/7397360 to your computer and use it in GitHub Desktop.
Save qrees/7397360 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
from collections import namedtuple, deque, defaultdict
import random
import time
import imp
import sys
Point = namedtuple('Point', ['x', 'y'])
class Board(object):
def __init__(self, width=10, height=10):
self.width = width
self.height = height
self.fields = [['.'] * width for _ in range(height)]
self.empty_fields = set(Point(x, y) for x in range(width) for y in range(height))
self.apples = set()
def __getitem__(self, p):
x, y = p
if x < 0 or x >= self.width or y < 0 or y >= self.height:
return '#'
return self.fields[y][x]
def __setitem__(self, p, value):
x, y = p
if x < 0 or x >= self.width or y < 0 or y >= self.height:
return
self.fields[y][x] = value
if value == 'o':
self.apples.add(Point(x, y))
else:
self.apples.discard(Point(x, y))
if value == '.':
self.empty_fields.add(Point(x, y))
else:
self.empty_fields.discard(Point(x, y))
def random_empty_field(self):
if len(self.empty_fields) == 0:
return None
return random.sample(self.empty_fields, 1)[0]
def apples(self):
return self.apples
def __str__(self):
result = []
for row in self.fields:
result.append(''.join(row))
return '\n'.join(result)
class Snake(object):
def __init__(self, parts, move, direction=None, color=None, name='annonymous'):
self.parts = deque(parts) if parts is not None else deque([Point(4, 4)])
self.direction = direction if direction is not None else 'right'
self.ate_apple = False
self.dead = False
self.name = name
self.color = color
self.move_direction = move
@property
def head(self):
return self.parts[-1]
def grow(self):
new_part = {'up': Point(self.head.x, self.head.y - 1),
'down': Point(self.head.x, self.head.y + 1),
'left': Point(self.head.x - 1, self.head.y),
'right': Point(self.head.x + 1, self.head.y)}[self.direction]
self.parts.append(new_part)
return new_part
def shrink(self):
return self.parts.popleft()
def move(self, bb):
self.direction = self.move_direction.move(bb)
if self.direction not in ['left', 'right', 'up', 'down']:
print("Wrong direction: %s" % self.direction)
self.dead = True
return (None, None)
if self.dead:
return (None, None)
added = self.grow()
removed = None
if not self.ate_apple:
removed = self.shrink()
self.ate_apple = False
return (added, removed)
def as_dict(self):
return {'name': self.name,
'parts': [[p.x, p.y] for p in self.parts],
'dead': self.dead,
'color': self.color}
class SingleJudge(object):
def __init__(self, movefunction, width=10, height=10):
self.width = width
self.height = height
self.board = Board(width, height)
self.snakes = []
for fun in movefunction:
self.snakes.append(self.spawn_snake('black', fun))
self.turn = 0
def spawn_snake(self, color, move):
p = self.board.random_empty_field()
self.board[p.x, p.y] = "#"
return Snake([p], move, color=color)
def spawn_apple(self):
p = self.board.random_empty_field()
if p is not None:
self.board[p.x, p.y] = 'o'
def kill_snake(self, snake):
for p in snake.parts:
self.board[p.x, p.y] = '.'
p = self.board.random_empty_field()
self.board[p.x, p.y] = "#"
snake.parts = deque([p])
snake.move_direction = imp.reload(snake.move_direction)
snake.dead = False
def check_collisions(self, heads, removed):
for p in removed:
self.board[p.x, p.y] = '.'
for p, snakes in heads.items():
# Check collisions between heads
if len(snakes) > 1:
for snake in snakes:
self.kill_snake(snake)
continue
# Check collisions between other parts
if self.board[p.x, p.y] == '#':
for snake in snakes:
self.kill_snake(snake)
continue
# Check collisions with apples
if self.board[p.x, p.y] == 'o':
for snake in snakes:
snake.ate_apple = True
self.board[p.x, p.y] = '#'
if self.turn % 5 == 0:
self.spawn_apple()
self.turn += 1
def run(self):
while True:
bb = str(self.board).splitlines()
bb = [list(x) for x in bb]
heads = defaultdict(list)
removed = []
for snake in self.snakes:
hh = snake.head
bb[hh.y][hh.x] = 'H'
#bb[hh.y] = bb[hh.y][:hh.x] + "H" + bb[hh.y][hh.x+1:]
head, tail = snake.move(["".join(x) for x in bb])
bb[hh.y][hh.x] = '#'
if head is not None:
heads[head].append(snake)
if tail is not None:
removed.append(tail)
if snake.dead:
self.kill_snake(snake)
self.check_collisions(heads, removed)
print(20*'\n')
sys.stdout.write("%s" % self.board)
sys.stdout.write("\n")
sys.stdout.flush()
time.sleep(0.1)
HEIGHT = 60
WIDTH = 80
def main():
if len(sys.argv) < 2:
print("Please add filename as first parameter")
exit()
else:
fs = sys.argv[1:]
mods = []
for f in fs:
mods.append(__import__(f))
judge = SingleJudge(mods, 80, 60)
judge.run()
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment