class Game(db.Model): __tablename__ = 'games' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.Text, unique=True, nullable=False, index=True) board = db.relationship( 'Board', uselist=False, back_populates='game', ) @classmethod def create(cls, name, board_size=DEFAULT_GRID_SIZE): self = cls(name=name) with db.session.begin_nested(): db.session.add(self) Board.create(game=self, size=board_size) return self
class Unit(db.Model): __tablename__ = 'units' id = db.Column(db.Integer, primary_key=True) unit_type_id = db.Column(db.Integer, db.ForeignKey('unit_types.id')) health = db.Column(db.Integer) strength = db.Column(db.Integer) range = db.Column(db.Integer) speed = db.Column(db.Integer) is_alive = db.Column(db.Boolean)
class UnitType(db.Model): __tablename__ = 'unit_types' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.Text, index=True) initial_health = db.Column(db.Integer) initial_strength = db.Column(db.Integer) initial_range = db.Column(db.Integer) initial_speed = db.Column(db.Integer)
class Board(db.Model): __tablename__ = 'boards' id = db.Column(db.Integer, primary_key=True) size = db.Column(db.Integer, nullable=False) game_id = db.Column( db.Integer, db.ForeignKey('games.id'), index=True, nullable=False, ) game = db.relationship( 'Game', back_populates='board', ) tiles = db.relationship( 'Tile', back_populates='board', ) @classmethod def create(cls, game, size=DEFAULT_GRID_SIZE): self = cls( game=game, size=size, ) with db.session.begin_nested(): db.session.add(self) for coords in self.grid: Tile.create(self, coords) return self @property def grid(self): if not hasattr(self, '_grid'): self._grid = HexGrid(size=self.size) return self._grid def tile(self, coords): coords = Coords(*coords) HexError.require_condition( self.grid.contains(coords), "coords are not within grid: {}", coords, ) tile = Tile.query.filter_by( board=self, a=coords.a, b=coords.b ).one_or_none() HexError.require_condition( tile is not None, "No tile is defined at those coords (should not happen): {}", coords, ) return tile def __iter__(self): for coords in self.grid: yield self.tile(coords)
class Tile(db.Model): __tablename__ = 'tiles' id = db.Column(db.Integer, primary_key=True) board_id = db.Column( db.Integer, db.ForeignKey('boards.id'), index=True, nullable=False, ) # Look into custom types coords = db.Column(db.ARRAY(db.Integer), index=True) # Terrain, units, etc... current_unit_id = db.Column( db.Integer, db.ForeignKey('units.id'), ) current_terrain_id = db.Column( db.Integer, db.ForeignKey('units.id'), ) board = db.relationship('Board', back_populates='tiles') @hybrid_property def a(self): return self.coords[0] @a.expression def a(cls): """ This is necessary because postgres uses 1-based indexing for arrays """ return Tile.coords[1] @hybrid_property def b(self): return self.coords[1] @b.expression def b(cls): """ This is necessary because postgres uses 1-based indexing for arrays """ return Tile.coords[2] @classmethod def create(cls, board, coords): self = cls( board=board, coords=list(coords), ) with db.session.begin_nested(): db.session.add(self) return self def __repr__(self): return "{class_name} ({id})".format( class_name=self.__class__.__name__, id=self.id, ) def __str__(self): return textwrap.dedent(""" {}: board: {}, coords: {}, a: {}, b: {}, """.format( repr(self), self.board.id, self.coords, self.a, self.b, ))