Skip to content

Instantly share code, notes, and snippets.

@dolohow
Created August 25, 2020 18:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dolohow/3ffc710ebe17f2f484542a33dc9f7444 to your computer and use it in GitHub Desktop.
Save dolohow/3ffc710ebe17f2f484542a33dc9f7444 to your computer and use it in GitHub Desktop.
import curses
import pdb
import random
import time
from curses import wrapper
GAME_BOARD_SIZE = (20, 20)
def debug(stdscr, data):
stdscr.addstr(25, 0, str(data))
class GameOver(Exception):
pass
class Point():
def __init__(self, y, x):
self.y = y
self.x = x
def __add__(self, other):
return Point(self.y + other.y, self.x + other.x)
def __eq__(self, other):
return self.x == other.x and self.y == other.y
def __repr__(self):
return f'({self.y}, {self.x})'
class Figure():
STATUS_NEW = 1
STATUS_MOVED = 2
def __init__(self, stdscr, points):
self.stdscr = stdscr
self.points = points
self.current_position = Point(0, 0)
self.status = self.STATUS_NEW
def draw(self, starting_position):
self.current_position = starting_position
for point in self.points:
self.stdscr.addstr(point.y + starting_position.y,
point.x + starting_position.x, '*')
def clear(self):
for p in self.points:
self.stdscr.addstr(p.y + self.current_position.y,
p.x + self.current_position.x, ' ')
def try_rotate(self, clockwise=True):
points = []
for point in self.points:
if clockwise:
x = -point.y + self.current_position.x
y = point.x + self.current_position.y
else:
x = point.y + self.current_position.x
y = -point.x + self.current_position.y
points.append((Point(y, x)))
return Figure(self.stdscr, points)
def rotate(self, clockwise=True):
self.clear()
for point in self.points:
tmp = point.x
if clockwise:
point.x = -point.y
point.y = tmp
else:
point.x = point.y
point.y = -tmp
self.draw(self.current_position)
def move(self, point):
self.clear()
self.current_position += point
self.draw(self.current_position)
def move_right(self):
self.move(Point(0, 1))
def move_left(self):
self.move(Point(0, -1))
def move_down(self):
self.move(Point(1, 0))
def get_current_position(self):
return [point + self.current_position for point in self.points]
def calculate_width(self):
width = 0
for point in self.points:
if point.x > width:
width = point.x
return width
class Board():
FIGURES = (
(Point(0, 1), Point(1, 1), Point(2, 0), Point(2, 1)),
(Point(0, 0), Point(1, 0), Point(2, 0), Point(2, 1)),
(Point(0, 0), Point(0, 1), Point(1, 0), Point(1, 1)),
(Point(0, 0), Point(0, 1), Point(0, 2), Point(0, 3)),
(Point(0, 1), Point(1, 0), Point(1, 1), Point(2, 0)),
)
def __init__(self, stdscr):
self.stdscr = stdscr
self.figures_spawned = []
def initialize(self):
for y in range(0, GAME_BOARD_SIZE[0]):
self.stdscr.addstr(y, 0, '*')
self.stdscr.addstr(y, GAME_BOARD_SIZE[0] + 1, '*')
for x in range(0, GAME_BOARD_SIZE[1] + 2):
self.stdscr.addstr(GAME_BOARD_SIZE[1], x, '*')
def draw_new_figure(self):
figure = Figure(self.stdscr, random.choice(self.FIGURES))
if self.will_figure_overlap(figure, Point(0, 0)):
raise GameOver
figure.draw(Point(0, random.randint(
1, GAME_BOARD_SIZE[1] - figure.calculate_width())))
return figure
def will_figure_overlap(self, new, direction):
current_position = new.get_current_position()
figures = [
figure_pos for spawned in self.figures_spawned for figure_pos in spawned.get_current_position()]
for point in current_position:
if point + direction in figures:
return True
return False
def will_figure_touch_right_border(self, figure):
for point in figure.get_current_position():
if point.x == GAME_BOARD_SIZE[1]:
return True
return False
def will_figure_touch_left_border(self, figure):
for point in figure.get_current_position():
if point.x == 1:
return True
return False
def will_figure_touch_bottom(self, figure):
for point in figure.get_current_position():
if point.y + 1 == GAME_BOARD_SIZE[0]:
return True
return False
def will_figure_touch_top(self, figure):
for point in figure.get_current_position():
if point.y < 0:
return True
return False
def move_figure_down(self, figure):
if self.will_figure_touch_bottom(figure) or self.will_figure_overlap(figure, Point(1, 0)):
self.figures_spawned.append(figure)
return False
figure.move_down()
return True
def move_figure_right(self, figure):
if self.will_figure_touch_right_border(figure) or self.will_figure_overlap(figure, Point(0, 1)):
return False
figure.move_right()
return True
def move_figure_left(self, figure):
if self.will_figure_touch_left_border(figure) or self.will_figure_overlap(figure, Point(0, -1)):
return False
figure.move_left()
return True
def rotate_figure(self, figure, clockwise=True):
new_position = figure.try_rotate(clockwise)
if self.will_figure_overlap(new_position, Point(0, 0)):
return
if (self.will_figure_touch_top(new_position) or
self.will_figure_touch_left_border(new_position) or
self.will_figure_touch_right_border(new_position)):
return
figure.rotate(clockwise)
def start(stdscr):
board = Board(stdscr)
board.initialize()
figure = board.draw_new_figure()
stdscr.refresh()
while True:
key = stdscr.getkey()
if key == 's':
if board.rotate_figure(figure, clockwise=True) and not board.move_figure_down(figure):
figure = board.draw_new_figure()
if key == 'w':
if board.rotate_figure(figure, clockwise=False) and not board.move_figure_down(figure):
figure = board.draw_new_figure()
if key == 'd':
if board.move_figure_right(figure) and not board.move_figure_down(figure):
figure = board.draw_new_figure()
if key == 'a':
if board.move_figure_left(figure) and not board.move_figure_down(figure):
figure = board.draw_new_figure()
stdscr.refresh()
def main(stdscr):
stdscr.clear()
start(stdscr)
stdscr.refresh()
wrapper(main)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment