def test_not_equal(): b1 = bag(dict(a=1, b=1, c=2)) b2 = bag(dict(c=2, b=1, a=1)) assert not (b1 != b2) b3 = bag(dict(c=3, b=1, a=1)) assert b1 != b3 assert b1 != "a string"
def test_update(): b1 = bag(dict(a=1, b=1)) b1.update(["c"]) assert b1 == bag(dict(a=1, b=1, c=1)) b1.update({"c": 0}) assert b1 == bag(dict(a=1, b=1, c=1)) b1.update(["c", "c", "c", "b", "c"]) assert b1 == bag(dict(a=1, b=2, c=5))
def test_intersection(): b1 = bag({"a": 1, "b": 0, 1: 4}) b2 = bag({"a": 1, "b": 1, 1: 2}) assert b1.intersection(b2) == b2.intersection(b1) == bag({"a": 1, 1: 2}) try: b1.intersection("a string") except TypeError: pass else: assert False
def test_difference(): b1 = bag({"a": 1, "b": 0, 1: 2}) b2 = bag({"a": 1, "b": 1, 1: 1}) assert b1.difference(b2) == bag({1: 1}) try: b1.difference("a string") except TypeError: pass else: assert False
def test_union(): b1 = bag(dict(a=1, b=1)) b2 = bag(dict(a=2, c=1)) b3 = b1.union(b2) assert b3 == bag(dict(a=3, b=1, c=1)) try: b1.union("a string") except TypeError: pass else: assert False
def test_init(): b = bag({"a": 1, "b": 0, 1: 2}) assert "a" in b assert "b" not in b assert 1 in b assert len(b) == 2 try: b = bag({"a": -1}) except ValueError: pass else: assert False, "should have raised"
def reveal_creatures(self, creature_names): """Reveal the creatures from creature_names, if they're not already known to be in this legion.""" if self.any_unknown: bag1 = bag(self.creature_names) bag2 = bag(creature_names) for creature_name, count2 in bag2.iteritems(): count1 = bag1[creature_name] while count2 > count1 and self.any_unknown: self.creatures.remove(Creature.Creature("Unknown")) creature = Creature.Creature(creature_name) self.creatures.append(creature) creature.legion = self count2 -= 1
def test_clear(): b = bag() b.add(1) assert b b.clear() assert not b assert len(b) == 0
def test_repr(): b = bag() b.add(1) b.add(1) b.add(2) b.remove(2) assert str(b) == "bag({1: 2})"
def test_iter(): b1 = bag({"a": 1, "b": 0, 1: 4}) lst = [] for el in b1: lst.append(el) assert "a" in lst assert 1 in lst assert "b" not in lst
def split_legion(self, playername, game_name, parent_markerid, child_markerid, parent_creature_names, child_creature_names): """Split a legion.""" logging.info("%s %s %s %s %s %s", playername, game_name, parent_markerid, child_markerid, parent_creature_names, child_creature_names) game = self.name_to_game(game_name) if not game: logging.warning("no game") return parent = game.find_legion(parent_markerid) if parent is None: logging.warning("no legion") return player = game.get_player_by_name(playername) if player is not game.active_player: logging.warning("wrong player") return if game.phase != Phase.SPLIT: logging.warning("wrong phase") return parent = player.markerid_to_legion.get(parent_markerid) if parent is None: logging.warning("no parent") return if child_markerid not in player.markerids_left: logging.warning("no marker") return if len(parent_creature_names) < 2: logging.warning("parent too short") return if len(parent_creature_names) > 5: logging.warning("parent too tall") return if len(child_creature_names) < 2: logging.warning("child too short") return if len(child_creature_names) > 5: logging.warning("child too tall") return if bag(parent.creature_names) != bag(parent_creature_names).union( bag(child_creature_names)): logging.warning("wrong creatures") game.split_legion(playername, parent_markerid, child_markerid, parent_creature_names, child_creature_names)
def _max_creatures_of_one_type(self): """Return the maximum number of creatures (not lords or demi-lords) of the same type in this legion.""" counts = bag(self.creature_names) maximum = 0 for name, num in counts.iteritems(): if (num > maximum and Creature.Creature(name).is_creature): maximum = num return maximum
def test_issuperset(): b1 = bag({"a": 1, "b": 0, 1: 4}) b2 = bag({"a": 1, "b": 1, 1: 2}) b3 = bag({"a": 9, "b": 9, 1: 9}) assert b1.issuperset(b1) assert b2.issuperset(b2) assert b3.issuperset(b3) assert not b1.issuperset(b2) assert not b1.issuperset(b3) assert not b2.issuperset(b1) assert not b2.issuperset(b3) assert b3.issuperset(b1) assert b3.issuperset(b2) try: b1.issuperset("a string") except TypeError: pass else: assert False
def test_discard(): b = bag() b.add(1) b.add(1) b.discard(1) assert b[1] == 1 assert 1 in b b.discard(1) assert b[1] == 0 assert 1 not in b b.discard("not in there")
def test_remove(): b = bag() b.add(1) b.add(1) b.remove(1) assert b[1] == 1 assert 1 in b b.remove(1) assert b[1] == 0 assert 1 not in b try: b.remove("not in there") except KeyError: pass else: assert False, "should have raised"
def is_legal_split(self, child1, child2): """Return whether this legion can be split into legions child1 and child2""" logging.info("%s %s", child1, child2) if len(self) < 4: return False if len(self) != len(child1) + len(child2): return False if len(child1) < 2 or len(child2) < 2: return False if (bag(self.creature_names) != bag(child1.creature_names + child2.creature_names) and bag(child1.creature_names).union(bag( child2.creature_names)) != bag({"Unknown": len(self)})): return False if len(self) == 8: if len(child1) != 4 or len(child2) != 4: return False if ((child1.num_lords != 1 or child2.num_lords != 1) and ((bag(child1.creature_names) != bag({"Unknown": 4}) or bag(child2.creature_names) != bag({"Unknown": 4})))): return False return True
def is_legal_split(self, child1, child2): """Return whether this legion can be split into legions child1 and child2""" logging.info("%s %s", child1, child2) if len(self) < 4: return False if len(self) != len(child1) + len(child2): return False if len(child1) < 2 or len(child2) < 2: return False if (bag(self.creature_names) != bag(child1.creature_names + child2.creature_names) and bag(child1.creature_names).union(bag(child2.creature_names)) != bag({"Unknown": len(self)})): return False if len(self) == 8: if len(child1) != 4 or len(child2) != 4: return False if ((child1.num_lords != 1 or child2.num_lords != 1) and ((bag(child1.creature_names) != bag({"Unknown": 4}) or bag(child2.creature_names) != bag({"Unknown": 4})))): return False return True
def split_legion(self, parent_markerid, child_markerid, parent_creature_names, child_creature_names): logging.info("%s %s %s %s", parent_markerid, child_markerid, parent_creature_names, child_creature_names) parent = self.markerid_to_legion.get(parent_markerid) if parent is None: return if child_markerid not in self.markerids_left: raise AssertionError("illegal marker") if (bag(parent.creature_names) != bag(parent_creature_names).union( bag(child_creature_names)) and bag(parent_creature_names).union(bag(child_creature_names)) != bag({"Unknown": len(parent)})): raise AssertionError("wrong creatures", "parent.creature_names", parent.creature_names, "parent_creature_names", parent_creature_names, "child_creature_names", child_creature_names) new_legion1 = Legion.Legion(self, parent_markerid, Creature.n2c(parent_creature_names), parent.hexlabel) new_legion2 = Legion.Legion(self, child_markerid, Creature.n2c(child_creature_names), parent.hexlabel) if not parent.is_legal_split(new_legion1, new_legion2): raise AssertionError("illegal split") del new_legion1 parent.creatures = Creature.n2c(parent_creature_names) for creature in parent.creatures: creature.legion = parent self.take_marker(child_markerid) new_legion2.add_observer(self.game) self.markerid_to_legion[child_markerid] = new_legion2 del parent # One action for our player with creature names action = Action.SplitLegion(self.game.name, self.name, parent_markerid, child_markerid, parent_creature_names, child_creature_names) logging.info(action) self.notify(action, names=[self.name]) # Another action for everyone (including our player, who will # ignore it as a duplicate) without creature names. action = Action.SplitLegion(self.game.name, self.name, parent_markerid, child_markerid, len(parent_creature_names) * ["Unknown"], len(child_creature_names) * ["Unknown"]) logging.info(action) self.notify(action)
def available_recruits_and_recruiters(self, mterrain, caretaker): """Return a list of tuples with creature names and recruiters that this legion could recruit in a masterhex with terrain type mterrain, if it moved there. Each tuple will contain the recruit as its first element, and the recruiters (if any) as its remaining elements. The list is sorted in the same order as within recruitdata. """ result_list = [] counts = bag(self.living_creature_names) recruits = recruitdata.data[mterrain] for sublist in self._gen_sublists(recruits): names = [tup[0] for tup in sublist] nums = [tup[1] for tup in sublist] for ii in xrange(len(sublist)): name = names[ii] num = nums[ii] if ii >= 1: prev = names[ii - 1] else: prev = None if prev == recruitdata.ANYTHING: # basic tower creature for jj in xrange(ii + 1): if nums[jj] and caretaker.counts.get(names[jj]): result_list.append((names[jj], )) else: if (prev == recruitdata.CREATURE and self._max_creatures_of_one_type() >= num): # guardian recruiters = [] for name2, num2 in counts.iteritems(): if (num2 >= num and Creature.Creature(name2).is_creature): recruiters.append(name2) for jj in xrange(ii + 1): if nums[jj] and caretaker.counts.get(names[jj]): for recruiter in recruiters: li = [names[jj]] for kk in xrange(num): li.append(recruiter) tup = tuple(li) result_list.append(tup) if counts[prev] >= num: # recruit up if num and caretaker.counts.get(name): li = [name] for kk in xrange(num): li.append(prev) tup = tuple(li) result_list.append(tup) if counts[name] and num: # recruit same or down for jj in xrange(ii + 1): if nums[jj] and caretaker.counts.get(names[jj]): result_list.append((names[jj], name)) def cmp_helper(tup1, tup2): ii = 0 while True: if len(tup1) < ii + 1: return -1 if len(tup2) < ii + 1: return 1 if tup1[ii] != tup2[ii]: c1 = Creature.Creature(tup1[ii]) c2 = Creature.Creature(tup2[ii]) diff = 100 * (c1.sort_value - c2.sort_value) if diff != 0: return int(diff) ii += 1 result_list.sort(cmp=cmp_helper) return result_list
def test_iteritems(): b1 = bag({"a": 1, "b": 0, 1: 4}) assert list(b1.iteritems()) == [("a", 1), (1, 4)]
def test_iterkeys(): b1 = bag({"a": 1, "b": 0, 1: 4}) assert list(b1.iterkeys()) == ["a", 1]
def test_keys(): b1 = bag({"a": 1, "b": 0, 1: 4}) assert b1.keys() == ["a", 1]
def test_equal(): b1 = bag(dict(a=1, b=1, c=2)) b2 = bag(dict(c=2, b=1, a=1)) assert b1 == b2 assert b1 != "a string"
def test_add(): b = bag() b.add(1) b.add(1) assert b[1] == 2 assert 1 in b
def test_copy(): b1 = bag() b1.add(1) b2 = b1.copy() assert len(b1) == len(b2) assert b1 == b2
def test_setitem(): b = bag() b[1] = 1 assert 1 in b assert b[1] == 1
def test_itervalues(): b1 = bag({"a": 1, "b": 0, 1: 4}) assert sorted(b1.itervalues()) == [1, 4]
def __init__(self, playername, attacker_legion, attacker_creature_names, defender_legion, defender_creature_names, def1, parent): gtk.Dialog.__init__(self, "Proposal - %s" % playername, parent) self.attacker_legion = attacker_legion self.attacker_creature_names = attacker_creature_names self.defender_legion = defender_legion self.defender_creature_names = defender_creature_names self.deferred = def1 self.set_icon(icon.pixbuf) self.set_transient_for(parent) self.set_destroy_with_parent(True) self.vbox.set_spacing(9) legion_name = gtk.Label( "Legion %s (%s) negotiates with %s (%s) in hex %s" % ( attacker_legion.markerid, attacker_legion.picname, defender_legion.markerid, defender_legion.picname, defender_legion.hexlabel)) self.vbox.pack_start(legion_name) attacker_hbox = gtk.HBox(spacing=15) self.vbox.pack_start(attacker_hbox) attacker_marker_hbox = gtk.HBox() attacker_hbox.pack_start(attacker_marker_hbox, expand=False) attacker_chits_hbox = gtk.HBox(spacing=3) attacker_hbox.pack_start(attacker_chits_hbox) attacker_marker = Marker.Marker(attacker_legion, True, scale=20) attacker_marker_hbox.pack_start(attacker_marker.event_box, expand=False) defender_hbox = gtk.HBox(spacing=15) self.vbox.pack_start(defender_hbox) defender_marker_hbox = gtk.HBox() defender_hbox.pack_start(defender_marker_hbox, expand=False) defender_chits_hbox = gtk.HBox(spacing=3) defender_hbox.pack_start(defender_chits_hbox) defender_marker = Marker.Marker(defender_legion, True, scale=20) defender_marker_hbox.pack_start(defender_marker.event_box, expand=False) attacker_chits = [] surviving_attackers = bag(attacker_creature_names) surviving_defenders = bag(defender_creature_names) for creature in attacker_legion.sorted_creatures: name = creature.name if name in surviving_attackers: surviving_attackers.remove(name) dead = False else: dead = True chit = Chit.Chit(creature, attacker_legion.player.color, scale=20, dead=dead) attacker_chits_hbox.pack_start(chit.event_box, expand=False) attacker_chits.append(chit) defender_chits = [] for creature in defender_legion.sorted_creatures: name = creature.name if name in surviving_defenders: surviving_defenders.remove(name) dead = False else: dead = True chit = Chit.Chit(creature, defender_legion.player.color, scale=20, dead=dead) defender_chits_hbox.pack_start(chit.event_box, expand=False) defender_chits.append(chit) self.add_button("Accept", ACCEPT) self.add_button("Reject", REJECT) self.add_button("Fight", FIGHT) self.connect("response", self.cb_response) self.show_all()
def available_recruits_and_recruiters(self, mterrain, caretaker): """Return a list of tuples with creature names and recruiters that this legion could recruit in a masterhex with terrain type mterrain, if it moved there. Each tuple will contain the recruit as its first element, and the recruiters (if any) as its remaining elements. The list is sorted in the same order as within recruitdata. """ result_list = [] counts = bag(self.living_creature_names) recruits = recruitdata.data[mterrain] for sublist in self._gen_sublists(recruits): names = [tup[0] for tup in sublist] nums = [tup[1] for tup in sublist] for ii in xrange(len(sublist)): name = names[ii] num = nums[ii] if ii >= 1: prev = names[ii - 1] else: prev = None if prev == recruitdata.ANYTHING: # basic tower creature for jj in xrange(ii + 1): if nums[jj] and caretaker.counts.get(names[jj]): result_list.append((names[jj],)) else: if (prev == recruitdata.CREATURE and self._max_creatures_of_one_type() >= num): # guardian recruiters = [] for name2, num2 in counts.iteritems(): if (num2 >= num and Creature.Creature( name2).is_creature): recruiters.append(name2) for jj in xrange(ii + 1): if nums[jj] and caretaker.counts.get(names[jj]): for recruiter in recruiters: li = [names[jj]] for kk in xrange(num): li.append(recruiter) tup = tuple(li) result_list.append(tup) if counts[prev] >= num: # recruit up if num and caretaker.counts.get(name): li = [name] for kk in xrange(num): li.append(prev) tup = tuple(li) result_list.append(tup) if counts[name] and num: # recruit same or down for jj in xrange(ii + 1): if nums[jj] and caretaker.counts.get(names[jj]): result_list.append((names[jj], name)) def cmp_helper(tup1, tup2): ii = 0 while True: if len(tup1) < ii + 1: return -1 if len(tup2) < ii + 1: return 1 if tup1[ii] != tup2[ii]: c1 = Creature.Creature(tup1[ii]) c2 = Creature.Creature(tup2[ii]) diff = 100 * (c1.sort_value - c2.sort_value) if diff != 0: return int(diff) ii += 1 result_list.sort(cmp=cmp_helper) return result_list