def test_encode_decode(self): for idx, variant in enumerate(VARIANTS): print(idx, variant) variant = variant.rstrip("960") FEN = sf.start_fen(variant) # fill the pockets with possible pieces for empty_pocket in ("[]", "[-]"): if empty_pocket in FEN: pocket = "".join([ i for i in set(FEN.split()[0]) if i in string.ascii_letters and i not in "Kk" ]) parts = FEN.split(empty_pocket) FEN = "%s[%s]%s" % (parts[0], pocket, parts[1]) board = FairyBoard(variant, initial_fen=FEN) moves = board.legal_moves() saved_restored = decode_moves(encode_moves(moves, variant), variant) self.assertEqual(saved_restored, moves)
async def save_game(self, with_clocks=False): if self.saved: return self.stopwatch.kill() if self.board.ply > 0: self.app["g_cnt"] -= 1 response = {"type": "g_cnt", "cnt": self.app["g_cnt"]} await lobby_broadcast(self.app["lobbysockets"], response) async def remove(keep_time): # Keep it in our games dict a little to let players get the last board # not to mention that BOT players want to abort games after 20 sec inactivity await asyncio.sleep(keep_time) try: del self.games[self.id] except KeyError: log.error("Failed to del %s from games" % self.id) if self.bot_game: try: if self.wplayer.bot: del self.wplayer.game_queues[self.id] if self.bplayer.bot: del self.bplayer.game_queues[self.id] except KeyError: log.error("Failed to del %s from game_queues" % self.id) self.saved = True loop = asyncio.get_event_loop() loop.create_task(remove(KEEP_TIME)) if self.board.ply < 3 and (self.db is not None): result = await self.db.game.delete_one({"_id": self.id}) log.debug("Removed too short game %s from db. Deleted %s game." % (self.id, result.deleted_count)) else: if self.result != "*": if self.rated: await self.update_ratings() if (not self.bot_game) and (not self.wplayer.anon) and ( not self.bplayer.anon): await self.save_crosstable() # self.print_game() new_data = { "d": self.date, "f": self.board.fen, "s": self.status, "r": R2C[self.result], 'm': encode_moves( map(grand2zero, self.board.move_stack) if self.variant in GRANDS else self.board.move_stack, self.variant) } if self.rated and self.result != "*": new_data["p0"] = self.p0 new_data["p1"] = self.p1 # Janggi game starts with a prelude phase to set up horses and elephants, so # initial FEN may be different compared to one we used when db game document was created if self.variant == "janggi": new_data["if"] = self.board.initial_fen if with_clocks: new_data["clocks"] = self.ply_clocks if self.manual_count: if self.board.count_started > 0: self.manual_count_toggled.append( (self.board.count_started, self.board.ply + 1)) new_data["mct"] = self.manual_count_toggled if self.db is not None: await self.db.game.find_one_and_update({"_id": self.id}, {"$set": new_data})
async def import_game(request): data = await request.post() app = request.app db = app["db"] users = app["users"] # print("---IMPORT GAME---") # print(data) # print("-----------------") wp = data["White"] bp = data["Black"] if wp in users: wplayer = users[wp] else: wplayer = User(app, username=wp, anon=True) users[wp] = wplayer if bp in users: bplayer = users[bp] else: bplayer = User(app, username=bp, anon=True) users[bp] = bplayer variant = data.get("Variant", "chess").lower() initial_fen = data.get("FEN", "") final_fen = data.get("final_fen", "") status = int(data.get("Status", UNKNOWNFINISH)) result = data.get("Result", "*") try: date = data.get("Date", "")[0:10] date = map(int, date.split("." if "." in date else "/")) date = datetime(*date, tzinfo=timezone.utc) except Exception: log.exception("Date tag parsing failed") date = datetime.now(timezone.utc) try: minute = False tc = data.get("TimeControl", "").split("+") if tc[0][-1] == "分": minute = True tc[0] = tc[0][:-1] if tc[1][-1] == "秒": tc[1] = tc[1][:-1] tc = list(map(int, tc)) base = int((tc[0] / 60) if not minute else tc[0]) inc = int(tc[1]) except Exception: log.exception("TimeControl tag parsing failed") base, inc = 0, 0 move_stack = data.get("moves", "").split(" ") moves = encode_moves( map(grand2zero, move_stack) if variant in GRANDS else move_stack, variant) game_id = await new_id(None if db is None else db.game) existing = await db.game.find_one({'_id': {'$eq': game_id}}) if existing: message = "Failed to create game. Game ID %s allready in mongodb." % game_id log.exception(message) return web.json_response({"error": message}) try: print(game_id, variant, initial_fen, wplayer, bplayer) new_game = Game(app, game_id, variant, initial_fen, wplayer, bplayer, rated=IMPORTED, create=False) except Exception: message = "Creating new Game %s failed!" % game_id log.exception(message) return web.json_response({"error": message}) document = { "_id": game_id, "us": [wplayer.username, bplayer.username], "v": V2C[variant], "b": base, "i": inc, "bp": new_game.byoyomi_period, "m": moves, "d": date, "f": final_fen, "s": status, "r": R2C[result], "x": new_game.level, "y": IMPORTED, "z": int(new_game.chess960), "by": data["username"], } if initial_fen or new_game.chess960: document["if"] = new_game.initial_fen if variant.endswith("shogi") or variant in ("dobutsu", "gorogoro", "gorogoroplus"): document["uci"] = 1 wrating = data.get("WhiteElo") brating = data.get("BlackElo") if wrating: document["p0"] = {"e": wrating} if brating: document["p1"] = {"e": brating} print(document) result = await db.game.insert_one(document) print("db insert IMPORTED game result %s" % repr(result.inserted_id)) return web.json_response({"gameId": game_id})
async def save_game(self, analysis=False): self.stopwatch.kill() async def remove(): # Keep it in our games dict a little to let players get the last board # not to mention that BOT players want to abort games after 20 sec inactivity await asyncio.sleep(60 * 10) try: del self.games[self.id] except KeyError: log.error("Failed to del %s from games" % self.id) if self.bot_game: try: if self.wplayer.bot: del self.wplayer.game_queues[self.id] if self.bplayer.bot: del self.bplayer.game_queues[self.id] except KeyError: log.error("Failed to del %s from game_queues" % self.id) if self.saved: return self.saved = True loop = asyncio.get_event_loop() self.tasks.add(loop.create_task(remove())) if self.ply < 3: result = await self.db.game.delete_one({"_id": self.id}) log.debug("Removed too short game %s from db. Deleted %s game." % (self.id, result.deleted_count)) else: self.print_game() if analysis: new_data = {"a": [step["analysis"] for step in self.steps]} else: new_data = { "d": self.date, "f": self.board.fen, "s": self.status, "r": R2C[self.result], 'm': encode_moves( map(usi2uci, self.board.move_stack) if self.variant[-5:] == "shogi" else map(grand2zero, self.board.move_stack) if self.variant == "xiangqi" or self.variant == "grand" or self.variant == "grandhouse" or self.variant == "shako" else self.board.move_stack, self.variant) } if self.rated and self.result != "*": new_data["p0"] = self.p0 new_data["p1"] = self.p1 await self.db.game.find_one_and_update({"_id": self.id}, {"$set": new_data})
async def save_game(self): if self.saved: return self.stopwatch.kill() if self.ply > 0: self.app["g_cnt"] -= 1 response = {"type": "g_cnt", "cnt": self.app["g_cnt"]} await lobby_broadcast(self.app["websockets"], response) async def remove(keep_time): # Keep it in our games dict a little to let players get the last board # not to mention that BOT players want to abort games after 20 sec inactivity await asyncio.sleep(keep_time) try: del self.games[self.id] except KeyError: log.error("Failed to del %s from games" % self.id) if self.bot_game: try: if self.wplayer.bot: del self.wplayer.game_queues[self.id] if self.bplayer.bot: del self.bplayer.game_queues[self.id] except KeyError: log.error("Failed to del %s from game_queues" % self.id) self.saved = True loop = asyncio.get_event_loop() loop.create_task(remove(KEEP_TIME)) if self.ply < 3 and (self.db is not None): result = await self.db.game.delete_one({"_id": self.id}) log.debug("Removed too short game %s from db. Deleted %s game." % (self.id, result.deleted_count)) else: if self.result != "*": if self.rated: await self.update_ratings() if (not self.bot_game) and (not self.wplayer.anon) and ( not self.bplayer.anon): await self.save_crosstable() # self.print_game() new_data = { "d": self.date, "f": self.board.fen, "s": self.status, "r": R2C[self.result], 'm': encode_moves( map(grand2zero, self.board.move_stack) if self.variant == "xiangqi" or self.variant == "grand" or self.variant == "grandhouse" or self.variant == "shako" else self.board.move_stack, self.variant) } if self.rated and self.result != "*": new_data["p0"] = self.p0 new_data["p1"] = self.p1 if self.db is not None: await self.db.game.find_one_and_update({"_id": self.id}, {"$set": new_data})
async def save_game(self): if self.saved: return self.saved = True if self.rated == IMPORTED: log.exception("Save IMPORTED game %s ???", self.id) return self.stopwatch.clock_task.cancel() try: await self.stopwatch.clock_task except asyncio.CancelledError: pass if self.board.ply > 0: self.app["g_cnt"][0] -= 1 response = {"type": "g_cnt", "cnt": self.app["g_cnt"][0]} await lobby_broadcast(self.app["lobbysockets"], response) async def remove(keep_time): # Keep it in our games dict a little to let players get the last board # not to mention that BOT players want to abort games after 20 sec inactivity await asyncio.sleep(keep_time) try: del self.games[self.id] except KeyError: log.info("Failed to del %s from games", self.id) if self.bot_game: try: if self.wplayer.bot: del self.wplayer.game_queues[self.id] if self.bplayer.bot: del self.bplayer.game_queues[self.id] except KeyError: log.info("Failed to del %s from game_queues", self.id) self.remove_task = asyncio.create_task(remove(KEEP_TIME)) if self.board.ply < 3 and (self.db is not None) and (self.tournamentId is None): result = await self.db.game.delete_one({"_id": self.id}) log.debug( "Removed too short game %s from db. Deleted %s game.", self.id, result.deleted_count, ) else: if self.result != "*": if self.rated == RATED: await self.update_ratings() if (not self.bot_game) and (not self.wplayer.anon) and ( not self.bplayer.anon): await self.save_crosstable() if self.tournamentId is not None: try: await self.app["tournaments"][self.tournamentId ].game_update(self) except Exception: log.exception("Exception in tournament game_update()") new_data = { "d": self.date, "f": self.board.fen, "s": self.status, "r": R2C[self.result], "m": encode_moves( map(grand2zero, self.board.move_stack) if self.variant in GRANDS else self.board.move_stack, self.variant, ), } if self.rated == RATED and self.result != "*": new_data["p0"] = self.p0 new_data["p1"] = self.p1 # Janggi game starts with a prelude phase to set up horses and elephants, so # initial FEN may be different compared to one we used when db game document was created if self.variant == "janggi": new_data["if"] = self.board.initial_fen if self.rated == RATED: new_data["t"] = [p["movetime"] for p in self.ply_clocks] if self.tournamentId is not None: new_data["wb"] = self.wberserk new_data["bb"] = self.bberserk if self.manual_count: if self.board.count_started > 0: self.manual_count_toggled.append( (self.board.count_started, self.board.ply + 1)) new_data["mct"] = self.manual_count_toggled if self.db is not None: await self.db.game.find_one_and_update({"_id": self.id}, {"$set": new_data})