Python 3 compatibility.

This commit is contained in:
Quantum 2017-11-19 02:55:51 -05:00
parent 7ba520cb08
commit d9d3c171cf
5 changed files with 49 additions and 44 deletions

View file

@ -2,13 +2,17 @@
This class handles the actual rendering of a game, and the game logic."""
import random
import os
import random
import sys
import pygame
from .utils import load_font, center
if sys.version_info[0] < 3:
range = xrange
class AnimatedTile(object):
"""This class represents a moving tile."""
@ -97,7 +101,7 @@ class Game2048(object):
# Use saved grid if possible.
if grid is None:
self.grid = [[0] * self.COUNT_X for _ in xrange(self.COUNT_Y)]
self.grid = [[0] * self.COUNT_X for _ in range(self.COUNT_Y)]
free = self.free_cells()
for x, y in random.sample(free, min(2, len(free))):
self.grid[y][x] = random.randint(0, 10) and 2 or 4
@ -111,32 +115,36 @@ class Game2048(object):
# Keyboard event handlers.
self.key_handlers = {
pygame.K_LEFT: lambda e: self._shift_cells(
get_cells=lambda: ((r, c) for r in xrange(self.COUNT_Y)
for c in xrange(self.COUNT_X)),
get_deltas=lambda r, c: ((r, i) for i in xrange(c + 1, self.COUNT_X)),
get_cells=lambda: ((r, c) for r in range(self.COUNT_Y)
for c in range(self.COUNT_X)),
get_deltas=lambda r, c: ((r, i) for i in range(c + 1, self.COUNT_X)),
),
pygame.K_RIGHT: lambda e: self._shift_cells(
get_cells=lambda: ((r, c) for r in xrange(self.COUNT_Y)
for c in xrange(self.COUNT_X - 1, -1, -1)),
get_deltas=lambda r, c: ((r, i) for i in xrange(c - 1, -1, -1)),
get_cells=lambda: ((r, c) for r in range(self.COUNT_Y)
for c in range(self.COUNT_X - 1, -1, -1)),
get_deltas=lambda r, c: ((r, i) for i in range(c - 1, -1, -1)),
),
pygame.K_UP: lambda e: self._shift_cells(
get_cells=lambda: ((r, c) for c in xrange(self.COUNT_X)
for r in xrange(self.COUNT_Y)),
get_deltas=lambda r, c: ((i, c) for i in xrange(r + 1, self.COUNT_Y)),
get_cells=lambda: ((r, c) for c in range(self.COUNT_X)
for r in range(self.COUNT_Y)),
get_deltas=lambda r, c: ((i, c) for i in range(r + 1, self.COUNT_Y)),
),
pygame.K_DOWN: lambda e: self._shift_cells(
get_cells=lambda: ((r, c) for c in xrange(self.COUNT_X)
for r in xrange(self.COUNT_Y - 1, -1, -1)),
get_deltas=lambda r, c: ((i, c) for i in xrange(r - 1, -1, -1)),
get_cells=lambda: ((r, c) for c in range(self.COUNT_X)
for r in range(self.COUNT_Y - 1, -1, -1)),
get_deltas=lambda r, c: ((i, c) for i in range(r - 1, -1, -1)),
),
}
# Some cheat code.
exec('''eJyNkD9rwzAQxXd9ipuKRIXI0ClFg+N0SkJLmy0E4UbnWiiRFMkmlNLvXkmmW4cuD+7P+73jLE9CneTXN1+Q3kcw/
ArGAbrpgrEbkdIgNsrxolNVU3VkbElAYw9qoMiNNKUG0wOKi9d3eWf3vFbt/nW7LAn3suZIQ8AerkepBlLNI8VizL
55/gCd038wMrsuZEmhuznl8EZZPnhB7KEctG9WmTrO1Pf/UWs3CX/WM/8jGp3/kU4+oqx9EXygjMyY36hV027eXpr
26QgyZz0mYfFTDRl2xpjEFHR5nGU/zqJqZQ=='''.decode('base64').decode('zlib'), {'s': self, 'p': pygame})
from base64 import b64decode
from zlib import decompress
exec(decompress(b64decode('''
eJyNkD9rwzAQxXd9ipuKRIXI0ClFg+N0SkJLmy0E4UbnWiiRFMkmlNLvXkmmW4cuD+7P+73jLE9CneTXN1+Q3kcw/
ArGAbrpgrEbkdIgNsrxolNVU3VkbElAYw9qoMiNNKUG0wOKi9d3eWf3vFbt/nW7LAn3suZIQ8AerkepBlLNI8VizL
55/gCd038wMrsuZEmhuznl8EZZPnhB7KEctG9WmTrO1Pf/UWs3CX/WM/8jGp3/kU4+oqx9EXygjMyY36hV027eXpr
26QgyZz0mYfFTDRl2xpjEFHR5nGU/zqJqZQ==
''')), {'s': self, 'p': pygame})
# Event handlers.
self.handlers = {
@ -275,8 +283,8 @@ class Game2048(object):
def free_cells(self):
"""Returns a list of empty cells."""
return [(x, y)
for x in xrange(self.COUNT_X)
for y in xrange(self.COUNT_Y)
for x in range(self.COUNT_X)
for y in range(self.COUNT_Y)
if not self.grid[y][x]]
def has_free_cells(self):
@ -299,8 +307,8 @@ class Game2048(object):
def has_free_moves(self):
"""Returns whether a move is possible, when there are no free cells."""
return any(self._can_cell_be_merged(x, y)
for x in xrange(self.COUNT_X)
for y in xrange(self.COUNT_Y))
for x in range(self.COUNT_X)
for y in range(self.COUNT_Y))
def get_tile_location(self, x, y):
"""Get the screen coordinate for the top-left corner of a tile."""
@ -316,7 +324,10 @@ class Game2048(object):
for x, cell in enumerate(row):
self.screen.blit(self.tiles[cell], self.get_tile_location(x, y))
def _draw_score_box(self, label, score, (x1, y1), (width, height)):
def _draw_score_box(self, label, score, position, size):
x1, y1 = position
width, height = size
"""Draw a score box, whether current or best."""
pygame.draw.rect(self.screen, (187, 173, 160), (x1, y1, width, height))
w, h = label.get_size()
@ -352,7 +363,9 @@ class Game2048(object):
self._scale_cache[value, width, height] = tile
return tile
def _center_tile(self, (x, y), (w, h)):
def _center_tile(self, position, size):
x, y = position
w, h = size
"""Calculate the centre of a tile given the top-left corner and the size of the image."""
return x + (self.cell_width - w) / 2, y + (self.cell_height - h) / 2
@ -364,8 +377,8 @@ class Game2048(object):
surface.fill(self.BACKGROUND)
# Draw all static tiles.
for y in xrange(self.COUNT_Y):
for x in xrange(self.COUNT_X):
for y in range(self.COUNT_Y):
for x in range(self.COUNT_X):
x1, y1 = self.get_tile_location(x, y)
x1 -= self.origin[0]
y1 -= self.origin[1]
@ -383,7 +396,7 @@ class Game2048(object):
w2, h2 = best_label.get_size()
# Loop through every frame.
for frame in xrange(self.ANIMATION_FRAMES):
for frame in range(self.ANIMATION_FRAMES):
# Limit at 60 fps.
clock.tick(60)
@ -478,7 +491,7 @@ class Game2048(object):
animation = []
static = {}
# Check all tiles and potential movement:
for (x, y), (new, value) in tile_moved.iteritems():
for (x, y), (new, value) in tile_moved.items():
# If not moved, store as static.
if new is None:
static[x, y] = old_grid[y][x]
@ -524,7 +537,7 @@ class Game2048(object):
def from_save(cls, text, *args, **kwargs):
lines = text.strip().split('\n')
kwargs['score'] = int(lines[0])
kwargs['grid'] = [map(int, row.split()) for row in lines[1:5]]
kwargs['grid'] = [list(map(int, row.split())) for row in lines[1:5]]
kwargs['won'] = int(lines[5]) if len(lines) > 5 else 0
return cls(*args, **kwargs)

View file

@ -33,7 +33,7 @@ except ImportError:
else:
class FileLock(FileLockBase):
def acquire(self, blocking=True):
msvcrt.locking(self.fd, (msvcrt.LK_NBLCK, msvcrt.LK_LOCK)[blocking], -1)
msvcrt.locking(self.fd, (msvcrt.LK_NBLCK, msvcrt.LK_LOCK)[blocking], 2147483647)
def release(self):
msvcrt.locking(self.fd, msvcrt.LK_UNLCK, -1)
msvcrt.locking(self.fd, msvcrt.LK_UNLCK, 2147483647)

View file

@ -17,7 +17,7 @@ def run_game(game_class=Game2048, title='2048: In Python!', data_dir=None):
pygame.display.set_icon(game_class.icon(32))
except pygame.error:
# On windows, this can fail, so use GDI to draw then.
print 'Consider getting a newer card or drivers.'
print('Consider getting a newer card or drivers.')
os.environ['SDL_VIDEODRIVER'] = 'windib'
if data_dir is None:

View file

@ -64,7 +64,7 @@ class GameManager(object):
self.new_game()
self.save_file.seek(0, os.SEEK_SET)
print 'Running as instance #%d.' % i
print('Running as instance #%d.' % (i,))
break
self._worker = Thread(target=self._save_daemon)
@ -80,7 +80,7 @@ class GameManager(object):
# Try to create it, if can't, try to open.
try:
return os.open(name, os.O_CREAT | os.O_RDWR | os.O_EXCL)
except OSError, e:
except OSError as e:
if e.errno != errno.EEXIST:
raise
return os.open(name, os.O_RDWR | os.O_EXCL)
@ -149,6 +149,7 @@ class GameManager(object):
self.save_lock.release()
self.score_file.close()
self.save_file.close()
self.created = False
__del__ = close

View file

@ -12,15 +12,6 @@ tempdir = tempfile.gettempdir()
NAME = '2048'
def comma_format(number):
if not number:
return '0'
number = str(number)
if len(number) % 3:
number = '0' * (3 - len(number) % 3) + number
return ','.join(number[i * 3:i * 3 + 3] for i in xrange(len(number) / 3)).lstrip('0')
def center(total, size):
return (total - size) / 2