def populate_life(zone_id): _zone = ZONES[zone_id] for faction_name in _zone['faction_spawn_list']: _spawn_profile = _zone['faction_spawn_list'][faction_name] if _spawn_profile['bases']: for b in range(_spawn_profile['bases']): for node_set_id in _zone['node_sets']: _node_set = _zone['node_sets'][node_set_id] _set_center_x, _set_center_y = _node_set['center'] _spawn_pos = [] for x, y in shapes.circle(_set_center_x, _set_center_y, 5): if (x, y) in _zone['solids']: continue _spawn_pos.append((x, y)) _min_squad_size, _max_squad_size = ai_factions.FACTIONS[faction_name]['base_size_range'] for i in range(random.randint(_min_squad_size, _max_squad_size)): _x, _y = _spawn_pos.pop(random.randint(0, len(_spawn_pos)-1)) _e = _spawn_profile['type'](_x, _y, 'Test NPC %s' % str(i+1)) if _e['ai']['meta']['is_squad_leader']: _squad = ai_squads.get_assigned_squad(_e) _squad['camp_id'] = node_set_id _node_set['owner'] = {'faction': faction_name, 'squad': _e['ai']['squad']} if _spawn_profile['trader']: _x, _y = _spawn_pos.pop(random.randint(0, len(_spawn_pos)-1)) _e = _spawn_profile['type'](_x, _y, 'Trader') else: for b in range(_spawn_profile['squads']): _spawn_pos = [] if 'spawn_pos' in _spawn_profile: _center_x, _center_y = _spawn_profile['spawn_pos'] else: _center_x, _center_y = random.sample([_zone['width'] - 50, _zone['height'] - 50, 50, 50], 2) for x, y in shapes.circle(_center_x, _center_y, 5): if (x, y) in _zone['solids']: continue _spawn_pos.append((x, y)) _min_squad_size, _max_squad_size = ai_factions.FACTIONS[faction_name]['squad_size_range'] for i in range(random.randint(_min_squad_size, _max_squad_size)): _x, _y = _spawn_pos.pop(random.randint(0, len(_spawn_pos)-1)) _e = _spawn_profile['type'](_x, _y, 'Test NPC %s' % str(i+1))
def get_push_position(squad, member_id): _member = entities.get_entity(member_id) _best_vantage = {'position': None, 'score': 1000} _vision = stats.get_vision(_member) _engage_range = int(round(_vision * .75)) for pos in squad['position_map_scores']: _scores = squad['position_map_scores'][pos] _score = _scores['vantage'] + _scores['member_coverage'] if not _scores['targets'] or _score < 6 or _score > _engage_range: continue if _score < _best_vantage['score']: _best_vantage['score'] = _score _best_vantage['position'] = pos[:] if not _best_vantage['position']: _member['ai']['meta']['has_firing_position'] = False return _x, _y = movement.get_position(_member) for coverage_pos in shapes.circle(_best_vantage['position'][0], _best_vantage['position'][1], 6): if not coverage_pos in squad['position_map_scores']: continue _c_dist = 15 * (1 - (numbers.distance(coverage_pos, (_x, _y)) / 6.0)) squad['position_map_scores'][coverage_pos]['member_coverage'] += _c_dist squad['position_map_scores'][_best_vantage['position']]['member_coverage'] += 20 return _best_vantage['position']
def create_position_map(squad): _coverage_positions = set() _known_targets = set() _known_squads = set() for member_id in squad['members']: _member = entities.get_entity(member_id) _x, _y = movement.get_position(_member) _sight = stats.get_vision(_member) if member_id in squad['member_position_maps']: _old_coverage_positions = squad['member_position_maps'][member_id].copy() else: _old_coverage_positions = set() _map_size = zones.get_active_size() squad['member_position_maps'][member_id] = set() squad['member_los_maps'][member_id] = tcod.map_new(_map_size[0], _map_size[1]) tcod.map_copy(zones.get_active_los_map(), squad['member_los_maps'][member_id]) _t = time.time() tcod.map_compute_fov(squad['member_los_maps'][member_id], _x, _y, radius=_sight, light_walls=False, algo=tcod.FOV_PERMISSIVE_2) for pos in shapes.circle(_x, _y, _sight): if pos[0] < 0 or pos[0] >= _map_size[0] or pos[1] < 0 or pos[1] >= _map_size[1]: continue if not tcod.map_is_in_fov(squad['member_los_maps'][member_id], pos[0], pos[1]): continue _coverage_positions.add(pos) squad['member_position_maps'][member_id].add(pos) #TODO: Do this elsewhere for target_id in _member['ai']['visible_targets']: if not target_id in entities.ENTITIES: continue _target = entities.get_entity(target_id) _known_squads.add((_target['ai']['faction'], _target['ai']['squad'])) #TODO: Is this right? _known_targets.update(_member['ai']['visible_targets']) _positions_to_remove = _old_coverage_positions - _coverage_positions squad['known_targets'].update(_known_targets) squad['known_squads'].update(_known_squads) squad['coverage_positions'].update(_coverage_positions) squad['coverage_positions'] = squad['coverage_positions'] - _positions_to_remove if squad['known_targets']: update_position_maps(squad) logging.debug('Updated local position map - requesting squad update') else: logging.debug('Updated local position map.')
def light(x, y, brightness, r=1., g=1., b=1., light_map=None): if '--no-fx' in sys.argv: return if light_map: _active_light_maps = zones.get_active_light_maps() _light_map = _active_light_maps[light_map] else: _light_map = post_processing.get_light_map() _width, _height = zones.get_active_size() for _x, _y in shapes.circle(x, y, brightness): if _x < 0 or _x >= _width or _y < 0 or _y >= _height: continue _brightness = 1 - ((numbers.float_distance((x, y), (_x, _y)) - 1.0) / float(brightness)) _r = numbers.clip(2 * (_brightness * r), 1, 4) _g = numbers.clip(2 * (_brightness * g), 1, 4) _b = numbers.clip(2 * (_brightness * b), 1, 4) _min_r = min(_light_map[0][_y, _x], _r) _max_r = max(_light_map[0][_y, _x], _r) _min_g = min([_light_map[1][_y, _x], _g]) _max_g = max([_light_map[1][_y, _x], _g]) _min_b = min([_light_map[2][_y, _x], _b]) _max_b = max([_light_map[2][_y, _x], _b]) _light_map[0][_y, _x] = numbers.interp(_min_r, _max_r, .5) _light_map[1][_y, _x] = numbers.interp(_min_g, _max_g, .5) _light_map[2][_y, _x] = numbers.interp(_min_b, _max_b, .5)
def _start_battle(attacking_squads=[], defending_squads=[]): global FADER create() _width, _height, _node_grid, _node_sets, _weight_map, _tile_map, _solids, _fsl, _trees, _inside, _lights, _spawns = mapgen_arena.generate(200, 200) _zone = zones.create('swamps', _width, _height, _node_grid, _node_sets, _weight_map, _tile_map, _solids, _fsl, _trees, _inside, _lights, _spawns) _attacking_spawn_x, _attacking_spawn_y = random.choice(list(_spawns['attacking'])) _attacking_spawn_positions = [(x, y) for x, y in shapes.circle(_attacking_spawn_x, _attacking_spawn_y, 5) if not (x, y) in _solids] for squad_id in attacking_squads: _squad = entities.get_entity(squad_id) for member_id in _squad['members']: _member = entities.get_entity(member_id) _spawn_x, _spawn_y = _attacking_spawn_positions.pop(random.randint(0, len(_attacking_spawn_positions) - 1)) entities.trigger_event(_member, 'set_position', x=_spawn_x, y=_spawn_y) _defending_spawn_x, _defending_spawn_y = random.choice(list(_spawns['defending'])) _attacking_spawn_positions = [(x, y) for x, y in shapes.circle(_defending_spawn_x, _defending_spawn_y, 5) if not (x, y) in _solids] for squad_id in defending_squads: _squad = entities.get_entity(squad_id) for member_id in _squad['members']: _member = entities.get_entity(member_id) _spawn_x, _spawn_y = _attacking_spawn_positions.pop(random.randint(0, len(_attacking_spawn_positions) - 1)) entities.trigger_event(_member, 'set_position', x=_spawn_x, y=_spawn_y) zones.activate(_zone) FADER = entities.create_entity() timers.register(FADER) fade_in() display.blit_background('tiles') while loop(): events.trigger_event('cleanup')
def get_cover_position(squad, member_id): _member = entities.get_entity(member_id) _best_coverage = {'position': None, 'score': 0} _inside = zones.get_active_inside_positions() if _member['movement']['path']['destination']: _hide_pos = _member['movement']['path']['destination'] else: _hide_pos = movement.get_position(_member) if _hide_pos in squad['position_map_scores']: _scores = squad['position_map_scores'][_hide_pos] _score = _scores['coverage'] + _scores['member_coverage'] if not _scores['targets'] and _score > 0: return _hide_pos for pos in squad['position_map_scores']: _scores = squad['position_map_scores'][pos] #TODO: Add or subtract here? Subtraction will make some NPCs run away from teammates _score = _scores['coverage'] + _scores['member_coverage'] if not pos in _inside: continue if _scores['targets'] or _score <= 0: continue if _score > _best_coverage['score']: _best_coverage['score'] = _score _best_coverage['position'] = pos[:] if not _best_coverage['position']: #print 'no good coverage position' return _x, _y = movement.get_position(_member) for coverage_pos in shapes.circle(_best_coverage['position'][0], _best_coverage['position'][1], 6): if not coverage_pos in squad['position_map_scores']: continue _c_dist = 10 * (1 - (numbers.distance(coverage_pos, (_x, _y)) / 3.0)) squad['position_map_scores'][coverage_pos][ 'member_coverage'] += _c_dist squad['position_map_scores'][ _best_coverage['position']]['member_coverage'] += 15 return _best_coverage['position']
def get_cover_position(squad, member_id): _member = entities.get_entity(member_id) _best_coverage = {'position': None, 'score': 0} _inside = zones.get_active_inside_positions() if _member['movement']['path']['destination']: _hide_pos = _member['movement']['path']['destination'] else: _hide_pos = movement.get_position(_member) if _hide_pos in squad['position_map_scores']: _scores = squad['position_map_scores'][_hide_pos] _score = _scores['coverage'] + _scores['member_coverage'] if not _scores['targets'] and _score > 0: return _hide_pos for pos in squad['position_map_scores']: _scores = squad['position_map_scores'][pos] #TODO: Add or subtract here? Subtraction will make some NPCs run away from teammates _score = _scores['coverage'] + _scores['member_coverage'] if not pos in _inside: continue if _scores['targets'] or _score <= 0: continue if _score > _best_coverage['score']: _best_coverage['score'] = _score _best_coverage['position'] = pos[:] if not _best_coverage['position']: #print 'no good coverage position' return _x, _y = movement.get_position(_member) for coverage_pos in shapes.circle(_best_coverage['position'][0], _best_coverage['position'][1], 6): if not coverage_pos in squad['position_map_scores']: continue _c_dist = 10 * (1 - (numbers.distance(coverage_pos, (_x, _y)) / 3.0)) squad['position_map_scores'][coverage_pos]['member_coverage'] += _c_dist squad['position_map_scores'][_best_coverage['position']]['member_coverage'] += 15 return _best_coverage['position']
def generate_shadow_map(width, height, solids, trees, inside): global SHADOWS SHADOWS = display.create_shader(width, height) SHADOWS[0] += 1 SHADOWS[1] += 1 SHADOWS[2] += 1 _taken = set() for x, y in solids: if (x, y) in trees: continue for y1 in range(-3, 4): for x1 in range(-3, 4): if (x + x1, y + y1) in solids or (x + x1, y + y1) in inside or ( x + x1, y + y1 ) in _taken or x + x1 >= width or y + y1 >= height: continue _shadow = numbers.clip( numbers.distance((x, y), (x + x1, y + y1)) / 5.0, .25, .6) + .25 if _shadow < SHADOWS[0][y + y1][x + x1]: SHADOWS[0][y + y1][x + x1] = _shadow SHADOWS[1][y + y1][x + x1] = _shadow SHADOWS[2][y + y1][x + x1] = _shadow _taken = set() for _x, _y in trees.keys(): _tree_size = float(trees[_x, _y]) for x, y in shapes.circle(_x, _y, int(_tree_size)): if (x, y) in solids or x >= width or y >= height or x < 0 or y < 0: continue _distance = numbers.float_distance((x, y), (_x, _y)) * 1.25 _shadow = numbers.clip(1 - ((_distance / _tree_size) + .25), .1, .9) SHADOWS[0][y][x] = numbers.clip(SHADOWS[0][y][x] - _shadow, .45, 1) SHADOWS[1][y][x] = numbers.clip(SHADOWS[1][y][x] - _shadow, .45, 1) SHADOWS[2][y][x] = numbers.clip(SHADOWS[2][y][x] - _shadow, .45, 1) return SHADOWS
def generate_shadow_map(width, height, solids, trees, inside): global SHADOWS SHADOWS = display.create_shader(width, height) SHADOWS[0] += 1 SHADOWS[1] += 1 SHADOWS[2] += 1 _taken = set() for x, y in solids: if (x, y) in trees: continue for y1 in range(-3, 4): for x1 in range(-3, 4): if (x+x1, y+y1) in solids or (x+x1, y+y1) in inside or (x+x1, y+y1) in _taken or x+x1 >= width or y+y1 >= height: continue _shadow = numbers.clip(numbers.distance((x, y), (x+x1, y+y1))/5.0, .25, .6) + .25 if _shadow < SHADOWS[0][y+y1][x+x1]: SHADOWS[0][y+y1][x+x1] = _shadow SHADOWS[1][y+y1][x+x1] = _shadow SHADOWS[2][y+y1][x+x1] = _shadow _taken = set() for _x, _y in trees.keys(): _tree_size = float(trees[_x, _y]) for x, y in shapes.circle(_x, _y, int(_tree_size)): if (x, y) in solids or x >= width or y >= height or x < 0 or y <0: continue _distance = numbers.float_distance((x, y), (_x, _y))*1.25 _shadow = numbers.clip(1 - ((_distance / _tree_size) + .25), .1, .9) SHADOWS[0][y][x] = numbers.clip(SHADOWS[0][y][x]-_shadow, .45, 1) SHADOWS[1][y][x] = numbers.clip(SHADOWS[1][y][x]-_shadow, .45, 1) SHADOWS[2][y][x] = numbers.clip(SHADOWS[2][y][x]-_shadow, .45, 1) return SHADOWS
def get_push_position(squad, member_id): _member = entities.get_entity(member_id) _best_vantage = {'position': None, 'score': 1000} _vision = stats.get_vision(_member) _engage_range = int(round(_vision * .75)) for pos in squad['position_map_scores']: _scores = squad['position_map_scores'][pos] _score = _scores['vantage'] + _scores['member_coverage'] if not _scores['targets'] or _score < 6 or _score > _engage_range: continue if _score < _best_vantage['score']: _best_vantage['score'] = _score _best_vantage['position'] = pos[:] if not _best_vantage['position']: _member['ai']['meta']['has_firing_position'] = False return _x, _y = movement.get_position(_member) for coverage_pos in shapes.circle(_best_vantage['position'][0], _best_vantage['position'][1], 6): if not coverage_pos in squad['position_map_scores']: continue _c_dist = 15 * (1 - (numbers.distance(coverage_pos, (_x, _y)) / 6.0)) squad['position_map_scores'][coverage_pos][ 'member_coverage'] += _c_dist squad['position_map_scores'][ _best_vantage['position']]['member_coverage'] += 20 return _best_vantage['position']
def generate(width, height): _weight_map, _tile_map, _solids, _node_grid = mapgen.create_map( width, height) _zoom = .95 _noise = tcod.noise_new(3) _low_grass = 25 _fsl = {} _building_space = set() _walls = set() _possible_trees = set() _river_start_x = random.randint(int(round(width * .35)), int(round(width * .65))) _river_start_y = 0 #random.randint(int(round(height * .15)), int(round(height * .85))) _x = _river_start_x _y = _river_start_y _px, _py = _river_start_x, _river_start_y _river_direction = 270 _turn_rate = random.randint(-1, 1) _river_tiles = set() _river_size = random.randint(7, 10) _ground_tiles = set() _possible_camps = set() while 1: for i in range(4, 10): for __x, __y in shapes.circle(_x, _y, _river_size): if __x < 0 or __y < 0 or __x >= width or __y >= height or ( __x, __y) in _solids: continue _river_tiles.add((__x, __y)) _tile = tiles.swamp_water(__x, __y) _tile_map[__y][__x] = _tile _weight_map[__y][__x] = _tile['w'] _river_direction += _turn_rate _xv, _yv = numbers.velocity(_river_direction, 1) _px += _xv _py += _yv _x = int(round(_px)) _y = int(round(_py)) if _x < 0 or _y < 0 or _x >= width or _y >= height or ( _x, _y) in _solids: break if _x < 0 or _y < 0 or _x >= width or _y >= height: break _turn_rate = random.uniform(-2.5, 2.5) _river_size = numbers.clip(_river_size + random.randint(-1, 1), 7, 10) for y in range(height): for x in range(width): if (x, y) in _river_tiles: continue _tile = tiles.grass(x, y) _tile_map[y][x] = _tile _weight_map[y][x] = _tile['w'] _ground_tiles.add((x, y)) tcod.noise_set_type(_noise, tcod.NOISE_WAVELET) for y in range(height): for x in range(width): if (x, y) in _river_tiles: continue _noise_values = [(_zoom * x / (constants.MAP_VIEW_WIDTH)), (_zoom * y / (constants.MAP_VIEW_HEIGHT))] _noise_value = 100 * tcod.noise_get_turbulence( _noise, _noise_values, tcod.NOISE_WAVELET) if _low_grass <= _noise_value <= 100: _tile = tiles.tall_grass(x, y) if _noise_value >= 40: if not x < width * .15 and not x > width * .85 and not y < height * .15 and not y > height * .85: _possible_camps.add((x, y)) if random.uniform(0, 1) > .5: _possible_trees.add((x, y)) elif _noise_value >= _low_grass - 10 and 10 * random.uniform( 0, 1) > _low_grass - _noise_value: _tile = tiles.grass(x, y) else: _tile = tiles.rock(x, y) _solids.add((x, y)) _tile_map[y][x] = _tile _weight_map[y][x] = _tile['w'] _trees = {} _tree_plots = _possible_trees - _solids - _river_tiles _used_trees = random.sample( _tree_plots, numbers.clip(int(round((width * height) * .002)), 0, len(_tree_plots))) for x, y in _used_trees: _size = random.randint(1, 3) for _x, _y in shapes.circle(x, y, _size): if _x < 0 or _y < 0 or _x >= width or _y >= height or ( _x, _y) in _solids: break _tile = tiles.tree(_x, _y) _weight_map[_y][_x] = _tile['w'] _tile_map[_y][_x] = _tile _trees[_x, _y] = random.uniform(2, 3.5) * _size _solids.add((_x, _y)) _ground_tiles = _ground_tiles - _solids _plot_pole_x, _plot_pole_y = width / 2, height / 2 _bushes = random.sample( _ground_tiles, numbers.clip(int(round((width * height) * .0003)), 0, len(_ground_tiles))) _camps = set() while len(_possible_camps): _camp_1 = random.choice(list(_possible_camps)) _possible_camps.remove(_camp_1) _camps.add(_camp_1) for camp_2 in _possible_camps.copy(): _dist = numbers.distance(_camp_1, camp_2) if _dist <= 250: _possible_camps.remove(camp_2) for x, y in _bushes: _walker_x = x _walker_y = y _last_dir = -2, -2 for i in range(random.randint(10, 15)): _tile = tiles.tree(_walker_x, _walker_y) _weight_map[_walker_y][_walker_x] = _tile['w'] _tile_map[_walker_y][_walker_x] = _tile _dir = random.randint(-1, 1), random.randint(-1, 1) _n_x = _walker_x + _dir[0] _n_y = _walker_y + _dir[1] if _n_x < 0 or _n_y < 0 or _n_x >= width or _n_y >= height or ( _n_x, _n_y) in _solids: break _last_dir = _dir[0] * -1, _dir[0] * -1 _walker_x = _n_x _walker_y = _n_y _camp_info = {} for c_x, c_y in _camps: _building_walls = random.sample(['north', 'south', 'east', 'west'], random.randint(2, 3)) _broken_walls = random.sample( _building_walls, numbers.clip(random.randint(0, 3), 0, len(_building_walls))) _camp = {'center': (c_x, c_y)} _camp_ground = [] for y in range(-10, 10 + 1): for x in range(-10, 10 + 1): _x = x + c_x _y = y + c_y if (_x, _y) in _solids or (_x, _y) in _river_tiles: continue if (x == -10 and 'west' in _building_walls) or ( y == -10 and 'north' in _building_walls) or ( x == 10 and 'east' in _building_walls) or ( y == 10 and 'south' in _building_walls): if x == -10 and 'west' in _building_walls and 'west' in _broken_walls and random.uniform( 0, 1) > .75: continue if x == 10 and 'east' in _building_walls and 'east' in _broken_walls and random.uniform( 0, 1) > .75: continue if y == -10 and 'north' in _building_walls and 'north' in _broken_walls and random.uniform( 0, 1) > .75: continue if y == 10 and 'south' in _building_walls and 'south' in _broken_walls and random.uniform( 0, 1) > .75: continue _tile = tiles.wooden_fence(_x, _y) _weight_map[_y][_x] = _tile['w'] _tile_map[_y][_x] = _tile _solids.add((_x, _y)) elif (x > -10 and x <= 10) and (y > -10 and y <= 10): _camp_ground.append((_x, _y)) _camp['ground'] = _camp_ground[:] _camp_info[c_x, c_y] = _camp mapgen.build_node_grid(_node_grid, _solids) for c_x, c_y in _camps: mapgen.add_plot_pole(c_x, c_y, 40, _solids) _fsl = { 'Terrorists': { 'bases': 1, 'squads': 0, 'trader': False, 'type': life.human_runner } } # #'Militia': {'bases': 0, 'squads': 1, 'trader': False, 'type': life.human_bandit}, # 'Wild Dogs': {'bases': 0, 'squads': 1, 'trader': False, 'type': life.wild_dog}} return width, height, _node_grid, mapgen.NODE_SETS.copy( ), _weight_map, _tile_map, _solids, _fsl, _trees, _building_space - _walls
def _start_battle(attacking_squads=[], defending_squads=[]): global FADER create() _width, _height, _node_grid, _node_sets, _weight_map, _tile_map, _solids, _fsl, _trees, _inside, _lights, _spawns = mapgen_arena.generate( 200, 200) _zone = zones.create('swamps', _width, _height, _node_grid, _node_sets, _weight_map, _tile_map, _solids, _fsl, _trees, _inside, _lights, _spawns) _attacking_spawn_x, _attacking_spawn_y = random.choice( list(_spawns['attacking'])) _attacking_spawn_positions = [ (x, y) for x, y in shapes.circle(_attacking_spawn_x, _attacking_spawn_y, 5) if not (x, y) in _solids ] for squad_id in attacking_squads: _squad = entities.get_entity(squad_id) for member_id in _squad['members']: _member = entities.get_entity(member_id) _spawn_x, _spawn_y = _attacking_spawn_positions.pop( random.randint(0, len(_attacking_spawn_positions) - 1)) entities.trigger_event(_member, 'set_position', x=_spawn_x, y=_spawn_y) _defending_spawn_x, _defending_spawn_y = random.choice( list(_spawns['defending'])) _attacking_spawn_positions = [ (x, y) for x, y in shapes.circle(_defending_spawn_x, _defending_spawn_y, 5) if not (x, y) in _solids ] for squad_id in defending_squads: _squad = entities.get_entity(squad_id) for member_id in _squad['members']: _member = entities.get_entity(member_id) _spawn_x, _spawn_y = _attacking_spawn_positions.pop( random.randint(0, len(_attacking_spawn_positions) - 1)) entities.trigger_event(_member, 'set_position', x=_spawn_x, y=_spawn_y) zones.activate(_zone) FADER = entities.create_entity() timers.register(FADER) fade_in() display.blit_background('tiles') while loop(): events.trigger_event('cleanup')
def get_vantage_point(squad, member_id): _member = entities.get_entity(member_id) _member_pos = movement.get_position(_member) _best_vantage = {'position': None, 'score': 1000} _engage_range = flags.get_flag(_member, 'engage_distance') _min_engage_range = flags.get_flag(_member, 'min_engage_distance') if _member['movement']['path']['destination']: if _member['movement']['path']['destination'] in squad[ 'position_map_scores']: _scores = squad['position_map_scores'][_member['movement']['path'] ['destination']] _score = _scores['vantage'] # + _scores['member_coverage'] _continue = False for target_id in squad['known_targets']: _last_known_position = _member['ai']['life_memory'][target_id][ 'last_seen_at'] _distance_to_target = numbers.distance( _member['movement']['path']['destination'], _last_known_position) if _distance_to_target < _min_engage_range: _continue = True break if not _continue and _scores[ 'targets'] and _score >= _min_engage_range and _score <= _engage_range: return _member['movement']['path']['destination'] for pos in squad['position_map_scores']: _scores = squad['position_map_scores'][pos] _dist = numbers.distance(_member_pos, pos) _score = _scores['vantage'] + _dist _continue = False if not _scores[ 'targets'] or _score - _dist < _min_engage_range or _score > _engage_range + _dist: continue for target_id in squad['known_targets']: _last_known_position = _member['ai']['life_memory'][target_id][ 'last_seen_at'] _distance_to_target = numbers.distance(pos, _last_known_position) if _distance_to_target < _min_engage_range: _continue = True break if _continue: continue if _score < _best_vantage['score']: _astar_distance = len( pathfinding.astar(_member_pos, pos, zones.get_active_astar_map(), zones.get_active_weight_map())) _best_vantage['score'] = _score + _scores['member_coverage'] + int( round((_astar_distance * .15))) _best_vantage['position'] = pos[:] if not _best_vantage['position']: _member['ai']['meta']['has_firing_position'] = False entities.trigger_event(_member, 'create_timer', time=60, exit_callback=_reset_fire_position) return _x, _y = movement.get_position(_member) _member_positions = set() for squad_member_id in squad['members']: if squad_member_id == member_id: continue _member_positions.add(movement.get_position_via_id(squad_member_id)) _v_p = _best_vantage['position'] _friendly_fire = False for pos in shapes.line((_x, _y), _best_vantage['position']): if pos in _member_positions: _friendly_fire = True break if _friendly_fire: for n_pos in [(_v_p[0] - 1, _v_p[1] - 1), (_v_p[0], _v_p[1] - 1), (_v_p[0] + 1, _v_p[1] - 1), (_v_p[0] - 1, _v_p[1]), (_v_p[0] + 1, _v_p[1]), (_v_p[0] - 1, _v_p[1] + 1), (_v_p[0], _v_p[1] + 1), (_v_p[0] + 1, _v_p[1] + 1)]: if not n_pos in squad['position_map_scores']: continue _break = False for nn_pos in shapes.line((_x, _y), n_pos): if nn_pos in _member_positions: _break = True break else: _v_p = n_pos break if _break: continue for coverage_pos in shapes.circle(_v_p[0], _v_p[1], 6): if not coverage_pos in squad['position_map_scores']: continue _c_dist = 15 * (1 - (numbers.distance(coverage_pos, (_x, _y)) / 6.0)) squad['position_map_scores'][coverage_pos][ 'member_coverage'] += _c_dist squad['position_map_scores'][_v_p]['member_coverage'] += 6 return _v_p
def create_position_map(squad): _coverage_positions = set() _known_targets = set() _known_squads = set() for member_id in squad['members']: _member = entities.get_entity(member_id) _x, _y = movement.get_position(_member) _sight = stats.get_vision(_member) if member_id in squad['member_position_maps']: _old_coverage_positions = squad['member_position_maps'][ member_id].copy() else: _old_coverage_positions = set() _map_size = zones.get_active_size() squad['member_position_maps'][member_id] = set() squad['member_los_maps'][member_id] = tcod.map_new( _map_size[0], _map_size[1]) tcod.map_copy(zones.get_active_los_map(), squad['member_los_maps'][member_id]) _t = time.time() tcod.map_compute_fov(squad['member_los_maps'][member_id], _x, _y, radius=_sight, light_walls=False, algo=tcod.FOV_PERMISSIVE_2) for pos in shapes.circle(_x, _y, _sight): if pos[0] < 0 or pos[0] >= _map_size[0] or pos[1] < 0 or pos[ 1] >= _map_size[1]: continue if not tcod.map_is_in_fov(squad['member_los_maps'][member_id], pos[0], pos[1]): continue _coverage_positions.add(pos) squad['member_position_maps'][member_id].add(pos) #TODO: Do this elsewhere for target_id in _member['ai']['visible_targets']: if not target_id in entities.ENTITIES: continue _target = entities.get_entity(target_id) _known_squads.add( (_target['ai']['faction'], _target['ai']['squad'])) #TODO: Is this right? _known_targets.update(_member['ai']['visible_targets']) _positions_to_remove = _old_coverage_positions - _coverage_positions squad['known_targets'].update(_known_targets) squad['known_squads'].update(_known_squads) squad['coverage_positions'].update(_coverage_positions) squad['coverage_positions'] = squad[ 'coverage_positions'] - _positions_to_remove if squad['known_targets']: update_position_maps(squad) logging.debug('Updated local position map - requesting squad update') else: logging.debug('Updated local position map.')
def populate_life(zone_id): _zone = ZONES[zone_id] for faction_name in _zone['faction_spawn_list']: _spawn_profile = _zone['faction_spawn_list'][faction_name] if _spawn_profile['bases']: for b in range(_spawn_profile['bases']): for node_set_id in _zone['node_sets']: _node_set = _zone['node_sets'][node_set_id] _set_center_x, _set_center_y = _node_set['center'] _spawn_pos = [] for x, y in shapes.circle(_set_center_x, _set_center_y, 5): if (x, y) in _zone['solids']: continue _spawn_pos.append((x, y)) _min_squad_size, _max_squad_size = ai_factions.FACTIONS[ faction_name]['base_size_range'] for i in range( random.randint(_min_squad_size, _max_squad_size)): _x, _y = _spawn_pos.pop( random.randint(0, len(_spawn_pos) - 1)) _e = _spawn_profile['type'](_x, _y, 'Test NPC %s' % str(i + 1)) if _e['ai']['meta']['is_squad_leader']: _squad = ai_squads.get_assigned_squad(_e) _squad['camp_id'] = node_set_id _node_set['owner'] = { 'faction': faction_name, 'squad': _e['ai']['squad'] } if _spawn_profile['trader']: _x, _y = _spawn_pos.pop( random.randint(0, len(_spawn_pos) - 1)) _e = _spawn_profile['type'](_x, _y, 'Trader') else: for b in range(_spawn_profile['squads']): _spawn_pos = [] if 'spawn_pos' in _spawn_profile: _center_x, _center_y = _spawn_profile['spawn_pos'] else: _center_x, _center_y = random.sample( [_zone['width'] - 50, _zone['height'] - 50, 50, 50], 2) for x, y in shapes.circle(_center_x, _center_y, 5): if (x, y) in _zone['solids']: continue _spawn_pos.append((x, y)) _min_squad_size, _max_squad_size = ai_factions.FACTIONS[ faction_name]['squad_size_range'] for i in range(random.randint(_min_squad_size, _max_squad_size)): _x, _y = _spawn_pos.pop( random.randint(0, len(_spawn_pos) - 1)) _e = _spawn_profile['type'](_x, _y, 'Test NPC %s' % str(i + 1))
def generate(width, height): _weight_map, _tile_map, _solids, _node_grid = mapgen.create_map(width, height) _zoom = .95 _noise = tcod.noise_new(3) _low_grass = 25 _fsl = {} _building_space = set() _walls = set() _possible_trees = set() _river_start_x = random.randint(int(round(width * .35)), int(round(width * .65))) _river_start_y = 0#random.randint(int(round(height * .15)), int(round(height * .85))) _x = _river_start_x _y = _river_start_y _px, _py = _river_start_x, _river_start_y _river_direction = 270 _turn_rate = random.randint(-1, 1) _river_tiles = set() _river_size = random.randint(7, 10) _ground_tiles = set() _possible_camps = set() while 1: for i in range(4, 10): for __x, __y in shapes.circle(_x, _y, _river_size): if __x < 0 or __y < 0 or __x >= width or __y >= height or (__x, __y) in _solids: continue _river_tiles.add((__x, __y)) _tile = tiles.swamp_water(__x, __y) _tile_map[__y][__x] = _tile _weight_map[__y][__x] = _tile['w'] _river_direction += _turn_rate _xv, _yv = numbers.velocity(_river_direction, 1) _px += _xv _py += _yv _x = int(round(_px)) _y = int(round(_py)) if _x < 0 or _y < 0 or _x >= width or _y >= height or (_x, _y) in _solids: break if _x < 0 or _y < 0 or _x >= width or _y >= height: break _turn_rate = random.uniform(-2.5, 2.5) _river_size = numbers.clip(_river_size + random.randint(-1, 1), 7, 10) for y in range(height): for x in range(width): if (x, y) in _river_tiles: continue _tile = tiles.grass(x, y) _tile_map[y][x] = _tile _weight_map[y][x] = _tile['w'] _ground_tiles.add((x, y)) tcod.noise_set_type(_noise, tcod.NOISE_WAVELET) for y in range(height): for x in range(width): if (x, y) in _river_tiles: continue _noise_values = [(_zoom * x / (constants.MAP_VIEW_WIDTH)), (_zoom * y / (constants.MAP_VIEW_HEIGHT))] _noise_value = 100 * tcod.noise_get_turbulence(_noise, _noise_values, tcod.NOISE_WAVELET) if _low_grass <= _noise_value <= 100: _tile = tiles.tall_grass(x, y) if _noise_value >= 40: if not x < width * .15 and not x > width * .85 and not y < height * .15 and not y > height * .85: _possible_camps.add((x, y)) if random.uniform(0, 1) > .5: _possible_trees.add((x, y)) elif _noise_value >= _low_grass - 10 and 10 * random.uniform(0, 1) > _low_grass-_noise_value: _tile = tiles.grass(x, y) else: _tile = tiles.rock(x, y) _solids.add((x, y)) _tile_map[y][x] = _tile _weight_map[y][x] = _tile['w'] _trees = {} _tree_plots = _possible_trees - _solids - _river_tiles _used_trees = random.sample(_tree_plots, numbers.clip(int(round((width * height) * .002)), 0, len(_tree_plots))) for x, y in _used_trees: _size = random.randint(1, 3) for _x, _y in shapes.circle(x, y, _size): if _x < 0 or _y < 0 or _x >= width or _y >= height or (_x, _y) in _solids: break _tile = tiles.tree(_x, _y) _weight_map[_y][_x] = _tile['w'] _tile_map[_y][_x] = _tile _trees[_x, _y] = random.uniform(2, 3.5) * _size _solids.add((_x, _y)) _ground_tiles = _ground_tiles - _solids _plot_pole_x, _plot_pole_y = width/2, height/2 _bushes = random.sample(_ground_tiles, numbers.clip(int(round((width * height) * .0003)), 0, len(_ground_tiles))) _camps = set() while len(_possible_camps): _camp_1 = random.choice(list(_possible_camps)) _possible_camps.remove(_camp_1) _camps.add(_camp_1) for camp_2 in _possible_camps.copy(): _dist = numbers.distance(_camp_1, camp_2) if _dist <= 250: _possible_camps.remove(camp_2) for x, y in _bushes: _walker_x = x _walker_y = y _last_dir = -2, -2 for i in range(random.randint(10, 15)): _tile = tiles.tree(_walker_x, _walker_y) _weight_map[_walker_y][_walker_x] = _tile['w'] _tile_map[_walker_y][_walker_x] =_tile _dir = random.randint(-1, 1), random.randint(-1, 1) _n_x = _walker_x + _dir[0] _n_y = _walker_y + _dir[1] if _n_x < 0 or _n_y < 0 or _n_x >= width or _n_y >= height or (_n_x, _n_y) in _solids: break _last_dir = _dir[0] * -1, _dir[0] * -1 _walker_x = _n_x _walker_y = _n_y _camp_info = {} for c_x, c_y in _camps: _building_walls = random.sample(['north', 'south', 'east', 'west'], random.randint(2, 3)) _broken_walls = random.sample(_building_walls, numbers.clip(random.randint(0, 3), 0, len(_building_walls))) _camp = {'center': (c_x, c_y)} _camp_ground = [] for y in range(-10, 10+1): for x in range(-10, 10+1): _x = x + c_x _y = y + c_y if (_x, _y) in _solids or (_x, _y) in _river_tiles: continue if (x == -10 and 'west' in _building_walls) or (y == -10 and 'north' in _building_walls) or (x == 10 and 'east' in _building_walls) or (y == 10 and 'south' in _building_walls): if x == -10 and 'west' in _building_walls and 'west' in _broken_walls and random.uniform(0, 1) > .75: continue if x == 10 and 'east' in _building_walls and 'east' in _broken_walls and random.uniform(0, 1) > .75: continue if y == -10 and 'north' in _building_walls and 'north' in _broken_walls and random.uniform(0, 1) > .75: continue if y == 10 and 'south' in _building_walls and 'south' in _broken_walls and random.uniform(0, 1) > .75: continue _tile = tiles.wooden_fence(_x, _y) _weight_map[_y][_x] = _tile['w'] _tile_map[_y][_x] = _tile _solids.add((_x, _y)) elif (x > -10 and x <= 10) and (y > -10 and y <= 10): _camp_ground.append((_x, _y)) _camp['ground'] = _camp_ground[:] _camp_info[c_x, c_y] = _camp mapgen.build_node_grid(_node_grid, _solids) for c_x, c_y in _camps: mapgen.add_plot_pole(c_x, c_y, 40, _solids) _fsl = {'Terrorists': {'bases': 1, 'squads': 0, 'trader': False, 'type': life.human_runner}} # #'Militia': {'bases': 0, 'squads': 1, 'trader': False, 'type': life.human_bandit}, # 'Wild Dogs': {'bases': 0, 'squads': 1, 'trader': False, 'type': life.wild_dog}} return width, height, _node_grid, mapgen.NODE_SETS.copy(), _weight_map, _tile_map, _solids, _fsl, _trees, _building_space - _walls
def get_vantage_point(squad, member_id): _member = entities.get_entity(member_id) _member_pos = movement.get_position(_member) _best_vantage = {'position': None, 'score': 1000} _engage_range = flags.get_flag(_member, 'engage_distance') _min_engage_range = flags.get_flag(_member, 'min_engage_distance') if _member['movement']['path']['destination']: if _member['movement']['path']['destination'] in squad['position_map_scores']: _scores = squad['position_map_scores'][_member['movement']['path']['destination']] _score = _scores['vantage']# + _scores['member_coverage'] _continue = False for target_id in squad['known_targets']: _last_known_position = _member['ai']['life_memory'][target_id]['last_seen_at'] _distance_to_target = numbers.distance(_member['movement']['path']['destination'], _last_known_position) if _distance_to_target < _min_engage_range: _continue = True break if not _continue and _scores['targets'] and _score >= _min_engage_range and _score <= _engage_range: return _member['movement']['path']['destination'] for pos in squad['position_map_scores']: _scores = squad['position_map_scores'][pos] _dist = numbers.distance(_member_pos, pos) _score = _scores['vantage'] + _dist _continue = False if not _scores['targets'] or _score - _dist < _min_engage_range or _score > _engage_range + _dist: continue for target_id in squad['known_targets']: _last_known_position = _member['ai']['life_memory'][target_id]['last_seen_at'] _distance_to_target = numbers.distance(pos, _last_known_position) if _distance_to_target < _min_engage_range: _continue = True break if _continue: continue if _score < _best_vantage['score']: _astar_distance = len(pathfinding.astar(_member_pos, pos, zones.get_active_astar_map(), zones.get_active_weight_map())) _best_vantage['score'] = _score + _scores['member_coverage'] + int(round((_astar_distance * .15))) _best_vantage['position'] = pos[:] if not _best_vantage['position']: _member['ai']['meta']['has_firing_position'] = False entities.trigger_event(_member, 'create_timer', time=60, exit_callback=_reset_fire_position) return _x, _y = movement.get_position(_member) _member_positions = set() for squad_member_id in squad['members']: if squad_member_id == member_id: continue _member_positions.add(movement.get_position_via_id(squad_member_id)) _v_p = _best_vantage['position'] _friendly_fire = False for pos in shapes.line((_x, _y), _best_vantage['position']): if pos in _member_positions: _friendly_fire = True break if _friendly_fire: for n_pos in [(_v_p[0]-1, _v_p[1]-1), (_v_p[0], _v_p[1]-1), (_v_p[0]+1, _v_p[1]-1), (_v_p[0]-1, _v_p[1]), (_v_p[0]+1, _v_p[1]), (_v_p[0]-1, _v_p[1]+1), (_v_p[0], _v_p[1]+1), (_v_p[0]+1, _v_p[1]+1)]: if not n_pos in squad['position_map_scores']: continue _break = False for nn_pos in shapes.line((_x, _y), n_pos): if nn_pos in _member_positions: _break = True break else: _v_p = n_pos break if _break: continue for coverage_pos in shapes.circle(_v_p[0], _v_p[1], 6): if not coverage_pos in squad['position_map_scores']: continue _c_dist = 15 * (1 - (numbers.distance(coverage_pos, (_x, _y)) / 6.0)) squad['position_map_scores'][coverage_pos]['member_coverage'] += _c_dist squad['position_map_scores'][_v_p]['member_coverage'] += 6 return _v_p