def decide_online_tour_players(c, remote): """ Sig: Peer ==> array, dictionary Pre: Peer is connected to another peer Post: Array containing list of players on this side of connection, dictionary containing whether \ players are human or computer controlled """ # Determine number of players while True: choice = input("How many players on this computer? [" + g.color("G", "1-7") + "](maximum 8 total) ") if type(int(choice)) == int: choice = int(choice) if choice >= 1 and choice <= 7: break # Send number of players and ensure remote and local don't exceed 8 c.send(choice) print("Confirming number of players...") remote_choice = c.receive() if remote_choice + choice > 8: print("Your total is over 8. Try again") decide_online_tour_players(c, remote) nr_players = choice player_list = [] # Strings of names human_dict = {} # Booleans. Key = player. True = Human, False = NPC # Determine names and human/computer controlled while True: choice = input("How many AI players? [" + g.color("G", "0-" + str(nr_players)) + "] ") if type(int(choice)) == int: choice = int(choice) if choice <= nr_players: break nr_ai = choice # Name human players for player in range(nr_players - nr_ai): name = input("Name player" + str(player + 1) + ": ") player_list.append(name) human_dict[name] = True # Name AI players names = [ "SKYNET", "MAX HEADROOM", "WATSON", "DEEP THOUGHT", "J.A.R.V.I.S.", "R2D2", "MU-TH-UR 6000", "TÄNKANDE AUGUST" ] for nr in range(nr_ai): # This is to ensure that server/client dont create players with the same name if remote: name = names[nr] else: name = names[nr + 4] player_list.append(name) human_dict[name] = False return player_list, human_dict
def vmd_label(molid, key, selection="all", label_color="white", textsize=1.0, offset=(0.0, 0.0, 0.0), idx_offset=None): """ Labels atoms by index, charge, etc. Input: > molid int; index of molecule to label > key str; attribute to label atom by > textsize float; size of label font > offset (1,3)-list; offset to shift the label by > selection str; selected atoms > num_offset int; offset to add to atomic index """ # select atoms to label selected_atoms = atomsel.atomsel(selection, molid) # complete selection of all atoms in order to label just the ones needed complete_selection = atomsel.atomsel("all", molid) atom_idxs = selected_atoms.get("index") print(len(atom_idxs)) # get its coordinates xs = complete_selection.get("x") ys = complete_selection.get("y") zs = complete_selection.get("z") values = complete_selection.get(key) if key == "index": if idx_offset is not None: values = [i + idx_offset for i in values] if key == "charge": total_charge = sum(values) print("Total charge is {}".format(total_charge)) del total_charge # set a label color graphics.color(molid, label_color) for atom_idx in atom_idxs: label_pos = (xs[atom_idx] + offset[0], ys[atom_idx] + offset[1], zs[atom_idx] + offset[2]) if key == "index": labelformat = "{}" else: labelformat = "{:2.3f}" label_text = labelformat.format(values[atom_idx]) graphics.text(molid, tuple(label_pos), label_text, textsize)
def online_vs(): """ Sig: None Pre: None Post: A game played between against a remote player """ while True: name, human = get_online_name() choice = input("Are you the first to start the game? [" + g.color("G", "Y") + "]es [" \ + g.color("R", "N") + "]no\n[" + g.color("R", "Q") + "]uit ") if choice == "Y" or choice == "y": # Create peer which will act as server c = peer.Peer(True) c.accept_client() while True: # Name, peer, Human, Server win = game.online_vs(name, c, human, True) win = playOnlineVersusTournament(True, c, name, 'test') if win != "DRAW": break else: g.make_header("Game draw! Replay game") if win == name: g.make_header("You've won!") else: g.make_header("You've lost!") c.teardown() break elif choice == "N" or choice == "n": # Create peer which will act as client c = peer.Peer(False) c.connect_to_server() while True: # Name, peer, Human, Server win = game.online_vs(name, c, human, False) if win != "DRAW": break else: g.make_header("Game draw! Replay game") # Name, peer, Human = True, Server = False if win == name: g.make_header("You've won!") else: g.make_header("You've lost!") c.teardown() break elif choice == "Q" or choice == "q": sys.exit() else: print("Invalid choice, try again")
def draw_dotted_line(molid, start, end, sradius=0.01, drawcolor="blue", sdist=0.1, vmd_material="Basic1Pantone"): """ Draw a dotted line between two pints 'start' and 'end'. Parameters ---------- molid : int id of the molecule to draw the arrow to start : np-array; (1,3)-tuple starting coordinates end : np-array; (1,3)-tuple ending coordinates sradius : float radii of the dots drawcolor : str color of the dots sdist : float distance between points """ graphics.material(molid, vmd_material) graphics.color(molid, drawcolor) # vector between start and end p_vector = end - start length_p_vector = np.linalg.norm(p_vector) # normed p_vector normed_p_vector = p_vector / length_p_vector # number of points num_points = int(length_p_vector / sdist) # first sphere for pt in range(num_points): csphere = start + normed_p_vector * sdist * pt graphics.sphere(molid, center=tuple(csphere), radius=sradius)
def get_online_name(): """ Sig: None Pre: None Post: Name, and boolean corresponding to whether player is human or NPC """ name = input("Input your name: ") while True: human = input("Are you a human player? [" + g.color("G", "Y") + "/" + g.color("R", "N") + "]") if human == "Y" or human == "y": human = True break if human == "n" or human == "n": human = False break return name, human
def decide_offline_tour_players(): player_list = [] # Strings of names human_dict = {} # Booleans. Key = player. True = Human, False = NPC # Decide nr players while True: choice = input("How many players? [" + g.color("G", "3-8") + "] ") if type(int(choice)) == int: choice = int(choice) if choice > 2 and choice < 9: break nr_players = choice # Decide nr AI players while True: choice = input("How many AI players? [" + g.color("G", "0-" + str(nr_players)) + "] ") if type(int(choice)) == int: choice = int(choice) if choice <= nr_players: break nr_ai = choice # Name human players for player in range(nr_players - nr_ai): name = input("Name player" + str(player + 1) + ": ") player_list.append(name) human_dict[name] = True # Name AI players names = [ "SKYNET", "MAX HEADROOM", "WATSON", "DEEP THOUGHT", "J.A.R.V.I.S.", "R2D2", "MU-TH-UR 6000", "TÄNKANDE AUGUST" ] for nr in range(nr_ai): name = names[nr] player_list.append(name) human_dict[name] = False return player_list, human_dict
def online_tour_play(): """ Sig: None Pre: None Post: A tournament played between local, and remote players. And/or termination of program """ g.make_header("Tournament play!") while True: choice = input("Are you the first to start the game? [" + g.color("G", "Y") + "]es ["\ + g.color("R", "N") + "]no\n[" + g.color("R", "Q") + "]uit ") if choice == "Y" or choice == "y": server_side_tournament() elif choice == "N" or choice == "n": client_side_tournament() elif choice == "Q" or choice == "q": sys.exit() else: print("Invalid choice, try again")
def get_local_names(): """ Sig: None Pre: None Post: List of names, and list of booleans corresponding to whether player is human or NPC """ players = [] humans = [] for i in range(2): name = input("Name player " + str(i + 1) + ": ") while True: human = input("Is this a human player? [" + g.color("G", "Y") + "/" + g.color("R", "N") + "]") if human == "Y" or human == "y": human = True break if human == "n" or human == "n": human = False break players.append(name) humans.append(human) return players, humans
def menu_options(): """ Sig: None Pre: None Post: A played game or tournament in the case of user choosing so, and termination of program """ playing = True while playing: g.make_header("Welcome to <game>!") print("You have the following options:\n 1[" + g.color("G", "v")\ + "]s1\n[" + g.color("G", "T") + "]ournament\n[" + g.color("R", "Q") + "]uit ") choice = input("Please make your " + g.color("G", "choice: ")) # 1 vs 1 game if choice == "V" or choice == "v": while True: print("Do you wish to play [" + g.color("G", "L") + "]ocal or [" + g.color("G", "O") + "]nline?\n["\ + g.color("R", "R") + "]eturn to previous options\n[" + g.color("R", "Q") + "]uit ") choice = input("Please make your " + g.color("G", "choice: ")) # Local game if choice == "L" or choice == "l": local_vs() playing = False break # Online game elif choice == "O" or choice == "o": online_vs() playing = False break elif choice == "R" or choice == "r": break elif choice == "Q" or choice == "q": sys.exit() else: print("Invalid choice, try again") # Tournament game elif choice == "T" or choice == "t": while True: print("Do you wish to play [" + g.color("G", "L") + "]ocal or [" + g.color("G", "O") + "]nline?\n["\ + g.color("R", "R") + "]eturn to previous options\n[" + g.color("R", "Q") + "]uit ") choice = input("Please make your " + g.color("G", "choice: ")) # Local tournament if choice == "L" or choice == "l": local_tour_play() playing = False break # Online tournament elif choice == "O" or choice == "o": online_tour_play() playing = False break elif choice == "R" or choice == "r": break elif choice == "Q" or choice == "q": sys.exit() else: print("Invalid choice, try again") elif choice == "Q" or choice == "q": sys.exit() else: print("Invalid choice, try again")
def draw_circle(molid, rotaxis, center, angle=360, drawcolor="blue", circle_radius=0.2, vmd_material="Basic1Pantone", cylinder_radius=0.01, cone_radius=0.02, cone_length=10): """ Draw a circle around center using a rotational axis. Parameters ---------- molid : int frame_id : int rotaxis : numpy-array {float float float} rotational axis center : numpy-array {float float float} center to rotate around angle : float or int angle to rotate about in degrees color : str color of the circle circle_radius : float circle_radius of the circle resolution : int vectors the circle consists of """ # change color and material of circle graphics.color(molid, drawcolor) graphics.material(molid, vmd_material) # norm rotational axis rotaxis /= np.linalg.norm(rotaxis) # create and scale first vector according to given radius normal1 = np.cross(rotaxis, center) normal1 /= np.linalg.norm(normal1) normal1 *= circle_radius vector_start = normal1 # double angle for more points angle *= 2 for cangle in range(angle - cone_length): #print(cangle) # convert angle to radians cangle = np.radians(cangle / 2) #print(cangle) # define quaternion according to current angle quaternion = Quaternion(axis=rotaxis, angle=cangle) # define end of vector vector_end = quaternion.rotate(normal1) #vector_end /= np.linalg.norm(vector_end) #vector_end *= radius graphics.cylinder(molid, tuple(center + vector_start), tuple(center + vector_end), radius=cylinder_radius, resolution=20, filled=1) #graphics.sphere(molid, tuple(center + vector_start), radius=0.02) # new starting point is old ending vector_start = vector_end # draw an arrow beginning 5 degrees before the last angle vector_start = vector_end quaternion = Quaternion(axis=rotaxis, angle=np.radians(angle / 2 + cone_length)) vector_end = quaternion.rotate(normal1) graphics.cone(molid, tuple(center + vector_start), tuple(center + vector_end), radius=cone_radius, resolution=20)
def draw_double_bonds(molid, frame_id, bonds, radius=0.02, filled=True, vmd_material="Basic1Pantone"): """ Draw double bonds using cylinders given a dictionary with according bonds. Parameters ---------- molid : int molecule id to draw the cylinder in frame_id : int id of the frame to use the coordinates from bonds : list {list {int, int, int, int}, list {int, int, int, int}, ...} first two integers of each sublist form the bond, the others form the vector which forms the plane in which the double will be located """ # TODO: since a double bond is always in a plane, both neighbor bonds # TODO: are also in that plane, therefor a plane can always easily # be defined without explicitly naming the neighbors selection_str = "index {}" element_colors = color.get_colormap("Element") graphics.material(molid, vmd_material) for cbond in bonds: selection_str1 = selection_str.format(cbond[0]) selection_str2 = selection_str.format(cbond[1]) selection_str3 = selection_str.format(cbond[2]) selection_str4 = selection_str.format(cbond[3]) # get vector which is the bond vt1_coords = vmd_coords_numpy_arrays(molid, frame_id, selection_str1) vt2_coords = vmd_coords_numpy_arrays(molid, frame_id, selection_str2) #print(vt1_coords) bond = vt2_coords - vt1_coords # get vector forms the plane with bond vector vt3_coords = vmd_coords_numpy_arrays(molid, frame_id, selection_str3) vt4_coords = vmd_coords_numpy_arrays(molid, frame_id, selection_str4) bond_neigh = vt4_coords - vt3_coords # get normal to bond vector and neighbor vector normal1 = np.cross(bond_neigh, bond) normal1 /= np.linalg.norm(normal1) # get normal to normal of bond and bond neigh # and bond - this is the desired shift vector for the bond normal2 = np.cross(bond, normal1) normal2 /= np.linalg.norm(normal2) # draw double bond tail_bond2 = vt1_coords + normal2 * 0.1 head_bond2 = vt2_coords + normal2 * 0.1 # center between tail and head (for coloring) center = bond / 2 + vt1_coords + normal2 * 0.1 # get color of atoms selection1 = atomsel.atomsel(selection_str1) selection2 = atomsel.atomsel(selection_str2) # get element name atom1_element = selection1.get("element")[0] atom2_element = selection2.get("element")[0] # get element color atom1_color = element_colors[atom1_element] atom2_color = element_colors[atom2_element] # draw double bond - atom 1 to center using corresponding color graphics.color(molid, atom1_color) graphics.cylinder(molid, tuple(tail_bond2), tuple(center), radius=radius, filled=filled) # draw double bond - center to atom 2 using corresponding color graphics.color(molid, atom2_color) graphics.cylinder(molid, tuple(center), tuple(head_bond2), radius=radius, filled=filled)
def vmd_draw_box(lines, molid=0, vmd_material="Basic1Pantone", drawcolor="blue", lstyle="solid", lwidth=1, lfreq=15): """ Draw the unit cell in molid. This function takes the output from the lines_to_draw function. Parameters ---------- molid : int, optional id of loaded molecule in vmd lines : {list{list, list}, list{list, list}} all lines with starting and endpoints that are to be drawn; this is the output from the lines_to_draw function lstyle : str; 'solid' or 'dashed' or '--' draw dashed lines or own dashed lines lwidth : int width of the line lfreq : int frequency a line shall be drawn, which is lfreq / 2 since every second line is skipped """ #all_molids = molecule.listall() graphics.material(molid, vmd_material) graphics.color(molid, drawcolor) for ucell_line in lines: #print(ucell_line) # use a more rough dashing than the built-in one if lstyle == "--": # divide current line into sublines pstart = ucell_line[0] # get the subline and norm it subline = ucell_line[1] - ucell_line[0] subline /= lfreq for cntr in range(lfreq): pstop = pstart + subline if cntr % 2 == 0: #print(cntr) graphics.line(molid, tuple(pstart), tuple(pstop), style="solid", width=lwidth) pstart = pstop else: graphics.line(molid, tuple(ucell_line[0]), tuple(ucell_line[1]), style=lstyle, width=lwidth)
def vmd_draw_angle(molid, frame, atomids=None, atm_coords=None, canvas=False, resolution=200, radius=0.5, drawcolor="blue", cylinder_radius=0.01): """ Draws part of a circle to visualize the measured angle. Input: > moldid int; index of molecule to draw the angle for > frame int; frame number to draw the angle for > atomids tuple; all three atom ids with second one as angular point > canvas boolean; draw a canvas between bow and angle axis > resolution int; number of cylinders and spheres that form the angle """ if atomids is not None: id1, id2, id3 = atomids # select all atoms sel = atomsel.atomsel("all", molid, frame) # get coordinates x = sel.get("x") y = sel.get("y") z = sel.get("z") # get rotational axis atm1Crds = np.array([x[id1], y[id1], z[id1]]) atm2Crds = np.array([x[id2], y[id2], z[id2]]) atm3Crds = np.array([x[id3], y[id3], z[id3]]) elif atm_coords is not None: atm1Crds, atm2Crds, atm3Crds = atm_coords else: raise Warning( "At least atomic coordinates or atom ids have to be provided!") # draw bows in the current molecule, transparent canvas in a new molecule if canvas is True: molecule.new("angle canvas") graphics_id = molecule.num() - 1 # ids start with 0 else: graphics_id = molid graphics.color(graphics_id, drawcolor) #pdb.set_trace() # define angle and rotational axis vt1 = atm1Crds - atm2Crds vt2 = atm3Crds - atm2Crds vtRot = np.cross(vt1, vt2) # unit vectors for quaternions vt1 /= np.linalg.norm(vt1) vt2 /= np.linalg.norm(vt2) vtRot /= np.linalg.norm(vtRot) # define angle offset max_angle = np.arccos(np.dot( vt1, vt2)) # denominator is 1 since vectors are normed print("Measured angles: {}".format(np.degrees(max_angle))) angle_offset = np.pi / resolution vt1 *= radius vt2 *= radius for cntr, theta in enumerate(np.arange(0, max_angle, angle_offset)): # previous vector if cntr == 0: vt_pre = vt1 + atm2Crds # define quaternion q = Quaternion(axis=vtRot, angle=theta) #print(q) # rotate vector vt_cur = q.rotate(vt1) vt_cur += atm2Crds if canvas is True and cntr != 0: graphics.triangle(graphics_id, tuple(vt_pre), tuple(atm2Crds), tuple(vt_cur)) else: graphics.cylinder(graphics_id, tuple(vt_pre), tuple(vt_cur), radius=cylinder_radius, resolution=20, filled=1) vt_pre = vt_cur if canvas is True: graphics.triangle(graphics_id, tuple(vt_pre), tuple(atm2Crds), tuple(vt2 + atm2Crds)) graphics.material(graphics_id, "Transparent") else: graphics.cylinder(graphics_id, tuple(vt_pre), tuple(vt2 + atm2Crds), radius=cylinder_radius, resolution=20, filled=1)
def vmd_draw_arrow(molid, start, end, cylinder_radius=0.4, cone_radius=1.0, cone_length=0.15, resolution=50, double_arrow=False, vmd_material="Basic1Pantone", drawcolor="blue", lstyle="solid"): """ Draws an arrow from start to end using the arrow color and a certain radius for the cylinder and the cone (top). Draw cylinder of 90 % of the max length and the tip from 75 % of the total arrow length. Input: > molid int; id of the molecule to draw the arrow to > start np-array; (1,3)-tuple with starting coordinates > end np-array; (1,3)-tuple with ending coordinates > cylinder_radius float; radius of the arrow base > cone_radius float; radius of the cone lstyle : str; solid | dashed draw a solid (default) or dashed arrow """ graphics.material(molid, vmd_material) graphics.color(molid, drawcolor) p_vector = end - start # shift starting point of the vector by cone_length towards the end point if double_arrow is True: # shorten vector so there is place for the cone at the starting point p_start = start + p_vector * cone_length else: p_start = start # shorten vector so there is place for the cone at the ending point p_end = start + p_vector * (1 - cone_length) graphics.cone(molid, tuple(p_end), tuple(end), radius=cone_radius, resolution=resolution) graphics.cone(molid, tuple(p_start), tuple(start), radius=cone_radius, resolution=resolution) if lstyle == "solid": graphics.cylinder(molid, tuple(p_start), tuple(p_end), radius=cylinder_radius, resolution=resolution) elif lstyle == "dashed": # length of a single cylinder len_cylinder = 0.08 # normed length of the vector between the cones p_vector_len = np.linalg.norm(p_start - p_end) # number of cylinders that fit between the cones with len_cylinder length ncylinders = int(p_vector_len // len_cylinder) p_vector_unit = (p_end - p_start) / p_vector_len # define the intermediate vector inter_end = [0, 0, 0] # draw vectors ncylinders times for i in range(ncylinders): inter_end = p_start + p_vector_unit * len_cylinder if i % 2 == 0: graphics.cylinder(molid, tuple(p_start), tuple(inter_end), radius=cylinder_radius, resolution=resolution) #pdb.set_trace() p_start = inter_end else: pass
def draw_torsion(molid, frame, atomids, canvas=False, resolution=50, radius=0.5, drawcolor="blue"): """ """ id1, id2, id3, id4 = atomids # draw bows in the current molecule, transparent canvas in a new molecule if canvas is True: molecule.new("angle canvas") graphics_id = molecule.num() - 1 # ids start with 0 else: graphics_id = molid graphics.color(graphics_id, drawcolor) # select all atoms sel = atomsel.atomsel("all", molid, frame) # get coordinates x = sel.get("x") y = sel.get("y") z = sel.get("z") # get rotational axis atm1Crds = np.array([x[id1], y[id1], z[id1]]) atm2Crds = np.array([x[id2], y[id2], z[id2]]) atm3Crds = np.array([x[id3], y[id3], z[id3]]) atm4Crds = np.array([x[id4], y[id4], z[id4]]) # define angle and rotational axis #vt1 = atm1Crds - atm2Crds #vt2 = atm3Crds - atm2Crds #vtRot = np.cross(vt1, vt2) # unit vectors for quaternions #vt1 /= np.linalg.norm(vt1) #vt2 /= np.linalg.norm(vt2) #vtRot /= np.linalg.norm(vtRot) #print(atm1Crds) _, cp1, cp2 = ag_geometry.get_dihedral(atm1Crds, atm2Crds, atm3Crds, atm4Crds, return_cross=True) # draw vectors between id2 and id3, therefor get the relevant vector center_pt = atm2Crds + (atm3Crds - atm2Crds) * 0.5 cp1 += center_pt cp2 += center_pt vmd_draw_angle(molid, frame, atm_coords=[cp1, center_pt, cp2], canvas=False, resolution=resolution, radius=radius, drawcolor="blue")