예제 #1
0
파일: field.py 프로젝트: saisai/pyquest
 def neighbour_locs(self, loc):
     """Return the list of neighbour locations of `tile`."""
     x, y = loc
     coords = (-1, 0, 1)
     locs = set(
         (x + n, y + m) for n in coords for m in coords) - set([(x, y)])
     return [Loc(*tup) for tup in locs if self.valid(Loc(*tup))]
예제 #2
0
파일: field.py 프로젝트: saisai/pyquest
    def find_shortest(self, origin, target, extra_vertices=None):
        """Find shortest path using given vertices and static level vertices."""
        nodes = defaultdict(dict)
        origin = getattr(origin, "loc", origin)
        target = getattr(target, "loc", target)

        # make a surrounding box (larger by 3 tiles in each direction than origin/target locations) as an
        # optimization to make dijkstra algorithm faster
        minx, maxx = min(origin.x, target.x), max(origin.x, target.x)
        miny, maxy = min(origin.y, target.y), max(origin.y, target.y)
        minx, maxx = max(0, minx - 3), min(xmax, maxx + 3)
        miny, maxy = max(0, miny - 3), min(ymax, maxy + 3)
        p1, p2 = Loc(minx, miny), Loc(maxx, maxy)

        # for dijkstra path alg, consider origin and destination as passable
        passable = lambda _loc: _loc in (origin, target) or not self.blocked(
            _loc)
        locs = [l for l in self if self.in_box((p1, p2), l)]
        locs = filter(passable, locs)

        for loc in locs:
            nlst = filter(passable, self.neighbour_locs(loc))
            for nloc in nlst:
                dist = 1 if (nloc.x == loc.x or nloc.y == loc.y) else 1.5
                nodes[loc][nloc] = dist

        # log("nodes", pformat(dict(nodes)))
        # find shortest path
        # log("origin", origin)
        # log("target", target)
        try:
            shortest = dijkstra.shortestPath(nodes, origin, target)
            return shortest[1:]
        except KeyError:
            # path is blocked completely
            return []

        return
        vertices = field.vertices + [origin, loc] + extra_vertices
        # make nodes dictionary for dijkstra function; dict is of format
        # {vertice1: {vertice2: distance}}
        for vertice in vertices:
            for vert2 in vertices:
                if vertice != vert2:
                    path = self.path(vertice, vert2)
                    if not self.blocked(path):
                        distance = self.distance(vertice, vert2)
                        if vertice in nodes:
                            nodes[vertice][vert2] = distance
                        else:
                            nodes[vertice] = {vert2: distance}
                        if vert2 in nodes:
                            nodes[vert2][vertice] = distance
                        else:
                            nodes[vert2] = {vertice: distance}
예제 #3
0
    def make_win_lines(self):
        lines, diag1, diag2 = [], [], []

        for n in range(3):
            lines.append([Loc(m, n) for m in range(3)])
            lines.append([Loc(n, m) for m in range(3)])
            diag1.append(Loc(n, n))
            diag2.append(Loc(2 - n, n))

        lines.extend((diag1, diag2))
        self.win_lines = lines
예제 #4
0
    def make_win_lines(self):
        """Create a list of winning lines -- when a player fills any one of them, he wins."""
        winlines, diag1, diag2 = [], [], []

        for n in range(size):
            winlines.append([Loc(m, n) for m in range(size)])
            winlines.append([Loc(n, m) for m in range(size)])

            diag1.append(Loc(n, n))
            diag2.append(Loc(size - n - 1, n))

        return winlines + [diag1, diag2]
예제 #5
0
    def __init__(self, size, def_tile, puzzle):
        super(SudokuBoard, self).__init__(size, def_tile)

        for tile, val in zip(self, puzzle):
            if val != blank:
                self[tile] = Initial(val)

        self.regions = [self.make_region(xo, yo) for xo in offsets for yo in offsets]

        lines = []
        for n in rng9:
            lines.extend(( [Loc(x, n) for x in rng9], [Loc(n, y) for y in rng9] ))
        self.lines = lines
예제 #6
0
파일: pyquest.py 프로젝트: saisai/pyquest
    def init_level(self):
        field.load_map("empty")
        level.populate()

        # make hero's party
        level.hero = Being('party', field.random(), level.last_index)
        level.last_index += 1
        level.hero.place()
        level.hoplite = Being("hoplite", Loc(1, 1), level.last_index)
        level.last_index += 1
        level.fencer = Being("fencer", Loc(1, 2), level.last_index)
        level.last_index += 1
        level.mage = Being("mage", Loc(1, 3), level.last_index)
        level.last_index += 1

        field.full_display([level.hero])
예제 #7
0
파일: being.py 프로젝트: saisai/pyquest
 def attack_hero(self, target=None):
     """Attack hero by autopilot."""
     if self.hostile:
         target = target or level.hero
         self.attack_hero_flag = True
         path = self.fullpath(target.loc)
         loc = first(path)
         if loc:
             self.move_to(Loc(*loc))
예제 #8
0
    def __init__(self, *args, **kwargs):
        num_mines = kwargs.pop("num_mines")

        super(MinesBoard, self).__init__(*args, **kwargs)
        self.divider = '-' * (self.width * 4 + 4)
        self.current = Loc(0,0)
        self.hl_visible = False

        for _ in range(num_mines):
            self.random_empty().mine = True

        for tile in self:
            tile.number = sum( nbtile.mine for nbtile in self.neighbours(tile) )
예제 #9
0
파일: pyquest.py 프로젝트: saisai/pyquest
    def test_special_attacks(self):
        level_num = 1
        field.load_map("local")
        level.hero = Being('party', field.random(), level.last_index)
        level.last_index += 1
        # level.hero.place()
        level.hoplite = Being("hoplite", Loc(36, 10), level.last_index)
        level.hoplite.place()
        level.last_index += 1
        level.fencer = Being("fencer", Loc(35, 10), level.last_index)
        level.fencer.place()
        level.last_index += 1
        level.mage = Being("mage", Loc(35, 11), level.last_index)
        level.mage.place()
        level.last_index += 1

        t = Being("troll", Loc(34, 9), level.last_index)
        t.team = "monsters"
        t.place()
        level.monsters = [t]
        level.last_index += 1
        conf.mode = "tactical"
예제 #10
0
파일: rooms.py 프로젝트: saisai/pyquest
    def burrow_points(self, loc, dirs, x_fin, y_fin):
        """ Return borrow points, used to tell if connecting corridor will interfere with other rooms or
            corridors.

            loc   : start location
            dirs  : tuple of directions where a dir is e.g. 0,1 for 'right'
            x_fin : terminate x dir at `x_fin` (similarly for `y_fin`)
        """
        start = loc
        points = []
        for dir in dirs:
            if dir[0] in (1, -1):
                x, y = loc
                step = dir[0]
                lst = range(x, x_fin + step, step)
                points.extend([Loc(x, y) for x in lst])
            elif dir[1] in (1, -1):
                x, y = loc
                step = dir[1]
                lst = range(y, y_fin + step, step)
                points.extend([Loc(x, y) for y in lst])

        return points
예제 #11
0
    def parse_fmt(self, inp, fmt):
        """Attempt to parse `inp` using `fmt` format; return False if there is mismatch."""
        from board import Loc

        fmt = fmt.split()
        inp = copy(inp)
        commands = []
        handlers = {"%d": int, "%f": float, "%s": str}
        regexes = dict(self.regexes)

        def nomatch(val):
            return bool(optional and not re.match(regex, val))

        for n, code in enumerate(fmt):
            optional = code.endswith('?')
            if optional: code = code[:-1]
            regex = "^%s$" % regexes.get(code, code)

            if not inp:
                if optional: continue
                else: raise ValueError

            if code == "loc":

                if nomatch(ujoin(inp[:2])):
                    continue
                else:
                    # print("inp", inp)
                    x, y = inp.pop(0), inp.pop(0)
                    loc = Loc(int(x) - 1, int(y) - 1)
                    if self.board and not self.board.valid(loc):
                        raise IndexError
                    commands.append(loc)

            elif code == "%hd":  # 'human' format, 1-indexed, integer
                if nomatch(first(inp)): continue
                else: commands.append(int(inp.pop(0)) - 1)

            else:
                if nomatch(first(inp)): continue
                else: commands.append(handlers.get(code, str)(inp.pop(0)))

        if inp: raise ValueError
        return commands
예제 #12
0
파일: field.py 프로젝트: saisai/pyquest
 def get_loc(self, origin, moves):
     """ Get a location by performing a series of moves from origin. This is
         used by being.special_attack() to find out if a special attack is valid
         for current locations of party and monsters. Example:
         get_loc((5,5), (("right", 1), ("up", 1)))   => (6,6)
         Note that only "right", "up", "down", "left" directions are possible.
     """
     x, y = origin
     for dir, dist in moves:
         if dir == "up":
             # note that 0 is top of screen and then it increases as it goes down
             y -= dist
         elif dir == "right":
             x += dist
         elif dir == "down":
             y += dist
         elif dir == "left":
             x -= dist
     return Loc(x, y)
예제 #13
0
    def turn(self):
        """Get player's move, return Location to move OR return `newgame_code` to start a new game."""
        reversi.check_for_quit()

        # get button click or move click on a tile
        button = reversi.get_button_click(self.newgame, self.hints)
        if not button:
            pass  # click outside of tiles / buttons
        elif button == self.newgame:
            board.reset()
            return newgame_code
        elif button == self.hints:
            board.toggle_hints(self.piece)
        else:
            move_to = board.get_clicked_tile(Loc(button))
            if move_to and board.is_valid_move(self.piece, move_to):
                return move_to

        self.newgame, self.hints = board.buttons()
        reversi.mainclock_tick()
예제 #14
0
파일: field.py 프로젝트: saisai/pyquest
    def path(self, origin, target):
        """ Build navigation path.
            Note: this is a 'dumb' path, it will go over walls and monsters.
        """
        origin = getattr(origin, "loc", origin)
        target = getattr(target, "loc", target)
        x, y = target
        ox, oy = origin
        path = []

        # for _ in range(100):
        while True:
            # log(path)
            if (ox, oy) == tuple(target):
                return path
            if x == ox:
                if y > oy:
                    oy += 1
                else:
                    oy -= 1
            elif y == oy:
                if x > ox:
                    ox += 1
                else:
                    ox -= 1
            elif x > ox:
                if y > oy:
                    ox += 1
                    oy += 1
                else:
                    ox += 1
                    oy -= 1
            elif x < ox:
                if y > oy:
                    ox -= 1
                    oy += 1
                else:
                    ox -= 1
                    oy -= 1
            path.append(Loc(ox, oy))
예제 #15
0
파일: field.py 프로젝트: saisai/pyquest
 def get_coords(self, loc, direction):
     """ Returns coordinates of a cell adjacent to our cell in given direction.
         example: if we're at 1,1 and direction is l (right), return 1,2.
     """
     direction = int(direction)
     (x, y) = loc
     if direction == 108: x += 1  # right
     if direction == 107: y -= 1  # down
     if direction == 104: x -= 1  # left
     if direction == 106: y += 1  # up
     if direction == 98:
         x -= 1
         y += 1  # left + up
     if direction == 110:
         x += 1
         y += 1  # right + up
     if direction == 121:
         x -= 1
         y -= 1  # left + down
     if direction == 117:
         x += 1
         y -= 1  # right + down
     return Loc(x, y)
예제 #16
0
 def nlocs(self, loc):
     x, y = loc
     locs = ((x, y - 1), (x + 1, y), (x, y + 1), (x - 1, y))
     locs = [Loc(*tup) for tup in locs]
     return [(loc if self.valid(loc) else None) for loc in locs]
예제 #17
0
 def __init__(self, *a, **kw):
     super().__init__(*a, **kw)
     self.current = Loc(0,0)
예제 #18
0
 def __init__(self, *a, **kw):
     super().__init__(*a, **kw)
     self.current = Loc(0, 0)
     self.hl_visible = False
예제 #19
0
 def __init__(self):
     x, y = board.middle()
     Piece(Loc(x, y), player1.char)
     Piece(Loc(x + 1, y + 1), player1.char)
     Piece(Loc(x + 1, y), player2.char)
     Piece(Loc(x, y + 1), player2.char)
예제 #20
0
 def make_region(self, xo, yo):
     """Make one region at x offset `xo` and y offset `yo`."""
     return [ Loc(xo + x, yo + y) for x in rng3 for y in rng3 ]
예제 #21
0
파일: field.py 프로젝트: saisai/pyquest
 def __iter__(self):
     for x in range(conf.xmax):
         for y in range(conf.ymax):
             yield Loc(x + 1, y + 1)
예제 #22
0
 def center(self):
     return Loc(self.width // 2, self.height // 2)