def play(request): if request.is_ajax(): try: space = int(request.POST['id']) board = Board.objects.get(pk=request.POST['board_id'][6:]) except KeyError: return HttpResponse('Error') except Board.DoesNotExist: raise Http404("That game doesn't seem to exist") try: board.make_move(space, 'X') except UnallowedError: data = {"msg": "That's not allowed!"} else: data = {} # Check if X's move ended the game if not board.check_for_end()[0]: O_space = _AI_move_random(board) data = {"O": O_space} ending = board.check_for_end() board.save() # Check if O's move ended the game if ending[0]: data.update({ "msg": ending[1]+' wins!\nRefresh to play again.', "end": "true"}) board.delete() # return a response with the appropriate JSON data return HttpResponse( json.dumps(data), content_type="application/json") elif request.method == 'GET': # Create a new board and put it in the database new_board = Board() new_board.save() return render(request, 'game/game.html', {'board_id': new_board.pk})
class StandardBoard: data = [] rows = 11 columns = 16 cells = [] G, T, R = 'G','T', 'R' C = 'T*' default_board = (G, G, G, G, R, R, R, R, R, G, T, G, R, G, G, G, G, C, G, G, R, G, G, G, G, G, G, G, R, G, G, C, G, G, G, R, R, T, G, G, G, G, G, G, R, R, G, G, R, R, R, R, G, G, G, G, G, G, G, G, G, R, R, R, G, G, G, G, G, G, G, G, G, G, G, G, G, T, R, R, G, G, G, G, G, G, G, G, G, G, G, G, G, G, R, G, R, R, R, R, G, G, G, G, T, G, G, G, R, R, R, G, G, C, G, R, R, R, R, G, G, G, G, G, R, G, G, G, G, G, G, G, G, G, R, R, R, R, R, R, R, G, C, G, G, G, G, G, G, T, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, T, G, G, G, G, G,) default_board_string = '|'.join(default_board) def __init__(self, game, turn_no=0): self.board = None if turn_no: self.board = Board.objects.filter(game=game, turn_no=turn_no).get() if not self.board: # raise pass else: self.board = Board(game=game, turn_no=1, rows=self.rows, columns=self.columns, board=self.default_board_string) self._parse_state(self.board.board) def _db_form(self): return '|'.join([ cell.db_form() for cell in self.cells]) def _parse_state(self, board_str): def convert(cell_str): if cell_str.startswith('G'): if '!' in cell_str: return Ground(special=Catastrophe()) elif '?' in cell_str: g = Ground(special=Unification()) g.special.piece = cell_str[-1] return g # XXX # civ_type = cell_str[2] # if civ_type == 's': # return Ground(piece=SettlementCiv(), special=Unification()) # elif civ_type == 't': # return Ground(piece=TempleCiv(), special=Unification()) # elif civ_type == 'm': # return Ground(piece=MerchantCiv(), special=Unification()) else: return Ground() elif cell_str.startswith('R'): if '!' in cell_str: return River(special=Catastrophe()) elif '?' in cell_str: return River(piece=FarmCiv(), special=Unification()) else: return River() elif cell_str.startswith('s'): return Ground(piece=SettlementCiv()) elif cell_str.startswith('t'): return Ground(piece=TempleCiv()) elif cell_str.startswith('f'): return River(piece=FarmCiv()) elif cell_str.startswith('m'): return Ground(piece=MerchantCiv()) elif cell_str.startswith('T'): if cell_str.startswith('T*'): return Ground(piece=TempleCiv(treasure=Treasure(is_corner=True))) else: return Ground(piece=TempleCiv(treasure=Treasure(is_corner=False))) elif cell_str.startswith('r'): ruler_type = cell_str[2] ruler_player_no = cell_str[1] if ruler_type == 's': return Ground(piece=SettlementRuler(ruler_player_no)) elif ruler_type == 't': return Ground(piece=TempleRuler(ruler_player_no)) elif ruler_type == 'f': return Ground(piece=FarmRuler(ruler_player_no)) elif ruler_type == 'm': return Ground(piece=MerchantRuler(ruler_player_no)) elif cell_str.startswith('M'): pass self.cells = [ convert(x) for x in board_str.split('|')] self.data = [ {} for _ in self.cells ] # XXX todo: unit test this function def treasure_to_claim(self): for region in self.pieces_by_region: player = None for type, player_no, _ in region['rulers']: if type.split("-")[1] == 'merchant': player = player_no if len(region['treasures']['corner']) + len(region['treasures']['normal']) > 1 and player: treasure_info = { 'player_no': player, 'corner': region['treasures']['corner'], 'normal': region['treasures']['normal'], } treasure_info.update(self._analyze_treasure(treasure_info)) return treasure_info return {} # XXX todo: unit test this function def _analyze_treasure(self, treasure): num_corner = len(treasure['corner']) num_normal = len(treasure['normal']) num_claim = num_corner + num_normal - 1 must_choose, can_choose, num_choose = [], [], 0 if num_corner > 0: if num_corner == num_claim: must_choose = treasure['corner'] can_choose = [] num_choose = 0 elif num_corner < num_claim: must_choose = treasure['corner'] can_choose = treasure['normal'] num_choose = num_claim - num_corner elif num_corner > num_claim: must_choose = [] can_choose = treasure['corner'] num_choose = num_claim else: must_choose = [] can_choose = treasure['normal'] num_choose = num_claim return { 'must_choose': must_choose, 'can_choose': can_choose, 'num_choose': num_choose } def find_unification_tile(self): for cell_no, cell in enumerate(self.cells): if cell.special and ('?' in cell.special.db_form()): return cell_no return None def is_ruler_placed(self, ruler_type, player_no): for cell_no, cell in enumerate(self.cells): if cell.piece and (cell.piece.db_form() == 'r' + player_no + ruler_type[6]): return cell_no return None def get_cell_no_for_unification(self): for cell_no, cell in enumerate(self.cells): if cell.special and ('?' in cell.db_form()): return [cell_no] return [] def get_cell_no_for_civ(self, color): cell_nos = [] for cell_no, cell in enumerate(self.cells): if cell.piece and (cell.piece.db_form() == color): cell_nos.append(cell_no) return cell_nos def get_cell_no_for_player_no_and_ruler(self, player_no, color): player_no = int(player_no) for cell_no, cell in enumerate(self.cells): if cell.piece and (cell.piece.db_form()[-1] == color) and (cell.piece.db_form()[0] == 'r') and (int(cell.piece.player_no) == player_no): return cell_no return -1 def place_unification(self, cell_no, civ): self.cells[cell_no].special = Unification() # XXX self.cells[cell_no].special.piece = civ.css_class_name() def save(self): self.board.board = self._db_form() self.board.save() def __iter__(self): return self.cells.__iter__() def __len__(self): return self.cells.__len__() def __getitem__(self, x): return self.cells.__getitem__(x) def __setitem__(self, x, y): return self.cells.__setitem__(x, y) def get_point(self, cell_no, civ): try: region = self.data[cell_no]['adjacent_kingdoms'][0] except IndexError: return None for name, player_no, _ in self.pieces_by_region[region]['rulers']: if name == 'ruler-' + civ.css_class_name(): return player_no for name, player_no, _ in self.pieces_by_region[region]['rulers']: if name == 'ruler-settlement': return player_no return None def add_ruler(self, cell_no, ruler, player_no): piece = _convert_ruler(ruler, player_no) self.cells[cell_no].piece = piece def remove_ruler(self, cell_no): self[cell_no].piece = None def add_civ(self, cell_no, civ): self.cells[cell_no].piece = civ def external_war_removal(self, region, civ): count = 0 for type, _, cell_no in self.pieces_by_region[region]['rulers']: if type.split("-")[1] == civ: self[cell_no].piece = None count += 1 for cell_no in self.pieces_by_region[region][civ]: mark = [] def assign_mark(index): mark.append(index) # XXX Check for treasure, too if civ == 'temple': pred = lambda index: self[index].has_ruler() do_on_adjacent_cells(cell_no, self, pred, assign_mark) if not mark: self[cell_no].piece = None count += 1 return count