def _create_memories(self, pc): world=rog.world() pos=world.component_for_entity(pc, cmp.Position) if world.has_component(pc, cmp.SenseSight): rang=world.component_for_entity(pc, cmp.SenseSight).sight else: self._discover_place(pos.x,pos.y,self.inanat(x,y)) for x in range( max(0, pos.x-rang), min(self.w, pos.x+rang+1) ): for y in range( max(0, pos.y-rang), min(self.h, pos.y+rang+1) ): if rog.can_see(pc,x,y): self._discover_place(x,y,self.inanat(x,y))
def add_sound(self, x,y, text1,text2, volume): for obj in self._listeners_sounds: if rog.can_see(obj, x,y): continue data=rog.can_hear(obj, x,y, volume) if data: dx,dy,volHeard=data if volHeard <= 1: dx=dy=0 # each entity gets its own Event object, # specific to its own perception. text=text1 if obj.stats.get("hearing") >= SUPER_HEARING else text2 lis=self.get_sounds(obj) lis.append(Event_Sound(dx,dy, text, volHeard)) self._sounds.update({obj : lis})
def add_sight(self, x, y, text): for obj in self._listeners_sights: if rog.can_see(obj, x, y): lis = self.get_sights(obj) lis.append(Event_Sight(x, y, text)) self._sights.update({obj: lis})
def _draw_what_player_sees(self, pc, sight): world=rog.world() pos=world.component_for_entity(pc, cmp.Position) for x in range( max(0, pos.x-sight), min(self.w, pos.x+sight+1) ): for y in range( max(0, pos.y-sight), min(self.h, pos.y+sight+1) ): ## print("tile at {} {} has light level {}".format(x ,y, self.get_light_value(x,y))) if not rog.can_see(pc, x, y, sight): continue # get return data from rog.can_see ret=rog.fetchglobalreturn() if ret: # unpack dist, plight = ret ents=self.thingsat(x, y) if ents: charDiscover = None entDrawn = False for ent in reversed(ents): # calculate visibility if ent==pc: visibility=10 #VISIBILITY_MAX else: camo = rog.getms(ent, 'camo') visibility=rog.visibility( pc,sight,plight,camo,dist) ## print('visibility: ',visibility) ## print('stats: s{}, l{}, c{}, d{}'.format(sight, plight, camo, dist)) if visibility<=0: continue # render data based on visibility rend=world.component_for_entity(ent, cmp.Draw) char = rend.char if visibility > 1 else '?' if not entDrawn: # draw top entity entDrawn = True # get render data fgcol=rend.fgcol # render libtcod.console_put_char( self.con_map_state, x,y, char ) ## if type(fgcol)==type("s"): # TEST ## print("~~~ problem entity: {} named '{}'".format( ## ent, rog.getname(ent))) libtcod.console_set_char_foreground( self.con_map_state, x,y, fgcol) self._apply_rendered_bgcol(x,y, ent) if world.has_component(ent, cmp.Creature): continue # don't discover creatures if charDiscover is None: charDiscover = char # we'll discover this entity break # only discover one entity # end for self._discover_place(x,y, charDiscover) else: libtcod.console_put_char_ex(self.con_map_state, x,y, self.get_char(x, y), self.get_color(x, y), self.get_bgcolor(x, y)) self._discover_place(x,y, None)
def stateless(bot): ''' Dumb temporary NPC controller function implementing a simple 8-directional desire system ''' world = rog.world() desires = Desires(wander=7) sight = rog.getms(bot, "sight") pos = world.component_for_entity(bot, cmp.Position) botCreature = world.component_for_entity(bot, cmp.Creature) ## botType=world.component_for_entity(bot, cmp.Draw).char #should not depend on draw component # Where should this go???? ## rog.run_fov_manager(bot) # moved to can_see # TODO: write this function def isFoe(myFaction, theirFaction): return True # TODO: re-implement listening # listen to events '''lis=rog.listen(bot) if lis: for ev in lis: if rog.can_see(bot,ev.x,ev.y): continue # hearing if not ev.volume: continue if rog.can_hear(bot, ev.x,ev.y, ev.volume): interest=5 _add_desire_direction( desires, bot.x,bot.y, ev.x,ev.y, interest) rog.clear_listen_events(bot)''' # iterate through each tile in sight and see what is there... # is there a better way to do this? # This code is a little slow. for x in range(pos.x - sight, pos.x + sight + 1): for y in range(pos.y - sight, pos.y + sight + 1): if (not rog.is_in_grid(x, y) # out of bounds or (x == pos.x and y == pos.y)): # ignore self continue if not rog.can_see(bot, x, y, sight): continue # can't see it here = rog.thingat(x, y) if here: isCreature = world.has_component(here, cmp.Creature) # decide what it is and what to do about it if isCreature: creature = world.component_for_entity(here, cmp.Creature) if rog.on(here, DEAD): continue # no interest in dead things interest = 0 #desire to fight if creature.faction == FACT_ROGUE: interest = 1000 #grouping behavior elif creature.faction == botCreature.faction: interest = 5 if (interest > 0): _add_desire_direction(desires, pos.x, pos.y, x, y, interest) elif (interest < 0): _add_fear_direction(desires, pos.x, pos.y, x, y, interest) #if thing is inanimate else: #food desire if hungry #treasure desire pass # pick the direction it wants to move in the most highest = -999 for i in range(3): for j in range(3): new = desires.get(j - 1, i - 1) if new > highest: highest = new coords = ( j - 1, i - 1, ) dx, dy = coords xto = pos.x + dx yto = pos.y + dy # out of bounds if not rog.is_in_grid(xto, yto): return # fight if there is a foe present mon = rog.monat(xto, yto) if (mon and mon is not bot): monFaction = world.component_for_entity(mon, cmp.Creature).faction if isFoe(botCreature.faction, monFaction): action.fight(bot, mon) return # or move elif not rog.solidat(xto, yto): if action.move(bot, dx, dy): return # if no action was done, just wait action.wait(bot)
def _get_reaction( ent:int, persuasion_type:int, personality:int, disposition:int, leverage=0, mx=1, value=0, style=0 ) -> int: ''' get reaction from an entity based on conversational parameters leverage: who has the power advantage? Pos: PC. TODO: implement! mx: multiplier for intensity value: value of transaction, if it's a barter or bribe Returns >0 values for positive reactions, <0 for negative the greater the value, the higher the intensity ''' world=rog.world() pc=rog.pc() DMAX = MAX_DISPOSITION reaction = -20 dice_size = 20 # ---- initialize ---- # # get stats for player speech = rog.getskill(pc, SKL_PERSUASION) speech_bonus_modf = 0.5 + speech/MAX_SKILL speech_penalty_modf = 2.25 - 2*speech/MAX_SKILL pc_idn = rog.getms(pc, 'idn') pc_bea = rog.getms(pc, 'bea') pc_cou = rog.getms(pc, 'cou') pc_str = rog.getms(pc, 'str')//MULT_STATS pc_int = rog.getms(pc, 'int')//MULT_STATS pc_pos = world.component_for_entity(pc, cmp.Position) # get stats for conversational partner ent_sight = rog.getms(ent,'sight') ent_cansee = rog.can_see(ent, pc_pos.x,pc_pos.y, ent_sight) disposition = get_effective_disposition(ent, disposition) # ---- basic reaction ---- # # (perceived) value of the transaction value_modf = max(1, (value//MULT_VALUE)*0.1) reaction += leverage # reaction based on existing disposition if disposition == 0: reaction -= 24 elif disposition < 0.1*DMAX: reaction -= 18 elif disposition < 0.2*DMAX: reaction -= 12 elif disposition < 0.3*DMAX: reaction -= 6 elif disposition < 0.4*DMAX: pass elif disposition < 0.5*DMAX: reaction += 3 elif disposition < 0.6*DMAX: reaction += 6 elif disposition < 0.7*DMAX: reaction += 9 elif disposition < 0.8*DMAX: reaction += 12 elif disposition < 0.9*DMAX: reaction += 15 elif disposition < DMAX: reaction += 18 else: reaction += 21 # ---- status reaction ---- # if world.has_component(ent, cmp.StatusAnnoyed): compo = world.component_for_entity(ent, cmp.StatusAnnoyed) if compo.entity == pc: reaction -= 40 # ---- special cases ---- # # people of high moral standing who never accept a bribe if world.has_component(ent, cmp.NeverAcceptsBribes): value_modf = 0 # rich people don't care about low-value deals if (world.has_component(ent, cmp.Rich) and value < 100*MULT_VALUE): value_modf = 0 if value < 10*MULT_VALUE: reaction -= 40 else: reaction -= 20 # ---- intensity, default reactions ---- # # intensity of the conversation based on transaction value intensity = 1 speech_mod = 0.4 # intensity, base reaction, random variation (size of dice), and # speech modifier (how much speech level affects reaction); # based on type of conversation / persuasion if persuasion_type==TALK_TORTURE: speech_mod = 1.25*speech_mod dice_size = 100 reaction -= 0.15*DMAX intensity = 10 * intensity elif persuasion_type==TALK_INTERROGATE: speech_mod = 1.5*speech_mod dice_size = 60 reaction -= 0.085*DMAX intensity = 5 * intensity elif persuasion_type==TALK_INTIMIDATION: reaction -= 0.01*DMAX intensity = 4 * intensity elif persuasion_type==TALK_BEG: speech_mod = 1.33334*speech_mod reaction -= 0.05*DMAX intensity = 3 * intensity elif persuasion_type==TALK_BARTER: dice_size = 40 intensity = 2 * intensity reaction -= 0.01*DMAX reaction += value_modf * value//MULT_VALUE elif persuasion_type==TALK_BRIBERY: dice_size = 40 intensity = 2 * intensity reaction -= 0.02*DMAX reaction += value_modf * value//MULT_VALUE elif persuasion_type==TALK_CHARM: # relies on speech skill speech_mod = 1.5*speech_mod reaction -= 20 elif persuasion_type==TALK_BOAST: # relies on perceived strength/fame speech_mod = 1.25*speech_mod reaction -= 40 reaction += rog.get_power_level(rog.pc()) elif persuasion_type==TALK_DEBATE: speech_mod = 1.5*speech_mod intensity = 2 * intensity elif persuasion_type==TALK_FLIRTATION: speech_mod = 1.5*speech_mod dice_size = 80 reaction -= 50 intensity = 2 * intensity elif persuasion_type==TALK_ASKFAVOR: reaction -= 0.025*DMAX intensity = 2 * intensity elif persuasion_type==TALK_FLATTERY: speech_mod = 1.5*speech_mod reaction -= 15 dice_size = 40 intensity = 1.5 * intensity # special combo-persuasion: Taunt -> Flattery if (world.has_component(ent, cmp.Taunted) and not world.has_component(ent, cmp.ComboTauntFlattery) ): if dice.roll(20) <= 5 + speech//5: reaction += 40 intensity += 0.1 rog.world().add_component(ent, cmp.ComboTauntFlattery()) diabetes(ent) # gives more diabetes than usual flattery elif persuasion_type==TALK_TAUNT: speech_mod = 1.2*speech_mod reaction -= 0.01*DMAX intensity = 1.5 * intensity elif persuasion_type==TALK_SMALLTALK: speech_mod = 0.75*speech_mod reaction += 5 intensity = 0.5 * intensity elif persuasion_type==TALK_GREETING: reaction += 1 intensity = 0.25 * intensity # ---- attraction ---- # attraction = 0 pc_isfemale = rog.get_gender(pc)=="female" pc_ismale = rog.get_gender(pc)=="male" # Sexual Attraction to Women if (ent_cansee and pc_isfemale and world.has_component(ent, cmp.AttractedToWomen) ): intensity += 1 attraction += get_attraction_feminine(pc_bea) # Sexual Attraction to Men elif (ent_cansee and pc_ismale and world.has_component(ent, cmp.AttractedToMen) ): intensity += 1 attraction += get_attraction_masculine( pc_bea, pc_idn, pc_cou, pc_str, pc_int ) # end if # apply attraction reaction attraction = rog.around(attraction) # flirtation-specific if persuasion_type==TALK_FLIRTATION: # # special cases # # sorry hun, I'm taken. if world.has_component(ent, cmp.Taken): reaction -= 20 # I don't do sex. if world.has_component(ent, cmp.Ascetic): reaction -= 40 # # # attraction matter more for flirtation than other # types of conversation. reaction += attraction else: # other reaction += attraction*0.5 # end if # ---- compatibility ---- # # personality compatibility pc_personality = rog.get_personality(pc) compat = get_compatibility(personality, pc_personality) if compat==1: reaction -= 20 elif compat==2: reaction -= 10 elif compat==3: pass elif compat==4: reaction += 10 elif compat==5: reaction += 20 ## print("personalities: ent: {}, player: {}".format( ## personality, pc_personality)) ## print("personalities: ent: {}, player: {}".format( ## PERSONALITIES[personality][0], PERSONALITIES[pc_personality][0])) ## print("personality compatibility: ", compat) # likes and dislikes likes=_get_likes(personality) dislikes=_get_dislikes(personality) if persuasion_type == likes[0]: reaction += ( 0.01*DMAX * speech_bonus_modf * mx ) * intensity elif persuasion_type == dislikes[0]: reaction -= ( 0.02*DMAX * speech_penalty_modf * mx ) * intensity # special cases # # intensity and energy level if ((personality==PERSON_NONCONFRONTATIONAL or personality==PERSON_LOWENERGY) and intensity >= 3 ): reaction -= 0.01*DMAX elif ((personality==ARGUMENTATIVE or personality==PERSON_BUBBLY) and intensity >= 3 ): reaction += 0.01*DMAX # never accepts bribes if (persuasion_type==TALK_BRIBERY and world.has_component(ent, cmp.NeverAcceptsBribes) ): reaction = -0.05*DMAX * mx # set reaction # diabetes from too much flattery if (persuasion_type==TALK_FLATTERY and world.has_component(ent, cmp.StatusDiabetes) ): reaction = -0.075*DMAX * speech_penalty_modf * mx # auxiliary likes/dislikes if (persuasion_type==TALK_BEG and personality==PERSON_PROUD): reaction -= 0.05*DMAX * mx elif (persuasion_type==TALK_INTERROGATE and personality==PERSON_RELAXED): reaction -= 0.02*DMAX * mx elif (persuasion_type==TALK_CHARM and personality==PERSON_LOWENERGY): reaction -= 0.01*DMAX * mx elif (persuasion_type==TALK_CHARM and personality==PERSON_BUBBLY): reaction += 0.01*DMAX * mx elif (persuasion_type==TALK_BOAST and personality==PERSON_PROACTIVE): reaction -= 0.01*DMAX * mx elif (persuasion_type==TALK_BOAST and personality==PERSON_MOTIVATED): reaction += 0.01*DMAX * mx # creeped out if (world.has_component(ent, cmp.StatusCreepedOut) and pc==world.component_for_entity(ent, cmp.StatusCreepedOut).entity): reaction -= 40 if persuasion_type==TALK_FLIRTATION else 20 # waste my time with 0 value offer -> minus some disp. if (persuasion_type==TALK_BRIBERY or persuasion_type==TALK_BARTER): if value == 0: reaction = min(-10, value) # add speech modifier reaction += speech * speech_mod # add element of random chance -- size of dice determined above reaction += dice.roll(dice_size) # trying to charm while already charmed -> loss of disposition if persuasion_type==TALK_CHARM: if world.has_component(ent, cmp.StatusCharmed): reaction = min(reaction - 100, -20) elif persuasion_type==TALK_BOAST: if world.has_component(ent, cmp.StatusCharmed): reaction = min(reaction - 100, -20) # people who have a hard time learning to like/trust others if (disposition >= 0.5*DMAX # lose reaction once disp crosses a threshold and world.has_component(ent, cmp.Untrusting)): reaction -= 20 if (world.has_component(ent, cmp.Antisocial)): reaction -= 10 return math.ceil(abs(reaction)) * rog.sign(reaction)
def stateless(bot): # desire to move in a particular coordinate desires = Desires(wander=7) # listen to events '''lis=rog.listen(bot) if lis: for ev in lis: if rog.can_see(bot,ev.x,ev.y): continue # hearing if not ev.volume: continue if rog.can_hear(bot, ev.x,ev.y, ev.volume): interest=5 _add_desire_direction( desires, bot.x,bot.y, ev.x,ev.y, interest) rog.clear_listen_events(bot)''' # iterate through each tile in sight and see what is there... # is there a better way to do this? # This code is a little slow. sight = bot.stats.sight for x in range(bot.x - sight, bot.x + sight + 1): for y in range(bot.y - sight, bot.y + sight + 1): if (not rog.is_in_grid(x, y) #out of bounds or (x == bot.x and y == bot.y)): #ignore self continue if not rog.can_see(bot, x, y): continue #bot can't see it here = rog.thingat(x, y) if here: # decide what it is and what to do about it if rog.is_creature(here): if rog.on(here, DEAD): continue #no interest in dead things interest = 0 #desire to fight if here.faction == FACT_ROGUE: interest = 1000 #desire to run away #elif here.type == '@': # interest=-1000 #grouping behavior elif here.type == bot.type: interest = 5 if (interest > 0): _add_desire_direction(desires, bot.x, bot.y, x, y, interest) elif (interest < 0): _add_fear_direction(desires, bot.x, bot.y, x, y, interest) #if thing is inanimate else: #food desire if hungry #treasure desire pass # pick the direction it wants to move in the most highest = -999 for i in range(3): for j in range(3): new = desires.get(j - 1, i - 1) if new > highest: highest = new coords = ( j - 1, i - 1, ) dx, dy = coords xto = bot.x + dx yto = bot.y + dy # out of bounds if not rog.is_in_grid(xto, yto): return # fight if there is a monster present mon = rog.monat(xto, yto) if (mon and mon is not bot): if not mon.type == bot.type: ##TEMPORARY action.fight(bot, mon) return # or move elif not rog.solidat(xto, yto): if action.move(bot, dx, dy): return # if no action was done, just wait action.wait(bot)