def __init__(self, player, node, action="nothing", target=EmptyNode()): self.player = player self.node = node self.action = action self.target = target self.color = cnames.values()[player] self.id = None
def simulate(self): nodes = {} for n in self.state.graph: nodes[n.id] = GameNode(id=n.id, edges=n.edges, owner=n.owner, units=[]) nodes[n.id].n_attacking = n.n_attacking nodes[n.id].n_defending = n.n_defending nodes["EMPTY"] = EmptyNode() players = {} for p in self.players.values(): p_nodes = [nodes[n.id] for n in p.nodes] np = p.__class__(p.id, [], p_nodes, nodes[p.home.id]) np.number = p.number players[np.id] = np for n in self.state.graph: for u in n: nu = Unit(u.player, nodes[n.id], u.action, nodes[u.target.id]) nu.id = u.id nodes[n.id].units.append(nu) players[u.player].add_unit(nu) nodes.pop("EMPTY", None) return Game([players[p] for p in self.players], GameGraph([nodes[n.id] for n in self.state.graph]), self.fall)
def get_legal_actions(self, pos, unit): actions = [] for e in pos.edges: node = self.graph.get_node(e) if not node.is_empty() and node.owner != unit.player: actions.append({"action": "support", "target": node}) actions.append({"action": "attack", "target": node}) actions.append({"action": "nothing", "target": EmptyNode()}) return actions
def update(self): # Needed to make attackers stop attacking empty nodes after they have been conquered. if self.target.is_empty(): if self.action == "attack": self.target.remove_attack() elif self.action == "support": self.target.remove_support() self.action = "nothing" if self.action == "nothing": self.target = EmptyNode()
def update_nodes(self): for node in self.graph.nodes.values(): # TODO: Replace with list getter if node.n_attacking > node.n_defending: # Make each unit back off by creating a fake move for u in node.units: pos = [p for p in self.get_legal_positions(u) if not p == u.node] if len(pos) > 0: move = GameMove(unit=u, origin=node, destination=pos[np.random.choice(len(pos), 1)], action="nothing", target=EmptyNode()) self.update_positions(move) self.update_actions(move) else: self.destroy_unit(u) # There can only be units owned by 1 player at any time on a node. # It makes sense that all the units in the array will have the same # owner, given how movement is regulated. So it doesn't' matter which one we pick. if len(node.units) > 0: node.change_ownership(node.units[0].player) else: node.change_ownership(None) node.n_attacking = 0 node.n_defending = len(node.units) for n in self.graph: for u in n: if u.target.is_empty(): u.action = "nothing" if u.action == "attack": u.target.add_attack() elif u.action == "support": u.target.add_support() else: u.target = EmptyNode()
def add_move(self, move, DEBUG=False): if DEBUG: print "####################################################################################" print "Evaluating Move", move print "Origin node BEFORE move", move.origin # These two methods must be called in this order. This makes sure actions are updated # only after movement has occurred. moved = self.update_positions(move) if moved: if DEBUG: print "Movement successful" self.update_actions(move) else: if DEBUG: print "Movement not successful" # If the unit tried to move to an occupied block, move it back to its origin. self.update_actions(GameMove(move.unit, move.origin, move.origin, "nothing", EmptyNode())) if DEBUG: print "Unit after move", move.unit print "Destination Node after move", move.destination print "Target after move", move.target print "Origin Node after move", move.origin
def play(self, game): if len(self.units) == 0: return [] for u in self.units: u.my_turn = True u.selected_action = { "origin": u.node, "destination": u.node, "unit": u, "action": "nothing", "target": EmptyNode() } f = tk.Frame() aid = self.canvas.after(30, self.draw_menu) f.wait_variable(self.move_completed) self.canvas.after_cancel(aid) self.canvas.delete("move_menu") for u in self.units: u.my_turn = False return [GameMove(**u.selected_action) for u in self.units]
def generate_unit(self): return HumanInteractionUnit(self.id, self.home, "nothing", EmptyNode())
def generate_unit(self): return Unit(self.id, self.home, "nothing", EmptyNode())
def __init__(self): Unit.__init__(self, 100, EmptyNode(), "nothing", EmptyNode()) self.id = "EMPTY"
def reset_action(self): self.selected_action["action"] = "nothing" self.selected_action["target"] = EmptyNode()