def _init_game(self, config): cards = tlist() num = config.rules.num_numbers for n, c in config.cards.items(): if n in config.rules.num_royals: cards.extend([c]*config.rules.num_royals[n]) else: cards.extend([c]*num) self.state.discard_pile = self.create_object('discard_pile', top_face_up=config.rules.discard_market, seed=self.RNG.getrandbits(32), default='card') self.state.deck = self.create_object('draw_pile', discard_pile=self.state.discard_pile, cards=cards, seed=self.RNG.getrandbits(32), default='card') self.state.deck.shuffle() self.state.market = self.create_object('market', neutral=tset(), _log=self.log, _deck=self.state.deck) self.state.royal_phases = config.rules.royal_phases for i, player in enumerate(self.players): player.hand = tset(self.state.deck.draw(config.rules.hand_size.starting)) player.buildings = tdict({bld:tlist() for bld in config.rules.counts}) player.vps = 0 player.hand_limit = config.rules.hand_size.max player.coins = 3 player.order = i + 1 if i == 0: self.state.herald = player
def execute_trade(offer, demand, bank, from_player, to_player=None, log=None): # gain_res(res, bank, player, delta, log=None) offer_res = tlist() demand_res = tlist() for res in offer.keys(): if offer[res] > 0: offer_res.extend([res]*offer[res]) gain_res(res, bank, from_player, -offer[res]) if to_player is not None: gain_res(res, bank, to_player, offer[res]) if demand[res] > 0: demand_res.extend([res]*demand[res]) if to_player is not None: gain_res(res, bank, to_player, -demand[res]) gain_res(res, bank, from_player, demand[res]) if log is not None: if to_player is None: log.writef('{} trades with the bank:', from_player) log.iindent() log.writef('Paying {} {}', len(offer_res), offer_res[0]) log.writef('Receiving 1 {}', demand_res[0]) log.dindent() else: log.writef('{} trades with {}:', from_player, to_player) log.iindent() log.writef('Paying: {}', ', '.join(offer_res) if len(offer_res) else '-nothing-') log.writef('Receiving: {}', ', '.join(demand_res) if len(demand_res) else '-nothing-') log.dindent()
def build_catan_map(G, hex_info, ports, number_info, RNG): start_field = None for field in G.fields: if field.val == 'A': start_field = field assert start_field is not None, 'could not find the start field' outside = get_outside_corners(start_field) for idx, port_type in ports.items(): outside[idx].port = port_type # set hex types hextypes = tlist() for res, num in hex_info.items(): hextypes.extend([res] * num) RNG.shuffle(hextypes) for field, hextype in zip(G.fields, hextypes): field.res = hextype del field.val hinums = number_info.hi options = tlist(f for f in G.fields if f.res != 'desert') assert len(options) == ( len(number_info.hi) + len(number_info.reg)), 'not the right number of tiles' remaining = tset() for num in hinums: idx = RNG.randint(0, len(options) - 1) f = options[idx] f.num = num options.remove(f) for n in f.neighbors: if n is not None and n in options: remaining.add(n) options.remove(n) remaining.update(options) regnums = number_info.reg RNG.shuffle(regnums) for f, num in zip(remaining, regnums): f.num = num
def get_sites(self, options, table): sites = np.array( [tdict(ID=a[0].ID) for a in options['loc-settlement']]) for site in sites: c = table[site['ID']] site.nums = tlist(n.num for n in c.fields if n is not None and 'num' in n) site.ress = tlist(n.res for n in c.fields if n is not None and 'res' in n) site.val = sum(6 - abs(n - 7) for n in site.nums) if 'port' in c: site.port = c.port return sites
def compute_debt(self, C, player, action=None): if 'debt' not in self: self.debt = tdict() self.choices = tdict() lim = C.state.hand_limit for player in C.players: if player.num_res > lim: self.debt[player] = player.num_res // 2 self.choices[player] = tlist() elif action is not None: res, = action self.choices[player].append(res) gain_res(res, C.state.bank, player, -1) C.log[player].writef('1 of your {} is stolen.', res) self.debt[player] -= 1 if self.debt[player] < 1: del self.debt[player] C.log.writef('{} loses: {}', player, ', '.join(self.choices[player])) del self.choices[player] if len(self.debt): raise Decide('debt') raise Switch('loc')
def _create_start_phase(self, C, config, settings, **kwargs): super()._create_start_phase(C, config, settings, player_order=tlist(C.players), real_estate=C.state.world.corners, **kwargs)
def set_counter(self, C, player, action=None): if action is not None: cmd, *rest = action if cmd == 'reject': del self.responses[player] elif cmd == 'accept': self.responses[player] = 'accept' else: if player not in self.counter_offers: self.counter_offers[player] = tlist( [self.offer.copy(), self.demand.copy()]) res, = rest delta = -1**(cmd == 'demand') self.give(res, delta, *self.counter_offers[player]) # check if some players havent responded yet for r in self.responses.values(): if r is None: raise stg.Switch('commit') raise stg.Decide('counter')
def select_stand(self, C, player, action=None): if action is None: players = tlist(p for p in C.players if len(p.hand)) if len(players) == 0: raise PhaseComplete self.sel = Selection( players, log=C.log, option_fn=lambda p: p.hand, status='You may choose cards for your market stand.') else: stands = self.sel.step(player, action) if stands is not None: for p, stand in stands.items(): if len(stand): self.done = tset() for p, stand in stands.items(): p.market.update(stand) C.log.writef( '{}\'s stand contains: {}', p, ', '.join(str(card) for card in stand)) for card in stand: p.hand.remove(card) card.visible.update(C.players) raise stg.Switch('prep') raise PhaseComplete raise stg.Decide('select')
def observe(self, mind, me, options, table, opponents, **status): hexs = tlist(table[a.ID] for a, in options['loc']) remaining = tlist() for h in hexs: if 'num' in h: for c in h.corners: if 'building' in c and c.building.player.name != me.name and c.building.player.num_res > 0: info = tdict() info.val = 6 - abs(h.num - 7) info.res = h.res info.ID = h._id info.vp = c.building.player.vps remaining.append(info) self.remaining = remaining
def run_auction(self, C, player, action=None): if action is None: self.bids = tdict({p: 0 for p in C.players if p.money == 0}) else: bid, = action self.bids[player] = bid if len(self.bids) == len(C.players): # resolve auction mx, cost = None, None for p, bid in self.bids.items(): C.log.writef('{} bids {}', p, bid) if mx is None or bid > mx: cost = mx mx = bid if cost is None: cost = 0 if mx > 0: self.cost = cost winners = tlist(p for p, bid in self.bids.items() if bid == mx) self.winners = util.sort_by(winners, [p.order for p in winners]) raise stg.Switch('collection') else: C.log.writef('No one bid anything') raise stg.Switch('market') raise stg.Decide('auction')
def _end_game(self): out = tdict() winners = tlist() for name in self.players.values(): winners.append(name) out.winner = random.choice(winners) print('winner is {}'.format(out.winner)) return out
def __init__(self, address, storage, owner, **props): super().__init__( harvest=None, owner=owner, storage=storage, address=address, intruders=tlist(), # face up **props)
def _init_game(self, C, config, settings): for name in config.rules.counts: register_object(game='aristocracy', name=name, cls=Building) KingPhase.neutral_num = config.neutral_market.king QueenPhase.neutral_num = config.neutral_market.queen JackPhase.neutral_num = config.neutral_market.jack cards = tlist() num = config.rules.num_numbers for n, c in config.cards.items(): if n in config.rules.num_royals: cards.extend([c] * config.rules.num_royals[n]) else: cards.extend([c] * num) C.state.discard_pile = C.create_object( 'discard_pile', top_face_up=config.rules.discard_market, seed=C.RNG.getrandbits(32), default='card') C.state.deck = C.create_object('draw_pile', discard_pile=C.state.discard_pile, cards=cards, seed=C.RNG.getrandbits(32), default='card') C.state.discard_pile._draw_pile = C.state.deck C.state.deck.shuffle() C.state.market = C.create_object('market', neutral=tset(), _log=C.log, _deck=C.state.deck) for i, player in enumerate(C.players): player.hand = tset() player._draw_increment = config.rules.draw_cards player._deck = C.state.deck player.hand = tset() player.market = tset() player.buildings = tdict( {bld: tset() for bld in config.rules.counts}) player.vps = 0 player.hand_limit = config.rules.max_hand_size player.money = config.rules.starting.coins player.order = i - 1 if i == 0: C.state.herald = player
def post_phase(self, C, player, action=None): if 'candidates' not in self: self.candidates = tlist( p for p in C.players if satisfies_vic_req(p, C.config.rules.victory_conditions)) if len(self.candidates): raise stg.Switch('claim') raise SwitchPhase('queen')
def run_ball(self, C, player, action=None): if action is None: self.sel = Selection(tlist(p for p in C.players if len(p.hand)), log=C.log, option_fn=lambda p: p.hand, status='You may choose cards to attend the ball.') else: done = self.sel.step(player, action) if done is not None: # run ball ball = tlist(C.state.market) for p, sel in done: p.hand -= sel ball.extend(sel) C.RNG.shuffle(ball) C.log.writef('The ball features: {}'.format(', '.join(map(str, ball)))) C.RNG.shuffle(ball) ball = tset(ball) for p, sel in done: for _ in range(len(sel)): card = ball.pop() card.visible.clear() card.visible.add(p) p.hand.add(card) C.state.market.clear() C.state.market.update(ball) for card in C.state.market: card.visible.update(C.players) raise stg.Switch('market') raise stg.Decide('ball')
def execute(self, C, player=None, action=None): if self.available is None: self.available = tset(C.state.world.corners) if action is not None: loc, = action if loc.obj_type == 'Edge': build(C, 'road', player, loc) self.settled = None self.player_order.pop() if len(self.player_order) == 0: raise SwitchPhase('main', stack=False) if len(self.player_order) == len(C.players): self.on_second = True elif loc.obj_type == 'Corner': build(C, 'settlement', player, loc) self.settled = loc for e in loc.edges: if e is not None: for c in e.corners: self.available.discard(c) if self.on_second: res = tlist() for f in loc.fields: if f is not None and f.res != 'desert': res.append(f.res) for r in res: gain_res(r, C.state.bank, player, 1) if len(res) == 3: s = '{}, {}, and {}'.format(*res) elif len(res) == 2: s = '{} and {}'.format(*res) elif len(res) == 1: s = '{}'.format(*res) else: s = 'no resources' C.log.writef('{} gains: {}', player, s)
def _init_game(self, config): # update player props self.players['Player1'].symbol = config.basic.characters.p1 self.players['Player2'].symbol = config.basic.characters.p2 # init state side = config.basic.side_length self.state.map = gsm.Array(np.zeros((side, side), dtype=int)) self.state.turn_counter = -1 self.state.player_order = tlist(self.players.values()) if self.state.player_order[0].name != self._select_player(): self.state.player_order = self.state.player_order[::-1]
def _end_game(self): out = tdict() vps = tdict({player.name: player.vps for player in self.players}) out.vps = vps mx = max(vps.values()) winners = tlist() for name, V in vps.items(): if V == mx: winners.append(name) if len(winners) == 1: out.winner = winners[0] return out out.winners = winners return out
def _end_game(self, C): out = tdict() vps = tdict({player.name: player.vps for player in C.players}) out.vps = vps mx = max(vps.values()) # TODO: break ties with money and hand card values winners = tlist() for name, V in vps.items(): if V == mx: winners.append(name) if len(winners) == 1: out.winner = winners[0] return out out.winners = winners return out
def _init_game(self, config): cards = tlist() for n, c in config.cards.items(): cards.extend([c]) self.state.deck = self.table.create(obj_type='deck52', cards=cards, seed=self.RNG.getrandbits(64), default='card') self.state.deck.shuffle() for i, player in enumerate(self.players): player.order = i + 1 player.hand = tset() for k in range(5): c1 = self.state.deck.draw() c1.face_down(player) #c1.visible = tset([player]) player.hand.add( c1 ) #bei 1 card kann add nehmen, bei set of cards muss update nehmen! self.state.deck.count = len(self.state.deck)
def set_settlement(self, C, player, action=None): if action is None: self.active = self.player_order.pop() raise Decide('settlement') loc, = action assert_(loc.obj_type == 'Corner', f'{loc} should be a corner') build(C, 'settlement', player, loc) self.settled = loc for e in loc.edges: if e is not None: for c in e.corners: self.available.discard(c) if self.on_second: res = tlist() for f in loc.fields: if f is not None and f.res != 'desert': res.append(f.res) for r in res: gain_res(r, C.state.bank, player, 1) if len(res) == 3: s = '{}, {}, and {}'.format(*res) elif len(res) == 2: s = '{} and {}'.format(*res) elif len(res) == 1: s = '{}'.format(*res) else: s = 'no resources' C.log.writef('{} gains: {}', player, s) raise Switch('road')
def get_outside_corners(field): # start corner must be N of the field at seam "1" def get_next(options, prev): for x in options: if x is not None and x != prev and None in x.fields: return x raise Exception('No next found') start = field.corners[0] e = field.edges[0] x1, f, x2 = start.fields assert f == field and x1 is None and x2 is None, 'Not the right corner' corners = tlist([start]) c = get_next(e.corners, start) while c != start: corners.append(c) e = get_next(c.edges, e) c = get_next(e.corners, c) return corners
def _set_phase_stack(self, config): self.stack.set_player_order(tlist(self.players)) return tlist(['tic'])
def __init__(self, address, owner, **props): super().__init__(harvest=None, owner=owner, address=address, intruders=tlist(), **props)
def _peek(self): if self._top_face_up is not None: self.next = tlist(list(self._objs._data)[:self._top_face_up])
def _set_phase_stack(self, config): self.stack.set_player_order(tlist(self.players)) return tlist([self.create_phase('king')])
def __init__(self, seed, default, top_face_up): super().__init__(cards=tlist(), seed=seed, default=default, top_face_up=top_face_up)
def _set_phase_stack(self, config): return tlist([self.create_phase('turn')])
def _init_game(self, config): res_names = config.rules.res_names # update player props for player in self.players.values(): player.reserve = tdict(config.rules.building_limits) player.buildings = tdict(road=tset(), settlement=tset(), city=tset()) player.resources = tdict({res: 0 for res in res_names}) player.devcards = tset() player.past_devcards = tset() player.vps = 0 player.ports = tset() self.state.costs = config.rules.building_costs bank = tdict() for res in res_names: bank[res] = config.rules.num_res self.state.bank = bank self.state.rewards = config.rules.victory_points self.state.production = config.rules.resource_pays self.state.reqs = config.rules.reqs self.state.victory_condition = config.rules.victory_condition self.state.hand_limit = config.rules.hand_limit # init map G = grid.make_hexgrid(config.map.map, table=self.table, enable_corners=True, enable_edges=True, field_obj_type='hex', grid_obj_type='board') build_catan_map(G, config.map.fields, config.map.ports, config.rules.numbers, self.RNG) self.state.world = G # robber and numbers numbers = tdict() loc = None for f in G.fields: if f.res == 'desert': loc = f else: if f.num not in numbers: numbers[f.num] = tset() numbers[f.num].add(f) assert loc is not None, 'couldnt find the desert' self.state.robber = self.table.create('robber', loc=loc) self.state.desert = loc self.state.numbers = numbers loc.robber = self.state.robber # setup dev card deck cards = tlist() for name, info in config.dev.items(): cards.extend([tdict(name=name, desc=info.desc)] * info.num) self.state.dev_deck = self.table.create(obj_type='devdeck', cards=cards, seed=self.RNG.getrandbits(64), default='devcard') self.state.dev_deck.shuffle() self.state.bank_trading = config.rules.bank_trading self.state.msgs = config.msgs self.state.rolls = tstack()
def execute(self, C, player=None, action=None): if 'knight' not in self: # enforce hand limit if 'debt' in self: # debts have been tabulated if len(self.debt): # there are still outstanding debts res, = action self.choices[player].append(res) gain_res(res, C.state.bank, player, -1) C.log[player].writef('1 of your {} is stolen.', res) self.debt[player] -= 1 if self.debt[player] < 1: del self.debt[player] C.log.writef('{} loses: {}', player, ', '.join(self.choices[player])) del self.choices[player] action = None else: lim = C.state.hand_limit self.debt = tdict() self.choices = tdict() for player in C.players: if player.num_res > lim: self.debt[player] = player.num_res // 2 self.choices[player] = tlist() if len(self.debt): return else: self.debt = tdict() if 'loc' not in self: if action is None: return # if 'knight' not in self: # C.log.writef('{} may move the {}.', player, C.state.robber) loc, = action self.loc = loc if loc == 'cancel': C.log[player].write('Cancel knight') raise PhaseComplete prev = C.state.robber.loc del prev.robber loc.robber = C.state.robber C.state.robber.loc = loc if 'knight' not in self: C.log.writef('{} moves {} to {}', player, C.state.robber, self.loc) self.steal_options = steal_options(self.loc, player) if len(self.steal_options) == 0: self.target = None elif len(self.steal_options) == 1: self.target = self.steal_options.pop() else: return elif 'target' not in self: self.target, = action if self.target == 'cancel': C.log[player].write('Cancel knight') raise PhaseComplete if 'target' in self: self.stolen = None if self.target is not None: opp = self.target if opp.num_res > 0: self.stolen = C.RNG.choice(sum([[r]*n for r,n in opp.resources.items()],[])) gain_res(self.stolen, C.state.bank, opp, -1) gain_res(self.stolen, C.state.bank, player, 1) if 'knight' in self: play_dev(player, self.knight) C.log.writef('{} plays {}', player, self.knight) C.log.writef('{} moves {} to {}', player, C.state.robber, self.loc) if self.stolen is not None: C.log.writef('{} steals a resource card from {}', player, opp) C.log[opp].writef('You lose a {}', self.stolen) C.log[player].writef('You gain a {}', self.stolen) raise PhaseComplete