def __getBestOpening(self):
     totalWeight = 0
     choice = None
     if self.board.variant not in (
         ASEANCHESS,
         CAMBODIANCHESS,
         MAKRUKCHESS,
         HORDECHESS,
         PLACEMENTCHESS,
         SITTUYINCHESS,
         LOSERSCHESS,
         SUICIDECHESS,
         GIVEAWAYCHESS,
         ATOMICCHESS,
         KINGOFTHEHILLCHESS,
         THREECHECKCHESS,
         RACINGKINGSCHESS,
     ):
         for move, weight, learn in getOpenings(self.board):
             totalWeight += weight
             if totalWeight == 0:
                 break
             if not move or random.randrange(totalWeight) < weight:
                 choice = move
     if choice is None:
         self.outOfBook = True
     return choice
Example #2
0
    def shown_changed(self, board, shown):
        self.openings = getOpenings(self.board.model.getBoardAtPly(shown))
        self.openings.sort(lambda a, b: sum(b[1:]) - sum(a[1:]))

        self.board.bluearrow = None
        self.store.clear()

        if not self.openings and self.sw.get_child() == self.tv:
            self.sw.remove(self.tv)
            label = gtk.Label(_("In this position,\nthere is no book move."))
            label.set_property("yalign", 0.1)
            self.sw.add_with_viewport(label)
            self.sw.get_child().set_shadow_type(gtk.SHADOW_NONE)
            self.sw.show_all()
            return

        if self.openings and self.sw.get_child() != self.tv:
            self.sw.remove(self.sw.get_child())
            self.sw.add(self.tv)

        i = 0
        for move, wins, draws, loses in self.openings:
            games = wins + draws + loses
            if not games: continue
            wins, draws, loses = \
                    map(lambda x: x/float(games), (wins, draws, loses))
            b = self.board.model.getBoardAtPly(shown)
            if conf.get("figuresInNotation", False):
                move = toFAN(b, parseSAN(b, move))
            else:
                move = toSAN(b, parseSAN(b, move), True)
            self.store.append([move, str(games), (wins, draws, loses)])
 def shown_changed (self, board, shown):
     self.openings = getOpenings(self.board.model.getBoardAtPly(shown))
     self.openings.sort(lambda a, b: sum(b[1:])-sum(a[1:]))
     
     self.board.bluearrow = None
     self.store.clear()
     
     if not self.openings and self.sw.get_child() == self.tv:
         self.sw.remove(self.tv)
         label = gtk.Label(_("In this position,\nthere is no book move."))
         label.set_property("yalign",0.1)
         self.sw.add_with_viewport(label)
         self.sw.get_child().set_shadow_type(gtk.SHADOW_NONE)
         self.sw.show_all()
         return
     
     if self.openings and self.sw.get_child() != self.tv:
         self.sw.remove(self.sw.get_child())
         self.sw.add(self.tv)
     
     i = 0
     for move, wins, draws, loses in self.openings:
         games = wins+draws+loses
         if not games: continue
         wins, draws, loses = \
                 map(lambda x: x/float(games), (wins, draws, loses))
         b = self.board.model.getBoardAtPly(shown)
         if conf.get("figuresInNotation", False):
             move = toFAN(b, parseSAN(b, move))
         else:
             move = toSAN(b, parseSAN(b, move), True)
         self.store.append ([move, str(games), (wins,draws,loses)])
Example #4
0
            def on_book_created(persp, event):
                self.assertTrue(os.path.isfile(BIN))

                testcase = testcases[0]
                board = LBoard(Board)
                board.applyFen(testcase[0])
                openings = book.getOpenings(board)
                self.assertEqual(
                    sorted(openings),
                    sorted([(newMove(E2, E4), 2, 0), (newMove(A2, A4), 0, 0)]))

                testcase = testcases[-1]
                board = LBoard(Board)
                board.applyFen(testcase[0])
                openings = book.getOpenings(board)
                self.assertEqual(openings, [])

                event.set()
Example #5
0
 def __getBestOpening (self):
     score = 0
     move = None
     for m, w, d, l in getOpenings(self.board):
         s = (w+d/3.0)*random.random()
         if not move or s > score:
             move = m
             score = s
     return move
Example #6
0
            def on_book_created(persp, event):
                self.assertTrue(os.path.isfile(BIN))

                book.path = BIN
                book.bookfile = True

                testcase = testcases[0]
                board = LBoard(Board)
                board.applyFen(testcase[0])
                openings = book.getOpenings(board)
                self.assertEqual(sorted(openings), sorted([(newMove(E2, E4), 2, 0), (newMove(A2, A4), 0, 0)]))

                testcase = testcases[-1]
                board = LBoard(Board)
                board.applyFen(testcase[0])
                openings = book.getOpenings(board)
                self.assertEqual(openings, [])

                event.set()
Example #7
0
 def __getBestOpening (self):
     totalWeight = 0
     choice = None
     if self.board.variant not in (LOSERSCHESS, SUICIDECHESS, ATOMICCHESS):
         for move, weight, histGames, histScore in getOpenings(self.board):
             totalWeight += weight
             if totalWeight == 0:
                 break
             if not move or random.randrange(totalWeight) < weight:
                 choice = move
     return choice
Example #8
0
 def __getBestOpening(self):
     totalWeight = 0
     choice = None
     if self.board.variant not in (LOSERSCHESS, SUICIDECHESS, ATOMICCHESS,
                                   KINGOFTHEHILLCHESS):
         for move, weight, histGames, histScore in getOpenings(self.board):
             totalWeight += weight
             if totalWeight == 0:
                 break
             if not move or random.randrange(totalWeight) < weight:
                 choice = move
     return choice
    def shownChanged(self, boardview, shown):
        m = boardview.model
        if m is None or m.isPlayingICSGame():
            return

        b = m.getBoardAtPly(shown, boardview.shown_variation_idx)
        parent = self.empty_parent()

        openings = getOpenings(b.board)
        openings.sort(key=lambda t: t[1], reverse=True)
        if not openings:
            return

        totalWeight = 0.0
        # Polyglot-formatted books have space for learning data.
        # See version ac31dc37ec89 for an attempt to parse it.
        # In this version, we simply ignore it. (Most books don't have it.)
        for move, weight, learn in openings:
            totalWeight += weight

        self.opening_names = []
        for move, weight, learn in openings:
            if totalWeight != 0:
                weight /= totalWeight
            goodness = min(float(weight * len(openings)), 1.0)
            weight = "%0.1f%%" % (100 * weight)

            opening = get_eco(b.move(Move(move)).board.hash)
            if opening is None:
                eco = ""
            #                self.opening_names.append("")
            else:
                eco = "%s - %s %s" % (opening[0], opening[1], opening[2])
            #                self.opening_names.append("%s %s" % (opening[1], opening[2]))

            self.store.append(
                parent,
                [
                    (b, Move(move), None),
                    (weight, 1, goodness),
                    0,
                    False,
                    eco,
                    False,
                    False,
                ],
            )
        tp = Gtk.TreePath(self.path)
        self.tv.expand_row(tp, False)
Example #10
0
 def __getBestOpening(self):
     totalWeight = 0
     choice = None
     if self.board.variant not in (ASEANCHESS, CAMBODIANCHESS, MAKRUKCHESS, HORDECHESS, PLACEMENTCHESS,
                                   SITTUYINCHESS, LOSERSCHESS, SUICIDECHESS, GIVEAWAYCHESS,
                                   ATOMICCHESS, KINGOFTHEHILLCHESS, THREECHECKCHESS, RACINGKINGSCHESS):
         for move, weight, learn in getOpenings(self.board):
             totalWeight += weight
             if totalWeight == 0:
                 break
             if not move or random.randrange(totalWeight) < weight:
                 choice = move
     if choice is None:
         self.outOfBook = True
     return choice
Example #11
0
 def __getBestOpening (self):
     totalWeight = 0
     choice = None
     if self.board.variant not in (ASEANCHESS, CAMBODIANCHESS, MAKRUKCHESS, \
                                   SITTUYINCHESS, LOSERSCHESS, SUICIDECHESS,\
                                   ATOMICCHESS, KINGOFTHEHILLCHESS, THREECHECKCHESS):
         for move, weight, histGames, histScore in getOpenings(self.board):
             totalWeight += weight
             if totalWeight == 0:
                 break
             if not move or random.randrange(totalWeight) < weight:
                 choice = move
     if choice is None:
         self.outOfBook = True
     return choice
Example #12
0
    def get_book_move(self):
        openings = getOpenings(self.boards[-1].board)
        openings.sort(key=lambda t: t[1], reverse=True)
        if not openings:
            return None

        total_weights = 0
        for move, weight, learn in openings:
            total_weights += weight

        if total_weights < 1:
            return None

        choice = random.randint(0, total_weights - 1)

        current_sum = 0
        for move, weight, learn in openings:
            current_sum += weight
            if current_sum > choice:
                return Move(move)
Example #13
0
    def shownChanged(self, boardview, shown):
        m = boardview.model
        if m is None:
            return
        if m.isPlayingICSGame():
            return

        b = m.getBoardAtPly(shown, boardview.shown_variation_idx)
        parent = self.empty_parent()

        openings = getOpenings(b.board)
        openings.sort(key=lambda t: t[1], reverse=True)
        if not openings:
            return

        totalWeight = 0.0
        # Polyglot-formatted books have space for learning data.
        # See version ac31dc37ec89 for an attempt to parse it.
        # In this version, we simply ignore it. (Most books don't have it.)
        for move, weight, games, score in openings:
            totalWeight += weight

        self.opening_names = []
        for move, weight, games, score in openings:
            if totalWeight != 0:
                weight /= totalWeight
            goodness = min(float(weight * len(openings)), 1.0)
            weight = "%0.1f%%" % (100 * weight)

            opening = get_eco(b.move(Move(move)).board.hash)
            if opening is None:
                eco = ""
#                self.opening_names.append("")
            else:
                eco = "%s - %s %s" % (opening[0], opening[1], opening[2])
#                self.opening_names.append("%s %s" % (opening[1], opening[2]))

            self.store.append(parent, [(b, Move(move), None), (
                weight, 1, goodness), 0, False, eco, False, False])
        tp = Gtk.TreePath(self.path)
        self.tv.expand_row(tp, False)
Example #14
0
    def run(self):
        while True:
            try:
                line = raw_input()
            except EOFError:
                line = "quit"
            lines = line.split()

            try:
                if not lines:
                    continue

                log.debug(line, extra={"task": "xboard"})

                ########## CECP commands ##########
                # See http://home.hccnet.nl/h.g.muller/engine-intf.html

                if lines[0] == "xboard":
                    pass

                elif lines[0] == "protover":
                    stringPairs = [
                        "=".join(
                            [k,
                             '"%s"' % v if isinstance(v, str) else str(v)])
                        for k, v in self.features.items()
                    ]
                    self.print("feature %s" % " ".join(stringPairs))
                    self.print("feature done=1")

                elif lines[0] in ("accepted", "rejected"):
                    # We only really care about one case:
                    if tuple(lines) == ("rejected", "debug"):
                        self.debug = False

                elif lines[0] == "new":
                    self.__stopSearching()
                    self.board = LBoard(NORMALCHESS)
                    self.board.applyFen(FEN_START)
                    self.outOfBook = False
                    self.forced = False
                    self.playingAs = BLACK
                    self.clock[:] = self.basetime, self.basetime
                    self.searchtime = 0
                    self.sd = MAXPLY
                    if self.analyzing:
                        self.__analyze()

                elif lines[0] == "variant":
                    if len(lines) > 1:
                        if lines[1] == "fischerandom":
                            self.board.variant = FISCHERRANDOMCHESS
                        elif lines[1] == "crazyhouse":
                            self.board.variant = CRAZYHOUSECHESS
                            self.board.iniHouse()
                        elif lines[1] == "wildcastle":
                            self.board.variant = WILDCASTLESHUFFLECHESS
                        elif lines[1] == "losers":
                            self.board.variant = LOSERSCHESS
                        elif lines[1] == "suicide":
                            self.board.variant = SUICIDECHESS
                        elif lines[1] == "atomic":
                            self.board.variant = ATOMICCHESS
                            self.board.iniAtomic()
                        elif lines[1] == "3check":
                            self.board.variant = THREECHECKCHESS
                        elif lines[1] == "kingofthehill":
                            self.board.variant = KINGOFTHEHILLCHESS
                            self.print("setup (PNBRQKpnbrqk) 8x8+0_fairy %s" %
                                       FEN_START)
                        elif lines[1] == "asean":
                            self.board = LBoard(ASEANCHESS)
                            self.board.applyFen(ASEANSTART)
                        elif lines[1] == "makruk":
                            self.board = LBoard(MAKRUKCHESS)
                            self.board.applyFen(MAKRUKSTART)
                        elif lines[1] == "cambodian":
                            self.board = LBoard(CAMBODIANCHESS)
                            self.board.applyFen(KAMBODIANSTART)
                            self.print(
                                "setup (PN.R.M....SKpn.r.m....sk) 8x8+0_makruk %s"
                                % KAMBODIANSTART)
                            self.print("piece K& KiN")
                            self.print("piece M& FifD")
                        elif lines[1] == "sittuyin":
                            self.board = LBoard(SITTUYINCHESS)
                            self.board.applyFen(SITTUYINSTART)
                            self.print(
                                "setup (PN.R.F....SKpn.r.f....sk) 8x8+6_bughouse %s"
                                % SITTUYINSTART)
                            self.print("piece N& Nj@3")
                            self.print("piece S& FfWj@3")
                            self.print("piece F& Fjb@3")
                            self.print("piece R& R@1")
                            self.print("piece K& Kj@3")
                            self.print("piece P& fmWfcFj@3")

                elif lines[0] == "quit":
                    self.forced = True
                    self.__stopSearching()
                    sys.exit(0)

                elif lines[0] == "random":
                    leval.random = True

                elif lines[0] == "force":
                    if not self.forced and not self.analyzing:
                        self.forced = True
                        self.__stopSearching()

                elif lines[0] == "go":
                    self.playingAs = self.board.color
                    self.forced = False
                    self.__go()

                elif lines[0] == "playother":
                    self.playingAs = 1 - self.board.color
                    self.forced = False
                    # TODO: start pondering, if possible

                elif lines[0] in ("black", "white"):
                    newColor = lines[0] == "black" and BLACK or WHITE
                    self.__stopSearching()
                    self.playingAs = 1 - newColor
                    if self.board.color != newColor:
                        self.board.setColor(newColor)
                        self.board.setEnpassant(None)
                    if self.analyzing:
                        self.__analyze()

                elif lines[0] == "level":
                    self.movestogo = int(lines[1])
                    inc = int(lines[3])
                    minutes = lines[2].split(":")
                    # Per protocol spec, strip off any non-numeric suffixes.
                    for i in range(len(minutes)):
                        minutes[i] = re.match(r'\d*', minutes[i]).group()
                    self.basetime = int(minutes[0]) * 60
                    if len(minutes) > 1 and minutes[1]:
                        self.basetime += int(minutes[1])
                    self.clock[:] = self.basetime, self.basetime
                    self.increment = inc, inc

                elif lines[0] == "st":
                    self.searchtime = float(lines[1])

                elif lines[0] == "sd":
                    self.sd = int(lines[1])

                # Unimplemented: nps

                elif lines[0] == "time":
                    self.clock[self.playingAs] = float(lines[1]) / 100.

                elif lines[0] == "otim":
                    self.clock[1 - self.playingAs] = float(lines[1]) / 100.

                elif lines[0] == "usermove":
                    self.__stopSearching()
                    try:
                        move = parseAny(self.board, lines[1])
                    except ParsingError as e:
                        self.print("Error (unknown command): %s" % lines[1])
                        self.print(self.board)
                        continue
                    if not validateMove(self.board, move):
                        self.print("Illegal move: %s" % lines[1])
                        self.print(self.board)
                        continue
                    self.board.applyMove(move)
                    self.playingAs = self.board.color
                    if not self.forced and not self.analyzing:
                        self.__go()
                    if self.analyzing:
                        self.__analyze()

                elif lines[0] == "?":
                    if not self.forced and not self.analyzing:
                        self.__stopSearching()

                elif lines[0] == "ping":
                    self.print("pong %s" % lines[1])

                elif lines[0] == "draw":
                    if self.__willingToDraw():
                        self.print("offer draw")

                elif lines[0] == "result":
                    # We don't really care what the result is at the moment.
                    pass

                elif lines[0] == "setboard":
                    self.__stopSearching()
                    try:
                        self.board = LBoard(self.board.variant)
                        fen = " ".join(lines[1:])
                        self.board.applyFen(
                            fen.replace("[", "/").replace("]", ""))
                    except SyntaxError as e:
                        self.print("tellusererror Illegal position: %s" %
                                   str(e))

                # "edit" is unimplemented. See docs. Exiting edit mode returns to analyze mode.

                elif lines[0] == "hint":
                    pass  # TODO: Respond "Hint: MOVE" if we have an expected reply

                elif lines[0] == "bk":
                    entries = getOpenings(self.board)
                    if entries:
                        totalWeight = sum(entry[1] for entry in entries)
                        for entry in entries:
                            self.print("\t%s\t%02.2f%%" %
                                       (toSAN(self.board, entry[0]),
                                        entry[1] * 100.0 / totalWeight))

                elif lines[0] == "undo":
                    self.__stopSearching()
                    self.board.popMove()
                    if self.analyzing:
                        self.__analyze()

                elif lines[0] == "remove":
                    self.__stopSearching()
                    self.board.popMove()
                    self.board.popMove()
                    if self.analyzing:
                        self.__analyze()

                elif lines[0] in ("hard", "easy"):
                    self.ponder = (lines[0] == "hard")

                elif lines[0] in ("post", "nopost"):
                    self.post = (lines[0] == "post")

                elif lines[0] == "analyze":
                    self.analyzing = True
                    self.__analyze()

                elif lines[0] in ("name", "rating", "ics", "computer"):
                    pass  # We don't care.

                # Unimplemented: pause, resume

                elif lines[0] == "memory":
                    # FIXME: this is supposed to control the *total* memory use.
                    if lsearch.searching:
                        self.print("Error (already searching):", line)
                    else:
                        limit = int(lines[1])
                        if limit < 1:
                            self.print("Error (limit too low):", line)
                        else:
                            pass
                            # TODO implement
                            #lsearch.setHashSize(limit)

                elif lines[0] == "cores":
                    pass  # We aren't SMP-capable.

                elif lines[0] == "egtpath":
                    if len(lines) >= 3 and lines[1] == "gaviota":
                        conf.set("egtb_path", conf.get("egtb_path", lines[2]))
                        from pychess.Utils.lutils.lsearch import enableEGTB
                        enableEGTB()

                elif lines[0] == "option" and len(lines) > 1:
                    name, eq, value = lines[1].partition("=")
                    if value:
                        value = int(
                            value
                        )  # CECP spec says option values are *always* numeric
                    if name == "skipPruneChance":
                        if 0 <= value <= 100:
                            self.skipPruneChance = value / 100.0
                        else:
                            self.print(
                                "Error (argument must be an integer 0..100): %s"
                                % line)

                ########## CECP analyze mode commands ##########
                # See http://www.gnu.org/software/xboard/engine-intf.html#11

                elif lines[0] == "exit":
                    if self.analyzing:
                        self.__stopSearching()
                        self.analyzing = False

                # Periodic updates (".") are not implemented.

                ########## Custom commands ##########

                elif lines[0] == "moves":
                    self.print(self.board)
                    self.print([
                        toSAN(self.board, move)
                        for move in genAllMoves(self.board)
                    ])

                elif lines[0] == "captures":
                    self.print(self.board)
                    self.print([
                        toSAN(self.board, move)
                        for move in genCaptures(self.board)
                    ])

                elif lines[0] == "evasions":
                    self.print(self.board)
                    self.print([
                        toSAN(self.board, move)
                        for move in genCheckEvasions(self.board)
                    ])

                elif lines[0] == "benchmark":
                    benchmark()

                elif lines[0] == "profile":
                    if len(lines) > 1:
                        import cProfile
                        cProfile.runctx("benchmark()", locals(), globals(),
                                        lines[1])
                    else:
                        self.print("Usage: profile outputfilename")

                elif lines[0] == "perft":
                    root = "0" if len(lines) < 3 else lines[2]
                    depth = "1" if len(lines) == 1 else lines[1]
                    if root.isdigit() and depth.isdigit():
                        perft(self.board, int(depth), int(root))
                    else:
                        self.print("Error (arguments must be integer")

                elif len(lines) == 1:
                    # A GUI without usermove support might try to send a move.
                    try:
                        move = parseAny(self.board, line)
                    except:
                        self.print("Error (unknown command): %s" % line)
                        continue
                    if not validateMove(self.board, move):
                        self.print("Illegal move: %s" % lines[0])
                        self.print(self.board)
                        continue
                    self.__stopSearching()
                    self.board.applyMove(move)
                    self.playingAs = self.board.color
                    if not self.forced and not self.analyzing:
                        self.__go()
                    if self.analyzing:
                        self.__analyze()

                else:
                    self.print("Error (unknown command): %s" % line)
            except IndexError:
                self.print("Error (missing argument): %s" % line)
Example #15
0
    def run (self):
        while True:
            try:
                line = raw_input()
            except EOFError:
                line = "quit"
            lines = line.split()
            if 1:
            #try:
                if not lines:
                    continue
     
                ########## CECP commands ##########
                # See http://www.gnu.org/software/xboard/engine-intf.html#8
                
                elif lines[0] == "xboard":
                    pass
     
                elif lines[0] == "protover":
                    stringPairs = ["=".join([k, '"%s"' % v if type(v) is str else str(v)]) for k,v in self.features.iteritems()]
                    print "feature %s" % " ".join(stringPairs)
                    print "feature done=1"
                
                elif lines[0] in ("accepted", "rejected"):
                    # We only really care about one case:
                    if tuple(lines) == ("rejected", "debug"):
                        self.debug = False
     
                elif lines[0] == "new":
                    self.__stopSearching()
                    self.board = LBoard(NORMALCHESS)
                    self.board.applyFen(FEN_START)
                    self.forced = False
                    self.playingAs = BLACK
                    self.clock[:] = self.basetime, self.basetime
                    self.searchtime = 0
                    self.sd = MAXPLY
                    if self.analyzing:
                        self.__analyze()
                
                elif lines[0] == "variant":
                    if len(lines) > 1:
                        if lines[1] == "fischerandom":
                            self.board.variant = FISCHERRANDOMCHESS
                        elif lines[1] == "crazyhouse":
                            self.board.variant = CRAZYHOUSECHESS
                            self.board.iniHouse()
                        elif lines[1] == "wildcastle":
                            self.board.variant = WILDCASTLESHUFFLECHESS
                        elif lines[1] == "losers":
                            self.board.variant = LOSERSCHESS
                        elif lines[1] == "suicide":
                            self.board.variant = SUICIDECHESS
                        elif lines[1] == "atomic":
                            self.board.variant = ATOMICCHESS
                            self.board.iniAtomic()
                
                elif lines[0] == "quit":
                    self.forced = True
                    self.__stopSearching()
                    sys.exit(0)
                    
                elif lines[0] == "random":
                    leval.random = True
     
                elif lines[0] == "force":
                    if not self.forced and not self.analyzing:
                        self.forced = True
                        self.__stopSearching()
                
                elif lines[0] == "go":
                    self.playingAs = self.board.color
                    self.forced = False
                    self.__go()
                
                elif lines[0] == "playother":
                    self.playingAs = 1-self.board.color
                    self.forced = False
                    # TODO: start pondering, if possible
                
                elif lines[0] in ("black", "white"):
                    newColor = lines[0] == "black" and BLACK or WHITE
                    self.__stopSearching()
                    self.playingAs = 1-newColor
                    if self.board.color != newColor:
                        self.board.setColor(newColor)
                        self.board.setEnpassant(None)
                    if self.analyzing:
                        self.__analyze()
                
                elif lines[0] == "level":
                    self.movestogo = int(lines[1])
                    inc = int(lines[3])
                    minutes = lines[2].split(":")
                    # Per protocol spec, strip off any non-numeric suffixes.
                    for i in xrange(len(minutes)):
                        minutes[i] = re.match(r'\d*', minutes[i]).group()
                    self.basetime = int(minutes[0])*60
                    if len(minutes) > 1 and minutes[1]:
                        self.basetime += int(minutes[1])
                    self.clock[:] = self.basetime, self.basetime
                    self.increment = inc, inc
                
                elif lines[0] == "st":
                    self.searchtime = float(lines[1])
     
                elif lines[0] == "sd":
                    self.sd = int(lines[1])
                
                # Unimplemented: nps
                
                elif lines[0] == "time":
                    self.clock[self.playingAs] = float(lines[1])/100.
                
                elif lines[0] == "otim":
                    self.clock[1-self.playingAs] = float(lines[1])/100.
                
                elif lines[0] == "usermove":
                    self.__stopSearching()
                    try:
                        move = parseAny (self.board, lines[1])
                    except ParsingError, e:
                        print "Error (unknown command):", lines[1]
                        print self.board
                        continue
                    if not validateMove(self.board, move):
                        print "Illegal move", lines[1]
                        print self.board
                        continue
                    self.board.applyMove(move)
                    self.playingAs = self.board.color
                    if not self.forced and not self.analyzing:
                        self.__go()
                    if self.analyzing:
                        self.__analyze()
                
                elif lines[0] == "?":
                    if not self.forced and not self.analyzing:
                        self.__stopSearching()
                
                elif lines[0] == "ping":
                    print "pong", lines[1]
                    
                elif lines[0] == "draw":
                    if self.__willingToDraw():
                        print "offer draw"
                
                elif lines[0] == "result":
                    # We don't really care what the result is at the moment.
                    pass
                    
                elif lines[0] == "setboard":
                    self.__stopSearching()
                    try:
                        self.board = LBoard(self.board.variant)
                        fen = " ".join(lines[1:])
                        self.board.applyFen(fen.replace("[", "/").replace("]", ""))
                    except SyntaxError as e:
                        print "tellusererror Illegal position:", str(e)
                    if self.analyzing:
                        self.__analyze()
                
                # "edit" is unimplemented. See docs. Exiting edit mode returns to analyze mode.
     
                elif lines[0] == "hint":
                    pass # TODO: Respond "Hint: MOVE" if we have an expected reply
                
                elif lines[0] == "bk":
                    entries = getOpenings(self.board)
                    if entries:
                        totalWeight = sum(entry[1] for entry in entries)
                        for entry in entries:
                            print "\t%s\t%02.2f%%" % (toSAN(self.board, entry[0]), entry[1] * 100.0 / totalWeight)
                
                elif lines[0] == "undo":
                    self.__stopSearching()
                    self.board.popMove()
                    if self.analyzing:
                        self.__analyze()
     
                elif lines[0] == "remove":
                    self.__stopSearching()
                    self.board.popMove()
                    self.board.popMove()
                    if self.analyzing:
                        self.__analyze()
                
                elif lines[0] in ("hard", "easy"):
                    self.ponder = (lines[0] == "hard")
                
                elif lines[0] in ("post", "nopost"):
                    self.post = (lines[0] == "post")
                
                elif lines[0] == "analyze":
                    self.analyzing = True
                    self.__analyze()
     
                elif lines[0] in ("name", "rating", "ics", "computer"):
                    pass # We don't care.
     
                # Unimplemented: pause, resume
     
                elif lines[0] == "memory":
                    # FIXME: this is supposed to control the *total* memory use.
                    if lsearch.searching:
                        print "Error (already searching):", line
                    else:
                        limit = int(lines[1])
                        if limit < 1:
                            print "Error (limit too low):", line
                        else:
                            pass
                            # TODO implement
                            #lsearch.setHashSize(limit)
     
                elif lines[0] == "cores":
                    pass # We aren't SMP-capable.
     
                elif lines[0] == "egtpath":
                    # TODO: Accept "egtpath TYPE PATH" commands, at least for Gaviota EGTBs
                    pass
     
                elif lines[0] == "option" and len(lines) > 1:
                    name, eq, value = lines[1].partition("=")
                    if value: value = int(value) # CECP spec says option values are *always* numeric
                    if name == "skipPruneChance":
                        if 0 <= value <= 100:
                            self.skipPruneChance = value / 100.0
                        else:
                            print "Error (argument must be an integer 0..100):", line
     
                ########## CECP analyze mode commands ##########
                # See http://www.gnu.org/software/xboard/engine-intf.html#11
     
                elif lines[0] == "exit":
                    if self.analyzing:
                        self.__stopSearching()
                        self.analyzing = False
     
                # Periodic updates (".") are not implemented.
     
                ########## Custom commands ##########
     
                elif lines[0] == "egtb":
                    enableEGTB()
                
                elif lines[0] == "benchmark":
                    benchmark()
                
                elif lines[0] == "profile":
                    if len(lines) > 1:
                        import cProfile
                        cProfile.runctx("benchmark()", locals(), globals(), lines[1])
                    else:
                        print "Usage: profile outputfilename"
                
                elif len(lines) == 1:
                    # A GUI without usermove support might try to send a move.
                    try:
                        move = parseAny (self.board, line)
                    except:
                        print "Error (unknown command):", line
                        continue
                    if not validateMove(self.board, move):
                        print "Illegal move", lines[0]
                        print self.board
                        continue
                    self.__stopSearching()
                    self.board.applyMove(move)
                    self.playingAs = self.board.color
                    if not self.forced and not self.analyzing:
                        self.__go()
                    if self.analyzing:
                        self.__analyze()

                else:
                    print "Error (unknown command):", line
Example #16
0
    def run(self):
        while True:
            try:
                line = get_input()
            except EOFError:
                line = "quit"
            lines = line.split()

            try:
                if not lines:
                    continue

                log.debug(line, extra={"task": "xboard"})

                # CECP commands
                # See http://home.hccnet.nl/h.g.muller/engine-intf.html

                if lines[0] == "xboard":
                    pass

                elif lines[0] == "protover":
                    stringPairs = ["=".join([k, '"%s"' % v if isinstance(
                        v, str) else str(v)]) for k, v in self.features.items()]
                    self.print("feature %s" % " ".join(stringPairs))
                    self.print("feature done=1")

                elif lines[0] in ("accepted", "rejected"):
                    # We only really care about one case:
                    if tuple(lines) == ("rejected", "debug"):
                        self.debug = False

                elif lines[0] == "new":
                    self.__stopSearching()
                    self.board = LBoard(NORMALCHESS)
                    self.board.applyFen(FEN_START)
                    self.outOfBook = False
                    self.forced = False
                    self.playingAs = BLACK
                    self.clock[:] = self.basetime, self.basetime
                    self.searchtime = 0
                    self.sd = MAXPLY
                    if self.analyzing:
                        self.__analyze()

                elif lines[0] == "variant":
                    if len(lines) > 1:
                        if lines[1] == "fischerandom":
                            self.board.variant = FISCHERRANDOMCHESS
                        elif lines[1] == "crazyhouse":
                            self.board.variant = CRAZYHOUSECHESS
                            self.board.iniHouse()
                        elif lines[1] == "wildcastle":
                            self.board.variant = WILDCASTLESHUFFLECHESS
                        elif lines[1] == "losers":
                            self.board.variant = LOSERSCHESS
                        elif lines[1] == "suicide":
                            self.board.variant = SUICIDECHESS
                        elif lines[1] == "giveaway":
                            self.board.variant = GIVEAWAYCHESS
                        elif lines[1] == "atomic":
                            self.board.variant = ATOMICCHESS
                            self.board.iniAtomic()
                        elif lines[1] == "3check":
                            self.board.variant = THREECHECKCHESS
                        elif lines[1] == "kingofthehill":
                            self.board.variant = KINGOFTHEHILLCHESS
                            self.print("setup (PNBRQKpnbrqk) 8x8+0_fairy %s" %
                                       FEN_START)
                        elif lines[1] == "horde":
                            self.board = LBoard(HORDECHESS)
                            self.board.applyFen(HORDESTART)
                        elif lines[1] == "asean":
                            self.board = LBoard(ASEANCHESS)
                            self.board.applyFen(ASEANSTART)
                        elif lines[1] == "makruk":
                            self.board = LBoard(MAKRUKCHESS)
                            self.board.applyFen(MAKRUKSTART)
                        elif lines[1] == "cambodian":
                            self.board = LBoard(CAMBODIANCHESS)
                            self.board.applyFen(KAMBODIANSTART)
                            self.print(
                                "setup (PN.R.M....SKpn.r.m....sk) 8x8+0_makruk %s"
                                % KAMBODIANSTART)
                            self.print("piece K& KiN")
                            self.print("piece M& FifD")
                        elif lines[1] == "sittuyin":
                            self.board = LBoard(SITTUYINCHESS)
                            self.board.applyFen(SITTUYINSTART)
                            self.print(
                                "setup (PN.R.F....SKpn.r.f....sk) 8x8+6_bughouse %s"
                                % SITTUYINSTART)
                            self.print("piece N& Nj@3")
                            self.print("piece S& FfWj@3")
                            self.print("piece F& Fjb@3")
                            self.print("piece R& R@1")
                            self.print("piece K& Kj@3")
                            self.print("piece P& fmWfcFj@3")

                elif lines[0] == "quit":
                    self.forced = True
                    self.__stopSearching()
                    sys.exit(0)

                elif lines[0] == "random":
                    leval.random = True

                elif lines[0] == "force":
                    if not self.forced and not self.analyzing:
                        self.forced = True
                        self.__stopSearching()

                elif lines[0] == "go":
                    self.playingAs = self.board.color
                    self.forced = False
                    self.__go()

                elif lines[0] == "playother":
                    self.playingAs = 1 - self.board.color
                    self.forced = False
                    # TODO: start pondering, if possible

                elif lines[0] in ("black", "white"):
                    newColor = lines[0] == "black" and BLACK or WHITE
                    self.__stopSearching()
                    self.playingAs = 1 - newColor
                    if self.board.color != newColor:
                        self.board.setColor(newColor)
                        self.board.setEnpassant(None)
                    if self.analyzing:
                        self.__analyze()

                elif lines[0] == "level":
                    self.movestogo = int(lines[1])
                    inc = int(lines[3])
                    minutes = lines[2].split(":")
                    # Per protocol spec, strip off any non-numeric suffixes.
                    for i in range(len(minutes)):
                        minutes[i] = re.match(r'\d*', minutes[i]).group()
                    self.basetime = int(minutes[0]) * 60
                    if len(minutes) > 1 and minutes[1]:
                        self.basetime += int(minutes[1])
                    self.clock[:] = self.basetime, self.basetime
                    self.increment = inc, inc

                elif lines[0] == "st":
                    self.searchtime = float(lines[1])

                elif lines[0] == "sd":
                    self.sd = int(lines[1])

                # Unimplemented: nps

                elif lines[0] == "time":
                    self.clock[self.playingAs] = float(lines[1]) / 100.

                elif lines[0] == "otim":
                    self.clock[1 - self.playingAs] = float(lines[1]) / 100.

                elif lines[0] == "usermove":
                    self.__stopSearching()
                    try:
                        move = parseAny(self.board, lines[1])
                    except ParsingError as err:
                        self.print("Error (unknown command): %s" % lines[1])
                        self.print(self.board.prepr(ascii=ASCII))
                        continue
                    if not validateMove(self.board, move):
                        self.print("Illegal move: %s" % lines[1])
                        self.print(self.board.prepr(ascii=ASCII))
                        continue
                    self.board.applyMove(move)
                    self.playingAs = self.board.color
                    if not self.forced and not self.analyzing:
                        self.__go()
                    if self.analyzing:
                        self.__analyze()

                elif lines[0] == "?":
                    if not self.forced and not self.analyzing:
                        self.__stopSearching()

                elif lines[0] == "ping":
                    self.print("pong %s" % lines[1])

                elif lines[0] == "draw":
                    if self.__willingToDraw():
                        self.print("offer draw")

                elif lines[0] == "result":
                    # We don't really care what the result is at the moment.
                    pass

                elif lines[0] == "setboard":
                    self.__stopSearching()
                    try:
                        self.board = LBoard(self.board.variant)
                        fen = " ".join(lines[1:])
                        self.board.applyFen(fen.replace("[", "/").replace("]",
                                                                          ""))
                    except SyntaxError as err:
                        self.print("tellusererror Illegal position: %s" %
                                   str(err))

                # "edit" is unimplemented. See docs. Exiting edit mode returns to analyze mode.

                elif lines[0] == "hint":
                    pass  # TODO: Respond "Hint: MOVE" if we have an expected reply

                elif lines[0] == "bk":
                    entries = getOpenings(self.board)
                    if entries:
                        totalWeight = sum(entry[1] for entry in entries)
                        for entry in entries:
                            self.print("\t%s\t%02.2f%%" %
                                       (toSAN(self.board, entry[0]), entry[1] *
                                        100.0 / totalWeight))

                elif lines[0] == "undo":
                    self.__stopSearching()
                    self.board.popMove()
                    if self.analyzing:
                        self.__analyze()

                elif lines[0] == "remove":
                    self.__stopSearching()
                    self.board.popMove()
                    self.board.popMove()
                    if self.analyzing:
                        self.__analyze()

                elif lines[0] in ("hard", "easy"):
                    self.ponder = (lines[0] == "hard")

                elif lines[0] in ("post", "nopost"):
                    self.post = (lines[0] == "post")

                elif lines[0] == "analyze":
                    self.analyzing = True
                    self.__analyze()

                elif lines[0] in ("name", "rating", "ics", "computer"):
                    pass  # We don't care.

                # Unimplemented: pause, resume

                elif lines[0] == "memory":
                    # FIXME: this is supposed to control the *total* memory use.
                    if lsearch.searching:
                        self.print("Error (already searching):", line)
                    else:
                        limit = int(lines[1])
                        if limit < 1:
                            self.print("Error (limit too low):", line)
                        else:
                            pass
                            # TODO implement
                            # lsearch.setHashSize(limit)

                elif lines[0] == "cores":
                    pass  # We aren't SMP-capable.

                elif lines[0] == "egtpath":
                    if len(lines) >= 3 and lines[1] == "gaviota":
                        conf.set("egtb_path", conf.get("egtb_path", lines[2]))
                        from pychess.Utils.lutils.lsearch import enableEGTB
                        enableEGTB()

                elif lines[0] == "option" and len(lines) > 1:
                    name, eq, value = lines[1].partition("=")
                    if value:
                        value = int(
                            value
                        )  # CECP spec says option values are *always* numeric
                    if name == "skipPruneChance":
                        if 0 <= value <= 100:
                            self.skipPruneChance = value / 100.0
                        else:
                            self.print(
                                "Error (argument must be an integer 0..100): %s"
                                % line)

                # CECP analyze mode commands
                # See http://www.gnu.org/software/xboard/engine-intf.html#11

                elif lines[0] == "exit":
                    if self.analyzing:
                        self.__stopSearching()
                        self.analyzing = False

                # Periodic updates (".") are not implemented.

                # Custom commands

                elif lines[0] == "moves":
                    self.print(self.board.prepr(ascii=ASCII))
                    self.print([toSAN(self.board, move)
                                for move in genAllMoves(self.board)])

                elif lines[0] == "captures":
                    self.print(self.board.prepr(ascii=ASCII))
                    self.print([toSAN(self.board, move)
                                for move in genCaptures(self.board)])

                elif lines[0] == "evasions":
                    self.print(self.board.prepr(ascii=ASCII))
                    self.print([toSAN(self.board, move)
                                for move in genCheckEvasions(self.board)])

                elif lines[0] == "benchmark":
                    if len(lines) > 1:
                        benchmark(int(lines[1]))
                    else:
                        benchmark()

                elif lines[0] == "profile":
                    if len(lines) > 1:
                        import cProfile
                        cProfile.runctx("benchmark()", locals(), globals(),
                                        lines[1])
                    else:
                        self.print("Usage: profile outputfilename")

                elif lines[0] == "perft":
                    root = "0" if len(lines) < 3 else lines[2]
                    depth = "1" if len(lines) == 1 else lines[1]
                    if root.isdigit() and depth.isdigit():
                        perft(self.board, int(depth), int(root))
                    else:
                        self.print("Error (arguments must be integer")

                elif lines[0] == "stop_unittest":
                    break

                elif len(lines) == 1:
                    # A GUI without usermove support might try to send a move.
                    try:
                        move = parseAny(self.board, line)
                    except ParsingError:
                        self.print("Error (unknown command): %s" % line)
                        continue
                    if not validateMove(self.board, move):
                        self.print("Illegal move: %s" % lines[0])
                        self.print(self.board.prepr(ascii=ASCII))
                        continue
                    self.__stopSearching()
                    self.board.applyMove(move)
                    self.playingAs = self.board.color
                    if not self.forced and not self.analyzing:
                        self.__go()
                    if self.analyzing:
                        self.__analyze()

                else:
                    self.print("Error (unknown command): %s" % line)
            except IndexError:
                self.print("Error (missing argument): %s" % line)