def enemyNextMove(enemy: Enemy, game: Dungeon): """ Selects the next move for a given enemy according to the predetermined move strategies for enemies. If no valid moves are possible, then returns the enemy's location. """ enemyBoardNum = whichBoardInLevel(game.levels[game.currLevel], enemy.location) possMoves = enemyPossibleMoves(enemy, game) log("possible enemy moves to choose from:", str(possMoves)) if len(possMoves) == 0: return enemy.location playersInOurRoom, playersInOurLevel = getPlayersInRoomAndLevel( enemyBoardNum, game) if len(playersInOurRoom) != 0: playerLocs = [player.location for player in playersInOurRoom] return enemyStrat(possMoves, playerLocs) elif len(playersInOurLevel) != 0: playerLocs = [player.location for player in playersInOurLevel] return enemyStrat(possMoves, playerLocs) else: # No valid move log("shouldn't EVER EZVER EVER get here. green man you must MOVE") return enemy.location
def benchmark_B(handsfile): from MrIf import MrIf from MrGreed import MrGreed from MrZeroTree import MrZeroTree from OfflineInterface import OfflineInterface, read_std_hands, play_a_test ifs = [MrIf(room=255, place=i, name='I%d' % (i)) for i in range(4)] gs = [MrGreed(room=255, place=i, name='G%d' % (i)) for i in range(4)] zs = [ MrZeroTree(room=255, place=i, name='Z%d' % (i), mcts_b=10, mcts_k=2, sample_b=-1, sample_k=-2) for i in [0, 2] ] I_GI = OfflineInterface([gs[0], ifs[1], gs[2], ifs[3]], print_flag=False) I_ZG = OfflineInterface([zs[0], gs[1], zs[1], gs[3]], print_flag=False) hands = read_std_hands(handsfile) stats = [] for k, hand in hands: stats.append(play_a_test(I_ZG, hand, 2)) print("%4d" % (stats[-1], ), end=" ", flush=True) else: print("") log("benchmark result: %.2f %.2f" % (numpy.mean(stats), numpy.sqrt(numpy.var(stats) / (len(stats) - 1))))
def save_to_checkpoint(self, path=None): if path is None: path = self.config.checkpoint_path self.saver.save(self.sess, path + 'model.ckpt', global_step=self.global_step) log('checkpoint has been saved to :' + path + 'model.ckpt')
def gen_data_for_o(N1=2,N2=1,save=False): from OfflineInterface import OfflineInterface import pickle global for_o for_o=([],[],[],[]) g=[MrGreed(room=0,place=i,name='greed%d'%(i)) for i in range(4)] offlineinterface=OfflineInterface(g,print_flag=False) stats=[] for k,l in itertools.product(range(N1),range(N2)): if l==0: cards=offlineinterface.shuffle() else: cards=cards[39:52]+cards[0:39] offlineinterface.shuffle(cards=cards) for i,j in itertools.product(range(13),range(4)): offlineinterface.step() stats.append(offlineinterface.clear()) print(".",end=" ",flush=True) offlineinterface.prepare_new() print("") if save: with open("Greed_%d.data"%(N1),'wb') as f: pickle.dump(for_o,f) log("saved") return for_o
def example_DJ(): zt3 = MrZeroTree(room=255, place=3, name='zerotree3', mcts_b=10, mcts_k=2, sample_b=-1, sample_k=-2) zt3.cards_list = [ "HQ", "HJ", "H8", "SA", "S5", "S4", "S3", "CQ", "CJ", "C4" ] zt3.cards_on_table = [1, "DJ", "D8"] zt3.history = [[0, "H3", "H5", "H4", "H7"], [3, "S6", "SJ", "HK", "S10"], [0, "DQ", "DA", "D9", "D3"]] zt3.scores = [["HK"], [], [], ["H3", "H5", "H4", "H7"]] """cards_dict=MrGreed.gen_cards_dict(zt3.cards_list) legal_choice=MrGreed.gen_legal_choice("D",cards_dict,zt3.cards_list) zt3.select_interact_cards(legal_choice)""" """cards_played,scores_stage,void_info_stage=zt3.public_info() log(cards_played) for i in range(14): log("after stage %d: %s\n%s"%(i,scores_stage[i],void_info_stage[i]),end="") input()""" #log(zt3.pick_a_card()) #return l = [zt3.pick_a_card() for i in range(50)] log("%d %d %d" % (len([i[0] for i in l if i[0] == "H" ]), len([i[0] for i in l if i[0] == "C" ]), len([i[0] for i in l if i[0] == "S"])))
def stat_r_log(fname): import re,numpy from Util import INIT_CARDS with open(fname,"r") as f: lines=f.readlines() dict_val={};dict_reg={} for l in lines: if "reg" in l: add_dict(l.split("reg")[1],dict_reg) elif "r/beta" in l: add_dict(l.split("r/beta")[1],dict_val) l_val=[(c,numpy.mean(dict_val[c]),numpy.sqrt(numpy.var(dict_val[c])),numpy.var(dict_val[c])/numpy.sqrt(len(dict_val[c])-1)) for c in INIT_CARDS] l_reg=[(c,numpy.mean(dict_reg[c]),numpy.sqrt(numpy.var(dict_reg[c])),numpy.var(dict_reg[c])/numpy.sqrt(len(dict_reg[c])-1)) for c in INIT_CARDS] """line_vals=[] for i in range(4): val=[v for c,v,s,e in l_val[i*13:i*13+13]] err=[e for c,v,s,e in l_val[i*13:i*13+13]] line_vals.append((l_val[i*13][0][0],val,err))""" line_val_vars=[] for i in range(4): var=[float("%.4f"%(s)) for c,v,s,e in l_val[i*13:i*13+13]] line_val_vars.append((l_val[i*13][0][0],var)) line_regs=[] for i in range(4): val=[float("%.4f"%(v)) for c,v,s,e in l_reg[i*13:i*13+13]] err=[float("%.1e"%(e)) for c,v,s,e in l_reg[i*13:i*13+13]] line_regs.append((l_reg[i*13][0][0],val,err)) """line_reg_vars=[] for i in range(4): var=[s for c,v,s,e in l_reg[i*13:i*13+13]] line_reg_vars.append((l_reg[i*13][0][0],var))""" log(line_regs) log(line_val_vars)
def close(self): """ Closes the database connection. After calling this method, the instance will become unusable. """ log(LogLevel.Info, "Closing database connection.") self._db_close() self.active = False
def main(): from MrZeroTree import BETA,MCTS_EXPL,BENCH_SMP_B,BENCH_SMP_K log("BETA: %.2f, VALUE_RENORMAL: %d, MCTS_EXPL: %d, BENCH_SMP_B: %d, BENCH_SMP_K: %.1f"\ %(BETA,VALUE_RENORMAL,MCTS_EXPL,BENCH_SMP_B,BENCH_SMP_K)) pv_net=PV_NET();log("init pv_net: %s"%(pv_net)) #start_from="./ZeroNets/from-zero-14d/PV_NET-17-9479221-450.pkl" #pv_net=torch.load(start_from);log("start from: %s"%(start_from)) train(pv_net)
def save(self): """ Saves this Thing to the database, only if it has been changed since it was last loaded. """ if self._dirty: log(LogLevel.Trace, "ThingProxy#{0}: Saving dirty Thing".format(self._id)) self._thing.force_save() self._dirty = False
def getWorld(): global _world if not _world: # Instantiate singleton log(LogLevel.Debug, "Instantiating world singleton") _world = World() return _world
def test_3rd(): g0=MrGreed(room=0,place=0,name="if0") g0.history=[(0,'C2','C3','C4','C5'),(3,'C6','C7','D2','C8'),(2,'D3','D4','D5','D6'),(1,'S2','S3','S4','S5')] g0.cards_list=['H6','H7','HJ','HA','SQ','DJ','DK'] g0.cards_on_table=[2,'H8','HQ'] #g0.cards_on_table=[2,'CA','CJ'] log(g0.cards_list) log(g0.pick_a_card())
def test_da(): global print_level print_level=2 g0=MrGreed(room=0,place=0,name="g0") g0.cards_list=['H2','H3','H4','H5','H6','H7','H8','H9','HJ','D9','DA'] g0.history=[(2,'D3','D4','DJ','D6'),(1,'S2','S3','S4','S5')] g0.cards_on_table=[2, 'D7', 'D8'] g0.scores=[[],[],[],['DJ']] log(g0.pick_a_card())
def save_object(self, thing): """ Saves a modified object back to the database. """ if not active: raise DatabaseNotConnected() log(LogLevel.Trace, "Saving {0} to the database...".format(thing)) assert thing is not None, "Cannot save None!" self._db_save_object(thing)
def log_source(s): s = s.split("\n") s2 = [] for j, i in enumerate(s): if not i.strip().startswith("#") and len(i.strip()) > 0: #if i.strip().startswith("if"): # s2.append(s[j-1]) s2.append(i) log("\n".join(s2))
def connectionMade(self): h = self.transport.getHost() if type(h) is SSHTransportAddress: self.sshmode = True h = h.address log(LogLevel.Info, "Incoming connection from {0}".format(h)) self.host = h.host if self.avatar: self.player = self.world.connect(self.avatar.username) self.complete_login()
def test_legal_mask(): n0 = MrNN(room=0, place=0, name="n0") n0.cards_list = [ 'S4', 'S6', 'S9', 'SA', 'H7', 'HK', 'DJ', 'C7', 'C8', 'CQ' ] n0.cards_on_table = [3, 'H8'] mycards_oh = n0.gen_mycards_oh() log("get mycards_oh: %s" % (mycards_oh)) legal_mask = n0.gen_legal_mask(mycards_oh) log("get legal_mask: %s" % (legal_mask))
def pick_a_card(self, suit=None): suit = self.decide_suit() log("%s, %s, %s, %s" % (self.name, suit, self.cards_on_table, self.cards_list)) while True: choice = input("your turn: ") if choice in self.cards_list: break else: log("%s is not your cards. " % (choice), end="") return choice
def test_by_touchstone(): h = [[0, 'CA', 'C10', 'CQ', 'C3'], [0, 'D3', 'DQ', 'D6', 'D9'], [1, 'S10', 'SA', 'SQ', 'SK'], [2, 'S4', 'SJ', 'S3', 'S6'], [3, 'H5', 'H8', 'H7', 'H9'], [2, 'H6', 'HJ', 'HQ', 'H10'], [0, 'S8', 'CK', 'CJ', 'S7'], [0, 'S9', 'D10', 'C6', 'S2'], [0, 'C9', 'C8', 'C4', 'D8'], [0, 'DK', 'D7', 'D4', 'DA'], [3, 'H4', 'HA', 'C7', 'HK']] s = ScenarioGen(2, h, [0, 'D5', 'C5'], ['C2', 'H3'], number=10, method=0) log(s.distribute_most_important(s.find_most_important())) log(s.void_info) print(list(s))
def lineReceived(self, line): log(LogLevel.Debug, "Received line: {0}".format(line)) try: self.user.process_line(line) except Exception as ex: from traceback import print_exc print_exc(ex) self.write_line("Suddenly the dungeon collapses!! You die... (Server error)") self.terminal.loseConnection() self._cpos_input() self.terminal.eraseToDisplayEnd() self.drawInputLine()
def possi_rectify(self, cards_lists, thisuit): """ posterior probability rectify cards_lists is in absolute order """ cards_lists = copy.deepcopy(cards_lists) scores = copy.deepcopy(self.scores) result = 1.0 for history in [ self.cards_on_table, ] + self.history[::-1]: if len(history) == 5: for c in history[1:]: if c in SCORE_DICT: scores[last_winner].remove(c) last_winner = history[0] cards_on_table = copy.copy(history) pnext = (cards_on_table[0] + len(history) - 1) % 4 for i in range(len(cards_on_table) - 1): pnext = (pnext - 1) % 4 choice = cards_on_table.pop() cards_lists[pnext].append(choice) #不用修正我自己 if pnext == self.place: continue #决定是否需要修正 nece = self.decide_rect_necessity(thisuit, choice) if nece < 0: continue suit = cards_on_table[1][0] if len(cards_on_table) > 1 else "A" cards_dict = MrGreed.gen_cards_dict(cards_lists[pnext]) legal_choice = MrGreed.gen_legal_choice( suit, cards_dict, cards_lists[pnext]) possi_pvnet = self.possi_rectify_pvnet(cards_lists, scores, cards_on_table, pnext, legal_choice, choice) if print_level >= 4: log("rectify %s(%d): %.4e" % (choice, nece, possi_pvnet), end="") input() result *= possi_pvnet else: assert len(scores[0]) == len(scores[1]) == len(scores[2]) == len( scores[3]) == 0, "scores left not zero: %s" % (scores, ) assert len(cards_lists[0]) == len(cards_lists[1]) == len( cards_lists[2]) == len( cards_lists[3]) == 13, "cards_lists not equal 4x13: %s" % ( cards_lists, ) if print_level >= 3: log("final cards possi: %.4e" % (result)) return result
def pick_a_card(self): #确认桌上牌的数量和自己坐的位置相符 assert (self.cards_on_table[0] + len(self.cards_on_table) - 1) % 4 == self.place #utility datas suit = self.decide_suit() #inherited from MrRandom cards_dict = MrGreed.gen_cards_dict(self.cards_list) #如果别无选择 if cards_dict.get(suit) != None and len(cards_dict[suit]) == 1: choice = cards_dict[suit][0] if print_level >= 1: log("I have no choice but %s" % (choice)) return choice if print_level >= 1: log("my turn: %s, %s" % (self.cards_on_table, self.cards_list)) fmt_scores = MrGreed.gen_fmt_scores( self.scores ) #in absolute order, because self.scores is in absolute order #log("fmt scores: %s"%(fmt_scores)) d_legal = { c: 0 for c in MrGreed.gen_legal_choice(suit, cards_dict, self.cards_list) } #dict of legal choice sce_gen = ScenarioGen(self.place, self.history, self.cards_on_table, self.cards_list, number=MrRandTree.N_SAMPLE, METHOD1_PREFERENCE=100) for cards_list_list in sce_gen: cards_lists = [None, None, None, None] cards_lists[self.place] = copy.copy(self.cards_list) for i in range(3): cards_lists[(self.place + i + 1) % 4] = cards_list_list[i] if print_level >= 1: log("get scenario: %s" % (cards_lists)) cards_on_table_copy = copy.copy(self.cards_on_table) gamestate = GameState(cards_lists, fmt_scores, cards_on_table_copy, self.place) searcher = mcts(iterationLimit=200, explorationConstant=100) searcher.search(initialState=gamestate) for action, node in searcher.root.children.items(): if print_level >= 1: log("%s: %s" % (action, node)) d_legal[action] += node.totalReward / node.numVisits if print_level >= 1: log("d_legal: %s" % (d_legal)) input("press any key to continue...") best_choice = MrGreed.pick_best_from_dlegal(d_legal) return best_choice
def requestAvatarId(self, credentials): try: user = credentials.username if self.db.player_login(user, credentials.password) == -1: log(LogLevel.Info, "{0} failed user authentication".format(user)) return defer.fail(cred_error.UnauthorizedLogin("Authentication failure: No such user or bad password")) else: log(LogLevel.Debug, "Successful auth for {0}".format(user)) return defer.succeed(user) except Exception as e: from traceback import print_exc print_exc(e)
def test_net_accu(net, testloder): with torch.no_grad(): test_iter = testloder.__iter__() i = test_iter.__next__() netout = net(i[0]) test_loss = F.l1_loss(netout.view(-1), i[1]) try: test_iter.__next__() log("testloader can still be loaded!") raise KeyBoardInterrupt except StopIteration: pass return test_loss
def test_greed_play(): cards = copy.copy(INIT_CARDS) cards.remove('S2') cards.remove('S3') random.shuffle(cards) cards_ll = [cards[0:12], cards[12:24], cards[24:37], cards[37:50]] for i in cards_ll: i.sort(key=cards_order) log(cards_ll) fmt_score_l = [[0, 0, False, False], [0, 0, False, False], [0, 0, False, False], [0, 0, False, False]] s = Leaf.produce_1(['S2', 'S3'], cards_ll, 2, fmt_score_l) log(s.greed_play())
def complete_login(self): """ This code is run when a character is successfully connected to. """ self.my_state = State.LoggedIn log(LogLevel.Notice, "{0}#{1} connected from {2}".format(self.player.name, self.player.id, "<unknown>")) # Make them look around and check their inventory location = self.player.parent # Get room that the player is in self.send_message( "Welcome, {0}! You are currently in: {1}\r\n{2}".format( self.player.name, location.name, location.get_desc_for(self.player) ) ) self.send_message("You are carrying: {0}".format(", ".join(map(lambda x: x.name, self.player.contents))))
def get_thing(self, obj): """ Retrieves the Thing with the given database ID. Actually returns a ThingProxy that facilitates lazy-loading of Things and allows Things to be unloaded in the background to save memory, and transparently loaded again upon demand. """ if not obj in self.cache: log(LogLevel.Trace, "Cache: MISS #{0}".format(obj)) return self.ThingProxy(self, obj) else: log(LogLevel.Trace, "Cache: Hit #{0}".format(obj)) return self.cache[obj]
def complete_login(self): """ This code is run after a character is successfully connected to. When this function is called, the self.player object should already be initialized. """ self.my_state = State.LoggedIn log(LogLevel.Notice, "{0}#{1} connected from {2}".format(self.player.name, self.player.id, '<unknown>')) self.send_message("To disconnect, type @quit") # Make them look around and check their inventory location = self.player.parent # Get room that the player is in self.send_message("Welcome, {0}! You are currently in: {1}\r\n{2}".format(self.player.name, location.name, location.get_desc_for(self.player))) self.send_message("You are carrying: {0}".format(', '.join(map(lambda x: x.name, self.player.contents))))
def player_login(self, username, password): """ Verifies a player login. Returns -1 if login failed, or a database ID if successful. Password may be None to locate a player by username without verifying """ if not active: raise DatabaseNotConnected() log( LogLevel.Trace, "Verifying salted sha1 password hash for user {0}, password {1} (redacted)".format( username, "*" * len(password) ), ) result = self._db_get_user(username) if not result: log(LogLevel.Trace, "No matching records in database") return -1 pwhash, salt, obj = result log( LogLevel.Trace, "Successfully retrieved hash={0}, salt={1}, obj={2} from database".format(pwhash, salt, obj) ) ret = obj if pwhash == self.hash_pass(password, salt.decode("hex_codec")) else -1 if ret == -1: log(LogLevel.Debug, "Password hash mismatch for user {0}".format(username)) return ret
def test_with_c10(): para_dir = "./NetPara20200715/" n0 = MrNN(room=0, place=0, name="n0") n0.prepare_net([(NN_First, para_dir + 'NN_First_11_121012.ckpt'), (NN_Second, para_dir + 'NN_Second_9_126004.ckpt'), (NN_Third, para_dir + 'NN_Third_7_130996.ckpt'), (NN_Last, para_dir + 'NN_Last_5_135988.ckpt')]) n0.cards_list = [ 'C3', 'CA', 'H2', 'H3', 'H4', 'H5', 'H6', 'H7', 'H8', 'H9', 'H10' ] n0.history = [(2, 'D3', 'D4', 'DJ', 'D6'), (1, 'S2', 'HJ', 'SQ', 'S5')] n0.cards_on_table = [2, 'C2', 'C10'] n0.scores = [['DJ'], [], ['HJ'], ['SQ', 'HA', 'HQ', 'HK']] log(n0.pick_a_card())
def manually_test(save_name): device_cpu=torch.device("cpu") pv_net=torch.load(save_name) pv_net.to(device_cpu) zt=MrZeroTree(room=255,place=3,name='zerotree3',pv_net=pv_net,device=device_cpu,train_mode=True) g=[MrGreed(room=255,place=i,name='greed%d'%(i)) for i in [0,1,2]] interface=OfflineInterface([g[0],g[1],g[2],zt],print_flag=True) interface.shuffle() for i,j in itertools.product(range(13),range(4)): interface.step() input() log(interface.clear()) interface.prepare_new()
def dataReceived(self, data): "When data is received, process it according to state." if self.sshmode: # TODO: Is "sshmode" ever used now that everything is split out into SSHProtocol? self.transport.write(data) if data == '\r': self.transport.write('\n') data = data.translate('\r', '\n') # Split to completed lines lines = filter(len, data.split('\n')) # eliminate empty lines lines[0] = self.buf+lines[0] self.buf = lines[-1] for line in lines[:-1]: self.process_line(line.strip()) else: log(LogLevel.Debug, "Received data without terminating newline, buffering: {0}".format(repr(data))) self.buf += data
def go(self, action): """Finds an action named action and executes it.""" # TODO: Execute actions #actions = filter(lambda x: x.type is Action, self.parent.contents + self.contents) actions = [x for x in self.parent.contents + self.contents if x.type is Action] #TODO: Search order log(LogLevel.Trace, "Found actions: {0}".format(repr(actions))) if exit.startswith('#'): actions = [x for x in actions if exit[1:] == x.id()] #actions = filter(lambda x: exit[1:] == x.id(), actions) else: actions = [x for x in actions if x.name.lower.startswith(exit.lower)] #actions = filter(lambda x: x.name.lower().startswith(exit.lower()), actions) if not actions: return "You can't go that way." elif len(actions) > 1: return "I don't know which one you mean!"
def example_SQ2(): zt3 = MrZeroTree(room=255, place=3, name='zerotree3', mcts_b=10, mcts_k=2, sample_b=-1, sample_k=-2) zt3.cards_list = [ "HQ", "HJ", "H8", "H7", "SA", "S3", "CJ", "C4", "CQ", "D3", "D10" ] zt3.cards_on_table = [2, "S6"] zt3.history = [[0, "S7", "SK", "S10", "S8"], [1, "C2", "C9", "C8", "C7"]] zt3.scores = [[], [], [], []] log(zt3.pick_a_card())
def purge_cache(self, expiry=3600): #TODO: Rename this function? """ Remove from the cache all cached objects older than the given time. Save any objects that have been modified since they were cached. """ threshold = int(time.time()) - expiry # Threshold is a time in the past cachesize = len(self.cache) #self.cache = [x for x in self.cache if x[1] > threshold] objects = self.live_set.copy() for obj in objects: if obj.cachetime < threshold: obj.unload() # Save and unload the object elif obj.dirty: obj.save() log(LogLevel.Trace, "Cache: Purged {0} stale objects from memory".format(len(objects)-len(self.live_set)))
def benchmark(save_name, epoch, device_num, print_process=False): """ benchmark raw network against MrGreed will be called by trainer """ import itertools, numpy N1 = 512 N2 = 2 log("start benchmark against MrGreed for %dx%d" % (N1, N2)) zt = [ MrZeroTreeSimple(room=255, place=i, name='zerotree%d' % (i), pv_net=save_name, device="cuda:%d" % (device_num), mcts_b=0, mcts_k=1, sample_b=BENCH_SMP_B, sample_k=BENCH_SMP_K) for i in [0, 2] ] g = [MrGreed(room=255, place=i, name='greed%d' % (i)) for i in [1, 3]] interface = OfflineInterface([zt[0], g[0], zt[1], g[1]], print_flag=False) stats = [] for k, l in itertools.product(range(N1), range(N2)): if l == 0: cards = interface.shuffle() else: cards = cards[39:52] + cards[0:39] interface.shuffle(cards=cards) for i, j in itertools.product(range(13), range(4)): interface.step() stats.append(interface.clear()) interface.prepare_new() if print_process and l == N2 - 1: print("%4d" % (sum([j[0] + j[2] - j[1] - j[3] for j in stats[-N2:]]) / N2), end=" ", flush=True) s_temp = [j[0] + j[2] - j[1] - j[3] for j in stats] s_temp = [sum(s_temp[i:i + N2]) / N2 for i in range(0, len(s_temp), N2)] log("benchmark at epoch %s's result: %.2f %.2f" % (epoch, numpy.mean(s_temp), numpy.sqrt(numpy.var(s_temp) / (len(s_temp) - 1))))
def test_gen_num_tables(): s = ScenarioGen(0, [ [0, 'S2', 'S3', 'S4', 'S5'], [0, 'S6', 'S7', 'S8', 'S9'], [0, 'S10', 'SJ', 'SQ', 'SK'], [0, 'H2', 'H3', 'H4', 'H5'], [0, 'H6', 'H7', 'H8', 'H9'], [0, 'H10', 'HJ', 'HQ', 'HK'], [0, 'C2', 'C3', 'C4', 'C5'], [0, 'C6', 'C7', 'C8', 'C9'], [0, 'C10', 'CJ', 'CQ', 'D7'], ], [0, 'SA', 'HA', 'D2'], ['D3', 'D4', 'D5', 'D6'], number=10, method=3) #,method=1) for i in s: log(i) input()
def benchmark(): from MrRandom import MrRandom, Human from MrIf import MrIf from OfflineInterface import OfflineInterface g = [MrGreed(room=0, place=i, name='greed%d' % (i)) for i in range(4)] f = [MrIf(room=0, place=i, name="if%d" % (i)) for i in range(4)] r = [MrRandom(room=0, place=i, name="random%d" % (i)) for i in range(4)] rt = [ MrRandTree(room=0, place=i, name='randtree%d' % (i)) for i in range(4) ] offlineinterface = OfflineInterface([f[0], g[1], f[2], g[3]], print_flag=False) N1 = 1024 N2 = 2 stats = [] log("%s vs. %s for %dx%d" % (offlineinterface.players[0].family_name(), offlineinterface.players[1].family_name(), N1, N2)) tik = time.time() for k, l in itertools.product(range(N1), range(N2)): if l == 0: cards = offlineinterface.shuffle() else: cards = cards[39:52] + cards[0:39] offlineinterface.shuffle(cards=cards) for i, j in itertools.product(range(13), range(4)): offlineinterface.step() """if i==7 and j==2: global print_level print_level=1 offlineinterface.print_flag=True log("start outputs")""" stats.append(offlineinterface.clear()) offlineinterface.prepare_new() if l == N2 - 1: print("%4d" % (sum([j[0] + j[2] - j[1] - j[3] for j in stats[-N2:]]) / N2), end=" ", flush=True) #print("%s"%(stats[-1]),end=" ",flush=True) tok = time.time() log("time consume: %ds" % (tok - tik)) for i in range(4): s_temp = [j[i] for j in stats] log("%dth player: %.2f %.2f" % ( i, numpy.mean(s_temp), numpy.sqrt(numpy.var(s_temp) / (len(s_temp) - 1)), ), l=2) s_temp = [j[0] + j[2] - j[1] - j[3] for j in stats] log("%.2f %.2f" % (numpy.mean(s_temp), numpy.sqrt(numpy.var(s_temp) / (len(s_temp) - 1))))
def load_object(self, world, obj): """ Loads and returns an object out of the database. """ if not active: raise DatabaseNotConnected() result = self._db_load_object(obj) try: obtype = DBType(result[0]) except IndexError as e: raise ValueError("Unknown DBType {0} while loading #{1} from the database!".format(result[0], obj)) log(LogLevel.Debug, "We loaded {1}#{0} (type={2}) out of the database!".format(result[1], obj, obtype)) newobj = Thing_of_type(obtype)(world, obj, *result[1:]) log(LogLevel.Debug, "Database.load_object(): Returning {0}".format(repr(newobj))) return newobj
def __init__(self): # Sanity check sqlite version 3.6.19 or greater v = sqlite3.sqlite_version_info if(v[0] < 3 or (v[0] == 3 and (v[1] < 6 or v[1] == 6 and v[2] < 19) ) ): log(LogLevel.Warn, "Sqlite backend needs a newer version of Sqlite.") log(LogLevel.Warn, "You have: Sqlite {0[0]}.{0[1]}.{0[2]}".format(v)) log(LogLevel.Warn, "You need: Sqlite 3.6.19 or later") log(LogLevel.Warn, "Continuing anyway, but foreign key constraints will not work.") log(LogLevel.Info, "Opening sqlite database connection.") self.conn = sqlite3.connect('world.db') self.active = True c = self.conn.cursor() c.execute('PRAGMA foreign_keys = ON') self._db_create_schema(c) c.close() self.conn.commit()
def gameend(self): # self.players_information looks like [['Sun', True, False], ['Miss.if0', True, True], ['Miss.if1', True, True], ['Miss.if2', True, True]] #? self.res.append(self.scores_num[self.place]) should_record = True for i in range(self.place): if self.players_information[i][2]: should_record = False break if should_record: log("I, %s, should record." % (self.name)) s = "\n".join( [", ".join([str(i) for i in trick]) for trick in self.history]) s += '\nresult: %s\n\n' % (", ".join( [str(n) for n in self.scores_num])) fname = [pl[0] for pl in self.players_information] fname = "Records/" + "Records_" + "_".join(fname) + ".txt" log("writing to %s:\n%s" % (fname, s)) with open(fname, 'a') as f: f.write(s)
def test_last(): g0=MrGreed(room=0,place=0,name="if0") #红桃就是躲 g0.cards_list=['H3','H7','HJ','HA'] g0.cards_on_table=[1, 'HQ', 'H8', 'H2'] #羊要给队友 #g0.cards_list=['D2','D7','DJ','S5','S8','S10'] #g0.cards_on_table=[1, 'D8', 'DA', 'HJ'] #不能把猪给队友 #g0.cards_list=['D2','D7','DQ','S5','S8','SQ'] #g0.cards_on_table=[1, 'S8', 'SA', 'S2'] #有 好东西/坏东西 要 拿到/避开 #g0.cards_list=['D2','D7','DQ','S5','S7','S10'] #g0.cards_on_table=[1, 'S8', 'S2', 'DJ'] #不得猪的情况下尽可能出大的 #g0.cards_list=['D2','D7','DQ','S5','S8','S10'] #g0.cards_on_table=[1, 'S8', 'SJ', 'S2'] #无药可救时出大的 #g0.cards_list=['D2','D7','DQ','S5','S8','S10'] #g0.cards_on_table=[1, 'S8', 'SQ', 'S2'] log(g0.pick_a_card())
def test_accu(NetClass, FileName, order): net = NetClass() log(net) net.load_state_dict(torch.load(FileName)) testdata = [] parse_data("./Greed_batch/Greed_batch1.txt", testdata, order, max_num=128) testloder = torch.utils.data.DataLoader(testdata, batch_size=len(testdata)) with torch.no_grad(): test_iter = testloder.__iter__() i = test_iter.__next__() log("data size: %s" % (i[0].size(), )) netout = net(i[0]) test_loss = loss_func_mul(netout, i[2], i[1]) test_corr = correct_num(netout, i[2], i[1]) / len(i[2]) try: test_iter.__next__() log("testloader can still be loaded!") raise KeyBoardInterrupt except StopIteration: log("testloader indeed stoped") log("%f %f" % (test_loss, test_corr))
def example_SQ(): zt3 = MrZeroTree(room=255, place=3, name='zerotree3', mcts_b=10, mcts_k=2, sample_b=-1, sample_k=-2) zt3.cards_list = [ "HQ", "HJ", "H8", "H7", "SA", "S6", "S5", "S4", "S3", "CQ", "CJ", "D3" ] zt3.cards_on_table = [1, "S7", "SJ"] zt3.history = [ [1, "C9", "C7", "C4", "H9"], ] zt3.scores = [[], ["H9"], [], []] """cards_dict=MrGreed.gen_cards_dict(zt3.cards_list) legal_choice=MrGreed.gen_legal_choice("S",cards_dict,zt3.cards_list) zt3.select_interact_cards(legal_choice)""" cards_played, scores_stage, void_info_stage = zt3.public_info() log(cards_played) for i in range(6): log("after stage %d: %s\n%s" % (i, scores_stage[i], void_info_stage[i]), end="") input() return log(zt3.pick_a_card())
def cmd_connect(self, params): """ This command allows a user to log in as a particular character. This can be used when not logged in, but requires a password to do so. """ log(LogLevel.Debug, "Received connect command from {0}".format(self.transport.getHost().host)) if self.my_state > State.New: # Already connected self.send_message("You are already connected.") return if len(params) < 2: self.send_message("You must provide both a character name and a password.") return user = params[0] passwd = params[1] # Try and auth to an account self.player = self.world.connect(user, passwd) if self.player: self.complete_login() else: self.send_message("Your login failed. Try again.") return
def init_session(self, mode='Train'): log('initializing the model...') log('train_mode: %s' % mode) self.saver = tf.train.Saver() config = tf.ConfigProto() config.gpu_options.allow_growth = True config.log_device_placement = False #: 是否打印设备分配日志 config.allow_soft_placement = True # : 如果你指定的设备不存在,允许TF自动分配设备 self.sess = tf.Session(config=config) # check from checkpoint ckpt_path = self.config.checkpoint_path log('check the checkpoint_path : %s' % ckpt_path) ckpt = tf.train.get_checkpoint_state(ckpt_path) if ckpt and ckpt.model_checkpoint_path: log('restoring from %s' % ckpt.model_checkpoint_path) self.saver.restore(self.sess, ckpt.model_checkpoint_path) elif mode != 'Train': raise FileNotFoundError('Inference mode asks the checkpoint !') else: log('does not find the checkpoint, use fresh parameters') self.sess.run(tf.global_variables_initializer())
def benchmark(handsfile, print_process=False): from MrGreed import MrGreed from MrZeroTree import MrZeroTree from OfflineInterface import OfflineInterface, read_std_hands, play_a_test import torch, inspect log_source(inspect.getsource(MrZeroTree.decide_rect_necessity)) #log_source(inspect.getsource(MrZeroTree.possi_rectify_pvnet)) zt0 = [ MrZeroTree(room=255, place=i, name='zerotree%d' % (i), mcts_b=10, mcts_k=2, sample_b=-1, sample_k=-2) for i in [0, 2] ] team1 = [MrGreed(room=255, place=i, name='greed%d' % (i)) for i in [1, 3]] interface = OfflineInterface([zt0[0], team1[0], zt0[1], team1[1]], print_flag=False) if interface.players[0].family_name().startswith("MrZeroTree"): p0 = interface.players[0] log("mcts_b/k: %d/%d, sample_b/k: %d/%d" % (p0.mcts_b, p0.mcts_k, p0.sample_b, p0.sample_k)) hands = read_std_hands(handsfile) N1 = len(hands) N2 = 2 log("%s for %dx%d on %s" % (interface, N1, N2, zt0[0].device)) stats = [] for k, hand in hands: stats.append(play_a_test(interface, hand, N2)) print("%4d" % (stats[-1], ), end=" ", flush=True) if (k + 1) % (N1 // 4) == 0: bench_stat(stats, N2) bench_stat(stats, N2)
def __init__(self, world, obj, name, flags, parent_id, owner_id, link_id, money, created, modified, lastused): # Keep a reference to the world instance self.world = world # Set up properties cache self._propcache = {} self._propdirty = set() # Set basic params self._obj, self.name, self.flags, self.money = (obj, name, flags, money) self._created, self._modified, self._lastused = (created, modified, lastused) ### # Precache our description self._propcache['_/desc'] = world.db.get_property(obj, '_/desc') self.owner = world.get_thing(owner_id) self.parent = world.get_thing(parent_id) self.link = world.get_thing(link_id) if link_id is not None else None log(LogLevel.Trace, 'A new Thing was instantiated with (ID:{0}) (name:{1}) (parentID:{2})'.format(self._obj, self.name, self.parent.id))
def connectionLost(self, data): if self.my_state < State.LoggedIn: pass log(LogLevel.Info, "{0} lost connection: {1}".format(self.host, data.getErrorMessage())) else: try: log(LogLevel.Info, "{0}#{1} [{2}] lost connection: {3}".format(self.player.name, self.player.id, self.host, data.getErrorMessage())) except: log(LogLevel.Info, "<UNKNOWN> {0} lost connection: {1}".format(self.host, data.getErrorMessage()))
def main(): from MrZeroTreeSimple import BETA,MCTS_EXPL,BENCH_SMP_B,BENCH_SMP_K from MrZ_NETs import VALUE_RENORMAL log("BETA: %.2f, VALUE_RENORMAL: %d, MCTS_EXPL: %d, BENCH_SMP_B: %d, BENCH_SMP_K: %.1f"\ %(BETA,VALUE_RENORMAL,MCTS_EXPL,BENCH_SMP_B,BENCH_SMP_K)) from MrZ_NETs import PV_NET_2 dev_train=0 start_from=None # or a path to netpara file pv_net=PV_NET_2() log("init pv_net: %s"%(pv_net)) if start_from==None: log("start from: zero") else: pv_net.load_state_dict(torch.load(start_from)) log("start_from: %s"%(start_from)) train(pv_net,dev_train_num=dev_train,dev_bench_num=1)
def main(): import World log(LogLevel.Notice, 'Initializing world...') world = World.getWorld() # Note: Currently, World is a singleton #world.db.db_get_user('admin') log(LogLevel.Debug, "Setting up ServerFactory") factory = protocol.ServerFactory() factory.protocol = BasicUserSession reactor.listenTCP(8888, factory) reactor.listenTCP(8822, SSHFactoryFactory(world)) log(LogLevel.Notice, 'Now listening for connections.') log(LogLevel.Debug, 'Launching reactor.run() main loop') def onShutdown(): log(LogLevel.Notice, "Shutting down...") world.close() reactor.addSystemEventTrigger('before', 'shutdown', onShutdown) reactor.run()
def __init__(self, *params): Thing.__init__(self, *params) log(LogLevel.Debug, 'A new Player object was instantiated!')
def onShutdown(): log(LogLevel.Notice, "Shutting down...") world.close()
def SSHFactoryFactory(world): """ Creates and returns a factory class that produces SSH sessions. This function is responsible for loading the SSH host keys that our SSH server will use, or generating them if they do not exist (if possible). The reason why we have a double-factory setup is twofold: First, we need to dynamically load (or maybe generate) SSH host keys, and for some reason, Twisted's SSHFactory seems to require the SSH keys to be present as class attributes. The connection and userauth classes to use also need to be set this way. Second, this allows us to create a separate SSHFactory per world, should we ever run more than one world on a single server. """ import os, sys from twisted.python.procutils import which if not os.path.exists('host_rsa'): if not sys.platform.startswith('linux'): log(LogLevel.Error, "SSH host keys are missing and I don't know how to generate them on this platform") log(LogLevel.Warn, 'Please generate the files "host_rsa" and "host_rsa.pub" for me.') raise SystemExit(1) log(LogLevel.Warn, 'SSH host keys are missing, invoking ssh-keygen to generate them') paths = which('ssh-keygen') if len(paths) == 0: log(LogLevel.Error, 'Could not find ssh-keygen on this system.') log(LogLevel.Warn, 'Please generate the files "host_rsa" and "host_rsa.pub" for me.') raise SystemExit(1) ret = os.spawnl(os.P_WAIT, paths[0], 'ssh-keygen', '-q', '-t', 'rsa', '-f', 'host_rsa', '-P', '', '-C', 'textgame-server') if ret != 0: log(LogLevel.Error, 'Failed generating SSH host keys. Is ssh-keygen installed on this system?') raise SystemExit(1) else: log(LogLevel.Info, 'Successfully generated SSH host keys') publicKey = file('host_rsa.pub', 'r').read() privateKey = file('host_rsa', 'r').read() # Global ban list shared by all factories. banlist = [] from textgame.db import Credentials from twisted.cred.portal import Portal class SSHFactory(conch_factory.SSHFactory): """ Factory responsible for generating SSHSessions. This SSHFactory is functionally identical to the built-in Conch SSHFactory, but is pre-configured with our SSH host keys. We also configure the SSHFactory with the services we are providing. In this case we are using our UserAuthService (a subclass of the built-in Conch SSHUserAuthServer) to authenticate users, and the built-in SSHConnection class to handle incoming connections. The built-in classes are configured via the Portal that is stored in the portal attribute. """ publicKeys = { 'ssh-rsa': keys.Key.fromString(data=publicKey) } privateKeys = { 'ssh-rsa': keys.Key.fromString(data=privateKey) } services = { 'ssh-userauth': UserAuthService, 'ssh-connection': connection.SSHConnection } # We should really be getting this motd from the world instance bannerText = "HERE BE DRAGONS!\nThis software is highly experimental." + \ "Try not to break it.\nDebug logging is enabled. DO NOT enter any real passwords!\n" # This Portal is the conduit through which we authenticate users. # The SSHRealm will generate user instances after auth succeeds. portal = Portal(SSHRealm(world), [ # This checker allows the Portal to verify passwords. Credentials.CredentialsChecker(world.db), # This checker allows the Portal to verify SSH keys. SSHPublicKeyChecker( Credentials.AuthorizedKeystore(world.db)), # This "checker" will create a new user, instead of # authenticating an existing one. #Database.NewUserCreator(world.db) ]) def buildProtocol(self, addr): # Reject this connection if the IP is banned. if addr.host in banlist: log.info("Rejecting connection from banned IP {0}".format(addr.host)) return None # otherwise all good; let superclass do the rest log.info("Incoming SSH connection from {0}".format(addr.host)) return conch_factory.SSHFactory.buildProtocol(self, addr) def banHost(self, host, duration=None): """ Bans a host from connecting. """ #TODO: Timed bans? log.info("Banning IP {0}".format(host)) banlist.append(host) return SSHFactory()
def process_line(self, line): """ Processes a line of input from the user. """ if line == "": return words = line.split() cmd = words[0] params = words[1:] if len(words) > 1 else [] # Are we logged in? if self.my_state < State.LoggedIn: # Only prelogin commands may be used if words[0] in prelogincmds: commands[words[0]](self, params) else: self.send_message("You're not connected to a character.") return # Code execution only proceeds beyond this point on a logged in character. # Commands are checked in the following order: # 1. Special prefixes (including @commands and the "say and :pose builtins) # 2. Matching actions (in order: player, room, objects in room, and then parent rooms) # 3. Builtin commands that do not have a special prefix # Builtin say command if line[0] == '"': # Echo back to the player self.send_message('You say, "{0}"'.format(line[1:])) # Send message to others who can hear it # TODO: Insert code here return # pose command if line[0] == ":": # Echo back to the player self.send_message("{0} {1}".format(self.player.name, line[1:])) # Send message to others who can see it # TODO: Insert code here return # If input begins with @, skip looking for actions (an action should never # begin with a @ character). Otherwise... if line[0] != "@": # Start the search at the player thing = self.player while True: log(LogLevel.Trace, "Searching {0} for {1}".format(thing.name, words[0])) # Retrieve a list of Actions contained by this thing, which match the word entered actions = [ x for x in thing.contents if x.type is Things.Action and x.name.lower().startswith(words[0].lower()) ] log(LogLevel.Trace, "{0} contains {1}, matching: {2}".format(thing, thing.contents, actions)) # Process list, and return if actions were found if self.process_action_list(actions): return log(LogLevel.Trace, "Searching {0}'s contents for {1}".format(thing.name, words[0])) # Retrieve a list of Items contained by this thing, and look for Actions on them actions = reduce( lambda x, y: x + y, [ [ action for action in item.contents if action.type is Things.Action and action.name.lower().startswith(words[0].lower()) ] for item in thing.contents if item.type is Things.Item ], [], ) log(LogLevel.Trace, "{0}'s contents contain matching: {1}".format(thing, actions)) # Process list, and return if actions were found if self.process_action_list(actions): return # Move to this Thing's parent and keep searching, unless we reached Room #0 # in which case we are at the root of the parent tree and we give up. if thing.id == 0: break else: thing = thing.parent # Command dispatch map. Most commands should be accessed this way. if words[0] in commands.keys(): try: log( LogLevel.Debug, "{0} running command: {1}{2}".format( "{0}#{1}".format(self.player.name, self.player.id) if self.player else self.transport.getHost().host, words[0], "({0})".format(", ".join(params) if (words[0] not in ("connect", "@connect")) else "[redacted]") if params else "", ), ) except TypeError, e: log(LogLevel.Trace, "words: {0}, params: {1}".format(repr(words), repr(params))) log(LogLevel.Trace, "Exception: {0}".format(repr(e))) commands[words[0]](self, params) return
def _db_create_schema(self, cursor=None): """ Create tables as required. """ c = cursor if cursor else self.conn.cursor() # Obtain list of tables c.execute("""SELECT name FROM sqlite_master WHERE type='table'""") tables = [str(x[0]) for x in c.fetchall()] log(LogLevel.Debug, repr(tables)) # The "meta" table is a simple key-value table that stores metadata about the database. if 'meta' not in tables: c.execute(""" CREATE TABLE IF NOT EXISTS meta ( -- Stores metadata about the database, such as schema version number. -- This data is stored as simple key-value pairs. key TEXT PRIMARY KEY ASC, -- Key name value NONE -- Value, can be any type ) """) c.execute("""INSERT INTO meta VALUES ('schema_version', 0)""") log(LogLevel.Info, '- Created meta table.') # This table stores basic data about an object. # Extended data is stored in a separate table. This is done in order to # make it faster to do basic queries about an object. if 'objects' not in tables: c.execute(""" CREATE TABLE IF NOT EXISTS objects ( -- This table stores basic data about an object. -- Extended data is stored in other tables, or as properties. -- This should make it faster to perform basic queries on an object. id INTEGER PRIMARY KEY ASC, -- Primary database ID of this object (alias to built in rowid column) name TEXT NOT NULL, -- Name of the object type INTEGER NOT NULL, -- Type of the object (Room=0, Player=1, Item=2, Action=3, Script=4) flags INTEGER NOT NULL, -- Bitfield of object flags parent INTEGER NOT NULL, -- ID of the parent object (i.e. location) of this object owner INTEGER NOT NULL, -- ID of owner of this object link INTEGER DEFAULT NULL, -- Link to another object (home, or action). Null if unlinked. money INTEGER DEFAULT 0 NOT NULL, -- Amount of currency that this object contains -- The following timestamps are in unix time: created INTEGER DEFAULT (strftime('%s','now')), -- Time of creation modified INTEGER DEFAULT (strftime('%s','now')), -- Time last modified in any way lastused INTEGER DEFAULT (strftime('%s','now')), -- Time last used (without modifying it) desc TEXT, -- Object description - this field is deprecated FOREIGN KEY(parent) REFERENCES objects(id), FOREIGN KEY(owner) REFERENCES objects(id), FOREIGN KEY(link) REFERENCES objects(id), -- Enforce the four possible types of object. CHECK( type >= 0 AND type <= 4 ) ) """) log(LogLevel.Info, '- Created objects table.') c.execute("""CREATE INDEX IF NOT EXISTS parent_index ON objects(parent) -- Contents of an object is determined by finding all objects whose parent is the container.""") c.execute("""CREATE INDEX IF NOT EXISTS owner_index ON objects(owner) -- Allow looking up or filtering objects by owner.""") c.execute("""CREATE INDEX IF NOT EXISTS link_index ON objects(link) -- Allow looking up or filtering objects by link - is this needed?""") # Create Room #0 (Universe) and Player #1 (Creator) # Initially create "The Universe" as owning itself, due to constraints now = time.time() # id name typ flg par own link $ cre. mod. used desc t = [(0, 'The Universe', 0, 0, 0, 0, None, 0, now, now, now, None), # desc fields here are now deprecated (1, 'The Creator', 1, 0, 0, 1, None, 0, now, now, now, None), # Other test objects (2, 'no tea', 2, 0, 1, 1, 1, 0, now, now, now, None), (3, 'west', 3, 0, 0, 1, 0, 0, now, now, now, None), (4, 'drink', 3, 0, 2, 1, 0, 0, now, now, now, None), ] c.executemany("""INSERT INTO objects VALUES(?,?, ?,?,?,?,?, ?, ?,?,?, ?)""", t) # Set Room #0's owner as God c.execute("""UPDATE objects SET owner=1 WHERE id=0""") log(LogLevel.Info, '-- Created initial database objects.') # Create users table if it does not exist if 'users' not in tables: c.execute(""" CREATE TABLE IF NOT EXISTS users ( -- Stores login information about user accounts. username TEXT PRIMARY KEY, -- Username (is primary key) password TEXT, -- Password hash (hexadecimal) salt TEXT, -- Salt used in hash (hexadecimal) email TEXT, -- Email address obj INTEGER, -- Character reference -- Note: In future, the "obj" field will be removed and a separate table -- created which allows each account to have multiple characters associated. FOREIGN KEY(obj) REFERENCES objects(id) ) """) log(LogLevel.Info, '- Created users table.') # Create admin user pwhash, salt = self.create_hash('admin') t = ('admin', pwhash, salt, 'admin@localhost', 1) c.execute("""INSERT INTO users VALUES (?, ?, ?, ?, ?)""", t) log(LogLevel.Info, '-- Created admin user.') #TODO: Obliterate messages table in favor of using properties # Stores extended data about an object, currently comprised of the following data: # - Object's long-form description ( # if 'messages' not in tables: # c.execute("""CREATE TABLE IF NOT EXISTS messages ( # obj INTEGER, -- ID of object # succ TEXT, -- Success message # fail TEXT, -- Failure message # osucc TEXT, -- External success message # ofail TEXT, -- External failure message # 'drop' TEXT, -- Message when item is dropped or exit "drops" a player # FOREIGN KEY(obj) REFERENCES objects(id) # )""") # t = [(0, None, None, None, None, None), # (1, None, None, None, None, None), # (2, None, None, None, None, None), # (3, "Life is peaceful there...", "The way is closed.", None, None, None)] # c.executemany("""INSERT INTO messages VALUES (?, ?, ?, ?, ?, ?)""", t) # log(LogLevel.Info, '- Created messages table.') # Table for storing arbitrary 'properties' about an object. if 'props' not in tables: c.execute(""" CREATE TABLE IF NOT EXISTS props ( -- Stores arbitrary properties about an object. -- This is essentially a set of key/value pairs associated with an object. -- Each row holds a single key/value pair. -- At a database level, key names are arbitrary, but the server uses a -- directory structure maintained using a naming convention for the keys. obj INTEGER, -- ID of object key TEXT, -- Name of this property value TEXT, -- Value of this property FOREIGN KEY(obj) REFERENCES objects(id) ) """) # Index by id and key, unique index to ensure an id-key pairing cannot exist twice. c.execute(""" CREATE UNIQUE INDEX IF NOT EXISTS key_index ON props( obj, key -- Properties are uniquely indexed by id-key pairing. -- This constraint ensures that an object cannot have the same key twice, -- which ensures our INSERT OR REPLACE statement will work correctly. ) """) # Assign sample property values to our starting objects. t=[ (0, '_/desc', "You can't hear anything, see anything, smell anything, feel anything, or taste anything, and you do not even know where you are or who you are or how you got here."), (1, '_/desc', "The being that you see cannot be described."), (2, '_/desc', "You really wish you had a cup of tea right about now."), (3, '_/desc', "There's nothing exciting in that direction."), (3, '_/succ', "Life is peaceful there..."), (3, '_/fail', "The way is closed."), (4, '_/fail', "You can't drink tea that you don't have."), ] c.executemany("""INSERT INTO props VALUES (?, ?, ?)""", t) log(LogLevel.Info, '- Created props table.') # Contains a list of IDs whose objects have been marked as deleted. # When a user requests deletion of an object, it is flagged as deleted, # and its ID is added to this table. This gives users a chance to undo. # When a new object is created, the first ID in this table (if any) is # removed and claimed as the ID of the new object. # The details of the deleted object with that ID are then overwritten # with those of the new object, and the old object is lost forever. # This system allows IDs to be reused and doesn't leave "holes" in the database. if 'deleted' not in tables: c.execute(""" CREATE TABLE IF NOT EXISTS deleted ( -- This single-column table allows objects to be marked as deleted. -- This allows ID values to be reused. -- It also potentially allows recycled objects to be recovered. obj INTEGER, -- The ID of a deleted object FOREIGN KEY(obj) REFERENCES object(id) ) """) log(LogLevel.Info, '- Created deleted IDs table.') # Many-to-many table for locks if 'locks' not in tables: c.execute(""" CREATE TABLE IF NOT EXISTS locks ( -- This many-to-many table contains basic locks for objects. obj INTEGER, -- ID of the object. lock INTEGER, -- ID of an object that has a lock on this object. FOREIGN KEY(obj) REFERENCES objects(id), FOREIGN KEY(lock) REFERENCES objects(id) ) """) log(LogLevel.Info, '- Created locks table.') # Many-to-many table for access control list entries if 'acl' not in tables: c.execute(""" CREATE TABLE IF NOT EXISTS acl ( -- This many-to-many table contains Access Control List entries. obj INTEGER, -- ID of the object to which access is being controlled. player INTEGER, -- ID of a player object which has some degree of access. flags INTEGER, -- Flags which describe what degree of access is allowed. FOREIGN KEY(obj) REFERENCES objects(id), FOREIGN KEY(player) REFERENCES objects(id) ) """) log(LogLevel.Info, '- Created acl table.') if 'scripts' not in tables: c.execute(""" CREATE TABLE IF NOT EXISTS scripts ( -- This table stores the executable content of scripts. obj INTEGER, -- ID of script object type INTEGER, -- Type of script (0=lua) script TEXT, -- Script content FOREIGN KEY(obj) REFERENCES objects(id) ) """) log(LogLevel.Info, '- Created scripts table.') if not cursor: c.close()
def contents(self): """Retrieves a list of objects contained in this object.""" items = self.world.get_contents(self) log(LogLevel.Trace, "Obtained contents for {0}: {1}".format(repr(self), repr(items))) return items
def use(self, user): # NOTE: What does it mean to "use" an item? Is this item-defined? Check spec log(LogLevel.Trace, "{0} used {1}".format(user, self))
def SSHFactoryFactory(world): """ Creates and returns a factory class that produces SSH sessions. This function is responsible for loading the SSH host keys that our SSH server will use, or generating them if they do not exist (if possible). The reason why we have a double-factory setup is twofold: First, we need to dynamically load (or maybe generate) SSH host keys, and for some reason, Twisted's SSHFactory seems to require the SSH keys to be present as class attributes. The connection and userauth classes to use also need to be set this way. Second, this allows us to create a separate SSHFactory per world, should we ever """ import os, sys from twisted.python.procutils import which if not os.path.exists('host_rsa'): if not sys.platform.startswith('linux'): log(LogLevel.Error, "SSH host keys are missing and I don't know how to generate them on this platform") log(LogLevel.Warn, 'Please generate the files "host_rsa" and "host_rsa.pub" for me.') raise SystemExit(1) log(LogLevel.Warn, 'SSH host keys are missing, invoking ssh-keygen to generate them') paths = which('ssh-keygen') if len(paths) == 0: log(LogLevel.Error, 'Could not find ssh-keygen on this system.') log(LogLevel.Warn, 'Please generate the files "host_rsa" and "host_rsa.pub" for me.') raise SystemExit(1) ret = os.spawnl(os.P_WAIT, paths[0], 'ssh-keygen', '-q', '-t', 'rsa', '-f', 'host_rsa', '-P', '', '-C', 'textgame-server') if ret != 0: log(LogLevel.Error, 'Failed generating SSH host keys. Is ssh-keygen installed on this system?') raise SystemExit(1) else: log(LogLevel.Info, 'Successfully generated SSH host keys') publicKey = file('host_rsa.pub', 'r').read() privateKey = file('host_rsa', 'r').read() import Database from twisted.cred.portal import Portal class SSHFactory(conch_factory.SSHFactory): """ Factory responsible for generating SSHSessions. This SSHFactory is functionaly identical to the built-in Conch SSHFactory, but is pre-configured with our SSH host keys. We also configure the SSHFactory with the services we are providing. In this case we are using the built-in Conch SSHUserAuthServer to authenticate users, and the built-in SSHConnection class to handle incoming connections. These built-in classes are configured via the Portal that is stored in the portal attribute. """ publicKeys = { 'ssh-rsa': keys.Key.fromString(data=publicKey) } privateKeys = { 'ssh-rsa': keys.Key.fromString(data=privateKey) } services = { 'ssh-userauth': userauth.SSHUserAuthServer, 'ssh-connection': connection.SSHConnection } # This Portal tells us how to authenticate users portal = Portal(SSHRealm(world), [Database.CredentialsChecker(world.db)]) return SSHFactory()
def connectionMade(self): h = self.transport.getHost() log(LogLevel.Info, "Incoming connection from {0}".format(h))
def requestAvatar(self, avatarId, mind, *interfaces): if IConchUser in interfaces: return interfaces[0], SSHUser(self.world, avatarId), lambda: None else: log(LogLevel.Error, "SSHRealm: No supported interfaces") raise NotImplementedError("No supported interfaces found.")