コード例 #1
0
ファイル: movevalidator.py プロジェクト: terileptil/alexis
    def is_valid(self, move: Move):
        """ Validate a move.
        :param move: The move to be validated.
        :return: boolean True if move is valid, otherwise a MoveValidationError is raised
        giving the reason for the move being invalid.
        """
        if move.is_valid is not None:
            return move.is_valid

        move.is_valid = False

        if move.direction == Direction.NOT_APPLICABLE:  # we must be passing or swapping letters
            move.is_valid = True
            return True  # Player must have passed or exchanged

        num_tiles = len(move.tiles)
        start_index = move.start_index

        # check we are playing a sensible number of tiles:
        if num_tiles < 1 or num_tiles > RACK_SIZE:
            raise MoveValidationError('move has invalid number of tiles')

        # get row or column as appropriate (columns come back transposed to a row):
        row = move.row

        # check we're not on a sentinel square
        if start_index < 1 or start_index >= BOARD_SIZE:
            raise MoveValidationError("starting square is off the board")

        if not row.square_is_empty(start_index):
            raise MoveValidationError("starting square is not free")

        if len(move.played_squares) < num_tiles:
            raise MoveValidationError("not enough free spaces")

        if not self.has_valid_hook(row, move.played_squares):
            raise MoveValidationError(
                "word must join an existing word or start square")

        row.place_tiles(move.played_squares, move.tiles)

        if not self.crosswords_valid(row):
            row.remove_tiles(move.played_squares)
            raise MoveValidationError("invalid cross-word formed")

        word_formed = row.word_at(start_index)
        if word_formed not in self.lexicon:
            row.remove_tiles(move.played_squares)
            raise MoveValidationError("'" + word_formed +
                                      "'is not a valid word")

        move.calculate_score()
        move.is_valid = True

        return True
コード例 #2
0
ファイル: aiplayer.py プロジェクト: terileptil/alexis
    def play_on_square(self, row, index, played_tiles, rack: Rack):

        valid_moves = []

        # get all the letters we could play on this square without making nonsense in the corresponding column:
        valid_cross_plays = [chr(64 + x) for x in range(1, 27) if read_bit(row.this_row_crosschecks[index], x)]

        # filter that to ones we can actually use with tiles from our rack (all of them if we have a blank!)
        valid_tiles = valid_cross_plays if '@' in rack else [x for x in valid_cross_plays if x in rack]

        # for each of the playable tiles, stick it in the square
        for tile_letter in valid_tiles:
            tile = rack.get_tile(tile_letter)
            played_tiles[index] = tile
            row.existing_letters[index] = ord(tile)-64

            if row.word_at(index) in self.game.lexicon:
                new_move = Move(row, np.where(played_tiles)[0][0], [tile for tile in played_tiles if tile])
                new_move.played_squares = np.where(played_tiles)[0]
                new_move.calculate_score()
                #DEBUG:
                #print(self.name+": Considering move: "+str(new_move))
                valid_moves.append(new_move)

            if len(rack) > 0: # if we still have tiles left
                # try extending into the next square on the left, only if we've made a middle part of a real word:
                if self.game.lexicon.contains_infix(row.word_at(index)):
                    valid_moves.extend(self.extend_left(index, played_tiles, row, rack))
                # and if we've made the start of a word yet, try extending that to the right
                if self.game.lexicon.contains_prefix(row.word_at(index)):
                    valid_moves.extend(self.extend_right(index, played_tiles, row, rack))

            # return the tile to the rack
            rack.add_tile(tile)
            # set board square back to no letter
            row.existing_letters[index] = 0
            # remove tile from list of played tiles:
            played_tiles[index] = None

        return valid_moves