def generate(self): shops = 0 hotel = 0 taverns = util.roll(1, self.rank, -1) if self.rank >= 3: if util.coinflip(): shops = util.roll(1, self.rank, -2) hotel = util.coinflip() #roll for number of houses. it'lee be 4-8 houses for small village #and 6-12 for town. and much for for large city. but that's it for now house_count = util.roll(self.rank, 3, self.rank) noble_house_count = util.roll(1, self.rank, -3) gl.logger.debug( 'Generating buildings: %d rooms, %d noble, %d tavern, %d shops, %d hotel' % (house_count, noble_house_count, taverns, shops, hotel)) gen = self.create_room_generator(house_count, noble_house_count, taverns, shops, hotel) self.generate_road() for x in (noble_house_count, taverns, shops, hotel): house_count += util.cap_lower(x, 0, 0) gl.logger.debug('Total number of houses: %d' % house_count) if self.room_placer is None: self.generate_rooms_random_place(house_count, gen) else: self.room_placer(self, house_count, gen)
def generate_rooms_along_road(self, house_count, room_gen, allow_crop = True): x = util.roll(2, 3) x2 = int(x) house_top = house_count / 2 + house_count % 2 house_bot = house_count / 2 for z in xrange(0, house_top): room = room_gen.next().materialize() if house_bot > 0: room2 = room_gen.next().materialize() y = self.roadminy - len(room) + (self.roadmaxy - self.roadminy) y2 = self.roadminy xw = x + len(room[0]); xh = y + len(room) if xw < self.width and xh < self.height: newxy = self.adjust_x_y_anywhere(x, y, xw, xh, -1, allow_crop) if newxy is None: continue x, y = newxy self.copy_room(room, x, y) x = xw x += util.roll(2,2) if house_bot > 0: x2w = x2 + len(room2[0]) y2w = y2 + len(room2) if x2w > self.width or y2w > self.height: continue newxy2 = self.adjust_x_y_anywhere(x2, y2, x2w, y2w, 1, allow_crop) if newxy2 is not None: x2, y2 = newxy2 self.copy_room(room2, x2, y2) x2 += len(room2[0]) x2 += util.roll(2,2) house_bot -= 1
def update(self): events = [] if roll(self.game.insanity_rate): self.insanity += 1 if self.is_infected: self.days_infected += 1 if self.days_infected == 3: self.is_alive = False else: if (roll(self.game.infection_rate) and not self.game.infected_someone_today): self.is_infected = True self.days_infected = 0 events.append(CharacterInfected(self)) self.game.infected_someone_today = True if self.insanity == 5: self.is_alive = False if self.game.food_rations > 0: self.game.food_rations -= 1 else: self.is_alive = False if self.is_alive: if not self.is_infected: self.game.turn_action_points += 1 else: del self.game.skill_commands[self.skill_command] events.append(CharacterDeath(self)) return events
def attack(self, whom): dmgs = [] for attack in self.base_dmg: dmg = util.roll(*attack) #let's roll 1d20 + HD for now, assuming that monster # can hit player no lees than 30% of the time # (thus checking it to be > 14) #TODO add player's/monsters' evade to calculations if util.roll(1, 20, self.base_hd) >= 14: dmgs.append(dmg) else: gl.message(self.name.capitalize() + ' misses ' + whom.name, 1) whom.take_damage(self, dmgs, attack)
def soothe(self): self.game.turn_action_points -= 1 if roll(90): self.insanity -= 1 return (CharacterSoothedResult(self, True),) else: return (CharacterSoothedResult(self, False),)
def bullets(self): self.game.turn_action_points -= 1 added_bullets = 0 if roll(75): added_bullets = randint(1, 10) self.game.bullets += added_bullets return (BulletsMade(added_bullets),)
def scavenge(self): self.game.turn_action_points -= 1 added_food = 0 if roll(60): added_food = randint(5, 10) self.game.food_rations += added_food return (FoodHuntResult(added_food),)
def search(self) -> None: self.time += SEARCH_TIME room = self.hero.room check = self.hero.awareness.bonus + roll() for nr in room.neighbors.values(): nr.reveal_hidden(check) self.look()
def _choose_map(generator_type, params, player_hd, theme, size): """ _choose_map(...) = > MapDef (or None if theme file does not exist) Loads the list of available maps and chooses a random one. Maps gets filtered first by number of parameters. Selection is based on weight/chance of a map. Also map is checked against unique maps list already generated. """ file = get_map_file(theme, size=size) if not file: return None av_maps = parse_file(file) total_maps_of_theme = len(av_maps) if total_maps_of_theme < 1: raise RuntimeError('No maps for MapRequest with theme [%s]' % theme) #now let's filter them leaving maps suitable for current generator/player HD and other params av_maps = filter(lambda x: _check_static_params(generator_type, player_hd, x, params), av_maps) tmap = None if not av_maps: return None while True: if total_maps_of_theme < 1: #if we iterated over enough maps and can't decide on them - break unless none is selected if tmap: break raise RuntimeError('Cannot select map of theme %s - too few maps available' % theme) total_maps_of_theme -= 1 # choose a random map from a weighed list tmap = random_from_list_weighted(av_maps) if tmap.chance > 0: if roll(1, tmap.chance) == 1: break else: break unique_maps_already_generated[tmap.id] = 1 #prepare a map return tmap.prepare(params)
def create_city(birth = False, city=False, depart = False): name = util.gen_name('city', world.cities_names) if birth: world.birth_place = name if city: world.birth_place_rank = util.roll(2, 3, 3) else: world.birth_place_rank = util.roll(1, 3, 1) if depart: world.depart_place = name world.current_city = name if city: world.depart_place_rank = util.roll(1, 3, 3) else: world.depart_place_rank = util.roll(1, 3) return name
def 血犹大第一可爱(self): skill_name = "血犹大第一可爱" if roll(30): self.log_skill(skill_name) defence_decreased = 5 log(f"【{self.enemy.name}】的防御力降低 {defence_decreased} 点") self.enemy.defence = max(0, self.enemy.defence - defence_decreased)
def attack(self, from_char, to_char): """ Perform an attack represented by self from from_char to to_char.""" print self.messages["prep_msg"] % (from_char.desc["job"], to_char.desc["job"], self.wpn_name) # calculate hit # Hit formula: # 1d20 + attribute vs defender's AC # roll 20 for crit print "Calculating hit chance:", attribute = from_char.effective_stats[self.attribute] hit_roll, crit_roll = roll(HIT_ROLL, True) hit_against = to_char.effective_stats["AC"] hit = attribute + hit_roll print "%d against %d" % (hit, hit_against) # calculate damage # Dmg formula: # roll 20 and > enemy's AC = max dmg # roll 20 and < enemy's AC = regular dmg # roll 1 = 0 dmg # noncrit roll and < enemy's AC = 0 dmg # # dmg = dmg roll + attacker's weapon attribute (dex or str) # critical hit roll if hit_roll >= self.crit_range: # crit and successful hit, max damage if hit > hit_against: dmg = attribute + roll(self.dmg_roll, True)[1] print "Critical! Max Damage!" print self.messages["hit_crit_msg"] print to_char.update_hp(-dmg) # crit but not enough to hit, regular damage else: dmg = attribute + roll(self.dmg_roll, False)[0] print "Critical!" print self.messages["hit_success_msg"] print to_char.update_hp(-dmg) # noncritical hit roll, but beats enemy's AC elif hit > hit_against and hit_roll > 1: # miss on natural 1 print self.messages["hit_success_msg"] print "Calculating damage:", dmg = attribute + roll(self.dmg_roll, True)[0] print to_char.update_hp(-dmg) else: print self.messages["hit_fail_msg"]
def place_random_monsters(self): #todo - maybe we should move this to mapgenerator (check for theme, etc) #choose random number of monsters #3d(dlvl) + 3d2 + 7 monsters total - at least 11 monsters on d1 and up-to 40 on d27 num_monsters = util.roll(1, gl.__dlvl__, util.roll(3, 2, 7)) num_monsters -= len(self.critters) free_squares = -2 for x in xrange(self.width): for y in xrange(self.height): tile = self.tile_at(x, y) if tile.passable(): free_squares += 1 num_monsters = util.cap(num_monsters, free_squares) #if it was capped - then map is too small... if num_monsters == free_squares: num_monsters = randrange(1, free_squares / 2) passes = num_monsters * 5 for i in range(num_monsters): if passes <= 0: break passes -= 1 #choose random spot for this monster x, y = self.find_random_square(self.has_critter_at) room = self._find_room(x, y) if room and room.src: if room.src.no_mon_gen: continue #determining critter level. it may vary from XL - 3 to XL + 1. To let is scale better multiply by 100 #cap it to be no lower than 1 crit_hd = max(randrange(gl.__xl__ - 3, gl.__xl__ + 1), 1) self.place_random_critter(gl.__dlvl__, crit_hd, x, y) #check for OOD monster. let's create OOD 10% of the time for now if libtcod.random_get_int(0, 0, 100) >= 89: crit_level = libtcod.random_get_int(0, gl.__dlvl__ + 2, gl.__dlvl__ + 3) crit_hd = max(randrange(gl.__xl__ - 3, gl.__xl__ + 3), 1) x, y = self.find_random_square(self.has_critter_at) room = self._find_room(x, y) if room and room.src: if room.src.no_mon_gen: return self.place_random_critter(crit_level, crit_hd, x, y)
def roll_dice(player: int) -> int: """Asks player to roll dice""" sides = 6 roll_again = input( "Player {}: Press ENTER to roll your dice...".format(player)) num_rolled = roll(sides) print("You rolled {}.".format(num_rolled)) return num_rolled
def place_random_monsters(self): #todo - maybe we should move this to mapgenerator (check for theme, etc) #choose random number of monsters #3d(dlvl) + 3d2 + 7 monsters total - at least 11 monsters on d1 and up-to 40 on d27 num_monsters = util.roll(1, gl.__dlvl__, util.roll(3, 2, 7)) num_monsters -= len(self.critters) free_squares = -2 for x in xrange(self.width): for y in xrange(self.height): tile = self.tile_at(x, y) if tile.passable(): free_squares += 1 num_monsters = util.cap(num_monsters, free_squares) #if it was capped - then map is too small... if num_monsters == free_squares: num_monsters = randrange(1 , free_squares / 2) passes = num_monsters * 5 for i in range(num_monsters): if passes <= 0: break passes -= 1 #choose random spot for this monster x, y = self.find_random_square(self.has_critter_at) room = self._find_room(x, y) if room and room.src: if room.src.no_mon_gen: continue #determining critter level. it may vary from XL - 3 to XL + 1. To let is scale better multiply by 100 #cap it to be no lower than 1 crit_hd = max(randrange(gl.__xl__ - 3, gl.__xl__ + 1), 1) self.place_random_critter(gl.__dlvl__, crit_hd, x, y) #check for OOD monster. let's create OOD 10% of the time for now if libtcod.random_get_int(0, 0, 100) >= 89: crit_level = libtcod.random_get_int(0, gl.__dlvl__ + 2, gl.__dlvl__ + 3) crit_hd = max(randrange(gl.__xl__ - 3, gl.__xl__ + 3), 1) x, y = self.find_random_square(self.has_critter_at) room = self._find_room(x, y) if room and room.src: if room.src.no_mon_gen: return self.place_random_critter(crit_level, crit_hd, x, y)
def 变成星星吧(self): skill_name = "变成星星吧" self.log_skill(skill_name) if roll(50): damageBase = LowerBoundedInteger(233) else: damageBase = LowerBoundedInteger(50) damage = Damage(self.get_damage_value(damageBase), False, True) self.cause_damage(damage)
def escape(self, bonus: int = 0) -> None: assert self.hero.room.monster monster = self.hero.room.monster self.time += ESCAPE_TIME check = self.hero.agility.bonus + roll() + bonus if check < monster.escape_dc: sounds.roar.play() monster.attack(self) self.hero.retreat()
def search_traps(self) -> None: """Search for traps within door""" self.time += SEARCH_TIME check = self.hero.awareness.bonus + roll() self.hero.room.reveal_traps(check) self.look() if self.hero.room.trap is None or self.hero.room.trap.hide_dc > 0: self.visit_room(title="Doesn't seem to be trapped...") else: self.visit_room(title="It's a trap!")
def hunt(self): self.game.turn_action_points -= 1 added_food = 0 bullets_used = 0 if roll(90) and self.game.bullets > 0: bullets_used = randint(1, min(6, self.game.bullets)) added_food = randint(5, 10) self.game.food_rations += added_food self.game.bullets -= bullets_used return (FoodHuntResult(added_food), BulletsUsed(bullets_used))
def roll_dice(player_num: int) -> int: """Asks player to roll dice""" sides = 6 player_colour = eval(f"Fore.{PLAYER_COLOURS[player_num]}") input( f"{player_colour}{Player.get(player_num):s}: Press ENTER to roll your dice" ) num_rolled = roll(sides) print("You rolled {}.".format(num_rolled)) return num_rolled
def place_monsters(self): #choose random number of monsters #3d(dlvl) + 3d2 + 7 monsters total - at least 11 monsters on d1 and up-to 40 on d27 num_monsters = util.roll(1, gl.__dlvl__, util.roll(3, 2, 7)) #cap monster generation for now num_monsters = util.cap(num_monsters, 30) for i in range(num_monsters): #choose random spot for this monster x, y = self.find_random_square(self.has_critter_at) #determining critter level. it may vary from XL - 3 to XL + 3. To let is scale better multiply by 100 #cap it to be no lower than 1 crit_hd = util.cap_lower(randrange(gl.__xl__ - 3, gl.__xl__ + 3), 1, 1) self.place_critter(gl.__dlvl__, crit_hd, x, y) #check for OOD monster. let's create OOD 10% of the time for now if libtcod.random_get_int(0, 0, 100) >= 89: crit_level = libtcod.random_get_int(0, gl.__dlvl__ + 2, gl.__dlvl__ + 3) crit_hd = util.cap_lower(randrange(gl.__xl__ - 3, gl.__xl__ + 3), 1, 1) x, y = self.find_random_square(self.has_critter_at) self.place_critter(crit_level, crit_hd, x, y)
def init_stats(self, min_stats): """ Initialize character stats.""" # zero out all stats init = {"str": 0, "dex": 0, "AC": 0, "max_HP": 0} self.base_stats.update(init) self.bonus_stats.update(init) self.effective_stats.update(init) # base stats = min stats + 2d6. self.base_stats.update(min_stats) for stat in self.base_stats.keys(): self.base_stats[stat] += roll("2d6", False)[0] # update effective stats self.update_stats()
def generate_road(self): ms_start = libtcod.sys_elapsed_milli() _h = self.height / 3 road_y = randrange(_h - util.roll(1, 10), _h + util.roll(1, 10)) len_no_break = randrange(self.break_road / 2, self.break_road) old_road_y = road_y delta = 0 if self.rank > self.RANK_CITY: delta = 1 for x in xrange(0, self.width): len_no_break -= 1 if len_no_break <= 0: len_no_break = randrange(self.break_road / 2, self.break_road) y_delta = util.roll(1, 3) #nope, try another turn if y_delta == 1: len_no_break = 1 elif y_delta == 2: old_road_y, road_y = road_y, util.cap_lower( road_y - 1, 0, 0) delta = -1 else: old_road_y, road_y = road_y, util.cap( road_y + 1, self.height) delta = 1 self.roadminy = min(self.roadminy, road_y) self.roadmaxy = max(self.roadmaxy, road_y) if old_road_y != road_y: self._map[old_road_y][x] = self.road() self._map[road_y][x] = self.road() old_road_y = road_y else: self._map[road_y][x] = self.road() if self.rank >= self.RANK_CITY: self._map[road_y + delta][x] = self.road() ms_end = libtcod.sys_elapsed_milli() print 'generated in ' + str(ms_end - ms_start) + ' ms'
def generate(self): shops = 0 hotel = 0 taverns = util.roll(1, self.rank, -1) if self.rank >=3: if util.coinflip(): shops = util.roll(1, self.rank, -2) hotel = util.coinflip() #roll for number of houses. it'lee be 4-8 houses for small village #and 6-12 for town. and much for for large city. but that's it for now house_count = util.roll(self.rank,3, self.rank) noble_house_count = util.roll(1, self.rank, -3) gl.logger.debug('Generating buildings: %d rooms, %d noble, %d tavern, %d shops, %d hotel' % (house_count, noble_house_count, taverns, shops, hotel)) gen = self.create_room_generator(house_count, noble_house_count, taverns, shops, hotel) self.generate_road() for x in (noble_house_count, taverns, shops, hotel): house_count += util.cap_lower(x, 0, 0) gl.logger.debug('Total number of houses: %d' % house_count) if self.room_placer is None: self.generate_rooms_random_place(house_count, gen) else: self.room_placer(self, house_count, gen)
def __init__(self): self.first_name = rn.random_nick() self.last_name = rn.random_nick() self.stre = roll('3d6') self.con = roll('3d6') self.dex = roll('3d6') self.int = roll('3d6') self.wis = roll('3d6') self.cha = roll('3d6')
def generate_rooms_along_road(self, house_count, room_gen, allow_crop=True): x = util.roll(2, 3) x2 = int(x) house_top = house_count / 2 + house_count % 2 house_bot = house_count / 2 for z in xrange(0, house_top): room = room_gen.next().materialize() if house_bot > 0: room2 = room_gen.next().materialize() y = self.roadminy - len(room) + (self.roadmaxy - self.roadminy) y2 = self.roadminy xw = x + len(room[0]) xh = y + len(room) if xw < self.width and xh < self.height: newxy = self.adjust_x_y_anywhere(x, y, xw, xh, -1, allow_crop) if newxy is None: continue x, y = newxy self.copy_room(room, x, y) x = xw x += util.roll(2, 2) if house_bot > 0: x2w = x2 + len(room2[0]) y2w = y2 + len(room2) if x2w > self.width or y2w > self.height: continue newxy2 = self.adjust_x_y_anywhere(x2, y2, x2w, y2w, 1, allow_crop) if newxy2 is not None: x2, y2 = newxy2 self.copy_room(room2, x2, y2) x2 += len(room2[0]) x2 += util.roll(2, 2) house_bot -= 1
def perform(self): effort = [] effort.append(roll('1d20') + self.mod(self.stre)) effort.append(roll('1d20') + self.mod(self.con)) effort.append(roll('1d20') + self.mod(self.dex)) effort.append(roll('1d20') + self.mod(self.int)) effort.append(roll('1d20') + self.mod(self.wis)) effort.append(roll('1d20') + self.mod(self.cha)) return effort
def generate_road(self): ms_start = libtcod.sys_elapsed_milli() _h = self.height / 3 road_y = randrange(_h - util.roll(1, 10), _h + util.roll(1, 10)) len_no_break = randrange(self.break_road / 2, self.break_road) old_road_y = road_y delta = 0 if self.rank > self.RANK_CITY: delta = 1 for x in xrange(0, self.width): len_no_break -= 1 if len_no_break <= 0: len_no_break = randrange(self.break_road / 2, self.break_road) y_delta = util.roll(1, 3) #nope, try another turn if y_delta == 1: len_no_break = 1 elif y_delta == 2: old_road_y, road_y = road_y, util.cap_lower(road_y - 1, 0, 0) delta = -1 else: old_road_y, road_y = road_y, util.cap(road_y + 1, self.height) delta = 1 self.roadminy = min(self.roadminy, road_y) self.roadmaxy = max(self.roadmaxy, road_y) if old_road_y != road_y: self._map[old_road_y][x] = self.road() self._map[road_y][x] = self.road() old_road_y = road_y else: self._map[road_y][x] = self.road() if self.rank >= self.RANK_CITY: self._map[road_y + delta][x] = self.road() ms_end = libtcod.sys_elapsed_milli() print 'generated in ' + str(ms_end - ms_start) + ' ms'
def disarm_trap(self) -> None: assert self.hero.room.trap assert self.hero.room.trap.hide_dc == 0 self.time += DISARM_TIME trap = self.hero.room.trap check = self.hero.agility.bonus + roll() if check >= trap.disarm_dc: self.add_message("You disarm it!") self.hero.room.trap = None self.visit_room() sounds.disarm.play() elif check >= trap.disarm_dc // 2: self.visit_room(title="This seems difficult to disarm...") else: self.trigger_trap("You triggered the {} trying to disarm it!") self.visit_room()
def test(stat, debug=False): """Take a test against a percentage stat. Pass debug=True to ouput roll details to stdout.""" r = util.roll(1,100) if debug or util.DEBUG: util.debugOut("roll: %d, stat: %d\n"%(r,stat)) result = False if stat > 5: if r <= round(stat/10.): result = util.crit elif r <= stat: result = True elif r <= 5: result = True if debug or util.DEBUG: util.debugOut("result: %r\n" % result) return result
def play_a_game(): positions = {'player1': 1, 'player2': 1} turns = {'player1': 1, # note this is wrong 'player2': 1} # note this is wrong ladders = { 3: 16, 5: 7, 15: 25, 18: 20, 21: 32 } snakes = { 12: 2, 14: 11, 17: 4, 31: 19, 35: 22 } roll_count = 0 # a double-check snake_count = 0 # new for question 2 last_square = 36 while max(positions.values()) < last_square: for player in sorted(positions.keys()): log.debug("%s plays turn %s" % (player, turns[player])) new_position = positions[player] + roll() roll_count += 1 if new_position in ladders.keys(): ladder_prob = randint(1,2) # new for q 3 if ladder_prob == 1: # 50% chance you can take the ladder new_position = ladders[new_position] if new_position in snakes.keys(): new_position = snakes[new_position] snake_count += 1 # New for question 2 positions[player] = new_position if new_position >= last_square: positions[player] = new_position break turns[player] += 1 # note this is wrong! game_stats = {'positions': positions, 'turns': turns, 'snake_count': snake_count, 'roll_count': roll_count} return game_stats
def break_door(self, bonus: int = 0) -> None: self.time += BREAK_TIME check = self.hero.strength.bonus + roll() + bonus assert self.hero.room.door sounds.force.play() if check >= self.hero.room.door.break_dc: self.hero.room.door = None if self.hero.room.trap: self.trigger_trap("As the door breaks, a {} is triggered!") # The trap is destroyed with the door self.hero.room.trap = None else: self.add_message("Crash! the door opens!") else: if self.hero.room.trap: self.trigger_trap("The door was trapped! you triggered a {}!") self.visit_door("...and the (trapped) door resists") else: self.visit_door("WHAAAM! The door resists...") self.look()
def fight(self, bonus: int = 0) -> None: assert self.hero.room.monster monster = self.hero.room.monster self.time += FIGHT_TIME check = self.hero.strength.bonus + roll() + bonus if check >= monster.ac: if bonus == 0: # FIXME: this shouldn't know about the boots sounds.fight.play() else: sounds.kungfu.play() if random.random() <= monster.drop_rate: self.hero.room.loot = treasure.Item.random() self.visit_treasure("The monster dies and drops a {}") else: self.add_message("You defeat the monster!") else: sounds.roar.play() monster.attack(self) self.hero.room.monster = None
def update(self): self.infected_someone_today = False events = [] self.days -= 1 if self.days == 0: if self.radio_repair_progress >= 50: events.append(RadioRepairResult(True)) events.append(GameEnd(True)) else: events.append(RadioRepairResult(False)) events.append(GameEnd(False)) return events self.fire -= 1 if self.fire <= 0: events.append(FireWentOut()) events.append(GameEnd(False)) return events for character in self.characters: cevt = character.update() for e in cevt: events.append(e) self.characters = [c for c in self.characters if c.is_alive] if len(self.characters) == 0: events.append(GameEnd(False)) if roll(30 - self.days): food_stolen = randint(1, min(8, self.food_rations)) self.food_rations -= food_stolen events.append(MonsterAttack(food_stolen)) if self.bullets > 0 and has_instance(self.characters, Soldier): bullets_used = randint(1, min(8, self.bullets)) self.bullets -= bullets_used events.append(BulletsUsed(bullets_used)) else: events.append(GameEnd(False)) return events
def _choose_map(generator_type, params, player_hd, theme, size): """ _choose_map(...) = > MapDef (or None if theme file does not exist) Loads the list of available maps and chooses a random one. Maps gets filtered first by number of parameters. Selection is based on weight/chance of a map. Also map is checked against unique maps list already generated. """ file = get_map_file(theme, size=size) if not file: return None av_maps = parse_file(file) total_maps_of_theme = len(av_maps) if total_maps_of_theme < 1: raise RuntimeError('No maps for MapRequest with theme [%s]' % theme) #now let's filter them leaving maps suitable for current generator/player HD and other params av_maps = filter( lambda x: _check_static_params(generator_type, player_hd, x, params), av_maps) tmap = None if not av_maps: return None while True: if total_maps_of_theme < 1: #if we iterated over enough maps and can't decide on them - break unless none is selected if tmap: break raise RuntimeError( 'Cannot select map of theme %s - too few maps available' % theme) total_maps_of_theme -= 1 # choose a random map from a weighed list tmap = random_from_list_weighted(av_maps) if tmap.chance > 0: if roll(1, tmap.chance) == 1: break else: break unique_maps_already_generated[tmap.id] = 1 #prepare a map return tmap.prepare(params)
def 崩坏世界的歌姬(self): skill_name = "崩坏世界的歌姬" if roll(30): self.log_skill(skill_name) log(f"【{self.name}】对【{self.enemy.name}】造成【麻痹】") self.enemy.status.append(self.麻痹(self.enemy))
def 不是针对你(self): skill_name = "不是针对你" if self.enemy.name == "琪亚娜" or roll(25): log(f"【{self.name}】的技能【{skill_name}】发动!!!") self.针对你 = True log(f"【{self.name}】获得了攻击力上升buff")
if util.coinflip(): name = choice(names) names.remove(name) if debug_names: npc.name = name + str(npc.__class__) npc.is_demon = demon logger.debug('Creating reference NPC ' + str(npc.__class__) + ' for ' + name + ' from background') for npc in world.mNPC: if isinstance(npc, instances) and npc.name is not None: names.append(npc.name) while True: world.reset() artefacts_count = util.roll(*ARTEFACTS_COUNT) logger.debug('Rolled for %d artefacts ' % (artefacts_count)) world.artefacts = items.generate_artefacts(artefacts_count, check=world.artefact_names) from background import make_story story = make_story() print story #######FIRST_PHASE: (all the NPC inhabiting the world except those, generated inside quests nly) #first let's define our world's population: this will include # all the NPC's of all types we have, except those which can be placed inside quesuts only #now let's roll for number of quest-givers. we do want them to exist min_quest_givers = util.roll(*QUEST_GIVER_ROLL) actual_quest_givers = 0 while actual_quest_givers < min_quest_givers:
def 女仆的温柔清理(self, damage): skill_name = "女仆的温柔清理" if roll(35): self.log_skill(skill_name) damage.value -= 3 self.enemy.attack -= 4
def quaff(self, player): super(HealingPotion, self).quaff(player) player.hp = util.cap(player.hp + util.roll(2, 10, 1), player.base_hp) gl.message('You feel somewhat better')
def 音量太强(self): skill_name = "音量太强" if roll(35): self.log_skill(skill_name) log(f"【{self.name}】眩晕了!!!") self.status.append(self.眩晕(self))
def getTreasure(lvl): """get basic treasure""" r = {} cr = randrange(1, 101) + (lvl-2)*18 if(cr < 31): r['cash'] = [roll(5, 6), 0, 0, 0, 0] elif(cr < 61): r['cash'] = [0, roll(4,6), 0, 0, 0] elif(cr < 71): r['cash'] = [0, 0, roll(3, 6), 0, 0] elif(cr < 96): r['cash'] = [0,0,0,roll(3, 6),0] elif(cr < 101): r['cash'] = [0, 0, 0, 0, roll(1, 6)] elif(cr < 131): r['cash'] = [roll(4, 6)*100, 0, roll(1, 6)*10, 0, 0] elif(cr < 161): r['cash'] = [0, roll(6, 6)*10, 0, roll(2, 6)*10, 0] elif(cr < 171): r['cash'] = [0,0, roll(3, 6)*10, roll(2, 6)*10, 0] elif(cr < 196): r['cash'] = [0, 0, 0, roll(4, 6) * 10, 0] elif(cr < 201): r['cash'] = [0,0,0,roll(2, 6)*10, roll(3, 6)] elif(cr < 221): r['cash'] = [0, roll(4, 6)*100, 0, roll(1, 6)*100, 0] elif(cr < 236): r['cash'] = [0,0,roll(1, 6)*100, roll(1, 6)*100, 0] elif(cr < 276): r['cash'] = [0,0, 0, roll(2, 6)*100, roll(1, 6)*10] elif(cr < 301): r['cash'] = [0, 0, 0, roll(2, 6)*100, roll(2, 6)*10] elif(cr < 316): r['cash'] = [0, 0, roll(2, 6)*1000, roll(8, 6)*100, 0] elif(cr < 356): r['cash'] = [0, 0, 0, roll(1, 6)*1000, roll(1, 6)*100] else: r['cash'] = [0,0,0, roll(1, 6)*1000, roll(2, 6) * 100] return r
def getHoard(lvl): """get major reward""" r = {'cash': [], 'loot': ''} cr = randrange(1, 101) + (lvl-2)*18 if(cr < 101): r['cash'] = [roll(6, 6)*100, roll(3, 6)*100, 0, roll(2, 6)*10, 0] if(cr < 7): "nothin" elif(cr < 17): r['loot'] = str(roll(2, 6)) + ' 10 gp gems' elif(cr < 27): r['loot'] = str(roll(2, 4)) + ' 25 gp art objects' elif(cr < 37): r['loot'] = str(roll(2, 6)) + ' 50 gp gems' elif(cr < 45): r['loot'] = str(roll(2, 6)) + ' 10 gp gems and ' + str(roll(1, 6)) + ' Magic Items(table A)' elif(cr < 53): r['loot'] = str(roll(2, 4)) + ' 25 gp art objects and ' + str(roll(1, 6)) + ' Magic Items(table A)' elif(cr < 61): r['loot'] = str(roll(2, 6)) + ' 50 gp gems and ' + str(roll(1, 6)) + ' Magic Items(table A)' elif(cr < 66): r['loot'] = str(roll(2, 6)) + ' 10 gp gems and ' + str(roll(1, 4)) + ' Magic Items(table B)' elif(cr < 71): r['loot'] = str(roll(2, 4)) + ' 25 gp art objects and ' + str(roll(1, 4)) + ' Magic Items(table B)' elif(cr < 76): r['loot'] = str(roll(2, 6)) + ' 50 gp gems and ' + str(roll(1, 4)) + ' Magic Items(table B)' elif(cr < 79): r['loot'] = str(roll(2, 6)) + ' 10 gp gems and ' + str(roll(1, 4)) + ' Magic Items(table C)' elif(cr < 81): r['loot'] = str(roll(2, 4)) + ' 25 gp art objects and ' + str(roll(1, 4)) + ' Magic Items(table C)' elif(cr < 86): r['loot'] = str(roll(2, 6)) + ' 50 gp gems and ' + str(roll(1, 4)) + ' Magic Items(table C)' elif(cr < 93): r['loot'] = str(roll(2, 4)) + ' 25 gp art objects and ' + str(roll(1, 4)) + ' Magic Items(table F)' elif(cr < 98): r['loot'] = str(roll(2, 6)) + ' 50 gp gems and ' + str(roll(1, 4)) + ' Magic Items(table F)' elif(cr < 100): r['loot'] = str(roll(2, 4)) + ' 25 gp art objects and one Magic Item(table G)' else: r['loot'] = str(roll(2, 6)) + ' 50 gp gems and one Magic Item(table G)' elif(cr < 201): r['cash'] = [roll(2, 6)*100, roll(2, 6)*1000, 0, roll(6, 6)*100, roll(3, 6)*10] cr = cr - 100 if(cr < 5): "nothin" elif(cr < 11): r['loot'] = str(roll(2, 4)) + ' 25 gp art objects' elif(cr < 17): r['loot'] = str(roll(3, 6)) + ' 50 gp gems' elif(cr < 23): r['loot'] = str(roll(3, 6)) + ' 100 gp gems' elif(cr < 29): r['loot'] = str(roll(2, 4)) + ' 250 gp art objects' elif(cr < 33): r['loot'] = str(roll(2, 4)) + ' 25 gp art objects and ' + str(roll(1, 6)) + ' Magic Items(table A)' elif(cr < 37): r['loot'] = str(roll(3, 6)) + ' 50 gp gems and ' + str(roll(1, 6)) + ' Magic Items(table A)' elif(cr < 41): r['loot'] = str(roll(3, 6)) + ' 100 gp gems and ' + str(roll(1, 6)) + ' Magic Items(table A)' elif(cr < 45): r['loot'] = str(roll(2, 4)) + ' 250 gp art objects and ' + str(roll(1, 6)) + ' Magic Items(table A)' elif(cr < 50): r['loot'] = str(roll(2, 4)) + ' 25 gp art objects and ' + str(roll(1, 4)) + ' Magic Items(table B)' elif(cr < 55): r['loot'] = str(roll(3, 6)) + ' 50 gp gems and ' + str(roll(1, 4)) + ' Magic Items(table B)' elif(cr < 60): r['loot'] = str(roll(3, 6)) + ' 100 gp gems and ' + str(roll(1, 4)) + ' Magic Items(table B)' elif(cr < 64): r['loot'] = str(roll(2, 4)) + ' 250 gp art objects and ' + str(roll(1, 4)) + ' Magic Items(table B)' elif(cr < 67): r['loot'] = str(roll(2, 4)) + ' 25 gp art objects and ' + str(roll(1, 4)) + ' Magic Items(table C)' elif(cr < 70): r['loot'] = str(roll(3, 6)) + ' 50 gp gems and ' + str(roll(1, 4)) + ' Magic Items(table C)' elif(cr < 73): r['loot'] = str(roll(3, 6)) + ' 100 gp gems and ' + str(roll(1, 4)) + ' Magic Items(table C)' elif(cr < 75): r['loot'] = str(roll(2, 4)) + ' 250 gp art objects and ' + str(roll(1, 4)) + ' Magic Items(table C)' elif(cr < 77): r['loot'] = str(roll(2, 4)) + ' 25 gp art objects and 1 Magic Item(table D)' elif(cr < 79): r['loot'] = str(roll(3, 6)) + ' 50 gp gems and 1 Magic Item(table D)' elif(cr < 80): r['loot'] = str(roll(3, 6)) + ' 100 gp gems and 1 Magic Item(table D)' elif(cr < 81): r['loot'] = str(roll(2, 4)) + ' 250 gp art objects and 1 Magic Item(table D)' elif(cr < 85): r['loot'] = str(roll(2, 4)) + ' 25 gp art objects and ' + str(roll(1, 4)) + ' Magic Items(table F)' elif(cr < 89): r['loot'] = str(roll(3, 6)) + ' 50 gp gems and ' + str(roll(1, 4)) + ' Magic Items(table F)' elif(cr < 92): r['loot'] = str(roll(3, 6)) + ' 100 gp gems and ' + str(roll(1, 4)) + ' Magic Items(table F)' elif(cr < 95): r['loot'] = str(roll(2, 4)) + ' 250 gp art objects and ' + str(roll(1, 4)) + ' Magic Items(table F)' elif(cr < 97): r['loot'] = str(roll(3, 6)) + ' 100 gp gems and ' + str(roll(1, 4)) + ' Magic Items(table G)' elif(cr < 99): r['loot'] = str(roll(2, 4)) + ' 250 gp art objects and ' + str(roll(1, 4)) + ' Magic Items(table G)' elif(cr < 100): r['loot'] = str(roll(3, 6)) + ' 100 gp gems and 1 Magic Item(table H)' else: r['loot'] = str(roll(2, 4)) + ' 250 gp art objects and 1 Magic Item(table H)' elif(cr < 301): r['cash'] = [0,0,0, roll(4, 6)*1000, roll(5, 6)*100] cr = cr - 200 if(cr < 4): "nothin" elif(cr < 7): r['loot'] = str(roll(2, 4)) + ' 250 gp art objects' elif(cr < 11): r['loot'] = str(roll(2, 4)) + ' 750 gp art objects' elif(cr < 13): r['loot'] = str(roll(3, 6)) + ' 500 gp gems' elif(cr < 16): r['loot'] = str(roll(3, 6)) + ' 1000 gp gems' elif(cr < 20): r['loot'] = str(roll(2, 4)) + ' 250 gp art objects, ' + str(roll(1, 4)) + ' Magic Items(table A) and ' + str(roll(1, 6)) + ' Magic Items(table B)' elif(cr < 24): r['loot'] = str(roll(2, 4)) + ' 750 gp art objects, ' + str(roll(1, 4)) + ' Magic Items(table A) and ' + str(roll(1, 6)) + ' Magic Items(table B)' elif(cr < 27): r['loot'] = str(roll(3, 6)) + ' 500 gp gems, ' + str(roll(1, 4)) + ' Magic Items(table A) and ' + str(roll(1, 6)) + ' Magic Items(table B)' elif(cr < 30): r['loot'] = str(roll(3, 6)) + ' 1000 gp gems, ' + str(roll(1, 4)) + ' Magic Items(table A) and ' + str(roll(1, 6)) + ' Magic Items(table B)' elif(cr < 36): r['loot'] = str(roll(2, 4)) + ' 250 gp art objects and ' + str(roll(1, 6)) + ' Magic Ttems(table C)' elif(cr < 41): r['loot'] = str(roll(2, 4)) + ' 750 gp art objects and ' + str(roll(1, 6)) + ' Magic Ttems(table C)' elif(cr < 46): r['loot'] = str(roll(3, 6)) + ' 500 gp gems and ' + str(roll(1, 6)) + ' Magic Ttems(table C)' elif(cr < 51): r['loot'] = str(roll(3, 6)) + ' 1000 gp gems and ' + str(roll(1, 6)) + ' Magic Ttems(table C)' elif(cr < 55): r['loot'] = str(roll(2, 4)) + ' 250 gp art objects and ' + str(roll(1, 4)) + ' Magic Items(table D)' elif(cr < 59): r['loot'] = str(roll(2, 4)) + ' 750 gp art objects and ' + str(roll(1, 4)) + ' Magic Ttems(table D)' elif(cr < 63): r['loot'] = str(roll(3, 6)) + ' 500 gp gems and ' + str(roll(1, 4)) + ' Magic Ttems(table D)' elif(cr < 67): r['loot'] = str(roll(3, 6)) + ' 1000 gp gems and ' + str(roll(1, 4)) + ' Magic Ttems(table D)' elif(cr < 69): r['loot'] = str(roll(2, 4)) + ' 250 gp art objects and 1 Magic Item(table E)' elif(cr < 71): r['loot'] = str(roll(2, 4)) + ' 750 gp art objects and 1 Magic Item(table E)' elif(cr < 73): r['loot'] = str(roll(3, 6)) + ' 500 gp gems and 1 Magic Item(table E)' elif(cr < 75): r['loot'] = str(roll(3, 6)) + ' 1000 gp gems and 1 Magic Item(table E)' elif(cr < 77): r['loot'] = str(roll(2, 4)) + ' 250 gp art objects, 1 Magic Item(table F) and ' + str(roll(1, 4)) + ' Magic Item(table G)' elif(cr < 79): r['loot'] = str(roll(2, 4)) + ' 750 gp art objects, 1 Magic Item(table F) and ' + str(roll(1, 4)) + ' Magic Item(table G)' elif(cr < 81): r['loot'] = str(roll(3, 6)) + ' 500 gp gems, 1 Magic Item(table F) and ' + str(roll(1, 4)) + ' Magic Item(table G)' elif(cr < 83): r['loot'] = str(roll(3, 6)) + ' 1000 gp gems, 1 Magic Item(table F) and ' + str(roll(1, 4)) + ' Magic Item(table G)' elif(cr < 86): r['loot'] = str(roll(2, 4)) + ' 250 gp art objects and ' + str(roll(1, 4)) + ' Magic Items(table H)' elif(cr < 89): r['loot'] = str(roll(2, 4)) + ' 750 gp art objects and ' + str(roll(1, 4)) + ' Magic Ttems(table H)' elif(cr < 91): r['loot'] = str(roll(3, 6)) + ' 500 gp gems and ' + str(roll(1, 4)) + ' Magic Ttems(table H)' elif(cr < 93): r['loot'] = str(roll(3, 6)) + ' 1000 gp gems and ' + str(roll(1, 4)) + ' Magic Ttems(table H)' elif(cr < 95): r['loot'] = str(roll(2, 4)) + ' 250 gp art objects and 1 Magic Item(table I)' elif(cr < 97): r['loot'] = str(roll(2, 4)) + ' 750 gp art objects and 1 Magic Item(table I)' elif(cr < 99): r['loot'] = str(roll(3, 6)) + ' 500 gp gems and 1 Magic Item(table I)' else: r['loot'] = str(roll(3, 6)) + ' 1000 gp gems and 1 Magic Item(table I)' else: r['cash'] = [0, 0, 0, roll(12, 6)*1000, roll(8, 6)*1000] cr = cr - 300 if(cr < 3): "nothin" elif(cr < 6): r['loot'] = str(roll(3, 6)) + ' 1000 gp gems and ' + str(roll(1, 8)) + ' Magic Items(table C)' elif(cr < 9): r['loot'] = str(roll(1, 10)) + ' 2500 gp art objects and ' + str(roll(1, 8)) + ' Magic Items(table C)' elif(cr < 12): r['loot'] = str(roll(1, 4)) + ' 7500 gp art objects and ' + str(roll(1, 8)) + ' Magic Items(table C)' elif(cr < 15): r['loot'] = str(roll(1, 8)) + ' 5000 gp gems and ' + str(roll(1, 8)) + ' Magic Items(table C)' elif(cr < 23): r['loot'] = str(roll(3, 6)) + ' 1000 gp gems and ' + str(roll(1, 6)) + ' Magic Items(table D)' elif(cr < 31): r['loot'] = str(roll(1, 10)) + ' 2500 gp art objects and ' + str(roll(1, 6)) + ' Magic Items(table D)' elif(cr < 39): r['loot'] = str(roll(1, 4)) + ' 7500 gp art objects and ' + str(roll(1, 6)) + ' Magic Items(table D)' elif(cr < 47): r['loot'] = str(roll(1, 8)) + ' 5000 gp gems and ' + str(roll(1, 6)) + ' Magic Items(table D)' elif(cr < 53): r['loot'] = str(roll(3, 6)) + ' 1000 gp gems and ' + str(roll(1, 6)) + ' Magic Items(table E)' elif(cr < 59): r['loot'] = str(roll(1, 10)) + ' 2500 gp art objects and ' + str(roll(1, 6)) + ' Magic Items(table E)' elif(cr < 64): r['loot'] = str(roll(1, 4)) + ' 7500 gp art objects and ' + str(roll(1, 6)) + ' Magic Items(table E)' elif(cr < 69): r['loot'] = str(roll(1, 8)) + ' 5000 gp gems and ' + str(roll(1, 6)) + ' Magic Items(table E)' elif(cr < 70): r['loot'] = str(roll(3, 6)) + ' 1000 gp gems and ' + str(roll(1, 4)) + ' Magic Items(table G)' elif(cr < 71): r['loot'] = str(roll(1, 10)) + ' 2500 gp art objects and ' + str(roll(1, 4)) + ' Magic Items(table G)' elif(cr < 72): r['loot'] = str(roll(1, 4)) + ' 7500 gp art objects and ' + str(roll(1, 4)) + ' Magic Items(table G)' elif(cr < 73): r['loot'] = str(roll(1, 8)) + ' 5000 gp gems and ' + str(roll(1, 4)) + ' Magic Items(table G)' elif(cr < 75): r['loot'] = str(roll(3, 6)) + ' 1000 gp gems and ' + str(roll(1, 4)) + ' Magic Items(table H)' elif(cr < 77): r['loot'] = str(roll(1, 10)) + ' 2500 gp art objects and ' + str(roll(1, 4)) + ' Magic Items(table H)' elif(cr < 79): r['loot'] = str(roll(1, 4)) + ' 7500 gp art objects and ' + str(roll(1, 4)) + ' Magic Items(table H)' elif(cr < 81): r['loot'] = str(roll(1, 8)) + ' 5000 gp gems and ' + str(roll(1, 4)) + ' Magic Items(table H)' elif(cr < 86): r['loot'] = str(roll(3, 6)) + ' 1000 gp gems and ' + str(roll(1, 4)) + ' Magic Items(table I)' elif(cr < 91): r['loot'] = str(roll(1, 10)) + ' 2500 gp art objects and ' + str(roll(1, 4)) + ' Magic Items(table I)' elif(cr < 96): r['loot'] = str(roll(1, 4)) + ' 7500 gp art objects and ' + str(roll(1, 4)) + ' Magic Items(table I)' else: r['loot'] = str(roll(1, 8)) + ' 5000 gp gems and ' + str(roll(1, 4)) + ' Magic Items(table I)' return r
continue if isinstance(npc, instances) and len(names) > 0: if util.coinflip(): name = choice(names) names.remove(name) if debug_names: npc.name = name + str(npc.__class__) npc.is_demon = demon logger.debug('Creating reference NPC ' +str(npc.__class__) +' for ' + name + ' from background') for npc in world.mNPC: if isinstance(npc, instances) and npc.name is not None: names.append(npc.name) while True: world.reset() artefacts_count = util.roll(*ARTEFACTS_COUNT) logger.debug('Rolled for %d artefacts ' % (artefacts_count)) world.artefacts = items.generate_artefacts(artefacts_count, check=world.artefact_names) from background import make_story story = make_story() print story #######FIRST_PHASE: (all the NPC inhabiting the world except those, generated inside quests nly) #first let's define our world's population: this will include # all the NPC's of all types we have, except those which can be placed inside quesuts only #now let's roll for number of quest-givers. we do want them to exist min_quest_givers = util.roll(*QUEST_GIVER_ROLL) actual_quest_givers = 0 while actual_quest_givers < min_quest_givers: if actual_quest_givers > 0:
def begin_combat(characters, scene, can_run): """ Start combat. Start combat between the 'player' and 'boar' characters. Return 'death' if player dies or 'win' if boar dies. """ # characters is a dict with an entry for key 'player' and 'boar' player = characters["player"] boar = characters["boar"] print "*" * 10, print " Entering combat! ", print "*" * 10 # Determine initiative # NOTE: for debugging # print "Surprised = %s" % player.conditions['surprised'] # calculate initiative bonus b_bonus = 10 if player.conditions["surprised"] else 0 p_bonus = 10 if boar.conditions["surprised"] else 0 print "Rolling initiatives:" player_init = roll("1d20", True)[0] + p_bonus boar_init = roll("1d20", True)[0] + b_bonus print "Player's initiative: %d" % player_init print "Boar's initiative: %d" % boar_init if player_init > boar_init: turn = "player" else: turn = "boar" print "{} goes first.".format(turn), raw_input("Press any key to continue") # Start combat loop # escape flags escape = {"player": False, "boar": False} while True: print "-" * 20 ### PLAYER'S TURN ### if turn == "player": print "Player's turn:" # escape if the player has chosen to run away if escape["player"]: print "Run away! Run away!" return run_away(scene) print "HP: %d" % player.health["HP"] # loop until player has taken a turn took_turn = False while not took_turn: action = raw_input("> ") if action in player.attacks: player_attack = player.attacks[action] player_attack.attack(player, boar) took_turn = True # an attack counts as a turn elif action in SUPPORTED_ACTIONS: if action in ENV_ACTIONS["run"] and can_run: took_turn = True print "You turn to run away." escape["player"] = True # escape on next turn elif action in ENV_ACTIONS["run"] and not can_run: took_turn = True # attempt to run counts as a turn print "Can't run away!" elif action in ENV_ACTIONS["stats"]: print player.get_stats() elif action in ENV_ACTIONS["inventory"]: print player.get_inventory() elif action in ENV_ACTIONS["help"]: print combat_help(player) else: print "You can't do that." turn = "boar" raw_input("Press any key to continue.") ### BOSS' TURN ### elif turn == "boar": print "Boar's turn:" # escape if the boar has chosen to run away if escape["boar"]: print "The boar turned and ran away!" return scene.name # send the player back to same scene print "HP: %d" % boar.health["HP"] # output bloodied message if HP < 30% if boar.health["HP"] / float(boar.effective_stats["max_HP"]) < 0.3: print "The boar is bloodied!" # chance to run away if HP < 20% if boar.health["HP"] / float(boar.effective_stats["max_HP"]) < 0.2: if randint(1, 100) <= 75: # 75% chance print "The boar turns to run away." escape["boar"] = True # escape on next turn # boss makes its attack boar_attack = boar.attacks[choice(boar.attacks.keys())] boar_attack.attack(boar, player) turn = "player" ### COMBAT FINISHED ### if player.health["HP"] <= 0: return "death" elif boar.health["HP"] <= 0: return "win"
def dmg(self): #todo cap? return [(util.roll(self.skill, 4)) - randint(self.skill / randint(1, 2), self.skill)]
def shoot(self, shooter, target): if not shooter.can_shoot: print('unit is not permitted to shoot right now') return elif target.quantity <= 0 or shooter.quantity <= 0: print 'error, one unit is empty / wiped out' return elif target.allegiance == shooter.allegiance: print('(was gonna shoot but didnt because both units are from same army)') return elif self.is_locked(shooter) or self.is_locked(target): print('was gonna shoot but shooter or target is locked in close combat.') return # more assert eg closest-target Ld check TODO dist = util.distance(shooter.coord, target.coord) if shooter.rng < dist: print( 'Tried to shoot but target is out of range ({real}sq / {realin}", ' + 'range: {max}sq / {maxin}")').format( real=dist, realin=util.inches(dist), max=shooter.rng, maxin=util.inches(shooter.rng)) return print shooter.name_with_sprite() + ' is shooting at ' + target.name_with_sprite() shooter.can_shoot = False print ' ' + util.conjugateplural(shooter.quantity, "shooter") + "..." totalshotcount = shooter.shotspercreature * shooter.quantity attacks = [] for i in range(totalshotcount): attacks.append(Attack(shooter.shootstr, shooter.ap)) print ' ' + util.conjugateplural(len(attacks), "shot") + "..." # To Hit for attack in attacks: if not attack.active: continue need_to_roll = 7 - shooter.bs need_to_roll = util.constrain(need_to_roll, 2, 6) result = util.roll( 'Shooting to-hit roll, shooter needs a {goal}+'.format(goal = need_to_roll), successif = (lambda n: n>=need_to_roll)) if result < need_to_roll: attack.active = False # Attacks that do not hit, wound, etc are marked .active = False # And then removed. Might be clumsy. hits = [a for a in attacks if a.active] print ' ' + util.conjugateplural(len(hits), "hit") + "..." # To Wound for attack in hits: need_to_roll = target.t - shooter.shootstr + 4 need_to_roll = util.constrain(need_to_roll, 2, 6) result = util.roll( 'Shooting to-wound roll, shooter needs a {goal}+'.format(goal = need_to_roll), successif = (lambda n: n>=need_to_roll)) if result < need_to_roll: attack.active = False wounds = [a for a in hits if a.active] print ' ' + util.conjugateplural(len(wounds), "pre-saving wound") + "..." # Saves for attack in wounds: # TODO: invulnerable saves, cover saves if target.sv >= 7 or target.sv >= attack.ap: break need_to_roll = target.sv result = util.roll( 'Shooting armor save, target saves on a {goal}+'.format(goal = need_to_roll)) if result >= need_to_roll: attack.active = False unsaved_wounds = [a for a in wounds if a.active] # print final results summary print ' {n} casualties...'.format(n=len(unsaved_wounds)) if len(unsaved_wounds) > 0: # TODO bug, 1 unsaved wound led to multiple lost models. seen once 2015 aug 9. self.damage(target, len(unsaved_wounds)) print ' Now target has ' + str(target.quantity) + ' creatures left in it.'
#some of the listed NPCs are generate inside quests. First we should define those, # who will be encountered throughtout the game (marked as +). # Then we define quest_givers marked as *. # Quest targets are marked as # 1 for killable target (quest target itself), 2 for talk-only-target, 3 for guard-type (guard quest item), 4 break-down plot (change plot) # ! denotes NPCs which are occasionaly generated during quest generation-only! #Actualy we don't want classic quests. instead let's use the quest as some meating point for plot-oriented-NPC. i.e. if the player is sent #to obtain amulet from and wafull demon not neccessarily he should get it. Instead he should be given some important information and be directed to the next quest #######FIRST_PHASE: (all the NPC inhabiting the world instead of those, generated inside quesut ly) #first let's define our world's population: this will include # all the NPC's of all types we have, except those which can be placed inside quesuts only #let's roll for number of NPC. let it lay from . NOTE that we will also add types denoted by ! later. mNPC_count = util.roll(*MNPC_ROLL) #now let's roll for number of quest-givers. we do want them to exist min_quest_fivers = util.roll(*QUEST_GIVER_ROLL) #now let's roll for immobile NPCs. we don't want many of them. let em be 0-3 at 50% chance for now immobile_npc = 0 if util.coinflip(): to_roll = util.roll(*IMMOBILE_NPC_ROLL) for i in range(0, to_roll): immobile_npc += util.coinflip() unique_npc = util.roll(*UNIQUES_ROLL) traders_npc = util.roll(*TRADERS_ROLL) logger.debug("Rolled for %d main NPCs (%d NPC able to issue quests), %d immobile NPCs, %d uniques, %d traders)", mNPC_count, min_quest_fivers, immobile_npc, unique_npc, traders_npc) logger.debug("Total of %d NPCs (%d with traders)", mNPC_count + immobile_npc + unique_npc, mNPC_count + immobile_npc + unique_npc + traders_npc) #now toss #generate_plot()