summaryrefslogtreecommitdiff
path: root/examples/space_invaders/space_invaders.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2019-01-06 01:14:26 -0500
committermike bayer <mike_mp@zzzcomputing.com>2019-01-06 17:34:50 +0000
commit1e1a38e7801f410f244e4bbb44ec795ae152e04e (patch)
tree28e725c5c8188bd0cfd133d1e268dbca9b524978 /examples/space_invaders/space_invaders.py
parent404e69426b05a82d905cbb3ad33adafccddb00dd (diff)
downloadsqlalchemy-1e1a38e7801f410f244e4bbb44ec795ae152e04e.tar.gz
Run black -l 79 against all source files
This is a straight reformat run using black as is, with no edits applied at all. The black run will format code consistently, however in some cases that are prevalent in SQLAlchemy code it produces too-long lines. The too-long lines will be resolved in the following commit that will resolve all remaining flake8 issues including shadowed builtins, long lines, import order, unused imports, duplicate imports, and docstring issues. Change-Id: I7eda77fed3d8e73df84b3651fd6cfcfe858d4dc9
Diffstat (limited to 'examples/space_invaders/space_invaders.py')
-rw-r--r--examples/space_invaders/space_invaders.py278
1 files changed, 154 insertions, 124 deletions
diff --git a/examples/space_invaders/space_invaders.py b/examples/space_invaders/space_invaders.py
index 3ce280aec..d5437d8cf 100644
--- a/examples/space_invaders/space_invaders.py
+++ b/examples/space_invaders/space_invaders.py
@@ -1,7 +1,6 @@
import sys
from sqlalchemy.ext.declarative import declarative_base
-from sqlalchemy import create_engine, Integer, Column, ForeignKey, \
- String, func
+from sqlalchemy import create_engine, Integer, Column, ForeignKey, String, func
from sqlalchemy.orm import relationship, Session, joinedload
from sqlalchemy.ext.hybrid import hybrid_property, hybrid_method
import curses
@@ -18,7 +17,7 @@ if _PY3:
logging.basicConfig(
filename="space_invaders.log",
- format="%(asctime)s,%(msecs)03d %(levelname)-5.5s %(message)s"
+ format="%(asctime)s,%(msecs)03d %(levelname)-5.5s %(message)s",
)
logging.getLogger("sqlalchemy.engine").setLevel(logging.INFO)
@@ -47,7 +46,7 @@ COLOR_MAP = {
"M": curses.COLOR_MAGENTA,
"R": curses.COLOR_RED,
"W": curses.COLOR_WHITE,
- "Y": curses.COLOR_YELLOW
+ "Y": curses.COLOR_YELLOW,
}
@@ -56,7 +55,8 @@ class Glyph(Base):
to be painted on the screen.
"""
- __tablename__ = 'glyph'
+
+ __tablename__ = "glyph"
id = Column(Integer, primary_key=True)
name = Column(String)
type = Column(String)
@@ -68,11 +68,9 @@ class Glyph(Base):
def __init__(self, name, img, alt=None):
self.name = name
- self.data, self.width, self.height = \
- self._encode_glyph(img)
+ self.data, self.width, self.height = self._encode_glyph(img)
if alt is not None:
- self.alt_data, alt_w, alt_h = \
- self._encode_glyph(alt)
+ self.alt_data, alt_w, alt_h = self._encode_glyph(alt)
def _encode_glyph(self, img):
"""Receive a textual description of the glyph and
@@ -80,7 +78,7 @@ class Glyph(Base):
GlyphCoordinate.render().
"""
- img = re.sub(r'^\n', "", textwrap.dedent(img))
+ img = re.sub(r"^\n", "", textwrap.dedent(img))
color = "W"
lines = [line.rstrip() for line in img.split("\n")]
data = []
@@ -89,15 +87,15 @@ class Glyph(Base):
line = list(line)
while line:
char = line.pop(0)
- if char == '#':
+ if char == "#":
color = line.pop(0)
continue
render_line.append((color, char))
data.append(render_line)
width = max([len(rl) for rl in data])
data = "".join(
- "".join("%s%s" % (color, char) for color, char in render_line) +
- ("W " * (width - len(render_line)))
+ "".join("%s%s" % (color, char) for color, char in render_line)
+ + ("W " * (width - len(render_line)))
for render_line in data
)
return data, width, len(lines)
@@ -121,9 +119,10 @@ class GlyphCoordinate(Base):
score value.
"""
- __tablename__ = 'glyph_coordinate'
+
+ __tablename__ = "glyph_coordinate"
id = Column(Integer, primary_key=True)
- glyph_id = Column(Integer, ForeignKey('glyph.id'))
+ glyph_id = Column(Integer, ForeignKey("glyph.id"))
x = Column(Integer)
y = Column(Integer)
tick = Column(Integer)
@@ -132,11 +131,9 @@ class GlyphCoordinate(Base):
glyph = relationship(Glyph, innerjoin=True)
def __init__(
- self,
- session, glyph_name, x, y,
- tick=None, label=None, score=None):
- self.glyph = session.query(Glyph).\
- filter_by(name=glyph_name).one()
+ self, session, glyph_name, x, y, tick=None, label=None, score=None
+ ):
+ self.glyph = session.query(Glyph).filter_by(name=glyph_name).one()
self.x = x
self.y = y
self.tick = tick
@@ -152,8 +149,7 @@ class GlyphCoordinate(Base):
glyph = self.glyph
data = glyph.glyph_for_state(self, state)
for color, char in [
- (data[i], data[i + 1])
- for i in xrange(0, len(data), 2)
+ (data[i], data[i + 1]) for i in xrange(0, len(data), 2)
]:
x = self.x + col
@@ -163,7 +159,8 @@ class GlyphCoordinate(Base):
y + VERT_PADDING,
x + HORIZ_PADDING,
char,
- _COLOR_PAIRS[color])
+ _COLOR_PAIRS[color],
+ )
col += 1
if col == glyph.width:
col = 0
@@ -186,10 +183,7 @@ class GlyphCoordinate(Base):
width = min(glyph.width, MAX_X - x) or 1
for y_a in xrange(self.y, self.y + glyph.height):
y = y_a
- window.addstr(
- y + VERT_PADDING,
- x + HORIZ_PADDING,
- " " * width)
+ window.addstr(y + VERT_PADDING, x + HORIZ_PADDING, " " * width)
if self.label:
self._render_label(window, True)
@@ -236,21 +230,22 @@ class GlyphCoordinate(Base):
the given GlyphCoordinate."""
return ~(
- (self.x + self.width < other.x) |
- (self.x > other.x + other.width)
+ (self.x + self.width < other.x) | (self.x > other.x + other.width)
) & ~(
- (self.y + self.height < other.y) |
- (self.y > other.y + other.height)
+ (self.y + self.height < other.y)
+ | (self.y > other.y + other.height)
)
class EnemyGlyph(Glyph):
"""Describe an enemy."""
+
__mapper_args__ = {"polymorphic_identity": "enemy"}
class ArmyGlyph(EnemyGlyph):
"""Describe an enemy that's part of the "army". """
+
__mapper_args__ = {"polymorphic_identity": "army"}
def glyph_for_state(self, coord, state):
@@ -262,6 +257,7 @@ class ArmyGlyph(EnemyGlyph):
class SaucerGlyph(EnemyGlyph):
"""Describe the enemy saucer flying overhead."""
+
__mapper_args__ = {"polymorphic_identity": "saucer"}
def glyph_for_state(self, coord, state):
@@ -273,21 +269,25 @@ class SaucerGlyph(EnemyGlyph):
class MessageGlyph(Glyph):
"""Describe a glyph for displaying a message."""
+
__mapper_args__ = {"polymorphic_identity": "message"}
class PlayerGlyph(Glyph):
"""Describe a glyph representing the player."""
+
__mapper_args__ = {"polymorphic_identity": "player"}
class MissileGlyph(Glyph):
"""Describe a glyph representing a missile."""
+
__mapper_args__ = {"polymorphic_identity": "missile"}
class SplatGlyph(Glyph):
"""Describe a glyph representing a "splat"."""
+
__mapper_args__ = {"polymorphic_identity": "splat"}
def glyph_for_state(self, coord, state):
@@ -302,36 +302,39 @@ def init_glyph(session):
"""Create the glyphs used during play."""
enemy1 = ArmyGlyph(
- "enemy1", """
+ "enemy1",
+ """
#W-#B^#R-#B^#W-
#G| |
""",
"""
#W>#B^#R-#B^#W<
#G^ ^
- """
+ """,
)
enemy2 = ArmyGlyph(
- "enemy2", """
+ "enemy2",
+ """
#W***
#R<#C~~~#R>
""",
"""
#W@@@
#R<#C---#R>
- """
+ """,
)
enemy3 = ArmyGlyph(
- "enemy3", """
+ "enemy3",
+ """
#Y((--))
#M-~-~-~
""",
"""
#Y[[--]]
#M~-~-~-
- """
+ """,
)
saucer = SaucerGlyph(
@@ -351,35 +354,49 @@ def init_glyph(session):
#M|
#M- #Y+++ #M-
#M|
- """
+ """,
)
- ship = PlayerGlyph("ship", """
+ ship = PlayerGlyph(
+ "ship",
+ """
#Y^
#G=====
- """)
+ """,
+ )
- missile = MissileGlyph("missile", """
+ missile = MissileGlyph(
+ "missile",
+ """
|
- """)
+ """,
+ )
start = MessageGlyph(
"start_message",
"J = move left; L = move right; SPACE = fire\n"
- " #GPress any key to start")
- lose = MessageGlyph("lose_message",
- "#YY O U L O S E ! ! !")
- win = MessageGlyph(
- "win_message",
- "#RL E V E L C L E A R E D ! ! !"
+ " #GPress any key to start",
)
+ lose = MessageGlyph("lose_message", "#YY O U L O S E ! ! !")
+ win = MessageGlyph("win_message", "#RL E V E L C L E A R E D ! ! !")
paused = MessageGlyph(
- "pause_message",
- "#WP A U S E D\n#GPress P to continue")
+ "pause_message", "#WP A U S E D\n#GPress P to continue"
+ )
session.add_all(
- [enemy1, enemy2, enemy3, ship, saucer,
- missile, start, lose, win,
- paused, splat1])
+ [
+ enemy1,
+ enemy2,
+ enemy3,
+ ship,
+ saucer,
+ missile,
+ start,
+ lose,
+ win,
+ paused,
+ splat1,
+ ]
+ )
def setup_curses():
@@ -392,7 +409,8 @@ def setup_curses():
WINDOW_HEIGHT + (VERT_PADDING * 2),
WINDOW_WIDTH + (HORIZ_PADDING * 2),
WINDOW_TOP - VERT_PADDING,
- WINDOW_LEFT - HORIZ_PADDING)
+ WINDOW_LEFT - HORIZ_PADDING,
+ )
curses.start_color()
global _COLOR_PAIRS
@@ -416,24 +434,25 @@ def init_positions(session):
session.add(
GlyphCoordinate(
- session, "ship",
- WINDOW_WIDTH // 2 - 2,
- WINDOW_HEIGHT - 4)
+ session, "ship", WINDOW_WIDTH // 2 - 2, WINDOW_HEIGHT - 4
+ )
)
arrangement = (
- ("enemy3", 50), ("enemy2", 25),
- ("enemy1", 10), ("enemy2", 25),
- ("enemy1", 10))
+ ("enemy3", 50),
+ ("enemy2", 25),
+ ("enemy1", 10),
+ ("enemy2", 25),
+ ("enemy1", 10),
+ )
for (ship_vert, (etype, score)) in zip(
- xrange(5, 30, ENEMY_VERT_SPACING), arrangement):
+ xrange(5, 30, ENEMY_VERT_SPACING), arrangement
+ ):
for ship_horiz in xrange(0, 50, 10):
session.add(
GlyphCoordinate(
- session, etype,
- ship_horiz,
- ship_vert,
- score=score)
+ session, etype, ship_horiz, ship_vert, score=score
+ )
)
@@ -442,12 +461,9 @@ def draw(session, window, state):
database and render.
"""
- for gcoord in session.query(GlyphCoordinate).\
- options(joinedload("glyph")):
+ for gcoord in session.query(GlyphCoordinate).options(joinedload("glyph")):
gcoord.render(window, state)
- window.addstr(
- 1, WINDOW_WIDTH - 5,
- "Score: %.4d" % state['score'])
+ window.addstr(1, WINDOW_WIDTH - 5, "Score: %.4d" % state["score"])
window.move(0, 0)
window.refresh()
@@ -456,11 +472,11 @@ def check_win(session, state):
"""Return the number of army glyphs remaining -
the player wins if this is zero."""
- return session.query(
- func.count(GlyphCoordinate.id)
- ).join(
- GlyphCoordinate.glyph.of_type(ArmyGlyph)
- ).scalar()
+ return (
+ session.query(func.count(GlyphCoordinate.id))
+ .join(GlyphCoordinate.glyph.of_type(ArmyGlyph))
+ .scalar()
+ )
def check_lose(session, state):
@@ -470,12 +486,14 @@ def check_lose(session, state):
The player loses if this is non-zero."""
player = state["player"]
- return session.query(GlyphCoordinate).join(
- GlyphCoordinate.glyph.of_type(ArmyGlyph)
- ).filter(
- GlyphCoordinate.intersects(player) |
- GlyphCoordinate.bottom_bound
- ).count()
+ return (
+ session.query(GlyphCoordinate)
+ .join(GlyphCoordinate.glyph.of_type(ArmyGlyph))
+ .filter(
+ GlyphCoordinate.intersects(player) | GlyphCoordinate.bottom_bound
+ )
+ .count()
+ )
def render_message(session, window, msg, x, y):
@@ -490,9 +508,11 @@ def render_message(session, window, msg, x, y):
msg = GlyphCoordinate(session, msg, x, y)
# clear existing glyphs which intersect
- for gly in session.query(GlyphCoordinate).join(
- GlyphCoordinate.glyph
- ).filter(GlyphCoordinate.intersects(msg)):
+ for gly in (
+ session.query(GlyphCoordinate)
+ .join(GlyphCoordinate.glyph)
+ .filter(GlyphCoordinate.intersects(msg))
+ ):
gly.blank(window)
# render
@@ -551,12 +571,14 @@ def move_army(session, window, state):
# get the lower/upper boundaries of the army
# along the X axis.
- min_x, max_x = session.query(
- func.min(GlyphCoordinate.x),
- func.max(GlyphCoordinate.x + GlyphCoordinate.width),
- ).join(
- GlyphCoordinate.glyph.of_type(ArmyGlyph)
- ).first()
+ min_x, max_x = (
+ session.query(
+ func.min(GlyphCoordinate.x),
+ func.max(GlyphCoordinate.x + GlyphCoordinate.width),
+ )
+ .join(GlyphCoordinate.glyph.of_type(ArmyGlyph))
+ .first()
+ )
if min_x is None or max_x is None:
# no enemies
@@ -603,27 +625,26 @@ def move_player(session, window, state):
player.x -= 1
elif ch == FIRE_KEY and state["missile"] is None:
state["missile"] = GlyphCoordinate(
- session,
- "missile",
- player.x + 3,
- player.y - 1)
+ session, "missile", player.x + 3, player.y - 1
+ )
def move_missile(session, window, state):
"""Update the status of the current missile, if any."""
- if state["missile"] is None or \
- state["tick"] % 2 != 0:
+ if state["missile"] is None or state["tick"] % 2 != 0:
return
missile = state["missile"]
# locate enemy glyphs which intersect with the
# missile's current position; i.e. a hit
- glyph = session.query(GlyphCoordinate).\
- join(GlyphCoordinate.glyph.of_type(EnemyGlyph)).\
- filter(GlyphCoordinate.intersects(missile)).\
- first()
+ glyph = (
+ session.query(GlyphCoordinate)
+ .join(GlyphCoordinate.glyph.of_type(EnemyGlyph))
+ .filter(GlyphCoordinate.intersects(missile))
+ .first()
+ )
missile.blank(window)
if glyph or missile.top_bound:
# missle is done
@@ -642,15 +663,13 @@ def move_saucer(session, window, state):
saucer_interval = 500
saucer_speed_interval = 4
- if state["saucer"] is None and \
- state["tick"] % saucer_interval != 0:
+ if state["saucer"] is None and state["tick"] % saucer_interval != 0:
return
if state["saucer"] is None:
state["saucer"] = saucer = GlyphCoordinate(
- session,
- "saucer", -6, 1,
- score=random.randrange(100, 600, 100))
+ session, "saucer", -6, 1, score=random.randrange(100, 600, 100)
+ )
elif state["tick"] % saucer_speed_interval == 0:
saucer = state["saucer"]
saucer.blank(window)
@@ -663,8 +682,9 @@ def move_saucer(session, window, state):
def update_splat(session, window, state):
"""Render splat animations."""
- for splat in session.query(GlyphCoordinate).\
- join(GlyphCoordinate.glyph.of_type(SplatGlyph)):
+ for splat in session.query(GlyphCoordinate).join(
+ GlyphCoordinate.glyph.of_type(SplatGlyph)
+ ):
age = state["tick"] - splat.tick
if age > 10:
splat.blank(window)
@@ -683,8 +703,13 @@ def score(session, window, state, glyph):
state["score"] += glyph.score
# render a splat !
GlyphCoordinate(
- session, "splat1", glyph.x, glyph.y,
- tick=state["tick"], label=str(glyph.score))
+ session,
+ "splat1",
+ glyph.x,
+ glyph.y,
+ tick=state["tick"],
+ label=str(glyph.score),
+ )
def update_state(session, window, state):
@@ -713,19 +738,23 @@ def start(session, window, state, continue_=False):
init_positions(session)
- player = session.query(GlyphCoordinate).join(
- GlyphCoordinate.glyph.of_type(PlayerGlyph)
- ).one()
- state.update({
- "field_pos": 0,
- "alt": False,
- "tick": 0,
- "missile": None,
- "saucer": None,
- "player": player,
- "army_direction": 0,
- "flip": False
- })
+ player = (
+ session.query(GlyphCoordinate)
+ .join(GlyphCoordinate.glyph.of_type(PlayerGlyph))
+ .one()
+ )
+ state.update(
+ {
+ "field_pos": 0,
+ "alt": False,
+ "tick": 0,
+ "missile": None,
+ "saucer": None,
+ "player": player,
+ "army_direction": 0,
+ "flip": False,
+ }
+ )
if not continue_:
state["score"] = 0
@@ -748,7 +777,8 @@ def main():
while True:
update_state(session, window, state)
draw(session, window, state)
- time.sleep(.01)
+ time.sleep(0.01)
+
-if __name__ == '__main__':
+if __name__ == "__main__":
main()