Start reworking the engine

This commit is contained in:
Gergely Polonkai 2015-10-30 16:36:06 +01:00
parent daee3c1851
commit 9bdd26eb3b

View File

@ -7,154 +7,109 @@ class FieldType(Enum):
water = 2 water = 2
ship = 3 ship = 3
class ShipOrientation(Enum):
unknown = 0
none = 1
north = 2
south = 3
east = 4
west = 5
both = 6
class Field(object): class Field(object):
def __init__(self, fieldtype, fixed=False): def __init__(self):
if not isinstance(fieldtype, FieldType): self.__fixed = False
raise AttributeError("fieldtype must be a FieldType instance") self.__type = FieldType.empty
self.__marked_type = FieldType.empty
self.fixed = fixed self.__orientation = ShipOrientation.none
self.hidden_type = fieldtype
self.player_type = fieldtype if fixed else FieldType.empty
def is_ship(self, from_fixed=False):
return ((self.fixed or from_fixed) \
and self.hidden_type == FieldType.ship) \
or self.player_type == FieldType.ship
def is_water(self, from_fixed=False):
return ((self.fixed or from_fixed) \
and self.hidden_type == FieldType.water) \
or self.player_type == FieldType.water
@property @property
def marked_type(self): def marked_type(self):
return self.hidden_type if self.fixed else self.player_type return self.__type if self.__fixed else self.__marked_type
def __repr__(self): def set_fixed(self, typ=None, orientation=ShipOrientation.unknown):
return '<{} field>'.format(self.hidden_type.name) self.__fixed = True
if typ is not None:
self.__type = typ
self.__marked_type = typ
self.__orientation = orientation
def __str__(self):
typ = self.__type if self.__fixed else self.__marked_type
if typ == FieldType.empty:
return ' '
elif typ == FieldType.water:
return '~~'
elif typ == FieldType.ship:
if self.__orientation == ShipOrientation.unknown:
return '??'
elif self.__orientation == ShipOrientation.none:
return '<>'
elif self.__orientation == ShipOrientation.north:
return '^^'
elif self.__orientation == ShipOrientation.south:
return 'vv'
elif self.__orientation == ShipOrientation.west:
return ' <'
elif self.__orientation == ShipOrientation.east:
return '> '
elif self.__orientation == ShipOrientation.both:
return 'XX'
def set_type(self, typ, orientation=ShipOrientation.unknown):
self.__type = typ
self.__orientation = orientation
class Table(object): class Table(object):
def __init__(self, width, height): def __init__(self, width, height):
self.__fields = [] self.__fields = []
self.width = width self.__width = width
self.height = height self.__height = height
self.__col_counts = []
self.__row_counts = []
self.__ships = []
for x in range(1, width + 1): for count in range(0, height):
self.__fields.append([]) self.__fields.append([])
self.__row_counts.append(0)
for y in range(1, height + 1): for count in range(0, width):
self.__fields[x - 1].append(Field(FieldType.water)) self.__col_counts.append(0)
def __border_row(self): for row in range(0, height):
ret = Back.WHITE + Fore.BLACK + '+' self.__fields[row].append(Field())
for i in range(0, self.width): self.clean()
ret += '--+'
ret += " \n" + Style.RESET_ALL @property
def width(self):
return self.__width
return ret @property
def height(self):
return self.__height
def field(self, row, col): def __check_height(self, row):
if row < 0 \ if row not in range(0, self.__height):
or row >= self.height \ raise IndexError("Invalid row number")
or col < 0 \
or col >= self.width:
return None
return self.__fields[row][col] def __check_width(self, col):
if col not in range(0, self.__width):
raise IndexError("Invalid column number")
def col_ship_count(self, col): def row(self, row):
return len([r[col] for r in self.__fields \ self.__check_height(row)
if r[col].hidden_type == FieldType.ship])
def row_ship_count(self, row): # TODO: This doesnt feel right
return len([r for r in self.__fields[row] \ return self.__fields[row]
if r.hidden_type == FieldType.ship])
def __neighbours(self, row, col): def col(self, col):
return ( self.__check_width(col)
self.field(row - 2, col -1),
self.field(row - 1, col),
self.field(row, col - 1),
self.field(row - 1, col - 2)
)
def __str__(self): # TODO: This doesnt feel right
ret = self.__border_row() return [f[col] for f in f.__fields]
for row in range(0, self.height):
ret += Back.WHITE + Fore.BLACK + '|'
for col in range(0, self.width):
field = self.__fields[row][col]
typ = field.hidden_type if field.fixed else field.player_type
if typ == FieldType.empty:
ret += Back.WHITE + ' '
elif typ == FieldType.water:
ret += Back.CYAN + Fore.BLUE + '~~'
elif typ == FieldType.ship:
# Check neighbours
# upper, right, lower, left
neighbours = self.__neighbours(row + 1, col + 1)
all_waters = True
for n in neighbours:
all_waters = all_waters and \
(n is None \
or n.is_water(from_fixed=field.fixed))
neighs = [False if n is None \
else n.is_ship(from_fixed=field.fixed) \
for n in neighbours]
ret += Back.CYAN
# Ship above and below or left and right
if (neighs[0] and neighs[2]) \
or (neighs[1] and neighs[3]):
ret += Fore.RED + 'XX'
elif neighs[0]: # Ship above, not below
ret += Fore.RED + 'vv'
elif neighs[2]: # Ship below, not above
ret += Fore.RED + '^^'
elif neighs[1]: # Ship right, not left
ret += Fore.RED + ' <'
elif neighs[3]: # Ship on left, not right
ret += Fore.RED + '> '
elif all_waters:
ret += Fore.RED + 'oo'
else:
ret += Fore.BROWN + '??'
ret += Back.WHITE + Fore.BLACK + '|'
ret += " {:<3}\n".format(self.row_ship_count(row)) + Style.RESET_ALL
ret += self.__border_row()
ret += Back.WHITE + Fore.BLACK
for col in range(0, self.width):
ret += " {:<2}".format(self.col_ship_count(col))
ret += " \n" + Style.RESET_ALL
return ret
def add_ship(self, start_row, start_col, length, vertical):
row, col = start_row - 1, start_col - 1
for i in range(0, length):
self.__fields[row][col].hidden_type = FieldType.ship
if vertical:
row += 1
else:
col += 1
def clean(self): def clean(self):
for row in self.__fields: for row in self.__fields:
@ -163,8 +118,44 @@ class Table(object):
field.player_type = FieldType.empty field.player_type = FieldType.empty
field.fixed = False field.fixed = False
def __check_collision(self, parts):
pass
def add_ship(self, start_row, start_col, length, vertical):
row, col = start_row - 1, start_col - 1
parts = []
for i in range(0, length):
parts.append((row, col))
if vertical:
row += 1
else:
col += 1
count = 0
for row, col in parts:
count += 1
orientation = ShipOrientation.unknown
if length == 1:
orientation=ShipOrientation.none
else:
if count == 1:
orientation = ShipOrientation.north if vertical \
else ShipOrientation.west
elif count == length:
orientation = ShipOrientation.south if vertical \
else ShipOrientation.east
else:
orientation = ShipOrientation.both
self.__fields[row][col].set_type(FieldType.ship,
orientation=orientation)
def reveal(self, row, col): def reveal(self, row, col):
self.__fields[row - 1][col - 1].fixed = True self.__fields[row - 1][col - 1].set_fixed()
def reveal_all(self): def reveal_all(self):
for row in self.__fields: for row in self.__fields:
@ -185,7 +176,37 @@ class Table(object):
return True return True
def mark(self, row, col, typ): def mark(self, row, col, typ):
self.__fields[row][col].player_type = typ field = self.__field(row, col)
if field is not None:
field.player_type = typ
def is_ship(self, row, col):
return self.__fields[row][col].player_type == FieldType.ship
def __str__(self):
def divider():
ret = '+'
for i in range(0, self.__width):
ret += '--+'
ret += "\n"
return ret
ret = divider()
for row in self.__fields:
ret += '|'
for field in row:
ret += '{}|'.format(field)
ret += "\n"
ret += divider()
return ret
class Solver(object): class Solver(object):
def __init__(self, table): def __init__(self, table):
@ -194,9 +215,8 @@ class Solver(object):
def mark_edges(self): def mark_edges(self):
for row in range(0, self.table.height): for row in range(0, self.table.height):
for col in range(0, self.table.width): for col in range(0, self.table.width):
field = self.table.field(row, col) if self.table.is_ship(row, col):
print("MARK!")
if field.marked_type == FieldType.ship:
self.table.mark(row - 1, col - 1, FieldType.water) self.table.mark(row - 1, col - 1, FieldType.water)
self.table.mark(row - 1, col + 1, FieldType.water) self.table.mark(row - 1, col + 1, FieldType.water)
self.table.mark(row + 1, col - 1, FieldType.water) self.table.mark(row + 1, col - 1, FieldType.water)