def add_car(self, lane, x=None, mode='moving'): # x is the front of the car x0, y0, w, h = self.rect dirn, cars = self.cars[lane] imgs = (self.car_crashed_imgs if mode == 'crashed' else self.car_imgs) imgs = imgs[weighted_rand(self.img_weightings)] iw, ih = imgs[0].get_size() if x is None: gap = conf.CAR_GAP[mode] if cars: # start after last car x = cars[-1].back(dirn) - dirn * gap if dirn == 1: x -= iw else: # choose a random position at the front if dirn == 1: mn = w - iw - gap mx = w - 1 else: mn = 1 - iw mx = gap x = randint(mn, mx) elif dirn == 1: x -= iw y = conf.ROAD_LANES[lane] - ih / 2 cars.append(Car(self, imgs[dirn == 1], (x, y)))
def __init__ (self, level, wmap, pos): self.level = level self.wmap = wmap # generate name gender = choice(conf.FORENAMES.keys()) name = weighted_rand(conf.TITLES) if isinstance(name, tuple): name = name[gender == 'female'] if name is None: name = '' else: name += ' ' fore = choice(conf.FORENAMES[gender]) sur = choice(conf.SURNAMES) if isinstance(sur, tuple): sur = sur[gender == 'female'] name += fore + ' ' + sur self.name = name self.pos = pos self.cons = [] self.knows = False self._know = [] self.selected = False self.sending = False img = level.game.img self._imgs = (img('person.png'), img('person-knows.png'), img('person-sel.png'), img('person-knows-sel.png')) w, h = self._imgs[0].get_size() self._offset = (-w / 2, -h / 2)
def add_car (self, lane, x = None, mode = 'moving'): # x is the front of the car x0, y0, w, h = self.rect dirn, cars = self.cars[lane] imgs = (self.car_crashed_imgs if mode == 'crashed' else self.car_imgs) imgs = imgs[weighted_rand(self.img_weightings)] iw, ih = imgs[0].get_size() if x is None: gap = conf.CAR_GAP[mode] if cars: # start after last car x = cars[-1].back(dirn) - dirn * gap if dirn == 1: x -= iw else: # choose a random position at the front if dirn == 1: mn = w - iw - gap mx = w - 1 else: mn = 1 - iw mx = gap x = randint(mn, mx) elif dirn == 1: x -= iw y = conf.ROAD_LANES[lane] - ih / 2 cars.append(Car(self, imgs[dirn == 1], (x, y)))
def _mk_news (self, items): if not isinstance(items, dict): items = dict((n, 1) for n in items) s = weighted_rand(items) if s is None: return None # substitute some values for c, sub in self._news_data.iteritems(): s = s.replace('%' + c, sub) return s
def add_con (p1, p2): # need to add dist to self.dists before creating Connection key = frozenset((p1, p2)) used_dists[key] = dists[key] # choose method types this_methods = set() for i in xrange(ir(max(1, n_methods()))): this_methods.add(weighted_rand(methods)) # create connection and add to stores c = Connection(level, (p1, p2), this_methods) self.cons.append(c) p1.cons.append(c) p2.cons.append(c) g1 = groups[p1] g2 = groups[p2] # merge groups g1.update(g2) for p, g in groups.iteritems(): if g is g2: groups[p] = g1
def add_enemies (self, difficulty): es = self.enemies d = difficulty ws = conf.ENEMY_WEIGHTINGS e_types = conf.ENEMIES # position w, h = conf.RES axis, side = choice(((0, 0), (0, 1), (1, 0), (1, 1))) bdys = ((-50, w + 50), (-50, h + 50)) x = bdys[axis][side] a, b = bdys[not axis] y = rand_in(a, b) pos = [0, 0] while d > 0: e = conf.ENEMIES[weighted_rand(ws)] d -= e['diff'] pos[axis] = x + rand_in(-25, 25) pos[not axis] = ev(.5 / difficulty) es.append(Enemy(self, pos, e['size'], e['mass'], e['health'], e['speed'], e['intelligence'], e['damage'], e['kb']))
def update (self): pos = self.body.position if self.re_eval <= 0: intelligence = self.intelligence # aim at the nearest player ps = self.level.players r = conf.ENEMY_TARGET_ACC * intelligence targets = [ ((1 / p.body.position.get_distance(pos)) * r, p) for p in ps ] + [(conf.ENEMY_LOST, None)] target = targets[weighted_rand(zip(*targets)[0])][1] if target is None: # aim somewhere random w, h = conf.RES b = conf.ENEMY_LOST_BORDER self.target = (rand_in(b, 1 - b) * w, rand_in(b, 1 - b) * h) self.targeting_player = False else: self.targeting_player = target self.target = target.body.position # speed mean_loss = conf.ENEMY_SPEED_THRESHOLD / intelligence self.speed = self.max_speed * (1 - ev(1. / mean_loss)) self.re_eval = ev(1. / conf.ENEMY_REEVAL) self.re_eval -= 1 to_move = tm = self.target - pos if to_move.get_length() < conf.ENEMY_MOVE_THRESHOLD: to_move = [0, 0] t = self.targeting_player if t: d = tm.get_length() if d < self.radius + t.radius: t.hit(self.damage * conf.ENEMY_DAMAGE, self.kb * conf.ENEMY_KNOCKBACK, tm.get_angle()) self.to_move = to_move ax, ay, a = Obj.update(self) self.update_aim(ax, ay, a)
def __init__ (self, level, size, selected): Widget.__init__(self, size) self.level = level self.selected = selected self.selecting = None self._sel_area = None self._actions = [] self._news = [] self.areas = areas = {} w, h = self.size # generate areas names = sample(conf.AREAS, conf.NUM_AREAS) n_rows = int(ceil(len(names) ** .5)) n_per_row = float(len(names)) / n_rows done_f = done = 0 dy = ir(h / float(n_rows)) y = dy / 2 for j in xrange(n_rows): done_f += n_per_row n_this_row = int(done_f) - done dx = ir(w / float(n_this_row)) x = dx / 2 for i in xrange(n_this_row): areas[names[done + i]] = (x, y) x += dx done += n_this_row y += dy # generate people self.people = ps = [] dists = {} self.dists = used_dists = {} b = conf.WMAP_BORDER x0 = y0 = b x1 = w - b y1 = h - b nearest = 2 * conf.PERSON_RADIUS + conf.PERSON_NEAREST for i in range(conf.NUM_PEOPLE): while True: x, y = randint(x0, x1), randint(y0, y1) this_dists = {} for p in ps: ox, oy = p.pos dist = ((ox - x) * (ox - x) + (oy - y) * (oy - y)) ** .5 if dist < nearest: break this_dists[p] = dist else: new_p = Person(level, self, (x, y)) for p, dist in this_dists.iteritems(): dists[frozenset((new_p, p))] = dist ps.append(new_p) break # compute all remaining distances for p1 in ps: for p2 in ps: if p1 is not p2: key = frozenset((p1, p2)) if key not in dists: x1, y1 = p1.pos x2, y2 = p2.pos dists[key] = ((x2 - x1) ** 2 + (y2 - y1) ** 2) ** .5 def add_con (p1, p2): # need to add dist to self.dists before creating Connection key = frozenset((p1, p2)) used_dists[key] = dists[key] # choose method types this_methods = set() for i in xrange(ir(max(1, n_methods()))): this_methods.add(weighted_rand(methods)) # create connection and add to stores c = Connection(level, (p1, p2), this_methods) self.cons.append(c) p1.cons.append(c) p2.cons.append(c) g1 = groups[p1] g2 = groups[p2] # merge groups g1.update(g2) for p, g in groups.iteritems(): if g is g2: groups[p] = g1 # generate connections methods = dict((method, data['freq']) for method, data in conf.METHODS.iteritems()) n_methods = conf.METHODS_PER_CON self.cons = [] # and group by whether connected groups = dict((p, set((p,))) for p in ps) n_cons = conf.CONS_PER_PERSON max_cons = conf.MAX_CONS_PER_PERSON # give everyone connections biased towards people near them for p in ps: # distances have a non-zero minimum others = dict((other, 1. / dists[frozenset((p, other))] ** \ conf.SHORT_CONNECTION_BIAS) for other in ps if other is not p) for c in p.cons: del others[c.other(p)] targets = [] this_n_cons = ir(max(1, min(max_cons, min(len(others), n_cons())))) for i in xrange(this_n_cons - len(p.cons)): other = weighted_rand(others) targets.append(other) del others[other] for other in targets: add_con(p, other) # reduce to one group by adding extra connections frozen_groups = set(frozenset(g) for g in groups.itervalues()) while len(frozen_groups) > 1: i = iter(frozen_groups) g1 = next(i) g2 = next(i) dist, p1, p2 = min(min((dists[frozenset((p1, p2))], p1, p2) for p2 in g2 if p2 is not p1) for p1 in g1) add_con(p1, p2) frozen_groups = set(frozenset(g) for g in groups.itervalues()) # give some people full names ps = ps[:min(conf.NUM_FULL_NAMES, len(ps))] for p, name in zip(ps, sample(conf.FULL_NAMES, len(ps))): p.name = name # let someone know self.n_know = 0 ps[0].recieve()