# -*- coding: utf-8 -*-
#
# @author acvcla@gmail.com

import random
import sys


class GameMap(object):
    
    MAX_MAP_SIZE = 100

    def __init__(self, rows, cols):
        """Inits GameMap with row and column count."""
        assert isinstance(rows, int)
        assert isinstance(cols, int)
        assert 0 < rows <= self.MAX_MAP_SIZE
        assert 0 < cols <= self.MAX_MAP_SIZE
        self.size = (rows, cols, )
        self.cells = [[0 for col in range(cols)] for row in range(rows)]

    @property
    def rows(self):
        return self.size[0]

    @property
    def cols(self):
        return self.size[1]

    def reset(self, possibility=0.5):
        """Reset the map with random data.

        Args:
            possibility: possibility of life cell
        """
        for row in range(self.rows):
            for col in range(self.cols):
                self.cells[row][col] = (random.random() <= possibility)

    def set(self, row, col, val):
        """Set specific cell in the map."""
        self.cells[row][col] = val

    def get_neighbor_count(self, row, col):
        """Get count of neighbors in specific cell.

        Args:
            row: row number
            col: column number

        Returns:
            Count of live neighbor cells
        """
        #两个方向的增量,便于枚举四周的格子
        dx = [-1,-1,-1,0,0,1,1,1]
        dy = [-1,0,1,-1,1,-1,0,1]
        cnt = 0
        for i in range(len(dx)):
            next_row = (row + dx[i]) % self.rows
            next_col = (col + dy[i]) % self.cols
            cnt += self.cells[next_row][next_col] #把四周活着的格子个数累加
        return cnt

    def get_neighbor_count_map(self):
        """Get count of neighbors of every cell in the map.

        Returns:
            A grid contains every cell's neighbor count.
        """
        return [[self.get_neighbor_count(row, col) for col in range(self.cols)] for row in range(self.rows)]

    def print_map(self, cell_maps=None, sep=' ', fd=sys.stdout):
        """Print the map to target file descriptor

        Args:
            cell_maps: mapping from cell value to a string that will be displayed.
            sep: separator between cells of the same row.
            fd: file descriptor, default standard output
        """
        if not cell_maps:
            cell_maps = ['0', '1']
        assert isinstance(cell_maps, list) or isinstance(cell_maps, dict)
        assert isinstance(sep, str)
        for row in self.cells:
            print(sep.join(map(lambda cell: cell_maps[cell], row)), file=fd)
