class Money(object): PRIMARY_KEY = "" VOLATILES = [] MULTILINES = ["comment"] SCHEMA = {} REFERENCES = {} WEAKREFS = {} def __init__(self, title=""): self.comment = "" self.copper_value = 0 self.races = Flags(RACE.NONE) #- Fine Inizializzazione - def __str__(self): r = "<" if self.comment: r += "C " r += "%d" % self.copper_value if self.races: return " %s" % self.races r += ">" return r #- Fine Metodo - def get_error_message(self, entity): if self.copper_value <= 0: return "copper_value non è un valore valido: %d" % self.copper_value elif self.races.get_error_message(RACE, "races") != "": return self.races.get_error_message(RACE, "races") return "" #- Fine Metodo - def copy(self, to_obj=None, avoid_volatiles=False): if not to_obj: to_obj = Money() copy_existing_attributes(self, to_obj, avoid_volatiles=avoid_volatiles) return to_obj #- Fine Metodo - def equals(self, money2): if not money2: return False if self.comment != money2.comment: return False if self.copper_value != money2.copper_value: return False if self.races != money2.races: return False return True
class Weapon(object): PRIMARY_KEY = "" VOLATILES = [] MULTILINES = ["comment"] SCHEMA = {} REFERENCES = {} WEAKREFS = {} def __init__(self): self.comment = "" self.category = Element(WEAPON.NONE) # Tipo di arma self.flags = Flags(WEAPONFLAG.NONE) # Flag di arma self.damage = "" # Danno dell'arma, se vuoto viene ricavato automaticamente tramite una tabella #- Fine Inizializzazione - def __str__(self): return "%r: %s" % (self, sorted(self.__dict__)) #- Fine Metodo - def get_error_message(self, entity): if self.category.get_error_message(WEAPON, "category") != "": return self.category.get_error_message(WEAPON, "category") elif self.flags.get_error_message(WEAPONFLAG, "flags") != "": return self.category.get_error_message(WEAPONFLAG, "flags") return "" #- Fine Metodo - def copy(self, to_obj=None, avoid_volatiles=False): if not to_obj: to_obj = Weapon() copy_existing_attributes(self, to_obj, avoid_volatiles=avoid_volatiles) return to_obj #- Fine Metodo - def equals(self, weapon2): if not weapon2: return False if self.comment != weapon2.comment: return False if self.category != weapon2.category: return False if self.flags != weapon2.flags: return False if self.damage != weapon2.damage: return False return True
class Plant(object): PRIMARY_KEY = "" VOLATILES = ["deferred_stage"] MULTILINES = ["comment"] SCHEMA = {"temperature" : ("", "temperature"), "humidity" : ("", "percent"), "contents" : ("", "int"), "worse_affects" : ("src.affect", "Affect"), "better_affects" : ("src.affect", "Affect")} REFERENCES = {"worse_entity" : ["proto_items", "proto_mobs"], "normal_entity" : ["proto_items", "proto_mobs"], "better_entity" : ["proto_items", "proto_mobs"], "dead_entity" : ["proto_items", "proto_mobs"]} WEAKREFS = {} def __init__(self): self.comment = "" self.sectors = Flags(SECTOR.NONE) # Settori in cui può essere seminato self.rpg_hours = 1 # Durata in ore rpg prima che questo stadio si attivi self.temperature = 20 # Temperatura media ideale self.humidity = 50 # Percentuale dell'umidità ideale self.contents = {} # Dizionario con valori di codice_entità/quantità per popolare il contenuto dell'entità di questo stadio self.worse_entity = None # Entità peggiore del prossimo stadio di crescita, se in questo stadio non viene curata o curata male self.normal_entity = None # Entità normale del prossimo stadio di crescita, se in questo stadio viene curata normalmente self.better_entity = None # Entità migliore del prossimo stadio di crescita, se in questo stadio viene curata molto bene self.dead_entity = None # Entità morta relativa al prossimo stadio self.worse_affects = [] # Affect che danneggiano la pianta self.better_affects = [] # Affect che migliorano la pianta self.decomposition_rpg_hours = config.purification_rpg_hours # Ore Rpg prima che il contenuto venga decomposto dopo essere caduta dalla pianta self.remaining_life = -1 # Cicli di vita rimanenti alla pianta prima di morire self.worse_counter = 0 # Contatore degli stadi di crescita andati male self.normal_counter = 0 # Contatore degli stadi di crescita andati normalmente self.better_counter = 0 # Contatore degli stadi di crescita andati ottimamente # Volatili self.deferred_stage = None #- Fine Inizializzazione - def get_error_message(self, entity): if self.remaining_life <= 0 and self.remaining_life != -1: return "remaining_life non è un'aspettativa di vita valida, deve essere maggiore di 0 oppure diverso da -1: %d" % self.remaining_life elif self.sectors.get_error_message(SECTOR, "sectors") != "": return self.sectors.get_error_message(SECTOR, "sectors") if self.rpg_hours <= 0: return "rpg_hours non è una durata in ore rpg valida: %d" % self.rpg_hours elif self.get_contents_error_message() != "": return self.get_contents_error_message() elif self.get_affects_error_message("worse_affects") != "": return self.get_affects_error_message("worse_affects") elif self.get_affects_error_message("better_affects") != "": return self.get_affects_error_message("better_affects") return "" #- Fine Metodo - def get_contents_error_message(self): for key, value in self.contents.iteritems(): if not key: return "contents con chiave non valida (%r) per il valore %s" % (key, value) if int(value) <= 0: return "contents con valore non valido (%d) per la chiave %s" % (int(value), key) return "" #- Fine Metodo - def get_affects_error_message(self, attr_name): if attr_name not in ("worse_affects", "better_affects"): log.bug("attr_name non è un parametro valido: %s" % attr_name) return "" # --------------------------------------------------------------------- for affect in getattr(self, attr_name): error_message = affect.get_error_message() if error_message != "": return error_message return "" #- Fine Metodo - def copy(self, to_obj=None, avoid_volatiles=False): if not to_obj: to_obj = Plant() copy_existing_attributes(self, to_obj, avoid_volatiles=avoid_volatiles) return to_obj #- Fine Metodo - def equals(self, plant2): if not plant2: return False if self.deferred_stage or plant2.deferred_stage: return False if self.comment != plant2.comment: return False if self.sectors != plant2.sectors: return False if self.rpg_hours != plant2.rpg_hours: return False if self.temperature != plant2.temperature: return False if self.humidity != plant2.humidity: return False if self.worse_entity != plant2.worse_entity: return False if self.normal_entity != plant2.normal_entity: return False if self.better_entity != plant2.better_entity: return False if self.dead_entity != plant2.dead_entity: return False if self.decomposition_rpg_hours != plant2.decomposition_rpg_hours: return False if self.remaining_life != plant2.remaining_life: return False if self.worse_counter != plant2.worse_counter: return False if self.normal_counter != plant2.normal_counter: return False if self.better_counter != plant2.better_counter: return False if len(self.contents) != len(plant2.contents): return False for key, value in self.contents.iteritems(): if key not in plant2.contents: return False if value != plant2.contents[key]: return False if len(self.worse_affects) != len(plant2.worse_affects): return False for affect in self.worse_affects: for affect2 in plant2.worse_affects: if affect == affect2: break else: return False if len(self.better_affects) != len(plant2.better_affects): return False for affect in self.better_affects: for affect2 in plant2.better_affects: if affect == affect2: break else: return False return True #- Fine Metodo - #--------------------------------------------------------------------------- def start_growth(self, entity, type_attr_name): if not entity: log.bug("entity non è parametro valido: %r" % entity) return if type_attr_name not in ("plant_type", "seed_type"): log.bug("type_attr_name non è parametro valido: %r" % type_attr_name) return # --------------------------------------------------------------------- seconds = self.rpg_hours * (config.seconds_in_minute * config.minutes_in_hour) self.deferred_stage = defer(seconds, self.next_stage, entity, type_attr_name) #- Fine Metodo - def stop_growth(self): if self.deferred_stage: self.deferred_stage.pause() self.deferred_stage = None #- Fine Metodo - def next_stage(self, old_entity, type_attr_name): if not old_entity: log.bug("old_entity non è parametro valido: %r" % old_entity) return if type_attr_name not in ("plant_type", "seed_type"): log.bug("type_attr_name non è parametro valido: %r" % type_attr_name) return # --------------------------------------------------------------------- # Pulisce la deferred relativa a questo metodo in qualsiasi caso self.deferred_stage = None entitype = getattr(old_entity, type_attr_name) if not entitype: log.bug("%s dell'entità precedente non valido: %r" % (type_attr_name, entitype)) return # (TD) deve scegliere quale delle tre entità worse, normal o better # in maniera non casuale ma basandosi su effettivi fattori ambientali entitypes = [] for entitype_name in ("worse_entity", "normal_entity", "better_entity"): if getattr(entitype, entitype_name): entitypes.append(entitype_name) if not entitypes: log.bug("Nessuna tipologia d'entità da utilizzare come prossimo stadio: %r" % entitypes) return choised_attr = random.choice(entitypes) # Se la vita della pianta è terminata e finalmente si trova un'entità # di pianta morta, allora la utilizza if entitype.remaining_life == 0 and entitype.dead_entity: choised_attr = "dead_entity" # --------------------------------------------------------------------- # Crea la nuova pianta a seconda delle scelte di cui sopra choised_entity = getattr(entitype, choised_attr) if not choised_entity: log.bug("Impossibile continuare con la crescita della pianta da %s per la scelta %s" % ( old_entity.code, choised_attr)) return if choised_entity.max_global_quantity > 0 and choised_entity.current_global_quantity >= choised_entity.max_global_quantity: return new_entity = choised_entity.CONSTRUCTOR(choised_entity.code) # Passa alcune caratteristiche della vecchia entità nella nuova # prima di distruggerla if new_entity.plant_type: new_entity.flags += FLAG.GROWING new_entity.plant_type.remaining_life = entitype.remaining_life new_entity.plant_type.worse_counter = entitype.worse_counter new_entity.plant_type.normal_counter = entitype.normal_counter new_entity.plant_type.better_counter = entitype.better_counter quality_attr = choised_attr.split("_")[0] + "_counter" setattr(new_entity.plant_type, quality_attr, getattr(new_entity.plant_type, quality_attr) + 1) # Inserisce la nuova entità in gioco new_entity.inject(old_entity.location) # --------------------------------------------------------------------- # Lista delle entità che cambieranno locazione nel ciclo sottostante # e che vengono passate nel trigger on_next_stage per comodità, vengono # salvati solo le entità frutta, seme e cibo entities = [] # Controlla come deve comportarsi con il contenuto della vecchia entità: # se passarlo alla nuova, oppure distruggerlo, oppure ancora farlo # cadere a terra flower_counter = 0 for content in old_entity.iter_contains(use_reversed=True): if content.entitype == ENTITYPE.FLOWER: flower_counter += 1 continue elif content.entitype in (ENTITYPE.FRUIT, ENTITYPE.SEED, ENTITYPE.FOOD): content = content.from_location(content.quantity, use_repop=False) in_room = content.get_in_room() container_carrier = content.get_container_carrier() # Più la pianta è grande e maggiore è la probabilità che il suo # contenuto cada nella stanza invece che nel vaso if in_room and container_carrier and random.randint(0, max(1, math.log(new_entity.get_weight()) - math.log(container_carrier.get_weight()))) == 0: content.to_location(in_room) entities.append(content) elif in_room and random.randint(0, max(1, math.log(new_entity.get_weight()))) == 0: content.to_location(in_room) entities.append(content) elif container_carrier: content.to_location(container_carrier) entities.append(content) else: content.to_location(old_entity.location) entities.append(content) # Tutte le entità inserite a terra attivano un timer per # rimuoverle e non creare inutili mucchi di semi content.start_purification(entitype.decomposition_rpg_hours, decomposition=True) else: # (BB) qui se passavano delle entità di tipo food invece di # ENTITYPE.FRUIT bacava i riferimenti, probabilmente il # problema c'è ancora, per questo l'elif sopra accetta # anche food content = content.from_location(content.quantity, use_repop=False) content.to_location(new_entity) # --------------------------------------------------------------------- # Si salva tutti i semi per sapere se entità da inserire nella pianta # sia solo di tipo seme oppure se eventuali semi sono mischiati ad # altre tipo di entità, ciò serve perché in tal caso i semi vengono # inseriti nelle altre tipologie di entità (frutti o fiori chessia) seeds = [] for proto_code, quantity in entitype.contents.iteritems(): prototype = database.get_proto_entity(proto_code) if not prototype: continue if prototype.entitype == ENTITYPE.SEED: seeds.append([prototype, quantity]) if len(seeds) == len(entitype.contents): seeds = [] # Ogni volta che la pianta produce dei semi diminuisce le proprie # risorse vitali if seeds and new_entity.plant_type.remaining_life > 0: new_entity.plant_type.remaining_life -= 1 # Crea l'eventuale contenuto voluto per la nuova entità for proto_code, quantity in entitype.contents.iteritems(): prototype = database.get_proto_entity(proto_code) if not prototype: continue # Se il prototipo è un seme da inserire in un frutto o simile allora lo salta for seed in seeds: if prototype == seed[0]: break else: add_content(prototype, quantity, choised_attr, flower_counter, new_entity, seeds) # Crea, se è il caso, una tipologia di contenitore alla nuova entità # per permettere ai giocatori ad interagire con la pianta if not new_entity.container_type and new_entity.entitype == ENTITYPE.PLANT: container = Container() container.max_weight = new_entity.get_carried_weight() * 2 new_entity.container_type = container # Avvisa dell'avvenuta crescita della pianta if new_entity.plant_type: message = "%s cresce: %s" else: message = "%s finisce di crescere: %s" log.plant(message % (old_entity.prototype.code, new_entity.prototype.code)) # Supporto gamescript, se viene forzato il ritorno non esegue # l'eventuale stadio successivo force_return = check_trigger(old_entity, "on_next_stage", old_entity, new_entity, choised_attr, entities) if force_return: return True # Ora si può rimuovere la vecchia pianta # (la si può estrarre completamente perché se possiede del contenuto non # viene raggruppata fisicamente, altrimenti si può rimuovere il gruppetto # senza problemi perché senza contenuto) old_entity.extract(old_entity.quantity, use_repop=False) # Prepara il lancio per il prossimo stage if choised_attr != "dead_entity" and new_entity.plant_type: new_entity.plant_type.start_growth(new_entity, "plant_type")
class Container(OpenableGenericType): PRIMARY_KEY = "" VOLATILES = [] MULTILINES = ["comment"] SCHEMA = {"max_weight" : ("", "weight")} REFERENCES = {} WEAKREFS = {} CLOSED_FLAG = CONTAINER.CLOSED SECRET_FLAG = CONTAINER.SECRET def __init__(self): super(Container, self).__init__() self.flags = Flags(CONTAINER.NONE) # Flag speciali di contenitore, sono praticamente uguali a quelle della porta self.max_weight = 0 # Massimo peso in grammi riempibile #- Fine Inizializzazione - def get_error_message(self, entity): msg = super(Container, self).get_error_message(entity) if msg: return msg elif self.flags.get_error_message(CONTAINER, "flags") != "": return self.flags.get_error_message(CONTAINER, "flags") # Viene accettato il valore zero per fare degli oggetti che sembrano # contenitori ma che non possono contenere nulla elif self.max_weight < 0: return "max_weight è minore di 0: %d" % self.max_weight return "" #- Fine Metodo - def copy(self, to_obj=None, avoid_volatiles=False): if not to_obj: to_obj = Container() copy_existing_attributes(self, to_obj, avoid_volatiles=avoid_volatiles) return to_obj #- Fine Metodo - def equals(self, container2): if not container2: return False if not super(Container, self).equals(container2): return False if self.flags != container2.flags: return False if self.max_weight != container2.max_weight: return False return True #- Fine Metodo - # ------------------------------------------------------------------------- def get_status(self, sex, looker=None): status = "" if CONTAINER.CLOSED in self.flags: # Se il contenitore è segreto non visualizza lo stato di aperto o chiuso if CONTAINER.SECRET not in self.flags: if sex == SEX.FEMALE: status += " chiusa" else: status += " chiuso" else: if sex == SEX.FEMALE: status += " aperta" else: status += " aperto" if looker and looker.trust >= TRUST.MASTER and CONTAINER.SECRET in self.flags: status += " (secret)" return status
class Command(Data): """ Gestisce tutte le caratteristiche di un comando. Se tra gli attributi cercate quelli che servono per chiamare il comando tramite il testo inviato dai giocatori qui non li troverete, per quel compito ci pensa la classe Input(). """ PRIMARY_KEY = "fun_name" VOLATILES = ["timer", "module", "function",] MULTILINES = ["mini_help"] SCHEMA = {} REFERENCES = {} WEAKREFS = {} def __init__(self, fun_name=""): self.comment = "" self.fun_name = fun_name or "" # Nome della funzione self.type = Element(CMDTYPE.INFORMATION) # Tipologia del comando self.trust = Element(TRUST.PLAYER) # Fiducia minima per digitarlo self.position = Element(POSITION.REST) # Posizione minima per utilizzarlo self.flags = Flags(CMDFLAG.NONE) # Flag dei comandi self.no_races = Flags(RACE.NONE) # Razze che NON possono usarlo (RACE.NONE significa che tutti lo possono utilizzare) self.mini_help = "" # Piccola descrizione dell'utilizzo del comando self.timer = 0.0 # Tempo totale di esecuzione del comando (anche se nelle pagine d'amministrazione visualizza il tempo medio) # Variabili volatili self.module = None # Riferimento al modulo che contiene la funzione self.function = None # Riferimento alla funzione if self.fun_name: self.import_module_and_function() #- Fine Inizializzazione - def get_error_message(self): """ Ritorna un messaggio di errore se qualcosa nel comando è sbagliata, altrimenti se tutto è a posto ritorna una stringa vuota. """ if not self.fun_name: msg = "il nome della funzione non è valido" elif (not self.fun_name.startswith("command_") and not self.fun_name.startswith("skill_") and not self.fun_name.startswith("social_")): msg = "il nome della funzione non inizia per command_, skill_ o social_" elif self.type.get_error_message(CMDTYPE, "type") != "": msg = self.type.get_error_message(CMDTYPE, "type") elif self.trust.get_error_message(TRUST, "trust") != "": msg = self.trust.get_error_message(TRUST, "trust") elif self.position.get_error_message(POSITION, "position") != "": msg = self.position.get_error_message(POSITION, "position") elif self.flags.get_error_message(CMDFLAG, "flags") != "": msg = self.flags.get_error_message(CMDFLAG, "flags") elif self.no_races.get_error_message(RACE, "no_races") != "": msg = self.no_races.get_error_message(RACE, "no_races") # Ignora i minihelp vuoti relativi ai comandi-social elif not self.mini_help and not self.fun_name.startswith("social_"): msg = "la stringa di mini help è vuota" elif self.timer < 0.0: msg = "il timer non può essere negativo: %f" % self.timer elif not self.module: msg = "modulo non importato" elif not self.function: msg = "funzione non importata" else: return "" # Se arriva qui significa che ha un messaggio da inviare log.bug("(Command: fun_name %s) %s" % (self.fun_name, msg)) return msg #- Fine Metodo - def get_total_use_count(self): """ Ritorna l'utilizzo totale della funzione di comando tra tutti gli input. """ total_use_count = 0 for inputs_name, inputs in yield_inputs_items(): for input in inputs: if input.command == self: total_use_count += input.counter_use return total_use_count #- Fine Metodo - def import_module_and_function(self): """ Importa il modulo che contiene la funzione del comando. """ if self.fun_name.startswith("command_"): package = "src.commands." elif self.fun_name.startswith("skill_"): package = "src.skills." elif self.fun_name.startswith("social_"): package = "src.socials." else: log.bug("la fun_name del comando è errata: %s" % self.fun_name) return None import_path = package + self.fun_name self.module = __import__(import_path, globals(), locals(), [""]) self.function = getattr(self.module, self.fun_name)
class Readable(object): PRIMARY_KEY = "" VOLATILES = [] MULTILINES = ["comment", "pages", "summary"] SCHEMA = {"visual_width" : ("", "css_measure"), "visual_height" : ("", "css_measure"), "padding" : ("", "css_measure"), "border_top" : ("", "css_border"), "border_right" : ("", "css_border"), "border_bottom" : ("", "css_border"), "border_left" : ("", "css_border"), "border_inside" : ("", "css_border"), "pages" : ("", "str")} REFERENCES = {} WEAKREFS = {} def __init__(self): self.comment = "" # Commento per gli area builder relativo all'entità leggibile self.title = "" # Titolo del libro self.author = "" # Autore o gli autori di questo libro self.summary = "" # Riassunto del libro che il giocatore carpisce esaminandolo self.language = Element(LANGUAGE.COMMON) # (TD) Lingua di questo libro self.flags = Flags(READABLE.NONE) # Flag relative alle entità leggibili self.visual_width = "" # Larghezza in pixel del libro sullo schermo self.visual_height = "" # Larghezza in pixel del libro sullo schermo self.padding = "" # Larghezza in pixel del padding della cornice del libro self.border_top = "" # Bordo css decorante il libro in alto self.border_right = "" # Bordo css decorante il libro a destra self.border_bottom = "" # Bordo css decorante il libro in basso self.border_left = "" # Bordo css decorante il libro a sinistra self.border_inside = "" # Bordo css decorante il libro tra le due pagine self.number_decoration_left = "" # Decorazione della pagina sinistra per i numeri di pagina self.number_decoration_right = "" # Decorazione della pagina sinistra per i numeri di pagina self.pages = [] # Lista delle pagine e relativo contenuto #- Fine Inizializzazione - def get_error_message(self, entity): if not self.title: return "title è una stringa non valida: %r" % self.title elif not self.author: return "author è una stringa non valida: %r" % self.author elif not self.summary: return "summary è una stringa non valida: %r" % self.summary elif self.language.get_error_message(LANGUAGE, "language") != "": return self.language.get_error_message(LANGUAGE, "language") elif self.flags.get_error_message(READABLE, "flags") != "": return self.flags.get_error_message(READABLE, "flags") elif READABLE.CENTER in self.flags and READABLE.RIGHT in self.flags: return "Non possono convivere le flag READABLE.CENTER e READABLE.RIGHT assieme." elif (self.number_decoration_left or self.number_decoration_right) and READABLE.NUMBERS not in self.flags: return "Nonostante sia stata definita una decorazione per i numeri non esiste la flag READABLE.NUMBERS che la mostrerebbe." elif not self.visual_width: return "visual_width è una stringa non valida: %r" % self.visual_width elif not self.visual_height: return "visual_height è una stringa non valida: %r" % self.visual_height elif not self.pages: return "dev'esservi almeno una pagina: %r" % self.pages return "" #- Fine Metodo - def copy(self, to_obj=None, avoid_volatiles=False): if not to_obj: to_obj = Readable() copy_existing_attributes(self, to_obj, avoid_volatiles=avoid_volatiles) return to_obj #- Fine Metodo - def equals(self, readable2): if not readable2: return False if self.comment != readable2.comment: return False if self.title != readable2.title: return False if self.author != readable2.author: return False if self.summary != readable2.summary: return False if self.language != readable2.language: return False if self.flags != readable2.flags: return False if self.visual_width != readable2.visual_width: return False if self.visual_height != readable2.visual_height: return False if self.padding != readable2.padding: return False if self.border_top != readable2.border_top: return False if self.border_right != readable2.border_right: return False if self.border_bottom != readable2.border_bottom: return False if self.border_left != readable2.border_left: return False if self.border_inside != readable2.border_inside: return False if self.number_decoration_left != readable2.number_decoration_left: return False if self.number_decoration_right != readable2.number_decoration_right: return False if len(self.pages) != len(readable2.pages): return False for page in self.pages: for page2 in readable2.pages: if page == page2: break else: return False return True #- Fine Metodo - # ------------------------------------------------------------------------- # (TD) entity e target serviranno in futuro per scramblerare la lingua del # libro se sconosciuta def get_pages(self, entity, target, page_number, from_location=None): if not entity: log.bug("entity non è un parametro valido: %r" % entity) return "" if not target: log.bug("target non è un parametro valido: %r" % target) return "" if page_number < 0 or page_number >= len(self.pages): log.bug("page_number non è un parametro valido: %r" % page_number) return "" # --------------------------------------------------------------------- # Prepara i bordi border_top = "" border_right = "" border_bottom = "" border_left = "" border_inside = "" if self.border_top: border_top = "border-top:%s;" % self.border_top if self.border_right: border_right = "border-right:%s;" % self.border_right if self.border_bottom: border_bottom = "border-bottom:%s;" % self.border_bottom if self.border_left: border_left = "border-left:%s;" % self.border_left if self.border_inside: border_inside = "border-right:%s;" % self.border_inside # Prepara il padding se esistente padding_style = "" if self.padding: padding_style = "padding:%s;" % self.padding # Prepara lo style css per l'output scritto della pagina alignment = "" if READABLE.CENTER in self.flags: alignment = '''text-align:center;''' if READABLE.RIGHT in self.flags: alignment = '''text-align:right;''' visual_style = ''' style="min-width:%s; max-width:%s; min-height:%s; max-height:%s; %s %s"''' % ( self.visual_width, self.visual_width, self.visual_height, self.visual_height, padding_style, alignment) # Ricava informazioni che servono a sfogliare il libro tramite click translated_input = translate_input(entity, "read", "en") if not translated_input: log.bug("Non è stato possibile tradurre l'input read per %s: %r" % (target.code, translated_input)) return False numbered_keyword = target.get_numbered_keyword(looker=entity) if page_number % 2 == 0 and page_number != len(self.pages)-1: minimum_page = max([0, page_number-2]) maximum_page = min([len(self.pages)-1, page_number+1]) else: minimum_page = max([0, page_number-1]) maximum_page = min([len(self.pages)-1, page_number+2]) if from_location: js_minimum_arguments = "%s %s %s %d" % (translated_input, numbered_keyword, from_location.get_numbered_keyword(looker=entity), minimum_page) js_maximum_arguments = "%s %s %s %d" % (translated_input, numbered_keyword, from_location.get_numbered_keyword(looker=entity), maximum_page) else: js_minimum_arguments = "%s %s %d" % (translated_input, numbered_keyword, minimum_page) js_maximum_arguments = "%s %s %d" % (translated_input, numbered_keyword, maximum_page) browse_to_left = '''<div style="float:left"><a href="javascript:sendInput('%s')" style="font-size:larger"><</a> </div>''' % js_minimum_arguments browse_to_right = '''<div style="float:left"> <a href="javascript:sendInput('%s')" style="font-size:larger">></a></div>''' % js_maximum_arguments # Gestisce la copertina e la retrocopertina o altre tipologie di entità # leggibili differenti da dei libri, ovvero con al massimo il fronte # e il retro if page_number == 0 or page_number == len(self.pages) - 1: style = "" if border_top or border_right or border_bottom or border_left: style = ''' style="float:left; %s%s%s%s"''' % (border_top, border_right, border_bottom, border_left) output = "" if page_number == len(self.pages) - 1: output += browse_to_left output += '''<div%s><div%s>%s</div></div>''' % (style, visual_style, self.pages[page_number]) if page_number == 0: output += browse_to_right output += '''<div style="clear:both;" />''' return output # A seconda che si voglia visualizzare una pagina a destra o a sinistra # sceglie il numero corretto di pagina da far visualizzare nell'altra if page_number % 2 == 0: left_page_number = page_number - 1 right_page_number = page_number else: left_page_number = page_number right_page_number = page_number + 1 # Prepara lo stile dei bordi preparati in precedenza, se ve n'erano left_style = '''style="float:left;%s%s%s%s"''' % (border_top, border_inside, border_bottom, border_left) right_style = '''style="float:left;%s%s%s"''' % (border_top, border_right, border_bottom) # Prepara il contenuto scritto delle pagine aggiungendo una pagina # vuota prima della retrocopertina se necessario left_output = self.pages[left_page_number] if len(self.pages) % 2 == 0 and page_number == len(self.pages) - 1: right_output = "" elif len(self.pages) % 2 == 1 and page_number == len(self.pages) - 2: right_output = "" else: right_output = self.pages[right_page_number] if MIML_SEPARATOR in left_output: left_output = target.parse_miml(left_output, looker=entity) if MIML_SEPARATOR in right_output: right_output = target.parse_miml(right_output, looker=entity) # Prepara l'output per i numeri di pagina left_page_number_output = "" right_page_number_output = "" if READABLE.NUMBERS in self.flags: if len(self.number_decoration_left) == 0: left_page_number_output = '''<center>%d</center>''' % left_page_number elif len(self.number_decoration_left) == 1: left_page_number_output = '''<center>%s%d</center>''' % (self.number_decoration_left, left_page_number) else: middle = int(math.ceil(len(self.number_decoration_left) / 2.0)) left_page_number_output = '''<center>%s%d%s</center>''' % (self.number_decoration_left[ : middle], left_page_number, self.number_decoration_left[middle : ]) if len(self.number_decoration_right) == 0: right_page_number_output = '''<center>%d</center>''' % right_page_number elif len(self.number_decoration_right) == 1: right_page_number_output = '''<center>%d%s</center>''' % (right_page_number, self.number_decoration_right) else: middle = int(math.floor(len(self.number_decoration_left) / 2.0)) right_page_number_output = '''<center>%s%d%s</center>''' % (self.number_decoration_right[ : middle], right_page_number, self.number_decoration_right[middle : ]) # Ecco l'output del libro in tutto il suo splendore output = browse_to_left output += '''<div %s><div%s>%s</div>%s</div>''' % (left_style, visual_style, left_output, left_page_number_output) output += '''<div %s><div%s>%s</div>%s</div>''' % (right_style, visual_style, right_output, right_page_number_output) output += browse_to_right output += '''<div style="clear:both;" />''' return output
class Readable(object): PRIMARY_KEY = "" VOLATILES = [] MULTILINES = ["comment", "pages", "summary"] SCHEMA = { "visual_width": ("", "css_measure"), "visual_height": ("", "css_measure"), "padding": ("", "css_measure"), "border_top": ("", "css_border"), "border_right": ("", "css_border"), "border_bottom": ("", "css_border"), "border_left": ("", "css_border"), "border_inside": ("", "css_border"), "pages": ("", "str") } REFERENCES = {} WEAKREFS = {} def __init__(self): self.comment = "" # Commento per gli area builder relativo all'entità leggibile self.title = "" # Titolo del libro self.author = "" # Autore o gli autori di questo libro self.summary = "" # Riassunto del libro che il giocatore carpisce esaminandolo self.language = Element(LANGUAGE.COMMON) # (TD) Lingua di questo libro self.flags = Flags( READABLE.NONE) # Flag relative alle entità leggibili self.visual_width = "" # Larghezza in pixel del libro sullo schermo self.visual_height = "" # Larghezza in pixel del libro sullo schermo self.padding = "" # Larghezza in pixel del padding della cornice del libro self.border_top = "" # Bordo css decorante il libro in alto self.border_right = "" # Bordo css decorante il libro a destra self.border_bottom = "" # Bordo css decorante il libro in basso self.border_left = "" # Bordo css decorante il libro a sinistra self.border_inside = "" # Bordo css decorante il libro tra le due pagine self.number_decoration_left = "" # Decorazione della pagina sinistra per i numeri di pagina self.number_decoration_right = "" # Decorazione della pagina sinistra per i numeri di pagina self.pages = [] # Lista delle pagine e relativo contenuto #- Fine Inizializzazione - def get_error_message(self, entity): if not self.title: return "title è una stringa non valida: %r" % self.title elif not self.author: return "author è una stringa non valida: %r" % self.author elif not self.summary: return "summary è una stringa non valida: %r" % self.summary elif self.language.get_error_message(LANGUAGE, "language") != "": return self.language.get_error_message(LANGUAGE, "language") elif self.flags.get_error_message(READABLE, "flags") != "": return self.flags.get_error_message(READABLE, "flags") elif READABLE.CENTER in self.flags and READABLE.RIGHT in self.flags: return "Non possono convivere le flag READABLE.CENTER e READABLE.RIGHT assieme." elif (self.number_decoration_left or self.number_decoration_right ) and READABLE.NUMBERS not in self.flags: return "Nonostante sia stata definita una decorazione per i numeri non esiste la flag READABLE.NUMBERS che la mostrerebbe." elif not self.visual_width: return "visual_width è una stringa non valida: %r" % self.visual_width elif not self.visual_height: return "visual_height è una stringa non valida: %r" % self.visual_height elif not self.pages: return "dev'esservi almeno una pagina: %r" % self.pages return "" #- Fine Metodo - def copy(self, to_obj=None, avoid_volatiles=False): if not to_obj: to_obj = Readable() copy_existing_attributes(self, to_obj, avoid_volatiles=avoid_volatiles) return to_obj #- Fine Metodo - def equals(self, readable2): if not readable2: return False if self.comment != readable2.comment: return False if self.title != readable2.title: return False if self.author != readable2.author: return False if self.summary != readable2.summary: return False if self.language != readable2.language: return False if self.flags != readable2.flags: return False if self.visual_width != readable2.visual_width: return False if self.visual_height != readable2.visual_height: return False if self.padding != readable2.padding: return False if self.border_top != readable2.border_top: return False if self.border_right != readable2.border_right: return False if self.border_bottom != readable2.border_bottom: return False if self.border_left != readable2.border_left: return False if self.border_inside != readable2.border_inside: return False if self.number_decoration_left != readable2.number_decoration_left: return False if self.number_decoration_right != readable2.number_decoration_right: return False if len(self.pages) != len(readable2.pages): return False for page in self.pages: for page2 in readable2.pages: if page == page2: break else: return False return True #- Fine Metodo - # ------------------------------------------------------------------------- # (TD) entity e target serviranno in futuro per scramblerare la lingua del # libro se sconosciuta def get_pages(self, entity, target, page_number, from_location=None): if not entity: log.bug("entity non è un parametro valido: %r" % entity) return "" if not target: log.bug("target non è un parametro valido: %r" % target) return "" if page_number < 0 or page_number >= len(self.pages): log.bug("page_number non è un parametro valido: %r" % page_number) return "" # --------------------------------------------------------------------- # Prepara i bordi border_top = "" border_right = "" border_bottom = "" border_left = "" border_inside = "" if self.border_top: border_top = "border-top:%s;" % self.border_top if self.border_right: border_right = "border-right:%s;" % self.border_right if self.border_bottom: border_bottom = "border-bottom:%s;" % self.border_bottom if self.border_left: border_left = "border-left:%s;" % self.border_left if self.border_inside: border_inside = "border-right:%s;" % self.border_inside # Prepara il padding se esistente padding_style = "" if self.padding: padding_style = "padding:%s;" % self.padding # Prepara lo style css per l'output scritto della pagina alignment = "" if READABLE.CENTER in self.flags: alignment = '''text-align:center;''' if READABLE.RIGHT in self.flags: alignment = '''text-align:right;''' visual_style = ''' style="min-width:%s; max-width:%s; min-height:%s; max-height:%s; %s %s"''' % ( self.visual_width, self.visual_width, self.visual_height, self.visual_height, padding_style, alignment) # Ricava informazioni che servono a sfogliare il libro tramite click translated_input = translate_input(entity, "read", "en") if not translated_input: log.bug("Non è stato possibile tradurre l'input read per %s: %r" % (target.code, translated_input)) return False numbered_keyword = target.get_numbered_keyword(looker=entity) if page_number % 2 == 0 and page_number != len(self.pages) - 1: minimum_page = max([0, page_number - 2]) maximum_page = min([len(self.pages) - 1, page_number + 1]) else: minimum_page = max([0, page_number - 1]) maximum_page = min([len(self.pages) - 1, page_number + 2]) if from_location: js_minimum_arguments = "%s %s %s %d" % ( translated_input, numbered_keyword, from_location.get_numbered_keyword(looker=entity), minimum_page) js_maximum_arguments = "%s %s %s %d" % ( translated_input, numbered_keyword, from_location.get_numbered_keyword(looker=entity), maximum_page) else: js_minimum_arguments = "%s %s %d" % ( translated_input, numbered_keyword, minimum_page) js_maximum_arguments = "%s %s %d" % ( translated_input, numbered_keyword, maximum_page) browse_to_left = '''<div style="float:left"><a href="javascript:sendInput('%s')" style="font-size:larger"><</a> </div>''' % js_minimum_arguments browse_to_right = '''<div style="float:left"> <a href="javascript:sendInput('%s')" style="font-size:larger">></a></div>''' % js_maximum_arguments # Gestisce la copertina e la retrocopertina o altre tipologie di entità # leggibili differenti da dei libri, ovvero con al massimo il fronte # e il retro if page_number == 0 or page_number == len(self.pages) - 1: style = "" if border_top or border_right or border_bottom or border_left: style = ''' style="float:left; %s%s%s%s"''' % ( border_top, border_right, border_bottom, border_left) output = "" if page_number == len(self.pages) - 1: output += browse_to_left output += '''<div%s><div%s>%s</div></div>''' % ( style, visual_style, self.pages[page_number]) if page_number == 0: output += browse_to_right output += '''<div style="clear:both;" />''' return output # A seconda che si voglia visualizzare una pagina a destra o a sinistra # sceglie il numero corretto di pagina da far visualizzare nell'altra if page_number % 2 == 0: left_page_number = page_number - 1 right_page_number = page_number else: left_page_number = page_number right_page_number = page_number + 1 # Prepara lo stile dei bordi preparati in precedenza, se ve n'erano left_style = '''style="float:left;%s%s%s%s"''' % ( border_top, border_inside, border_bottom, border_left) right_style = '''style="float:left;%s%s%s"''' % ( border_top, border_right, border_bottom) # Prepara il contenuto scritto delle pagine aggiungendo una pagina # vuota prima della retrocopertina se necessario left_output = self.pages[left_page_number] if len(self.pages) % 2 == 0 and page_number == len(self.pages) - 1: right_output = "" elif len(self.pages) % 2 == 1 and page_number == len(self.pages) - 2: right_output = "" else: right_output = self.pages[right_page_number] if MIML_SEPARATOR in left_output: left_output = target.parse_miml(left_output, looker=entity) if MIML_SEPARATOR in right_output: right_output = target.parse_miml(right_output, looker=entity) # Prepara l'output per i numeri di pagina left_page_number_output = "" right_page_number_output = "" if READABLE.NUMBERS in self.flags: if len(self.number_decoration_left) == 0: left_page_number_output = '''<center>%d</center>''' % left_page_number elif len(self.number_decoration_left) == 1: left_page_number_output = '''<center>%s%d</center>''' % ( self.number_decoration_left, left_page_number) else: middle = int(math.ceil(len(self.number_decoration_left) / 2.0)) left_page_number_output = '''<center>%s%d%s</center>''' % ( self.number_decoration_left[:middle], left_page_number, self.number_decoration_left[middle:]) if len(self.number_decoration_right) == 0: right_page_number_output = '''<center>%d</center>''' % right_page_number elif len(self.number_decoration_right) == 1: right_page_number_output = '''<center>%d%s</center>''' % ( right_page_number, self.number_decoration_right) else: middle = int(math.floor( len(self.number_decoration_left) / 2.0)) right_page_number_output = '''<center>%s%d%s</center>''' % ( self.number_decoration_right[:middle], right_page_number, self.number_decoration_right[middle:]) # Ecco l'output del libro in tutto il suo splendore output = browse_to_left output += '''<div %s><div%s>%s</div>%s</div>''' % ( left_style, visual_style, left_output, left_page_number_output) output += '''<div %s><div%s>%s</div>%s</div>''' % ( right_style, visual_style, right_output, right_page_number_output) output += browse_to_right output += '''<div style="clear:both;" />''' return output
class Door(OpenableGenericType): #PRIMARY_KEY = "" #VOLATILES = [] #MULTILINES = [] #SCHEMA = {} #REFERENCES = {} #WEAKREFS = {} CLOSED_FLAG = DOOR.CLOSED SECRET_FLAG = DOOR.SECRET def __init__(self): super(Door, self).__init__() self.flags = Flags(DOOR.NONE) self.bash_difficulty = 0 # Livello di difficoltà per il bash self.pass_door_difficulty = 0 # Livello di difficoltà per il pass door self.destination_open_message = "" # Messaggio d'apertura stile act a tutti gli altri al di là della porta self.destination_close_message = "" # Messaggio di chiusura stile act a tutti gli altri al di là della porta self.destination_lock_message = "" # Messaggio di blocco(key) stile act a tutti gli altri al di là della porta self.destination_unlock_message = "" # Messaggio di sblocco(key) stile act a tutti gli altri al di là della porta self.destination_bolt_message = "" # Messaggio di sprangata(bolt) stile act a tutti gli altri al di là della porta self.destination_unbolt_message = "" # Messaggio di desprangata(bolt) stile act a tutti gli altri al di là della porta self.reset_open_message = "" # Messaggio di apertura di una porta tramite un reset self.reset_close_message = "" # Messaggio di chiusura di una porta tramite un reset self.open_icon = "" # Icona rappresentante la porta aperta di giorno self.open_icon_night = "" # Icona rappresentante la porta aperta di notte #- Fine Inizializzazione - def get_error_message(self, entity): msg = super(Door, self).get_error_message(entity) if msg: return msg elif self.flags.get_error_message(DOOR, "flags") != "": return self.flags.get_error_message(DOOR, "flags") elif self.bash_difficulty < 0: return "bash_difficulty non può essere negativo: %s" % self.bash_difficulty elif self.pass_door_difficulty < 0: return "pass_door_difficulty non può essere negativo: %s" % self.pass_door_difficulty # L'esistenza dei diversi messaggi è slegata tra loro, ovvero possono # essere inizializzati tutti come solo uno di loro o, naturalmente, # nessuno, quindi non vi è bisogno di controllarli return "" #- Fine Metodo - def copy(self, to_obj=None, avoid_volatiles=False): if not to_obj: to_obj = Door() copy_existing_attributes(self, to_obj, avoid_volatiles=avoid_volatiles) return to_obj #- Fine Metodo - def equals(self, door2): if not door2: return False if not super(Door, self).equals(door2): return False if self.flags != door2.flags: return False if self.bash_difficulty != door2.bash_difficulty: return False if self.pass_door_difficulty != door2.pass_door_difficulty: return False if self.destination_open_message != door2.destination_open_message: return False if self.destination_close_message != door2.destination_close_message: return False if self.destination_lock_message != door2.destination_lock_message: return False if self.destination_unlock_message != door2.destination_unlock_message: return False if self.destination_bolt_message != door2.destination_bolt_message: return False if self.destination_unbolt_message != door2.destination_unbolt_message: return False if self.reset_open_message != door2.reset_open_message: return False if self.reset_close_message != door2.reset_close_message: return False if self.open_icon != door2.open_icon: return False if self.open_icon_night != door2.open_icon_night: return False return True #- Fine Metodo - # ------------------------------------------------------------------------- def get_status(self, sex, looker=None): status = "" if DOOR.CLOSED in self.flags: if sex == SEX.FEMALE: status += " chiusa" else: status += " chiuso" else: if sex == SEX.FEMALE: status += " aperta" else: status += " aperto" if looker and looker.trust >= TRUST.MASTER and DOOR.SECRET in self.flags: status += " (secret)" return status #- Fine Metodo - def get_icon(self): icon = "" if calendar.is_night(): icon = self.open_icon_night if not icon: icon = self.open_icon return icon #- Fine Metodo - #--------------------------------------------------------------------------- def send_open_messages(self, entity, target, verbs, direction=None, destination_room=None, target_on_destination=None): if not entity: log.bug("entity non è un parametro valido: %r" % entity) return if not target: log.bug("target non è un parametro valido: %r" % target) return if not verbs: log.bug("verbs non è un parametro valido: %r" % verbs) return False # --------------------------------------------------------------------- super(Door, self).send_open_messages(entity, target, verbs, direction, destination_room, target_on_destination) if destination_room and direction: target = target_on_destination or target if self.destination_open_message: message = self.destination_open_message if "%verb" in message: if message.startswith("%verb"): message = message % color_first_upper(verbs["it"]) else: message = message % verbs["it"].lower() if "%dir" in message: if message.startswith("%dir"): message = message % color_first_upper( direction.to_dir2) else: message = message % direction.to_dir2.lower() else: message = "Qualcuno, dall'altra parte, %s $N %s" % ( verbs["it"].lower(), direction.reverse_dir.to_dir2) entity.act(message, TO.OTHERS, target, destination_room, target_on_destination, send_to_location=destination_room) #- Fine Metodo - def send_close_messages(self, entity, target, verbs, direction=None, destination_room=None, target_on_destination=None): if not entity: log.bug("entity non è un parametro valido: %r" % entity) return if not target: log.bug("target non è un parametro valido: %r" % target) return if not verbs: log.bug("verbs non è un parametro valido: %r" % verbs) return False # --------------------------------------------------------------------- super(Door, self).send_close_messages(entity, target, verbs, direction, destination_room, target_on_destination) # Cose riguardanti solo le porte if destination_room and direction: target = target_on_destination or target if self.destination_close_message: message = self.destination_close_message if "%verb" in message: if message.startswith("%verb"): message = message % color_first_upper(verbs["it"]) else: message = message % verbs["it"].lower() if "%dir" in message: if message.startswith("%dir"): message = message % color_first_upper( direction.to_dir2) else: message = message % direction.to_dir2.lower() else: message = "Qualcuno, dall'altra parte, %s $N %s" % ( verbs["it"].lower(), direction.reverse_dir.to_dir2) entity.act(message, TO.OTHERS, target, destination_room, target_on_destination, send_to_location=destination_room) #- Fine Metodo - #--------------------------------------------------------------------------- def send_lock_messages(self, entity, target, verbs, direction=None, destination_room=None): if not entity: log.bug("entity non è un parametro valido: %r" % entity) return if not target: log.bug("target non è un parametro valido: %r" % target) return if not verbs: log.bug("verbs non è un parametro valido: %r" % verbs) return False # --------------------------------------------------------------------- super(Door, self).send_lock_messages(entity, target, verbs, direction, destination_room) if destination_room: if self.destination_lock_message: message = self.destination_lock_message if "%verb" in message: if message.startswith("%verb"): message = message % color_first_upper(verbs["it"]) else: message = message % verbs["it"].lower() if "%dir" in message: if message.startswith("%dir"): message = message % color_first_upper( direction.to_dir2) else: message = message % direction.to_dir2.lower() else: message = "Qualcuno, dall'altra parte, %s $N %s" % ( verbs["it"].lower(), direction.reverse_dir.to_dir2) entity.act(message, TO.OTHERS, target, destination_room, send_to_location=destination_room) #- Fine Metodo - def send_unlock_messages(self, entity, target, verbs, direction=None, destination_room=None): if not entity: log.bug("entity non è un parametro valido: %r" % entity) return if not target: log.bug("target non è un parametro valido: %r" % target) return if not verbs: log.bug("verbs non è un parametro valido: %r" % verbs) return False # --------------------------------------------------------------------- super(Door, self).send_unlock_messages(entity, target, verbs, direction, destination_room) if destination_room: if self.destination_unlock_message: message = self.destination_unlock_message if "%verb" in message: if message.startswith("%verb"): message = message % color_first_upper(verbs["it"]) else: message = message % verbs["it"].lower() if "%dir" in message: if message.startswith("%dir"): message = message % color_first_upper( direction.to_dir2) else: message = message % direction.to_dir2.lower() else: message = "Qualcuno, dall'altra parte, %s $N %s" % ( verbs["it"].lower(), direction.reverse_dir.to_dir2) entity.act(message, TO.OTHERS, target, destination_room, send_to_location=destination_room) #- Fine Metodo - #--------------------------------------------------------------------------- def send_unbolt_messages(self, entity, target, verbs, destination_room=None, direction=None): if not entity: log.bug("entity non è un parametro valido: %r" % entity) return if not target: log.bug("target non è un parametro valido: %r" % target) return if not verbs: log.bug("verbs non è un parametro valido: %r" % verbs) return False # --------------------------------------------------------------------- super(Door, self).send_unbolt_messages(entity, target, verbs, direction, destination_room) if destination_room and direction: if self.destination_unbolt_message: message = self.destination_unbolt_message if "%verb" in message: if message.startswith("%verb"): message = message % color_first_upper(verbs["it"]) else: message = message % verbs["it"].lower() if "%dir" in message: if message.startswith("%dir"): message = message % color_first_upper( direction.to_dir2) else: message = message % direction.to_dir2.lower() else: message = "Qualcuno, dall'altra parte, %s $N %s" % ( verbs["it"].lower(), direction.reverse_dir.to_dir2) entity.act(message, TO.OTHERS, target, destination_room, send_to_location=destination_room) #- Fine Metodo - def send_bolt_messages(self, entity, target, verbs, direction=None, destination_room=None): if not entity: log.bug("entity non è un parametro valido: %r" % entity) return if not target: log.bug("target non è un parametro valido: %r" % target) return if not verbs: log.bug("verbs non è un parametro valido: %r" % verbs) return False # --------------------------------------------------------------------- super(Door, self).send_bolt_messages(entity, target, verbs, direction, destination_room) # Cose riguardanti solo le porte if destination_room and direction: if self.destination_bolt_message: message = self.destination_bolt_message if "%verb" in message: if message.startswith("%verb"): message = message % color_first_upper(verbs["it"]) else: message = message % verbs["it"].lower() if "%dir" in message: if message.startswith("%dir"): message = message % color_first_upper( direction.to_dir2) else: message = message % direction.to_dir2.lower() else: message = "Qualcuno, dall'altra parte, %s $N %s" % ( verbs["it"].lower(), direction.reverse_dir.to_dir2) entity.act(message, TO.OTHERS, target, destination_room, send_to_location=destination_room)
class Account(Data): """ Contiene tutte le informazioni e le opzioni di un Account di gioco, in esso c'è anche la lista dei personaggi creati e giocabili dal giocatore dell'account. """ PRIMARY_KEY = "name" VOLATILES = ["player", "players"] MULTILINES = [] SCHEMA = { "players": ("src.player", "Player"), "player": ("src.player", "Player"), "aliases": ("src.account", "Alias"), "macros": ("src.account", "Macro"), "user_agents": ("", "str"), "created_time": ("", "datetime"), "last_bug_sended_at": ("", "datetime"), "last_comment_sended_at": ("", "datetime"), "last_typo_sended_at": ("", "datetime"), "last_idea_sended_at": ("", "datetime") } REFERENCES = {} WEAKREFS = {} def __init__(self, name=""): self.comment = "" self.created_time = datetime.datetime.now( ) # Data di creazione del'account self.name = name # Nome di login self.password = "" # Password self.email = "" # Indirizzo e-mail (opzionale) self.options = Flags(OPTION.NONE) self.show_logs = Flags(LOG.NONE) self.aliases = {} # Dizionario relativo agli alias self.macros = {} # Dizionario relativo alle macro # (TD) provare a convertire questi datetime in None e caricarli tramite schema self.last_bug_sended_at = None self.last_comment_sended_at = None self.last_typo_sended_at = None self.last_idea_sended_at = None self.sended_bugs = 0 # Bug totali inviati self.sended_comments = 0 # Typo totali inviati self.sended_ideas = 0 # Idee totali inviati self.sended_typos = 0 # Typo totali inviati self.user_agents = [ ] # Informazioni relative ai client browser utilizzati dal giocatore per entrare nel Mud self.resolution_width = 0 # Risoluzione in pixel del monitor del client in larghezza self.resolution_height = 0 # Risoluzione in pixel del monitor del client in altezza # Al primo account creato in assoluto dà poteri di Implementor, dando # per scontato che il primo giocatore che utilizza questo Mud sia il # futuro amministratore, ai successivi account dona la trust di player if not database["accounts"]: self.trust = Element(TRUST.IMPLEMENTOR) else: self.trust = Element(TRUST.PLAYER) # Attributi volatili self.players = {} # Dizionario dei giocatori creati dall'account self.player = None # Personaggio che si sta creando o utilizzando #- Fine Inizializzazione - def __repr__(self): return "%s %s" % (super(Account, self).__repr__, self.name) #- Fine Metodo - def get_error_message(self, already_in_database=True): """ Ritorna una stringa vuota se l'account non ha errori, altrimenti il messaggio d'errore. Bisogna passare l'argomento already_in_database uguale a False quando si controlla l'integrità di un account appena creato e che non si è ancora aggiunto al database degli account. """ msg = "" if already_in_database != True and already_in_database != False: msg = "L'argomento already_in_database non è un booleano valido: %s" % already_in_database # --------------------------------------------------------------------- # self.player è lecito che sia anche None se l'account non sta giocando if msg: pass elif get_error_message_name(self.name, already_in_database) != "": msg = "%s: %s" % (get_error_message_name( self.name, already_in_database), self.name) elif get_error_message_password(self.password) != "": msg = "%s: %s" % (get_error_message_password( self.password), self.password) elif get_error_message_email(self.email, already_in_database) != "": msg = "%s: %s" % (get_error_message_email( self.email, already_in_database), self.email) elif self.trust.get_error_message(TRUST, "trust") != "": msg = self.trust.get_error_message(TRUST, "trust") elif self.options.get_error_message(OPTION, "options") != "": msg = self.options.get_error_message(OPTION, "options") elif self.show_logs.get_error_message(LOG, "logs") != "": msg = self.show_logs.get_error_message(LOG, "logs") elif len(self.players) > config.max_account_players: msg = "Numero di personaggi superiore a %s" % config.max_account_players elif self._get_error_message_only_one_player() != "": msg = self._get_error_message_only_one_player() elif len(self.aliases) > config.max_aliases: msg = "Numero degli alias superiore al massimo (%d): %d" % ( config.max_aliases, len(self.aliases)) elif len(self.macros) > config.max_macros: msg = "Numero delle macro superiore al massimo (%d): %d" % ( config.max_macros, len(self.macros)) elif self.resolution_width < 0: msg = "Risoluzione del client in larghezza errato: %d" % self.resolution_width elif self.resolution_height < 0: msg = "Risoluzione del client in altezza errato: %d" % self.resolution_height else: return "" # Se ha trovato un errore invia il relativo messaggio log.bug("(Account: name %s) %s" % (self.name, msg)) return msg #- Fine Metodo - def _get_error_message_only_one_player(self): """ Controlla che due o più account non utilizzino lo stesso player. """ for player in self.players.itervalues(): for account in database["accounts"].itervalues(): if account.name == self.name: continue if player.code in account.players: return "Personaggio %s già esistente nell'account %s" % ( player.code, account.name) return "" #- Fine Metodo - # ------------------------------------------------------------------------- def get_id(self): """ Ritorna una o tutte tra le seguenti informazioni: il nome dell'account e il nome del personaggio. Molto utile da utilizzare nei messaggi di log. Questo metodo fa a coppia con quello nella classe Connection. """ player_name = "None" if self.player: player_name = self.player.code return "%s.%s" % (self.name, player_name) #- Fine Metodo - def check_alias(self, arg, argument): """ Controlla se argument sia un alias di un pg, se sì lo ritorna. """ if not arg: log.bug("arg non è un parametro valido: %r" % arg) return # --------------------------------------------------------------------- if arg not in self.aliases: return False alias = self.aliases[arg] argument = argument or "" interpret(self.player, "%s %s" % (alias.action, argument), use_check_alias=False) return True
class Exit(Describable): """ Gestisce una singola uscita di una stanza. """ PRIMARY_KEY = "direction" VOLATILES = [] MULTILINES = ["comment"] SCHEMA = {"extras" : ("src.extra", "ExtraDescription"), "height" : ("", "measure"), "depth" : ("", "measure"), "destination" : ("src.room", "Destination")} REFERENCES = {} WEAKREFS = {} IS_AREA = False IS_DESCR = True IS_ROOM = False IS_EXIT = True IS_WALL = False IS_ACTOR = False IS_MOB = False IS_ITEM = False IS_PLAYER = False IS_EXTRA = False IS_PROTO = False def __init__(self, direction=DIR.NONE): if not direction: log.bug("direction non è un parametro valido: %r" % direction) return # --------------------------------------------------------------------- self.comment = "" # Eventuale commento all'uscita self.direction = Element(direction) # Tipologia della direzione self.descr = "" # Descrizione di quello che si vede guardando la direzione self.descr_night = "" # Descrizione notturna di quello che si vede guardando la direzione self.descr_hearing = "" # Descrizione uditiva self.descr_hearing_night = "" # Descrizione uditiva notturna self.descr_smell = "" # Descrizione odorosa self.descr_smell_night = "" # Descrizione odorosa notturna self.descr_touch = "" # Descrizione tattile self.descr_touch_night = "" # Descrizione tattile notturna self.descr_taste = "" # Descrizione del sapore self.descr_taste_night = "" # Descrizione del sapore notturna self.descr_sixth = "" # Descrizione del sesto senso self.descr_sixth_night = "" # Descrizione del sesto senso notturna self.icon = "" # Icona rappresentante l'uscita di giorno self.icon_night = "" # Icona rappresentante l'uscita di notte self.extras = Extras() # Descrizioni extra dell'uscita self.flags = Flags(EXIT.NONE) # Flags dell'uscita self.destination = None # Stanza a cui l'uscita porta se questa differente rispetto alla direzione presa self.door = None # Oggetto porta se serve aprirla (se non viene indicata questa viene caricata dal limbo una porta di default) (TD) qui vorrei aggiungere anche una variabile finestra.. ma poi come gestire finestre e porte multiple? e il key_code nel qual caso una finestra sia chiudibile (cmq per ora continuo così.. in effetti potrei considerare il fatto di voler inserire più porte o finestre in una uscita come una eccezione e gestirla tramite gamescripts) self.entity_message = "" # Messaggio di movimento per colui che si sta spostando self.others_in_message = "" # Messaggio di movimento per gli altri della stanza di partenza self.others_out_message = "" # Messaggio di movimento per gli altri della stanza di arrivo #- Fine Inizializzazione - def get_error_message(self): """ Se c'è un errore nell'uscita ne ritorna il messaggio appropriato. """ if self.direction.get_error_message(DIR, "direction", allow_none=False) != "": msg = self.direction.get_error_message(DIR, "direction", allow_none=False) elif self.flags.get_error_message(EXIT, "flags") != "": msg = self.flags.get_error_message(EXIT, "flags") # elif (self.door and self.door.code not in database["items"] # and self.door and self.door.code not in database["mobs"]): # msg = "door dell'uscita non è un oggetto valido: %s" % self.door.code elif self.destination and self.destination.get_error_message() != "": msg = self.destination.get_error_message() elif self.extras.get_error_message(): msg = self.extras.get_error_message() else: return "" return "(exit %r): %s" % (self.direction, msg) #- Fine Metodo - def copy(self, to_obj=None, avoid_volatiles=False): if not to_obj: to_obj = Exit() copy_existing_attributes(self, to_obj, avoid_volatiles=avoid_volatiles) return to_obj #- Fine Metodo - def equals(self, exit2): # Non dovrebbe servire implementarli, ma inserisco questo "avviso" al caso raise NotImplementedError #- Fine Metodo - # ------------------------------------------------------------------------- def get_icon(self, room=None): if room: door = room.get_door(self.direction) else: door = None icon = "" if door and door.door_type and DOOR.CLOSED in door.door_type.flags and DOOR.SECRET not in door.door_type.flags: # L'icone dell'entità porta è intesa come chiusa icon = door.get_icon() if not icon: icon = "icons/door/default-door.png" elif door and door.door_type and DOOR.CLOSED not in door.door_type.flags: # Icona della porta aperta icon = door.door_type.get_icon() if not icon: icon = "icons/door/default-door-open.png" elif not door or (door.door_type and DOOR.SECRET not in door.door_type.flags): if calendar.is_night() and self.icon_night: # icona dell'uscita di notte icon = self.icon_night elif self.icon: # icona dell'uscita di giorno icon = self.icon # Inserisce di default dei simboli di una rosa dei venti if not icon: icon = "icons/compass/%s.png" % repr(self.direction).split(".")[1].lower() return icon #- Fine Metodo - def get_descr(self, type="", looker=None): """ Ritorna la descrizione dell'uscita. """ if type: type = "_" + type descr = "" if calendar.is_night(): descr = getattr(self, "descr%s_night" % type) if not descr: descr = getattr(self, "descr%s" % type) # Normale che possa accadere per qualsiasi tipologia di descrizione if not descr: return "" if self.ASCIIART_TAG_OPEN in descr: descr = self.convert_asciiart_linefeeds(descr) else: descr = put_final_dot(descr) if ".\n" in descr: descr = descr.replace(".\n", ".<br>") if "!\n" in descr: descr = descr.replace("!\n", "!<br>") if "?\n" in descr: descr = descr.replace("?\n", "?<br>") if "\n" in descr: descr = descr.replace("\n", " ") return descr
class Account(Data): """ Contiene tutte le informazioni e le opzioni di un Account di gioco, in esso c'è anche la lista dei personaggi creati e giocabili dal giocatore dell'account. """ PRIMARY_KEY = "name" VOLATILES = ["player", "players"] MULTILINES = [] SCHEMA = {"players" : ("src.player", "Player"), "player" : ("src.player", "Player"), "aliases" : ("src.account", "Alias"), "macros" : ("src.account", "Macro"), "user_agents" : ("", "str"), "created_time" : ("", "datetime"), "last_bug_sended_at" : ("", "datetime"), "last_comment_sended_at" : ("", "datetime"), "last_typo_sended_at" : ("", "datetime"), "last_idea_sended_at" : ("", "datetime")} REFERENCES = {} WEAKREFS = {} def __init__(self, name=""): self.comment = "" self.created_time = datetime.datetime.now() # Data di creazione del'account self.name = name # Nome di login self.password = "" # Password self.email = "" # Indirizzo e-mail (opzionale) self.options = Flags(OPTION.NONE) self.show_logs = Flags(LOG.NONE) self.aliases = {} # Dizionario relativo agli alias self.macros = {} # Dizionario relativo alle macro # (TD) provare a convertire questi datetime in None e caricarli tramite schema self.last_bug_sended_at = None self.last_comment_sended_at = None self.last_typo_sended_at = None self.last_idea_sended_at = None self.sended_bugs = 0 # Bug totali inviati self.sended_comments = 0 # Typo totali inviati self.sended_ideas = 0 # Idee totali inviati self.sended_typos = 0 # Typo totali inviati self.user_agents = [] # Informazioni relative ai client browser utilizzati dal giocatore per entrare nel Mud self.resolution_width = 0 # Risoluzione in pixel del monitor del client in larghezza self.resolution_height = 0 # Risoluzione in pixel del monitor del client in altezza # Al primo account creato in assoluto dà poteri di Implementor, dando # per scontato che il primo giocatore che utilizza questo Mud sia il # futuro amministratore, ai successivi account dona la trust di player if not database["accounts"]: self.trust = Element(TRUST.IMPLEMENTOR) else: self.trust = Element(TRUST.PLAYER) # Attributi volatili self.players = {} # Dizionario dei giocatori creati dall'account self.player = None # Personaggio che si sta creando o utilizzando #- Fine Inizializzazione - def __repr__(self): return "%s %s" % (super(Account, self).__repr__, self.name) #- Fine Metodo - def get_error_message(self, already_in_database=True): """ Ritorna una stringa vuota se l'account non ha errori, altrimenti il messaggio d'errore. Bisogna passare l'argomento already_in_database uguale a False quando si controlla l'integrità di un account appena creato e che non si è ancora aggiunto al database degli account. """ msg = "" if already_in_database != True and already_in_database != False: msg = "L'argomento already_in_database non è un booleano valido: %s" % already_in_database # --------------------------------------------------------------------- # self.player è lecito che sia anche None se l'account non sta giocando if msg: pass elif get_error_message_name(self.name, already_in_database) != "": msg = "%s: %s" % (get_error_message_name(self.name, already_in_database), self.name) elif get_error_message_password(self.password) != "": msg = "%s: %s" % (get_error_message_password(self.password), self.password) elif get_error_message_email(self.email, already_in_database) != "": msg = "%s: %s" % (get_error_message_email(self.email, already_in_database), self.email) elif self.trust.get_error_message(TRUST, "trust") != "": msg = self.trust.get_error_message(TRUST, "trust") elif self.options.get_error_message(OPTION, "options") != "": msg = self.options.get_error_message(OPTION, "options") elif self.show_logs.get_error_message(LOG, "logs") != "": msg = self.show_logs.get_error_message(LOG, "logs") elif len(self.players) > config.max_account_players: msg = "Numero di personaggi superiore a %s" % config.max_account_players elif self._get_error_message_only_one_player() != "": msg = self._get_error_message_only_one_player() elif len(self.aliases) > config.max_aliases: msg = "Numero degli alias superiore al massimo (%d): %d" % (config.max_aliases, len(self.aliases)) elif len(self.macros) > config.max_macros: msg = "Numero delle macro superiore al massimo (%d): %d" % (config.max_macros, len(self.macros)) elif self.resolution_width < 0: msg = "Risoluzione del client in larghezza errato: %d" % self.resolution_width elif self.resolution_height < 0: msg = "Risoluzione del client in altezza errato: %d" % self.resolution_height else: return "" # Se ha trovato un errore invia il relativo messaggio log.bug("(Account: name %s) %s" % (self.name, msg)) return msg #- Fine Metodo - def _get_error_message_only_one_player(self): """ Controlla che due o più account non utilizzino lo stesso player. """ for player in self.players.itervalues(): for account in database["accounts"].itervalues(): if account.name == self.name: continue if player.code in account.players: return "Personaggio %s già esistente nell'account %s" % (player.code, account.name) return "" #- Fine Metodo - # ------------------------------------------------------------------------- def get_id(self): """ Ritorna una o tutte tra le seguenti informazioni: il nome dell'account e il nome del personaggio. Molto utile da utilizzare nei messaggi di log. Questo metodo fa a coppia con quello nella classe Connection. """ player_name = "None" if self.player: player_name = self.player.code return "%s.%s" % (self.name, player_name) #- Fine Metodo - def check_alias(self, arg, argument): """ Controlla se argument sia un alias di un pg, se sì lo ritorna. """ if not arg: log.bug("arg non è un parametro valido: %r" % arg) return # --------------------------------------------------------------------- if arg not in self.aliases: return False alias = self.aliases[arg] argument = argument or "" interpret(self.player, "%s %s" % (alias.action, argument), use_check_alias=False) return True
class Command(Data): """ Gestisce tutte le caratteristiche di un comando. Se tra gli attributi cercate quelli che servono per chiamare il comando tramite il testo inviato dai giocatori qui non li troverete, per quel compito ci pensa la classe Input(). """ PRIMARY_KEY = "fun_name" VOLATILES = [ "timer", "module", "function", ] MULTILINES = ["mini_help"] SCHEMA = {} REFERENCES = {} WEAKREFS = {} def __init__(self, fun_name=""): self.comment = "" self.fun_name = fun_name or "" # Nome della funzione self.type = Element(CMDTYPE.INFORMATION) # Tipologia del comando self.trust = Element(TRUST.PLAYER) # Fiducia minima per digitarlo self.position = Element( POSITION.REST) # Posizione minima per utilizzarlo self.flags = Flags(CMDFLAG.NONE) # Flag dei comandi self.no_races = Flags( RACE.NONE ) # Razze che NON possono usarlo (RACE.NONE significa che tutti lo possono utilizzare) self.mini_help = "" # Piccola descrizione dell'utilizzo del comando self.timer = 0.0 # Tempo totale di esecuzione del comando (anche se nelle pagine d'amministrazione visualizza il tempo medio) # Variabili volatili self.module = None # Riferimento al modulo che contiene la funzione self.function = None # Riferimento alla funzione if self.fun_name: self.import_module_and_function() #- Fine Inizializzazione - def get_error_message(self): """ Ritorna un messaggio di errore se qualcosa nel comando è sbagliata, altrimenti se tutto è a posto ritorna una stringa vuota. """ if not self.fun_name: msg = "il nome della funzione non è valido" elif (not self.fun_name.startswith("command_") and not self.fun_name.startswith("skill_") and not self.fun_name.startswith("social_")): msg = "il nome della funzione non inizia per command_, skill_ o social_" elif self.type.get_error_message(CMDTYPE, "type") != "": msg = self.type.get_error_message(CMDTYPE, "type") elif self.trust.get_error_message(TRUST, "trust") != "": msg = self.trust.get_error_message(TRUST, "trust") elif self.position.get_error_message(POSITION, "position") != "": msg = self.position.get_error_message(POSITION, "position") elif self.flags.get_error_message(CMDFLAG, "flags") != "": msg = self.flags.get_error_message(CMDFLAG, "flags") elif self.no_races.get_error_message(RACE, "no_races") != "": msg = self.no_races.get_error_message(RACE, "no_races") # Ignora i minihelp vuoti relativi ai comandi-social elif not self.mini_help and not self.fun_name.startswith("social_"): msg = "la stringa di mini help è vuota" elif self.timer < 0.0: msg = "il timer non può essere negativo: %f" % self.timer elif not self.module: msg = "modulo non importato" elif not self.function: msg = "funzione non importata" else: return "" # Se arriva qui significa che ha un messaggio da inviare log.bug("(Command: fun_name %s) %s" % (self.fun_name, msg)) return msg #- Fine Metodo - def get_total_use_count(self): """ Ritorna l'utilizzo totale della funzione di comando tra tutti gli input. """ total_use_count = 0 for inputs_name, inputs in yield_inputs_items(): for input in inputs: if input.command == self: total_use_count += input.counter_use return total_use_count #- Fine Metodo - def import_module_and_function(self): """ Importa il modulo che contiene la funzione del comando. """ if self.fun_name.startswith("command_"): package = "src.commands." elif self.fun_name.startswith("skill_"): package = "src.skills." elif self.fun_name.startswith("social_"): package = "src.socials." else: log.bug("la fun_name del comando è errata: %s" % self.fun_name) return None import_path = package + self.fun_name self.module = __import__(import_path, globals(), locals(), [""]) self.function = getattr(self.module, self.fun_name)
class Area(Data, AreaResetsSuperclass): """ Contiene tutte le informazioni di un'area e i metodi per gestirla. """ PRIMARY_KEY = "code" VOLATILES = ["max_players", "upper_limit", "lower_limit", "rooms", "players", "mobs", "items", "room_scripts", "mob_scripts", "item_scripts", "player_scripts", "meteo", "proto_rooms", "proto_mobs", "proto_items"] MULTILINES = ["descr"] SCHEMA = {"climates" : ("src.climate", "Climate"), "maze" : ("src.games.maze", "Maze"), "wumpus" : ("src.games.wumpus", "Wumpus"), "wild" : ("src.wild", "Wild"), "room_resets" : ("src.reset", "RoomReset"), "echoes_dawn" : ("", "str"), "echoes_dawn_no_sun" : ("", "str"), "echoes_sunrise" : ("", "str"), "echoes_sunrise_no_sun" : ("", "str"), "echoes_noon" : ("", "str"), "echoes_noon_no_sun" : ("", "str"), "echoes_sunset" : ("", "str"), "echoes_sunset_no_sun" : ("", "str"), "echoes_dusk" : ("", "str"), "echoes_dusk_no_moon" : ("", "str"), "echoes_dusk_full_moon" : ("", "str"), "echoes_midnight" : ("", "str"), "echoes_midnight_no_moon" : ("", "str"), "echoes_midnight_full_moon" : ("", "str")} REFERENCES = {} WEAKREFS = {} IS_AREA = True IS_DESCR = False IS_ROOM = False IS_EXIT = False IS_WALL = False IS_ACTOR = False IS_MOB = False IS_ITEM = False IS_PLAYER = False IS_EXTRA = False IS_PROTO = False def __init__(self, code=""): self.comment = "" self.code = code # Codice identificativo dell'area self.name = "" # Nome esteso self.short = "" # Descrizioni breve dell'area self.short_night = "" # Descrizioni breve notturna dell'area self.descr = "" # Descrizione dell'area per la pagina web della lista delle aree self.creators = "" # Lista dei creatori, vale il codice dell'account (TD) in futuro sarà una lista per poter ricavare il riferimento self.level = 1 # Livello base per tutte le entità dell'area, se viene modificato questo anche tutte le entità aumentano o diminuiscono di livello in proporzione self.flags = Flags(AREA.NONE) # self.races = Flags(RACE.NONE) # Razze che si possono incontrare principalmente nell'area (TD) self.color = Element(COLOR.NONE) # Colore dell'area self.music = "" # File mid avviato quando uno entra nell'area self.music_wild = "" # File mid avviato quando uno esce dall'area ed entra nella wild self.climates = {} # Informazioni climatiche dell'area relativamente alle stagioni self.maze = None # Informazioni relative al labirinto self.wumpus = None # Informazioni relative alle aree wumpus self.wild = None # Struttura relativa alla wilderness self.landfill_code = "" # Codice della stanza prototipo in cui verranno inseriti gli oggetti "da buttare" self.repop_time = 0 # Minuti reali tra un repop di un'entità ed un'altro self.room_resets = [] # Lista dei reset dell'area # Attributi relativi alle liste dei messaggi di echo self.echoes_dawn = [] self.echoes_dawn_no_sun = [] self.echoes_sunrise = [] self.echoes_sunrise_no_sun = [] self.echoes_noon = [] self.echoes_noon_no_sun = [] self.echoes_sunset = [] self.echoes_sunset_no_sun = [] self.echoes_dusk = [] self.echoes_dusk_no_moon = [] self.echoes_dusk_full_moon = [] self.echoes_midnight = [] self.echoes_midnight_no_moon = [] self.echoes_midnight_full_moon = [] # Attributi volatili: self.max_players = 0 # Numero massimo di giocatori che sono stati presenti contemporaneamente nell'area nella sessione di gioco self.upper_limit = 0 # Limite di coordinata Z verso l'alto oltre la quale si esce dall'area self.lower_limit = 0 # Limite di coordinata Z verso il basso oltre la quale si esce dall'area self.rooms = {} # Stanze in-game nelle rispettive coordinate self.players = [] # Giocatori in-game che si trovano nelll'area self.mobs = [] # Mob in-game che si trovano nell'area self.items = [] # Oggetti in-game che si trovano nell'area self.meteo = Meteo() # Informazioni meteo in-game dell'area self.gamescripts = {} # Gamescript a livello di area # Liste relative ai dati modello dell'area, i prototipi self.proto_rooms = {} self.proto_mobs = {} self.proto_items = {} #- Fine Inizializzazione - def __repr__(self): return "%s %s" % (super(Area, self).__repr__, self.code) #- Fine Metodo - def get_error_message(self): """ Ritorna un messaggio di errore se la struttura dell'area contiene delle anomalie, altrimenti se tutto è corretto ritorna una stringa vuota. """ if not self.code: msg = "code dell'area non valido" elif not self.code.islower(): msg = "code dell'area per convenzione deve essere scritto in minuscolo: %s" % self.code elif not self.short: msg = "short dell'area non valido: %r" % self.short elif not self.name: msg = "name dell'area non valido: %r" % self.name elif not self.descr: msg = "descr dell'area non valida: %r" % self.descr elif self.get_error_message_creators() != "": msg = self.get_error_message_creators() elif self.level <= 0: msg = "Il livello di un'area non può essere uguale a 0 o negativo: %d" % self.level # elif self.races.get_error_message(RACE, "races") != "": # msg = self.races.get_error_message(RACE, "races") elif self.flags.get_error_message(AREA, "flags") != "": msg = self.flags.get_error_message(AREA, "flags") elif self.color.get_error_message(COLOR, "color") != "": msg = self.color.get_error_message(COLOR, "color") elif self.get_error_message_climates() != "": msg = self.get_error_message_climates() elif self.maze and self.maze.get_error_message() != "": msg = self.maze.get_error_message() elif self.wumpus and self.wumpus.get_error_message() != "": msg = self.wumpus.get_error_message() elif self.repop_time < config.min_repop_time or self.repop_time > config.max_repop_time: msg = "il repop time deve essere compreso tra %d e %d minuti invece è: %d" % ( config.min_repop_time, config.max_repop_time, self.repop_time) elif not self.landfill_code and not self.wild: msg = "landfill_code dell'area non valido: %r" % self.landfill_code elif self.get_error_message_resets() != "": msg = self.get_error_message_resets() else: return "" # Se arriva qui c'è un messaggio d'errore da inviare log.error("(Area: %s) %s" % (self.code, msg)) return msg #- Fine Metodo - def get_error_message_creators(self): if self.creators: from src.database import database hint = "controllare di aver inserito il nome con la maiuscola" for name in self.creators.split(): if name not in database["accounts"]: #return "area %s non ha trovato nell'etichetta Creators un nome tra quelli degli account: %s (%s)" % ( # self.code, name, hint) continue return "" #- Fine Metodo - def get_error_message_climates(self): for climate in self.climates: if climate.get_error_message() != "": return climate.get_error_message() return "" #- Fine Metodo - # (TD) def get_pedantic_messages(self): messages = [] if not self.short_night and "@empty_short_night" not in self.comment: messages.append("short_night non è stata scritta, da ignorare nel qual caso nell'area non sussistano grossi cambiamenti di luce o altro, tra giorno e notte. (@empty_short_night)") length = len(remove_colors(getattr(self, "descr"))) if length > config.max_google_translate * 2 and "@descr_too_long" not in self.comment: messages.append("descr è più lunga di %d caratteri: %d (@descr_too_long)" % (config.max_google_translate * 2, length)) for i, message in enumerate(messages): messages[i] = "(Area: code %s) %s" % (self.code, message) return messages #- Fine Metodo - def get_name(self, looker=None): # (TD) fare il sistema di self.name if calendar.is_night() and self.short_night: return self.short_night else: return self.short #- Fine Metodo - def extract_rooms(self, except_these=None): if except_these is None: except_these = [] for room in reversed(self.rooms.values()): if room.prototype.code not in except_these: room.extract(1) # (TD) L'estrazione del resto delle altre entità non dovrebbe servire, # tuttavia in futuro sarebbe il caso di aggiungere un check per # controllare i riferimenti #- Fine Metodo - # (TT) Questo metodo è uguale a quello in entity.py, possibilità di accorpare? def iter_contains(self, entity_tables=None, use_reversed=False): """ È curioso come a volte questo metodo possa essere utilizzato per iterare i codici dell entità prototipo passando un entity_tables uguale a questo: ("proto_items", "proto_mobs", "proto_rooms"); per avere i valori di prototipo invece basta utilizzare il metodo iter_protos. """ if not entity_tables: entity_tables = ["items", "mobs", "players"] if use_reversed: for type in entity_tables: for content in reversed(getattr(self, type)): yield content else: for type in entity_tables: for content in getattr(self, type): yield content #- Fine Metodo - def iter_protos(self, entity_tables=None, use_reversed=False): if not entity_tables: entity_tables = ["proto_items", "proto_mobs", "proto_rooms"] if use_reversed: for type in entity_tables: for content in reversed(getattr(self, type).values()): yield content else: for type in entity_tables: for content in getattr(self, type).values(): yield content #- Fine Metodo - def get_list_of_entities(looker, include_looker="dummy-parameter", avoid_inventory="dummy-parameter", avoid_equipment="dummy-parameter", admin_descrs="dummy-parameter"): return getattr(self, entity_type) #- Fine Metodo - def get_min_coord(self, axis): if axis not in ("x", "y", "z"): log.bug("axis non è una asse cartesiano valido: %s" % axis) return 0 #---------------------------------------------------------------------- coords = [] for room_reset in self.room_resets: coords.append(getattr(room_reset.destination, axis)) if coords: return min(coords) else: return 0 #- Fine Metodo - def get_max_coord(self, axis): if axis not in ("x", "y", "z"): log.bug("axis non è una asse cartesiano valido: %s" % axis) return 0 #---------------------------------------------------------------------- coords = [] for room_reset in self.room_resets: coords.append(getattr(room_reset.destination, axis)) if coords: return max(coords) else: return 0
class Shop(object): """ Classe che gestisce tutte le informazioni di un negoziante. """ PRIMARY_KEY = "" VOLATILES = [] MULTILINES = ["comment"] SCHEMA = {"buyables" : ("src.shop", "Buyable"), "sellables" : ("src.shop", "Sellable")} REFERENCES = {"proto_locations" : ["proto_rooms", "proto_mobs", "proto_items"], "proto_storages" : ["proto_rooms", "proto_mobs", "proto_items"]} WEAKREFS = {} def __init__(self): self.comment = "" # Commento relativo la struttura self.types = Flags(SHOP.NONE) # Tipologia/e di shop, se non impostata viene considerato un negozio qualsiasi self.proto_locations = [] # Prototipo delle locazioni in cui l'entità negozierà, se non ne viene indicata nessuna il negoziante è un venditore ambulante self.proto_storages = [] # Prototipo delle locazioni da cui l'entità prenderà la mercanzia da vendere self.buyables = [] # Entità comprabili da parte di un giocatore e relative informazioni di magazzino self.sellables = [] # Tipologie di entità vendibili da parte del giocatore, se non viene impostata allora si potrà vendere qualsiasi cosa self.entity_buy_message = "" # Messaggi di act relativi al comando buy avvenuto, sono messaggi facoltativi self.others_buy_message = "" self.target_buy_message = "" self.dealer_buy_message = "" self.entity_cannot_afford_message = "" # Messaggi di act relativi al comando buy se non si hanno i soldi necessari, sono messaggi facoltativi self.others_cannot_afford_message = "" self.target_cannot_afford_message = "" self.dealer_cannot_afford_message = "" self.entity_sell_message = "" # Messaggi di act relativi al comando sell avvenuto, sono messaggi facoltativi self.others_sell_message = "" self.target_sell_message = "" self.dealer_sell_message = "" self.entity_offer_message = "" # Messaggi di act relativi al comando offer avvenuto, sono messaggi facoltativi self.others_offer_message = "" self.target_offer_message = "" self.dealer_offer_message = "" self.entity_uninterested_message = "" # Messaggi di act relativi al disinteresse del mercante per un determinata entità offerta o venduta, sono messaggi facoltativi self.others_uninterested_message = "" self.target_uninterested_message = "" self.dealer_uninterested_message = "" #- Fine Inizializzazione - def get_error_message(self): if self.types.get_error_message(SHOP, "types") != "": return self.types.get_error_message(SHOP, "types") elif self.get_error_message_buyables() != "": return self.get_error_message_buyables() elif self.get_error_message_sellables() != "": return self.get_error_message_sellables() return "" #- Fine Metodo - def get_error_message_buyables(self): if not self.buyables: return "buyables non è stata impostata" for buyable in self.buyables: if buyable.get_error_message() != "": return buyable.get_error_message() return "" #- Fine Metodo - def get_error_message_sellables(self): for sellable in self.sellables: if sellable.entitype == ENTITYPE.NONE: if len(self.sellables) > 1: return "Quando si esplicita il valore di ENTITYPE.NONE in un sellable deve essere il solo e unico." for sellable in self.sellables: if sellable.get_error_message() != "": return sellable.get_error_message() return "" #- Fine Metodo - def copy(self, to_obj=None, avoid_volatiles=False): if not to_obj: to_obj = Shop() copy_existing_attributes(self, to_obj, avoid_volatiles=avoid_volatiles) return to_obj #- Fine Metodo - def equals(self, shop2): if not shop2: return False if self.comment != shop2.comment: return False if self.types != shop2.types: return False for location in self.proto_locations: for location2 in shop2.proto_locations: if location == location2: break else: return False for storage in self.proto_storages: for storage2 in shop2.proto_storages: if storage == storage2: break else: return False if len(self.buyables) != len(shop2.buyables): return False for buyable in self.buyables: for buyable2 in shop2.buyables: if buyable.equals(buyable2): break else: return False if len(self.sellables) != len(shop2.sellables): return False for sellable in self.sellables: for sellable2 in shop2.sellables: if sellable.equals(sellable2): break else: return False if self.entity_buy_message != shop2.entity_buy_message: return False if self.others_buy_message != shop2.others_buy_message: return False if self.target_buy_message != shop2.target_buy_message: return False if self.dealer_buy_message != shop2.dealer_buy_message: return False if self.entity_cannot_afford_message != shop2.entity_cannot_afford_message: return False if self.others_cannot_afford_message != shop2.others_cannot_afford_message: return False if self.target_cannot_afford_message != shop2.target_cannot_afford_message: return False if self.dealer_cannot_afford_message != shop2.dealer_cannot_afford_message: return False if self.entity_sell_message != shop2.entity_sell_message: return False if self.others_sell_message != shop2.others_sell_message: return False if self.target_sell_message != shop2.target_sell_message: return False if self.dealer_sell_message != shop2.dealer_sell_message: return False if self.entity_offer_message != shop2.entity_offer_message: return False if self.others_offer_message != shop2.others_offer_message: return False if self.target_offer_message != shop2.target_offer_message: return False if self.dealer_offer_message != shop2.dealer_offer_message: return False if self.entity_uninterested_message != shop2.entity_uninterested_message: return False if self.others_uninterested_message != shop2.others_uninterested_message: return False if self.target_uninterested_message != shop2.target_uninterested_message: return False if self.dealer_uninterested_message != shop2.dealer_uninterested_message: return False return True #- Fine Metodo - def in_location(self, dealer): """ Controlla se possa interagire nel luogo in cui si trova. """ if not dealer: log.bug("dealer non è un parametro valido: %s" % dealer) return 0 # --------------------------------------------------------------------- if not self.proto_locations: return True if dealer.location.prototype in self.proto_locations: return True return False #- Fine Metodo - def get_storage(self, dealer): """ Ritorna il luogo in cui vengono inserite le cose da vendere, il magazzino. """ if not dealer: log.bug("dealer non è un parametro valido: %s" % dealer) return 0 # --------------------------------------------------------------------- if not self.proto_storages: return dealer # Da priorità al dealer e alla locazione nel qual caso vi siano # più storages tutti nella stessa stanza if dealer.prototype in self.proto_storages: return dealer if dealer.location.prototype in self.proto_storages: return dealer.location for en in dealer.iter_contains(): if en.IS_PLAYER: continue if en.prototype in self.proto_storages: return en for en in dealer.location.iter_contains(): if en.IS_PLAYER: continue if en.prototype in self.proto_storages: return en # Adesso invece cerca tra le stanze dell'area for room in dealer.location.area.rooms.values(): if room.prototype in self.proto_storages: return room return None #- Fine Metodo - def get_buyable(self, purchase): """ Ritorna la struttura di buyable relativa alla mercanzia passata. """ if not purchase: log.bug("purchase non è un parametro valido: %s" % purchase) return None # --------------------------------------------------------------------- for buyable in self.buyables: if purchase.prototype == buyable.proto_entity: return buyable return None #- Fine Metodo - def get_sellable(self, target): """ Ritorna il sellable del negoziante relativo all'entità passata, se possibile. """ if not self.sellables: return None # Se viene impostato esplicitamente ENTITYPE.NONE allora accetta di # far vendere qualsiasi cosa al negoziante for sellable in self.sellables: if sellable.entitype == ENTITYPE.NONE: return sellable for sellable in self.sellables: if sellable.entitype == target.entitype: return sellable return None #- Fine Metodo - def storage_is_empty(self, storage): """ Ritorna verso se il magazzino passato non ha mercanzia da vendere. """ if not storage: log.bug("storage non è un parametro valido: %r" % storage) return False # --------------------------------------------------------------------- for en in storage.iter_contains(): for buyable in self.buyables: if en.prototype == buyable.proto_entity: return False return True #- Fine Metodo - def add_buyable(self, dealer, target, sellable, quantity): """ Aggiunge una nuova entità comprabile al negoziante ma senza che questa abbia futura possibilità di aggiornare il proprio magazzino. """ if not dealer: log.bug("dealer non è un parametro valido: %s" % dealer) return if not target: log.bug("target non è un parametro valido: %s" % target) return if not sellable: log.bug("sellable non è un parametro valido: %s" % sellable) return if quantity <= 0: log.bug("quantity non può essere minore o uguale a 0: %d" % quantity) return # --------------------------------------------------------------------- # Se non c'è nessun magazzino in cui inserire l'entità allora esce storage = self.get_storage(dealer) if not storage: target.extract() return if not storage.IS_ROOM and not storage.can_carry_target(target, quantity=quantity): target.extract() return # Crea un buyable e lo aggiunge alla lista delle mercanzie del negozio buyable = Buyable() buyable.proto_entity = target.prototype buyable.percent = sellable.buyback_percent self.buyables.append(buyable) #- Fine Metodo - def send_buy_messages(self, entity, purchase, dealer, verbs, quantity, pretty_price, discount): if not entity: log.bug("entity non è un parametro valido: %r" % entity) return if not purchase: log.bug("purchase non è un parametro valido: %r" % purchase) return if not dealer: log.bug("dealer non è un parametro valido: %r" % dealer) return if not verbs: log.bug("verbs non è un parametro valido: %r" % verbs) return if quantity < 0: log.bug("quantity non è un parametro valido: %d" % quantity) return if not pretty_price: log.bug("pretty_price non è un parametro valido: %r" % pretty_price) return if discount < 0: log.bug("discount non è un parametro valido: %d" % discount) return # --------------------------------------------------------------------- is_dispenser = SHOP.DISPENSER in dealer.shop.types discount_descr = "" if discount > 0: discount_descr = " scontato" quantity_descr = "" if quantity > 1: quantity_descr = "%d " % quantity if self.entity_buy_message: message = self.entity_buy_message if "%verb" in message: if message.startswith("%verb"): message = message.replace("%verb", color_first_upper(verbs["you"])) else: message = message.replace("%verb", verbs["you"].lower()) if "%quantity" in message: message = message.replace("%quantity", quantity_descr) if "%price" in message: message = message.replace("%price", pretty_price) else: if is_dispenser: message = "%s %s$N da $a inserendovi %s." % (color_first_upper(verbs["you"]), quantity_descr, pretty_price) else: message = "%s %s$N da $a pagandol$O %s%s." % (color_first_upper(verbs["you"]), quantity_descr, pretty_price, discount_descr) entity.act(message, TO.ENTITY, purchase, dealer) if self.others_buy_message: message = self.others_buy_message if "%verb" in message: if message.startswith("%verb"): message = message.replace("%verb", color_first_upper(verbs["it"])) else: message = message.replace("%verb", verbs["it"].lower()) if "%quantity" in message: message = message.replace("%quantity", quantity_descr) if "%price" in message: message = message.replace("%price", pretty_price) else: if is_dispenser: message = "$n %s %s$N da $a inserendovi %s." % (verbs["it"], quantity_descr, pretty_price) else: message = "$n %s %s$N da $a pagandol$O %s%s." % (verbs["it"], quantity_descr, pretty_price, discount_descr) entity.act(message, TO.OTHERS, purchase, dealer) if self.target_buy_message: message = self.target_buy_message if "%verb" in message: if message.startswith("%verb"): message = message.replace("%verb", color_first_upper(verbs["it"])) else: message = message.replace("%verb", verbs["it"].lower()) if "%quantity" in message: message = message.replace("%quantity", quantity_descr) if "%price" in message: message = message.replace("%price", pretty_price) else: if is_dispenser: message = "$n ti %s da $a inserendovi %s." % (verbs["it"], pretty_price) else: message = "$n ti %s da $a pagandoti %s%s." % (verbs["it"], pretty_price, discount_descr) entity.act(message, TO.TARGET, purchase, dealer) if self.dealer_buy_message: message = self.dealer_buy_message if "%verb" in message: if message.startswith("%verb"): message = message.replace("%verb", color_first_upper(verbs["it"])) else: message = message.replace("%verb", verbs["it"].lower()) if "%quantity" in message: message = message.replace("%quantity", quantity_descr) if "%price" in message: message = message.replace("%price", pretty_price) else: if is_dispenser: message = "$n ti %s %s$N inserendoti %s." % (verbs["it"], quantity_descr, pretty_price) else: message = "$n ti %s %s$N pagandol$O %s%s." % (verbs["it"], quantity_descr, pretty_price, discount_descr) entity.act(message, TO.TARGET, dealer, purchase) #- Fine Metodo - def send_cannot_afford_messages(self, entity, purchase, dealer, verbs, quantity, pretty_price): if not entity: log.bug("entity non è un parametro valido: %r" % entity) return if not purchase: log.bug("purchase non è un parametro valido: %r" % purchase) return if not dealer: log.bug("dealer non è un parametro valido: %r" % dealer) return if not verbs: log.bug("verbs non è un parametro valido: %r" % verbs) return if quantity < 0: log.bug("quantity non è un parametro valido: %d" % quantity) return if not pretty_price: log.bug("pretty_price non è un parametro valido: %r" % pretty_price) return # --------------------------------------------------------------------- quantity_descr = "" if quantity > 1: quantity_descr = "%d " % quantity if self.entity_cannot_afford_message: message = self.entity_buy_message if "%verb" in message: if message.startswith("%verb"): message = message.replace("%verb", color_first_upper(verbs["infinitive"])) else: message = message.replace("%verb", verbs["infinitive"].lower()) if "%quantity" in message: message = message.replace("%quantity", quantity_descr) if "%price" in message: message = message.replace("%price", pretty_price) else: message = "Non hai abbastanza soldi per poter %s %s$N da $a: costa %s." % (verbs["infinitive"], quantity_descr, pretty_price) entity.act(message, TO.ENTITY, purchase, dealer) if self.others_cannot_afford_message: message = self.others_buy_message if "%verb" in message: if message.startswith("%verb"): message = message.replace("%verb", color_first_upper(verbs["infinitive"])) else: message = message.replace("%verb", verbs["infinitive"].lower()) if "%quantity" in message: message = message.replace("%quantity", quantity_descr) if "%price" in message: message = message.replace("%price", pretty_price) else: message = "$n non sembra avere abbastanza soldi per poter %s %s$N." % (verbs["infinitive"], quantity_descr) entity.act(message, TO.OTHERS, purchase, dealer) if self.target_cannot_afford_message: message = self.target_buy_message if "%verb" in message: if message.startswith("%verb"): message = message.replace("%verb", color_first_upper(verbs["infinitive"])) else: message = message.replace("%verb", verbs["infinitive"].lower()) if "%quantity" in message: message = message.replace("%quantity", quantity_descr) if "%price" in message: message = message.replace("%price", pretty_price) else: message = "$n non ha abbastanza soldi per poterti %s da $a." % verbs["infinitive"] entity.act(message, TO.TARGET, purchase, dealer) if self.dealer_cannot_afford_message: message = self.dealer_buy_message if "%verb" in message: if message.startswith("%verb"): message = message.replace("%verb", color_first_upper(verbs["infinitive"])) else: message = message.replace("%verb", verbs["infinitive"].lower()) if "%quantity" in message: message = message.replace("%quantity", quantity_descr) if "%price" in message: message = message.replace("%price", pretty_price) else: message = "$n non ha abbastanza soldi per poter %s %s$a da te." % (verbs["infinitive"], quantity_descr) entity.act(message, TO.TARGET, dealer, purchase) #- Fine Metodo - def send_sell_messages(self, entity, target, dealer, verbs, quantity, pretty_price): if not entity: log.bug("entity non è un parametro valido: %r", entity) return if not target: log.bug("target non è un parametro valido: %r", target) return if not dealer: log.bug("dealer non è un parametro valido: %r", dealer) return if not verbs: log.bug("verbs non è un parametro valido: %r", verbs) return if quantity < 0: log.bug("quantity non è un parametro valido: %d" % quantity) return if not pretty_price: log.bug("pretty_price non è un parametro valido: %r", pretty_price) return # --------------------------------------------------------------------- quantity_descr = "" if quantity > 1: quantity_descr = "%d " % quantity if self.entity_sell_message: message = self.entity_sell_message if "%verb" in message: if message.startswith("%verb"): message = message.replace("%verb", color_first_upper(verbs["you"])) else: message = message.replace("%verb", verbs["you"].lower()) if "%quantity" in message: message = message.replace("%quantity", quantity_descr) if "%price" in message: message = message.replace("%price", pretty_price) elif quantity <= 1: message = "%s $a a $N per %s." % (color_first_upper(verbs["you"]), pretty_price) else: message = "%s $N, in %d unità, a $a per %s." % (color_first_upper(verbs["you"])) entity.act(message, TO.ENTITY, target, dealer) if self.others_sell_message: message = self.entity_sell_message if "%verb" in message: if message.startswith("%verb"): message = message.replace("%verb", color_first_upper(verbs["it"])) else: message = message.replace("%verb", verbs["it"].lower()) if "%quantity" in message: message = message.replace("%quantity", quantity_descr) if "%price" in message: message = message.replace("%price", pretty_price) elif quantity <= 1: message = "$n %s $N a $a per %s." % (verbs["it"], pretty_price) else: message = "$n %s $N, in %d unità, a $a per %s." % (verbs["it"], quantity, pretty_price) entity.act(message, TO.OTHERS, target, dealer) if target != entity: if self.target_sell_message: message = self.entity_sell_message if "%verb" in message: if message.startswith("%verb"): message = message.replace("%verb", color_first_upper(verbs["it"])) else: message = message.replace("%verb", verbs["it"].lower()) if "%quantity" in message: message = message.replace("%quantity", quantity_descr) if "%price" in message: message = message.replace("%price", pretty_price) elif quantity <= 1: message = "$n ti %s $N per %s." % (verbs["it"], pretty_price) else: message = "$n ti %s $N, in %d unità, per %s." % (verbs["it"], quantity, pretty_price) entity.act(message, TO.TARGET, target, dealer) if dealer != entity: if self.dealer_sell_message: message = self.entity_sell_message if "%verb" in message: if message.startswith("%verb"): message = message.replace("%verb", color_first_upper(verbs["it"])) else: message = message.replace("%verb", verbs["it"].lower()) if "%quantity" in message: message = message.replace("%quantity", quantity_descr) if "%price" in message: message = message.replace("%price", pretty_price) elif quantity <= 1: message = "$n ti %s a $N per %s." % (verbs["it"], pretty_price) else: message = "$n ti %s a $N, in %d unità, per %s." % (verbs["it"], quantity, pretty_price) entity.act(message, TO.TARGET, dealer, target) #- Fine Metodo - def send_offer_messages(self, entity, target, dealer, verbs, quantity, pretty_price): if not entity: log.bug("entity non è un parametro valido: %r", entity) return if not target: log.bug("target non è un parametro valido: %r", target) return if not dealer: log.bug("dealer non è un parametro valido: %r", dealer) return if not verbs: log.bug("verbs non è un parametro valido: %r", verbs) return if quantity < 0: log.bug("quantity non è un parametro valido: %d" % quantity) return if not pretty_price: log.bug("pretty_price non è un parametro valido: %r", pretty_price) return # --------------------------------------------------------------------- quantity_descr = "" if quantity > 1: quantity_descr = "%d " % quantity if self.entity_offer_message: message = self.entity_offer_message if "%verb" in message: if message.startswith("%verb"): message = message.replace("%verb", color_first_upper(verbs["it"])) else: message = message.replace("%verb", verbs["it"].lower()) if "%quantity" in message: message = message.replace("%quantity", quantity_descr) if "%price" in message: message = message.replace("%price", pretty_price) elif quantity <= 1: message = "$N ti %s %s per $N." % (verbs["it"], pretty_price) else: message = "$N ti %s %s per %d unità di $N." % (verbs["it"], pretty_price, quantity) entity.act(message, TO.ENTITY, target, dealer) if self.others_offer_message: message = self.entity_offer_message if "%verb" in message: if message.startswith("%verb"): message = message.replace("%verb", color_first_upper(verbs["it"])) else: message = message.replace("%verb", verbs["it"].lower()) if "%quantity" in message: message = message.replace("%quantity", quantity_descr) if "%price" in message: message = message.replace("%price", pretty_price) elif quantity <= 1: message = "$N %s %s a $n per $N." % (verbs["it"], pretty_price) else: message = "$N %s %s a $n per %d unità di $N." % (verbs["it"], pretty_price, quantity) entity.act(message, TO.OTHERS, target, dealer) if target != entity: if self.target_offer_message: message = self.entity_offer_message if "%verb" in message: if message.startswith("%verb"): message = message.replace("%verb", color_first_upper(verbs["you"])) else: message = message.replace("%verb", verbs["you"].lower()) if "%quantity" in message: message = message.replace("%quantity", quantity_descr) if "%price" in message: message = message.replace("%price", pretty_price) elif quantity <= 1: message = "%s a $n %s per $N." % (color_first_upper(verbs["you"]), pretty_price) else: message = "%s a $n %s per %d unità di $N." % (color_first_upper(verbs["you"], quantity), pretty_price) entity.act(message, TO.TARGET, target, dealer) if dealer != entity: if self.dealer_offer_message: message = self.entity_offer_message if "%verb" in message: if message.startswith("%verb"): message = message.replace("%verb", color_first_upper(verbs["it"])) else: message = message.replace("%verb", verbs["it"].lower()) if "%quantity" in message: message = message.replace("%quantity", quantity_descr) if "%price" in message: message = message.replace("%price", pretty_price) elif quantity <= 1: message = "$a %s a $n %s per te." % (verbs["it"], pretty_price) else: message = "$a %s a $n %s per %d unità di te." % (verbs["it"], pretty_price, quantity) entity.act(message, TO.TARGET, dealer, target) #- Fine Metodo - def send_uninterested_messages(self, entity, target, dealer): if not entity: log.bug("entity non è un parametro valido: %r", entity) return if not target: log.bug("target non è un parametro valido: %r", target) return if not dealer: log.bug("dealer non è un parametro valido: %r", dealer) return # --------------------------------------------------------------------- if self.entity_uninterested_message: entity.act(self.entity_uninterested_message, TO.ENTITY, target, dealer) else: entity.act("$N non è una tipologia che a $a possa interessare.", TO.ENTITY, target, dealer) if self.others_uninterested_message: entity.act(self.others_uninterested_message, TO.OTHERS, target, dealer) else: entity.act("$N di $n non è una tipologia che a $a possa interessare.", TO.OTHERS, target, dealer) if self.target_uninterested_message: entity.act(self.target_uninterested_message, TO.TARGET, target, dealer) else: entity.act("Non sei una tipologia che a $a possa interessare.", TO.TARGET, target, dealer) if self.dealer_uninterested_message: entity.act(self.dealer_uninterested_message, TO.TARGET, dealer, target) else: entity.act("Non sei interessato a $a di $n, non è simile alla tua mercanzia.", TO.TARGET, dealer, target)
class ExtraDescription(MIMLParserSuperclass): """ Gestisce una descrizione extra. """ PRIMARY_KEY = "keywords" VOLATILES = [] MULTILINES = [ "comment", "descr", "descr_night", "descr_hearing", "descr_hearing_night", "descr_smell", "descr_smell_night", "descr_touch", "descr_touch_night", "descr_taste", "descr_taste_night", "descr_sixth", "descr_sixth_night" ] SCHEMA = {} REFERENCES = {"author": ["players", "proto_mobs", "proto_items"]} WEAKREFS = {} IS_AREA = False IS_DESCR = True IS_ROOM = False IS_EXIT = False IS_WALL = False IS_ACTOR = False IS_MOB = False IS_ITEM = False IS_PLAYER = False IS_EXTRA = True IS_PROTO = False def __init__(self, keywords=""): if not keywords and keywords != "": log.bug("keywords passato non è una stringa valida: %s" % keywords) return # --------------------------------------------------------------------- self.comment = "" # Eventuale commento alle extra self.keywords = keywords # Parole chiave con cui accedere all'extra self.descr = "" # Descrizione diurna self.descr_night = "" # Descrizione notturna self.descr_hearing = "" # Descrizione uditiva self.descr_hearing_night = "" # Descrizione uditiva notturna self.descr_smell = "" # Descrizione odorosa self.descr_smell_night = "" # Descrizione odorosa notturna self.descr_touch = "" # Descrizione tattile self.descr_touch_night = "" # Descrizione tattile notturna self.descr_taste = "" # Descrizione del sapore self.descr_taste_night = "" # Descrizione del sapore notturna self.descr_sixth = "" # Descrizione del sesto senso self.descr_sixth_night = "" # Descrizione del sesto senso notturna self.flags = Flags( EXTRA.NONE ) # Flag per indicare la tipologia di extra e altre proprietà particolari self.author = None # Entità che ha scritto, o disegnato, l'extra #- Fine Inizializzazione - def get_error_message(self): # E' possibile evitare di inserire sia la descrizione notturna che # quella diurna di ognuno dei 6 sensi, (TD) cmq almeno una descr ci # deve essere msg = "" if not self.keywords: msg = "keywords di extra non valida" # Non bisogna controllare neppure la descr perché potrebbe essere # EXTRA.NIGHT_ONLY (TD) fare un check migliore elif self.flags.get_error_message(EXTRA, "flags") != "": msg = self.flags.get_error_message(EXTRA, "flags") return msg #- Fine Funzione - def copy(self, to_obj=None, avoid_volatiles=False): if not to_obj: to_obj = ExtraDescription() copy_existing_attributes(self, to_obj, avoid_volatiles=avoid_volatiles) return to_obj #- Fine Funzione - def equals(self, extra2): if not extra2: return False items1 = self.__dict__.items() items2 = extra2.__dict__.items() if len(items1) != len(items2): return False for attr, value in items1: if getattr(extra2, attr) != value: return False return True #- Fine Metodo - # ------------------------------------------------------------------------- def get_descr(self, type="", looker=None, parent=None): """ Ritorna la descrizione dell'extra. """ if type: type = "_" + type if calendar.is_night(): descr_night = getattr(self, "descr%s_night" % type) if descr_night: return put_final_dot(color_first_upper(descr_night)) elif EXTRA.DAY_ONLY in self.flags: return "" # Non c'è bisogno di implementare la EXTRA.DAY_ONLY perché # concettualmente già funziona così, l'ho aggiunta perché i builder # si trovano meglio a inserirla esplicitamente in alcuni casi descr = getattr(self, "descr%s" % type) if MIML_SEPARATOR in descr: if parent: descr = parent.parse_miml(descr, looker) else: log.bug( "Anche se il parametro è opzionale è inteso come dovuto: %r" % parent) if descr: return put_final_dot(color_first_upper(descr)) else: # Può accadere quando il type è una stringa indicante un senso # differente da quello della vista return ""
class Container(OpenableGenericType): PRIMARY_KEY = "" VOLATILES = [] MULTILINES = ["comment"] SCHEMA = {"max_weight": ("", "weight")} REFERENCES = {} WEAKREFS = {} CLOSED_FLAG = CONTAINER.CLOSED SECRET_FLAG = CONTAINER.SECRET def __init__(self): super(Container, self).__init__() self.flags = Flags( CONTAINER.NONE ) # Flag speciali di contenitore, sono praticamente uguali a quelle della porta self.max_weight = 0 # Massimo peso in grammi riempibile #- Fine Inizializzazione - def get_error_message(self, entity): msg = super(Container, self).get_error_message(entity) if msg: return msg elif self.flags.get_error_message(CONTAINER, "flags") != "": return self.flags.get_error_message(CONTAINER, "flags") # Viene accettato il valore zero per fare degli oggetti che sembrano # contenitori ma che non possono contenere nulla elif self.max_weight < 0: return "max_weight è minore di 0: %d" % self.max_weight return "" #- Fine Metodo - def copy(self, to_obj=None, avoid_volatiles=False): if not to_obj: to_obj = Container() copy_existing_attributes(self, to_obj, avoid_volatiles=avoid_volatiles) return to_obj #- Fine Metodo - def equals(self, container2): if not container2: return False if not super(Container, self).equals(container2): return False if self.flags != container2.flags: return False if self.max_weight != container2.max_weight: return False return True #- Fine Metodo - # ------------------------------------------------------------------------- def get_status(self, sex, looker=None): status = "" if CONTAINER.CLOSED in self.flags: # Se il contenitore è segreto non visualizza lo stato di aperto o chiuso if CONTAINER.SECRET not in self.flags: if sex == SEX.FEMALE: status += " chiusa" else: status += " chiuso" else: if sex == SEX.FEMALE: status += " aperta" else: status += " aperto" if looker and looker.trust >= TRUST.MASTER and CONTAINER.SECRET in self.flags: status += " (secret)" return status
class Door(OpenableGenericType): #PRIMARY_KEY = "" #VOLATILES = [] #MULTILINES = [] #SCHEMA = {} #REFERENCES = {} #WEAKREFS = {} CLOSED_FLAG = DOOR.CLOSED SECRET_FLAG = DOOR.SECRET def __init__(self): super(Door, self).__init__() self.flags = Flags(DOOR.NONE) self.bash_difficulty = 0 # Livello di difficoltà per il bash self.pass_door_difficulty = 0 # Livello di difficoltà per il pass door self.destination_open_message = "" # Messaggio d'apertura stile act a tutti gli altri al di là della porta self.destination_close_message = "" # Messaggio di chiusura stile act a tutti gli altri al di là della porta self.destination_lock_message = "" # Messaggio di blocco(key) stile act a tutti gli altri al di là della porta self.destination_unlock_message = "" # Messaggio di sblocco(key) stile act a tutti gli altri al di là della porta self.destination_bolt_message = "" # Messaggio di sprangata(bolt) stile act a tutti gli altri al di là della porta self.destination_unbolt_message = "" # Messaggio di desprangata(bolt) stile act a tutti gli altri al di là della porta self.reset_open_message = "" # Messaggio di apertura di una porta tramite un reset self.reset_close_message = "" # Messaggio di chiusura di una porta tramite un reset self.open_icon = "" # Icona rappresentante la porta aperta di giorno self.open_icon_night = "" # Icona rappresentante la porta aperta di notte #- Fine Inizializzazione - def get_error_message(self, entity): msg = super(Door, self).get_error_message(entity) if msg: return msg elif self.flags.get_error_message(DOOR, "flags") != "": return self.flags.get_error_message(DOOR, "flags") elif self.bash_difficulty < 0: return "bash_difficulty non può essere negativo: %s" % self.bash_difficulty elif self.pass_door_difficulty < 0: return "pass_door_difficulty non può essere negativo: %s" % self.pass_door_difficulty # L'esistenza dei diversi messaggi è slegata tra loro, ovvero possono # essere inizializzati tutti come solo uno di loro o, naturalmente, # nessuno, quindi non vi è bisogno di controllarli return "" #- Fine Metodo - def copy(self, to_obj=None, avoid_volatiles=False): if not to_obj: to_obj = Door() copy_existing_attributes(self, to_obj, avoid_volatiles=avoid_volatiles) return to_obj #- Fine Metodo - def equals(self, door2): if not door2: return False if not super(Door, self).equals(door2): return False if self.flags != door2.flags: return False if self.bash_difficulty != door2.bash_difficulty: return False if self.pass_door_difficulty != door2.pass_door_difficulty: return False if self.destination_open_message != door2.destination_open_message: return False if self.destination_close_message != door2.destination_close_message: return False if self.destination_lock_message != door2.destination_lock_message: return False if self.destination_unlock_message != door2.destination_unlock_message: return False if self.destination_bolt_message != door2.destination_bolt_message: return False if self.destination_unbolt_message != door2.destination_unbolt_message: return False if self.reset_open_message != door2.reset_open_message: return False if self.reset_close_message != door2.reset_close_message: return False if self.open_icon != door2.open_icon: return False if self.open_icon_night != door2.open_icon_night: return False return True #- Fine Metodo - # ------------------------------------------------------------------------- def get_status(self, sex, looker=None): status = "" if DOOR.CLOSED in self.flags: if sex == SEX.FEMALE: status += " chiusa" else: status += " chiuso" else: if sex == SEX.FEMALE: status += " aperta" else: status += " aperto" if looker and looker.trust >= TRUST.MASTER and DOOR.SECRET in self.flags: status += " (secret)" return status #- Fine Metodo - def get_icon(self): icon = "" if calendar.is_night(): icon = self.open_icon_night if not icon: icon = self.open_icon return icon #- Fine Metodo - #--------------------------------------------------------------------------- def send_open_messages(self, entity, target, verbs, direction=None, destination_room=None, target_on_destination=None): if not entity: log.bug("entity non è un parametro valido: %r" % entity) return if not target: log.bug("target non è un parametro valido: %r" % target) return if not verbs: log.bug("verbs non è un parametro valido: %r" % verbs) return False # --------------------------------------------------------------------- super(Door, self).send_open_messages(entity, target, verbs, direction, destination_room, target_on_destination) if destination_room and direction: target = target_on_destination or target if self.destination_open_message: message = self.destination_open_message if "%verb" in message: if message.startswith("%verb"): message = message % color_first_upper(verbs["it"]) else: message = message % verbs["it"].lower() if "%dir" in message: if message.startswith("%dir"): message = message % color_first_upper(direction.to_dir2) else: message = message % direction.to_dir2.lower() else: message = "Qualcuno, dall'altra parte, %s $N %s" % (verbs["it"].lower(), direction.reverse_dir.to_dir2) entity.act(message, TO.OTHERS, target, destination_room, target_on_destination, send_to_location=destination_room) #- Fine Metodo - def send_close_messages(self, entity, target, verbs, direction=None, destination_room=None, target_on_destination=None): if not entity: log.bug("entity non è un parametro valido: %r" % entity) return if not target: log.bug("target non è un parametro valido: %r" % target) return if not verbs: log.bug("verbs non è un parametro valido: %r" % verbs) return False # --------------------------------------------------------------------- super(Door, self).send_close_messages(entity, target, verbs, direction, destination_room, target_on_destination) # Cose riguardanti solo le porte if destination_room and direction: target = target_on_destination or target if self.destination_close_message: message = self.destination_close_message if "%verb" in message: if message.startswith("%verb"): message = message % color_first_upper(verbs["it"]) else: message = message % verbs["it"].lower() if "%dir" in message: if message.startswith("%dir"): message = message % color_first_upper(direction.to_dir2) else: message = message % direction.to_dir2.lower() else: message = "Qualcuno, dall'altra parte, %s $N %s" % (verbs["it"].lower(), direction.reverse_dir.to_dir2) entity.act(message, TO.OTHERS, target, destination_room, target_on_destination, send_to_location=destination_room) #- Fine Metodo - #--------------------------------------------------------------------------- def send_lock_messages(self, entity, target, verbs, direction=None, destination_room=None): if not entity: log.bug("entity non è un parametro valido: %r" % entity) return if not target: log.bug("target non è un parametro valido: %r" % target) return if not verbs: log.bug("verbs non è un parametro valido: %r" % verbs) return False # --------------------------------------------------------------------- super(Door, self).send_lock_messages(entity, target, verbs, direction, destination_room) if destination_room: if self.destination_lock_message: message = self.destination_lock_message if "%verb" in message: if message.startswith("%verb"): message = message % color_first_upper(verbs["it"]) else: message = message % verbs["it"].lower() if "%dir" in message: if message.startswith("%dir"): message = message % color_first_upper(direction.to_dir2) else: message = message % direction.to_dir2.lower() else: message = "Qualcuno, dall'altra parte, %s $N %s" % (verbs["it"].lower(), direction.reverse_dir.to_dir2) entity.act(message, TO.OTHERS, target, destination_room, send_to_location=destination_room) #- Fine Metodo - def send_unlock_messages(self, entity, target, verbs, direction=None, destination_room=None): if not entity: log.bug("entity non è un parametro valido: %r" % entity) return if not target: log.bug("target non è un parametro valido: %r" % target) return if not verbs: log.bug("verbs non è un parametro valido: %r" % verbs) return False # --------------------------------------------------------------------- super(Door, self).send_unlock_messages(entity, target, verbs, direction, destination_room) if destination_room: if self.destination_unlock_message: message = self.destination_unlock_message if "%verb" in message: if message.startswith("%verb"): message = message % color_first_upper(verbs["it"]) else: message = message % verbs["it"].lower() if "%dir" in message: if message.startswith("%dir"): message = message % color_first_upper(direction.to_dir2) else: message = message % direction.to_dir2.lower() else: message = "Qualcuno, dall'altra parte, %s $N %s" % (verbs["it"].lower(), direction.reverse_dir.to_dir2) entity.act(message, TO.OTHERS, target, destination_room, send_to_location=destination_room) #- Fine Metodo - #--------------------------------------------------------------------------- def send_unbolt_messages(self, entity, target, verbs, destination_room=None, direction=None): if not entity: log.bug("entity non è un parametro valido: %r" % entity) return if not target: log.bug("target non è un parametro valido: %r" % target) return if not verbs: log.bug("verbs non è un parametro valido: %r" % verbs) return False # --------------------------------------------------------------------- super(Door, self).send_unbolt_messages(entity, target, verbs, direction, destination_room) if destination_room and direction: if self.destination_unbolt_message: message = self.destination_unbolt_message if "%verb" in message: if message.startswith("%verb"): message = message % color_first_upper(verbs["it"]) else: message = message % verbs["it"].lower() if "%dir" in message: if message.startswith("%dir"): message = message % color_first_upper(direction.to_dir2) else: message = message % direction.to_dir2.lower() else: message = "Qualcuno, dall'altra parte, %s $N %s" % (verbs["it"].lower(), direction.reverse_dir.to_dir2) entity.act(message, TO.OTHERS, target, destination_room, send_to_location=destination_room) #- Fine Metodo - def send_bolt_messages(self, entity, target, verbs, direction=None, destination_room=None): if not entity: log.bug("entity non è un parametro valido: %r" % entity) return if not target: log.bug("target non è un parametro valido: %r" % target) return if not verbs: log.bug("verbs non è un parametro valido: %r" % verbs) return False # --------------------------------------------------------------------- super(Door, self).send_bolt_messages(entity, target, verbs, direction, destination_room) # Cose riguardanti solo le porte if destination_room and direction: if self.destination_bolt_message: message = self.destination_bolt_message if "%verb" in message: if message.startswith("%verb"): message = message % color_first_upper(verbs["it"]) else: message = message % verbs["it"].lower() if "%dir" in message: if message.startswith("%dir"): message = message % color_first_upper(direction.to_dir2) else: message = message % direction.to_dir2.lower() else: message = "Qualcuno, dall'altra parte, %s $N %s" % (verbs["it"].lower(), direction.reverse_dir.to_dir2) entity.act(message, TO.OTHERS, target, destination_room, send_to_location=destination_room)
class Shop(object): """ Classe che gestisce tutte le informazioni di un negoziante. """ PRIMARY_KEY = "" VOLATILES = [] MULTILINES = ["comment"] SCHEMA = { "buyables": ("src.shop", "Buyable"), "sellables": ("src.shop", "Sellable") } REFERENCES = { "proto_locations": ["proto_rooms", "proto_mobs", "proto_items"], "proto_storages": ["proto_rooms", "proto_mobs", "proto_items"] } WEAKREFS = {} def __init__(self): self.comment = "" # Commento relativo la struttura self.types = Flags( SHOP.NONE ) # Tipologia/e di shop, se non impostata viene considerato un negozio qualsiasi self.proto_locations = [ ] # Prototipo delle locazioni in cui l'entità negozierà, se non ne viene indicata nessuna il negoziante è un venditore ambulante self.proto_storages = [ ] # Prototipo delle locazioni da cui l'entità prenderà la mercanzia da vendere self.buyables = [ ] # Entità comprabili da parte di un giocatore e relative informazioni di magazzino self.sellables = [ ] # Tipologie di entità vendibili da parte del giocatore, se non viene impostata allora si potrà vendere qualsiasi cosa self.entity_buy_message = "" # Messaggi di act relativi al comando buy avvenuto, sono messaggi facoltativi self.others_buy_message = "" self.target_buy_message = "" self.dealer_buy_message = "" self.entity_cannot_afford_message = "" # Messaggi di act relativi al comando buy se non si hanno i soldi necessari, sono messaggi facoltativi self.others_cannot_afford_message = "" self.target_cannot_afford_message = "" self.dealer_cannot_afford_message = "" self.entity_sell_message = "" # Messaggi di act relativi al comando sell avvenuto, sono messaggi facoltativi self.others_sell_message = "" self.target_sell_message = "" self.dealer_sell_message = "" self.entity_offer_message = "" # Messaggi di act relativi al comando offer avvenuto, sono messaggi facoltativi self.others_offer_message = "" self.target_offer_message = "" self.dealer_offer_message = "" self.entity_uninterested_message = "" # Messaggi di act relativi al disinteresse del mercante per un determinata entità offerta o venduta, sono messaggi facoltativi self.others_uninterested_message = "" self.target_uninterested_message = "" self.dealer_uninterested_message = "" #- Fine Inizializzazione - def get_error_message(self): if self.types.get_error_message(SHOP, "types") != "": return self.types.get_error_message(SHOP, "types") elif self.get_error_message_buyables() != "": return self.get_error_message_buyables() elif self.get_error_message_sellables() != "": return self.get_error_message_sellables() return "" #- Fine Metodo - def get_error_message_buyables(self): if not self.buyables: return "buyables non è stata impostata" for buyable in self.buyables: if buyable.get_error_message() != "": return buyable.get_error_message() return "" #- Fine Metodo - def get_error_message_sellables(self): for sellable in self.sellables: if sellable.entitype == ENTITYPE.NONE: if len(self.sellables) > 1: return "Quando si esplicita il valore di ENTITYPE.NONE in un sellable deve essere il solo e unico." for sellable in self.sellables: if sellable.get_error_message() != "": return sellable.get_error_message() return "" #- Fine Metodo - def copy(self, to_obj=None, avoid_volatiles=False): if not to_obj: to_obj = Shop() copy_existing_attributes(self, to_obj, avoid_volatiles=avoid_volatiles) return to_obj #- Fine Metodo - def equals(self, shop2): if not shop2: return False if self.comment != shop2.comment: return False if self.types != shop2.types: return False for location in self.proto_locations: for location2 in shop2.proto_locations: if location == location2: break else: return False for storage in self.proto_storages: for storage2 in shop2.proto_storages: if storage == storage2: break else: return False if len(self.buyables) != len(shop2.buyables): return False for buyable in self.buyables: for buyable2 in shop2.buyables: if buyable.equals(buyable2): break else: return False if len(self.sellables) != len(shop2.sellables): return False for sellable in self.sellables: for sellable2 in shop2.sellables: if sellable.equals(sellable2): break else: return False if self.entity_buy_message != shop2.entity_buy_message: return False if self.others_buy_message != shop2.others_buy_message: return False if self.target_buy_message != shop2.target_buy_message: return False if self.dealer_buy_message != shop2.dealer_buy_message: return False if self.entity_cannot_afford_message != shop2.entity_cannot_afford_message: return False if self.others_cannot_afford_message != shop2.others_cannot_afford_message: return False if self.target_cannot_afford_message != shop2.target_cannot_afford_message: return False if self.dealer_cannot_afford_message != shop2.dealer_cannot_afford_message: return False if self.entity_sell_message != shop2.entity_sell_message: return False if self.others_sell_message != shop2.others_sell_message: return False if self.target_sell_message != shop2.target_sell_message: return False if self.dealer_sell_message != shop2.dealer_sell_message: return False if self.entity_offer_message != shop2.entity_offer_message: return False if self.others_offer_message != shop2.others_offer_message: return False if self.target_offer_message != shop2.target_offer_message: return False if self.dealer_offer_message != shop2.dealer_offer_message: return False if self.entity_uninterested_message != shop2.entity_uninterested_message: return False if self.others_uninterested_message != shop2.others_uninterested_message: return False if self.target_uninterested_message != shop2.target_uninterested_message: return False if self.dealer_uninterested_message != shop2.dealer_uninterested_message: return False return True #- Fine Metodo - def in_location(self, dealer): """ Controlla se possa interagire nel luogo in cui si trova. """ if not dealer: log.bug("dealer non è un parametro valido: %s" % dealer) return 0 # --------------------------------------------------------------------- if not self.proto_locations: return True if dealer.location.prototype in self.proto_locations: return True return False #- Fine Metodo - def get_storage(self, dealer): """ Ritorna il luogo in cui vengono inserite le cose da vendere, il magazzino. """ if not dealer: log.bug("dealer non è un parametro valido: %s" % dealer) return 0 # --------------------------------------------------------------------- if not self.proto_storages: return dealer # Da priorità al dealer e alla locazione nel qual caso vi siano # più storages tutti nella stessa stanza if dealer.prototype in self.proto_storages: return dealer if dealer.location.prototype in self.proto_storages: return dealer.location for en in dealer.iter_contains(): if en.IS_PLAYER: continue if en.prototype in self.proto_storages: return en for en in dealer.location.iter_contains(): if en.IS_PLAYER: continue if en.prototype in self.proto_storages: return en # Adesso invece cerca tra le stanze dell'area for room in dealer.location.area.rooms.values(): if room.prototype in self.proto_storages: return room return None #- Fine Metodo - def get_buyable(self, purchase): """ Ritorna la struttura di buyable relativa alla mercanzia passata. """ if not purchase: log.bug("purchase non è un parametro valido: %s" % purchase) return None # --------------------------------------------------------------------- for buyable in self.buyables: if purchase.prototype == buyable.proto_entity: return buyable return None #- Fine Metodo - def get_sellable(self, target): """ Ritorna il sellable del negoziante relativo all'entità passata, se possibile. """ if not self.sellables: return None # Se viene impostato esplicitamente ENTITYPE.NONE allora accetta di # far vendere qualsiasi cosa al negoziante for sellable in self.sellables: if sellable.entitype == ENTITYPE.NONE: return sellable for sellable in self.sellables: if sellable.entitype == target.entitype: return sellable return None #- Fine Metodo - def storage_is_empty(self, storage): """ Ritorna verso se il magazzino passato non ha mercanzia da vendere. """ if not storage: log.bug("storage non è un parametro valido: %r" % storage) return False # --------------------------------------------------------------------- for en in storage.iter_contains(): for buyable in self.buyables: if en.prototype == buyable.proto_entity: return False return True #- Fine Metodo - def add_buyable(self, dealer, target, sellable, quantity): """ Aggiunge una nuova entità comprabile al negoziante ma senza che questa abbia futura possibilità di aggiornare il proprio magazzino. """ if not dealer: log.bug("dealer non è un parametro valido: %s" % dealer) return if not target: log.bug("target non è un parametro valido: %s" % target) return if not sellable: log.bug("sellable non è un parametro valido: %s" % sellable) return if quantity <= 0: log.bug("quantity non può essere minore o uguale a 0: %d" % quantity) return # --------------------------------------------------------------------- # Se non c'è nessun magazzino in cui inserire l'entità allora esce storage = self.get_storage(dealer) if not storage: target.extract() return if not storage.IS_ROOM and not storage.can_carry_target( target, quantity=quantity): target.extract() return # Crea un buyable e lo aggiunge alla lista delle mercanzie del negozio buyable = Buyable() buyable.proto_entity = target.prototype buyable.percent = sellable.buyback_percent self.buyables.append(buyable) #- Fine Metodo - def send_buy_messages(self, entity, purchase, dealer, verbs, quantity, pretty_price, discount): if not entity: log.bug("entity non è un parametro valido: %r" % entity) return if not purchase: log.bug("purchase non è un parametro valido: %r" % purchase) return if not dealer: log.bug("dealer non è un parametro valido: %r" % dealer) return if not verbs: log.bug("verbs non è un parametro valido: %r" % verbs) return if quantity < 0: log.bug("quantity non è un parametro valido: %d" % quantity) return if not pretty_price: log.bug("pretty_price non è un parametro valido: %r" % pretty_price) return if discount < 0: log.bug("discount non è un parametro valido: %d" % discount) return # --------------------------------------------------------------------- is_dispenser = SHOP.DISPENSER in dealer.shop.types discount_descr = "" if discount > 0: discount_descr = " scontato" quantity_descr = "" if quantity > 1: quantity_descr = "%d " % quantity if self.entity_buy_message: message = self.entity_buy_message if "%verb" in message: if message.startswith("%verb"): message = message.replace("%verb", color_first_upper(verbs["you"])) else: message = message.replace("%verb", verbs["you"].lower()) if "%quantity" in message: message = message.replace("%quantity", quantity_descr) if "%price" in message: message = message.replace("%price", pretty_price) else: if is_dispenser: message = "%s %s$N da $a inserendovi %s." % (color_first_upper( verbs["you"]), quantity_descr, pretty_price) else: message = "%s %s$N da $a pagandol$O %s%s." % ( color_first_upper(verbs["you"]), quantity_descr, pretty_price, discount_descr) entity.act(message, TO.ENTITY, purchase, dealer) if self.others_buy_message: message = self.others_buy_message if "%verb" in message: if message.startswith("%verb"): message = message.replace("%verb", color_first_upper(verbs["it"])) else: message = message.replace("%verb", verbs["it"].lower()) if "%quantity" in message: message = message.replace("%quantity", quantity_descr) if "%price" in message: message = message.replace("%price", pretty_price) else: if is_dispenser: message = "$n %s %s$N da $a inserendovi %s." % ( verbs["it"], quantity_descr, pretty_price) else: message = "$n %s %s$N da $a pagandol$O %s%s." % ( verbs["it"], quantity_descr, pretty_price, discount_descr) entity.act(message, TO.OTHERS, purchase, dealer) if self.target_buy_message: message = self.target_buy_message if "%verb" in message: if message.startswith("%verb"): message = message.replace("%verb", color_first_upper(verbs["it"])) else: message = message.replace("%verb", verbs["it"].lower()) if "%quantity" in message: message = message.replace("%quantity", quantity_descr) if "%price" in message: message = message.replace("%price", pretty_price) else: if is_dispenser: message = "$n ti %s da $a inserendovi %s." % (verbs["it"], pretty_price) else: message = "$n ti %s da $a pagandoti %s%s." % ( verbs["it"], pretty_price, discount_descr) entity.act(message, TO.TARGET, purchase, dealer) if self.dealer_buy_message: message = self.dealer_buy_message if "%verb" in message: if message.startswith("%verb"): message = message.replace("%verb", color_first_upper(verbs["it"])) else: message = message.replace("%verb", verbs["it"].lower()) if "%quantity" in message: message = message.replace("%quantity", quantity_descr) if "%price" in message: message = message.replace("%price", pretty_price) else: if is_dispenser: message = "$n ti %s %s$N inserendoti %s." % ( verbs["it"], quantity_descr, pretty_price) else: message = "$n ti %s %s$N pagandol$O %s%s." % ( verbs["it"], quantity_descr, pretty_price, discount_descr) entity.act(message, TO.TARGET, dealer, purchase) #- Fine Metodo - def send_cannot_afford_messages(self, entity, purchase, dealer, verbs, quantity, pretty_price): if not entity: log.bug("entity non è un parametro valido: %r" % entity) return if not purchase: log.bug("purchase non è un parametro valido: %r" % purchase) return if not dealer: log.bug("dealer non è un parametro valido: %r" % dealer) return if not verbs: log.bug("verbs non è un parametro valido: %r" % verbs) return if quantity < 0: log.bug("quantity non è un parametro valido: %d" % quantity) return if not pretty_price: log.bug("pretty_price non è un parametro valido: %r" % pretty_price) return # --------------------------------------------------------------------- quantity_descr = "" if quantity > 1: quantity_descr = "%d " % quantity if self.entity_cannot_afford_message: message = self.entity_buy_message if "%verb" in message: if message.startswith("%verb"): message = message.replace( "%verb", color_first_upper(verbs["infinitive"])) else: message = message.replace("%verb", verbs["infinitive"].lower()) if "%quantity" in message: message = message.replace("%quantity", quantity_descr) if "%price" in message: message = message.replace("%price", pretty_price) else: message = "Non hai abbastanza soldi per poter %s %s$N da $a: costa %s." % ( verbs["infinitive"], quantity_descr, pretty_price) entity.act(message, TO.ENTITY, purchase, dealer) if self.others_cannot_afford_message: message = self.others_buy_message if "%verb" in message: if message.startswith("%verb"): message = message.replace( "%verb", color_first_upper(verbs["infinitive"])) else: message = message.replace("%verb", verbs["infinitive"].lower()) if "%quantity" in message: message = message.replace("%quantity", quantity_descr) if "%price" in message: message = message.replace("%price", pretty_price) else: message = "$n non sembra avere abbastanza soldi per poter %s %s$N." % ( verbs["infinitive"], quantity_descr) entity.act(message, TO.OTHERS, purchase, dealer) if self.target_cannot_afford_message: message = self.target_buy_message if "%verb" in message: if message.startswith("%verb"): message = message.replace( "%verb", color_first_upper(verbs["infinitive"])) else: message = message.replace("%verb", verbs["infinitive"].lower()) if "%quantity" in message: message = message.replace("%quantity", quantity_descr) if "%price" in message: message = message.replace("%price", pretty_price) else: message = "$n non ha abbastanza soldi per poterti %s da $a." % verbs[ "infinitive"] entity.act(message, TO.TARGET, purchase, dealer) if self.dealer_cannot_afford_message: message = self.dealer_buy_message if "%verb" in message: if message.startswith("%verb"): message = message.replace( "%verb", color_first_upper(verbs["infinitive"])) else: message = message.replace("%verb", verbs["infinitive"].lower()) if "%quantity" in message: message = message.replace("%quantity", quantity_descr) if "%price" in message: message = message.replace("%price", pretty_price) else: message = "$n non ha abbastanza soldi per poter %s %s$a da te." % ( verbs["infinitive"], quantity_descr) entity.act(message, TO.TARGET, dealer, purchase) #- Fine Metodo - def send_sell_messages(self, entity, target, dealer, verbs, quantity, pretty_price): if not entity: log.bug("entity non è un parametro valido: %r", entity) return if not target: log.bug("target non è un parametro valido: %r", target) return if not dealer: log.bug("dealer non è un parametro valido: %r", dealer) return if not verbs: log.bug("verbs non è un parametro valido: %r", verbs) return if quantity < 0: log.bug("quantity non è un parametro valido: %d" % quantity) return if not pretty_price: log.bug("pretty_price non è un parametro valido: %r", pretty_price) return # --------------------------------------------------------------------- quantity_descr = "" if quantity > 1: quantity_descr = "%d " % quantity if self.entity_sell_message: message = self.entity_sell_message if "%verb" in message: if message.startswith("%verb"): message = message.replace("%verb", color_first_upper(verbs["you"])) else: message = message.replace("%verb", verbs["you"].lower()) if "%quantity" in message: message = message.replace("%quantity", quantity_descr) if "%price" in message: message = message.replace("%price", pretty_price) elif quantity <= 1: message = "%s $a a $N per %s." % (color_first_upper( verbs["you"]), pretty_price) else: message = "%s $N, in %d unità, a $a per %s." % (color_first_upper( verbs["you"])) entity.act(message, TO.ENTITY, target, dealer) if self.others_sell_message: message = self.entity_sell_message if "%verb" in message: if message.startswith("%verb"): message = message.replace("%verb", color_first_upper(verbs["it"])) else: message = message.replace("%verb", verbs["it"].lower()) if "%quantity" in message: message = message.replace("%quantity", quantity_descr) if "%price" in message: message = message.replace("%price", pretty_price) elif quantity <= 1: message = "$n %s $N a $a per %s." % (verbs["it"], pretty_price) else: message = "$n %s $N, in %d unità, a $a per %s." % ( verbs["it"], quantity, pretty_price) entity.act(message, TO.OTHERS, target, dealer) if target != entity: if self.target_sell_message: message = self.entity_sell_message if "%verb" in message: if message.startswith("%verb"): message = message.replace( "%verb", color_first_upper(verbs["it"])) else: message = message.replace("%verb", verbs["it"].lower()) if "%quantity" in message: message = message.replace("%quantity", quantity_descr) if "%price" in message: message = message.replace("%price", pretty_price) elif quantity <= 1: message = "$n ti %s $N per %s." % (verbs["it"], pretty_price) else: message = "$n ti %s $N, in %d unità, per %s." % ( verbs["it"], quantity, pretty_price) entity.act(message, TO.TARGET, target, dealer) if dealer != entity: if self.dealer_sell_message: message = self.entity_sell_message if "%verb" in message: if message.startswith("%verb"): message = message.replace( "%verb", color_first_upper(verbs["it"])) else: message = message.replace("%verb", verbs["it"].lower()) if "%quantity" in message: message = message.replace("%quantity", quantity_descr) if "%price" in message: message = message.replace("%price", pretty_price) elif quantity <= 1: message = "$n ti %s a $N per %s." % (verbs["it"], pretty_price) else: message = "$n ti %s a $N, in %d unità, per %s." % ( verbs["it"], quantity, pretty_price) entity.act(message, TO.TARGET, dealer, target) #- Fine Metodo - def send_offer_messages(self, entity, target, dealer, verbs, quantity, pretty_price): if not entity: log.bug("entity non è un parametro valido: %r", entity) return if not target: log.bug("target non è un parametro valido: %r", target) return if not dealer: log.bug("dealer non è un parametro valido: %r", dealer) return if not verbs: log.bug("verbs non è un parametro valido: %r", verbs) return if quantity < 0: log.bug("quantity non è un parametro valido: %d" % quantity) return if not pretty_price: log.bug("pretty_price non è un parametro valido: %r", pretty_price) return # --------------------------------------------------------------------- quantity_descr = "" if quantity > 1: quantity_descr = "%d " % quantity if self.entity_offer_message: message = self.entity_offer_message if "%verb" in message: if message.startswith("%verb"): message = message.replace("%verb", color_first_upper(verbs["it"])) else: message = message.replace("%verb", verbs["it"].lower()) if "%quantity" in message: message = message.replace("%quantity", quantity_descr) if "%price" in message: message = message.replace("%price", pretty_price) elif quantity <= 1: message = "$N ti %s %s per $N." % (verbs["it"], pretty_price) else: message = "$N ti %s %s per %d unità di $N." % ( verbs["it"], pretty_price, quantity) entity.act(message, TO.ENTITY, target, dealer) if self.others_offer_message: message = self.entity_offer_message if "%verb" in message: if message.startswith("%verb"): message = message.replace("%verb", color_first_upper(verbs["it"])) else: message = message.replace("%verb", verbs["it"].lower()) if "%quantity" in message: message = message.replace("%quantity", quantity_descr) if "%price" in message: message = message.replace("%price", pretty_price) elif quantity <= 1: message = "$N %s %s a $n per $N." % (verbs["it"], pretty_price) else: message = "$N %s %s a $n per %d unità di $N." % ( verbs["it"], pretty_price, quantity) entity.act(message, TO.OTHERS, target, dealer) if target != entity: if self.target_offer_message: message = self.entity_offer_message if "%verb" in message: if message.startswith("%verb"): message = message.replace( "%verb", color_first_upper(verbs["you"])) else: message = message.replace("%verb", verbs["you"].lower()) if "%quantity" in message: message = message.replace("%quantity", quantity_descr) if "%price" in message: message = message.replace("%price", pretty_price) elif quantity <= 1: message = "%s a $n %s per $N." % (color_first_upper( verbs["you"]), pretty_price) else: message = "%s a $n %s per %d unità di $N." % ( color_first_upper(verbs["you"], quantity), pretty_price) entity.act(message, TO.TARGET, target, dealer) if dealer != entity: if self.dealer_offer_message: message = self.entity_offer_message if "%verb" in message: if message.startswith("%verb"): message = message.replace( "%verb", color_first_upper(verbs["it"])) else: message = message.replace("%verb", verbs["it"].lower()) if "%quantity" in message: message = message.replace("%quantity", quantity_descr) if "%price" in message: message = message.replace("%price", pretty_price) elif quantity <= 1: message = "$a %s a $n %s per te." % (verbs["it"], pretty_price) else: message = "$a %s a $n %s per %d unità di te." % ( verbs["it"], pretty_price, quantity) entity.act(message, TO.TARGET, dealer, target) #- Fine Metodo - def send_uninterested_messages(self, entity, target, dealer): if not entity: log.bug("entity non è un parametro valido: %r", entity) return if not target: log.bug("target non è un parametro valido: %r", target) return if not dealer: log.bug("dealer non è un parametro valido: %r", dealer) return # --------------------------------------------------------------------- if self.entity_uninterested_message: entity.act(self.entity_uninterested_message, TO.ENTITY, target, dealer) else: entity.act("$N non è una tipologia che a $a possa interessare.", TO.ENTITY, target, dealer) if self.others_uninterested_message: entity.act(self.others_uninterested_message, TO.OTHERS, target, dealer) else: entity.act( "$N di $n non è una tipologia che a $a possa interessare.", TO.OTHERS, target, dealer) if self.target_uninterested_message: entity.act(self.target_uninterested_message, TO.TARGET, target, dealer) else: entity.act("Non sei una tipologia che a $a possa interessare.", TO.TARGET, target, dealer) if self.dealer_uninterested_message: entity.act(self.dealer_uninterested_message, TO.TARGET, dealer, target) else: entity.act( "Non sei interessato a $a di $n, non è simile alla tua mercanzia.", TO.TARGET, dealer, target)
class Plant(object): PRIMARY_KEY = "" VOLATILES = ["deferred_stage"] MULTILINES = ["comment"] SCHEMA = { "temperature": ("", "temperature"), "humidity": ("", "percent"), "contents": ("", "int"), "worse_affects": ("src.affect", "Affect"), "better_affects": ("src.affect", "Affect") } REFERENCES = { "worse_entity": ["proto_items", "proto_mobs"], "normal_entity": ["proto_items", "proto_mobs"], "better_entity": ["proto_items", "proto_mobs"], "dead_entity": ["proto_items", "proto_mobs"] } WEAKREFS = {} def __init__(self): self.comment = "" self.sectors = Flags(SECTOR.NONE) # Settori in cui può essere seminato self.rpg_hours = 1 # Durata in ore rpg prima che questo stadio si attivi self.temperature = 20 # Temperatura media ideale self.humidity = 50 # Percentuale dell'umidità ideale self.contents = { } # Dizionario con valori di codice_entità/quantità per popolare il contenuto dell'entità di questo stadio self.worse_entity = None # Entità peggiore del prossimo stadio di crescita, se in questo stadio non viene curata o curata male self.normal_entity = None # Entità normale del prossimo stadio di crescita, se in questo stadio viene curata normalmente self.better_entity = None # Entità migliore del prossimo stadio di crescita, se in questo stadio viene curata molto bene self.dead_entity = None # Entità morta relativa al prossimo stadio self.worse_affects = [] # Affect che danneggiano la pianta self.better_affects = [] # Affect che migliorano la pianta self.decomposition_rpg_hours = config.purification_rpg_hours # Ore Rpg prima che il contenuto venga decomposto dopo essere caduta dalla pianta self.remaining_life = -1 # Cicli di vita rimanenti alla pianta prima di morire self.worse_counter = 0 # Contatore degli stadi di crescita andati male self.normal_counter = 0 # Contatore degli stadi di crescita andati normalmente self.better_counter = 0 # Contatore degli stadi di crescita andati ottimamente # Volatili self.deferred_stage = None #- Fine Inizializzazione - def get_error_message(self, entity): if self.remaining_life <= 0 and self.remaining_life != -1: return "remaining_life non è un'aspettativa di vita valida, deve essere maggiore di 0 oppure diverso da -1: %d" % self.remaining_life elif self.sectors.get_error_message(SECTOR, "sectors") != "": return self.sectors.get_error_message(SECTOR, "sectors") if self.rpg_hours <= 0: return "rpg_hours non è una durata in ore rpg valida: %d" % self.rpg_hours elif self.get_contents_error_message() != "": return self.get_contents_error_message() elif self.get_affects_error_message("worse_affects") != "": return self.get_affects_error_message("worse_affects") elif self.get_affects_error_message("better_affects") != "": return self.get_affects_error_message("better_affects") return "" #- Fine Metodo - def get_contents_error_message(self): for key, value in self.contents.iteritems(): if not key: return "contents con chiave non valida (%r) per il valore %s" % ( key, value) if int(value) <= 0: return "contents con valore non valido (%d) per la chiave %s" % ( int(value), key) return "" #- Fine Metodo - def get_affects_error_message(self, attr_name): if attr_name not in ("worse_affects", "better_affects"): log.bug("attr_name non è un parametro valido: %s" % attr_name) return "" # --------------------------------------------------------------------- for affect in getattr(self, attr_name): error_message = affect.get_error_message() if error_message != "": return error_message return "" #- Fine Metodo - def copy(self, to_obj=None, avoid_volatiles=False): if not to_obj: to_obj = Plant() copy_existing_attributes(self, to_obj, avoid_volatiles=avoid_volatiles) return to_obj #- Fine Metodo - def equals(self, plant2): if not plant2: return False if self.deferred_stage or plant2.deferred_stage: return False if self.comment != plant2.comment: return False if self.sectors != plant2.sectors: return False if self.rpg_hours != plant2.rpg_hours: return False if self.temperature != plant2.temperature: return False if self.humidity != plant2.humidity: return False if self.worse_entity != plant2.worse_entity: return False if self.normal_entity != plant2.normal_entity: return False if self.better_entity != plant2.better_entity: return False if self.dead_entity != plant2.dead_entity: return False if self.decomposition_rpg_hours != plant2.decomposition_rpg_hours: return False if self.remaining_life != plant2.remaining_life: return False if self.worse_counter != plant2.worse_counter: return False if self.normal_counter != plant2.normal_counter: return False if self.better_counter != plant2.better_counter: return False if len(self.contents) != len(plant2.contents): return False for key, value in self.contents.iteritems(): if key not in plant2.contents: return False if value != plant2.contents[key]: return False if len(self.worse_affects) != len(plant2.worse_affects): return False for affect in self.worse_affects: for affect2 in plant2.worse_affects: if affect == affect2: break else: return False if len(self.better_affects) != len(plant2.better_affects): return False for affect in self.better_affects: for affect2 in plant2.better_affects: if affect == affect2: break else: return False return True #- Fine Metodo - #--------------------------------------------------------------------------- def start_growth(self, entity, type_attr_name): if not entity: log.bug("entity non è parametro valido: %r" % entity) return if type_attr_name not in ("plant_type", "seed_type"): log.bug("type_attr_name non è parametro valido: %r" % type_attr_name) return # --------------------------------------------------------------------- seconds = self.rpg_hours * (config.seconds_in_minute * config.minutes_in_hour) self.deferred_stage = defer(seconds, self.next_stage, entity, type_attr_name) #- Fine Metodo - def stop_growth(self): if self.deferred_stage: self.deferred_stage.pause() self.deferred_stage = None #- Fine Metodo - def next_stage(self, old_entity, type_attr_name): if not old_entity: log.bug("old_entity non è parametro valido: %r" % old_entity) return if type_attr_name not in ("plant_type", "seed_type"): log.bug("type_attr_name non è parametro valido: %r" % type_attr_name) return # --------------------------------------------------------------------- # Pulisce la deferred relativa a questo metodo in qualsiasi caso self.deferred_stage = None entitype = getattr(old_entity, type_attr_name) if not entitype: log.bug("%s dell'entità precedente non valido: %r" % (type_attr_name, entitype)) return # (TD) deve scegliere quale delle tre entità worse, normal o better # in maniera non casuale ma basandosi su effettivi fattori ambientali entitypes = [] for entitype_name in ("worse_entity", "normal_entity", "better_entity"): if getattr(entitype, entitype_name): entitypes.append(entitype_name) if not entitypes: log.bug( "Nessuna tipologia d'entità da utilizzare come prossimo stadio: %r" % entitypes) return choised_attr = random.choice(entitypes) # Se la vita della pianta è terminata e finalmente si trova un'entità # di pianta morta, allora la utilizza if entitype.remaining_life == 0 and entitype.dead_entity: choised_attr = "dead_entity" # --------------------------------------------------------------------- # Crea la nuova pianta a seconda delle scelte di cui sopra choised_entity = getattr(entitype, choised_attr) if not choised_entity: log.bug( "Impossibile continuare con la crescita della pianta da %s per la scelta %s" % (old_entity.code, choised_attr)) return if choised_entity.max_global_quantity > 0 and choised_entity.current_global_quantity >= choised_entity.max_global_quantity: return new_entity = choised_entity.CONSTRUCTOR(choised_entity.code) # Passa alcune caratteristiche della vecchia entità nella nuova # prima di distruggerla if new_entity.plant_type: new_entity.flags += FLAG.GROWING new_entity.plant_type.remaining_life = entitype.remaining_life new_entity.plant_type.worse_counter = entitype.worse_counter new_entity.plant_type.normal_counter = entitype.normal_counter new_entity.plant_type.better_counter = entitype.better_counter quality_attr = choised_attr.split("_")[0] + "_counter" setattr(new_entity.plant_type, quality_attr, getattr(new_entity.plant_type, quality_attr) + 1) # Inserisce la nuova entità in gioco new_entity.inject(old_entity.location) # --------------------------------------------------------------------- # Lista delle entità che cambieranno locazione nel ciclo sottostante # e che vengono passate nel trigger on_next_stage per comodità, vengono # salvati solo le entità frutta, seme e cibo entities = [] # Controlla come deve comportarsi con il contenuto della vecchia entità: # se passarlo alla nuova, oppure distruggerlo, oppure ancora farlo # cadere a terra flower_counter = 0 for content in old_entity.iter_contains(use_reversed=True): if content.entitype == ENTITYPE.FLOWER: flower_counter += 1 continue elif content.entitype in (ENTITYPE.FRUIT, ENTITYPE.SEED, ENTITYPE.FOOD): content = content.from_location(content.quantity, use_repop=False) in_room = content.get_in_room() container_carrier = content.get_container_carrier() # Più la pianta è grande e maggiore è la probabilità che il suo # contenuto cada nella stanza invece che nel vaso if in_room and container_carrier and random.randint( 0, max( 1, math.log(new_entity.get_weight()) - math.log(container_carrier.get_weight()))) == 0: content.to_location(in_room) entities.append(content) elif in_room and random.randint( 0, max(1, math.log(new_entity.get_weight()))) == 0: content.to_location(in_room) entities.append(content) elif container_carrier: content.to_location(container_carrier) entities.append(content) else: content.to_location(old_entity.location) entities.append(content) # Tutte le entità inserite a terra attivano un timer per # rimuoverle e non creare inutili mucchi di semi content.start_purification(entitype.decomposition_rpg_hours, decomposition=True) else: # (BB) qui se passavano delle entità di tipo food invece di # ENTITYPE.FRUIT bacava i riferimenti, probabilmente il # problema c'è ancora, per questo l'elif sopra accetta # anche food content = content.from_location(content.quantity, use_repop=False) content.to_location(new_entity) # --------------------------------------------------------------------- # Si salva tutti i semi per sapere se entità da inserire nella pianta # sia solo di tipo seme oppure se eventuali semi sono mischiati ad # altre tipo di entità, ciò serve perché in tal caso i semi vengono # inseriti nelle altre tipologie di entità (frutti o fiori chessia) seeds = [] for proto_code, quantity in entitype.contents.iteritems(): prototype = database.get_proto_entity(proto_code) if not prototype: continue if prototype.entitype == ENTITYPE.SEED: seeds.append([prototype, quantity]) if len(seeds) == len(entitype.contents): seeds = [] # Ogni volta che la pianta produce dei semi diminuisce le proprie # risorse vitali if seeds and new_entity.plant_type.remaining_life > 0: new_entity.plant_type.remaining_life -= 1 # Crea l'eventuale contenuto voluto per la nuova entità for proto_code, quantity in entitype.contents.iteritems(): prototype = database.get_proto_entity(proto_code) if not prototype: continue # Se il prototipo è un seme da inserire in un frutto o simile allora lo salta for seed in seeds: if prototype == seed[0]: break else: add_content(prototype, quantity, choised_attr, flower_counter, new_entity, seeds) # Crea, se è il caso, una tipologia di contenitore alla nuova entità # per permettere ai giocatori ad interagire con la pianta if not new_entity.container_type and new_entity.entitype == ENTITYPE.PLANT: container = Container() container.max_weight = new_entity.get_carried_weight() * 2 new_entity.container_type = container # Avvisa dell'avvenuta crescita della pianta if new_entity.plant_type: message = "%s cresce: %s" else: message = "%s finisce di crescere: %s" log.plant(message % (old_entity.prototype.code, new_entity.prototype.code)) # Supporto gamescript, se viene forzato il ritorno non esegue # l'eventuale stadio successivo force_return = check_trigger(old_entity, "on_next_stage", old_entity, new_entity, choised_attr, entities) if force_return: return True # Ora si può rimuovere la vecchia pianta # (la si può estrarre completamente perché se possiede del contenuto non # viene raggruppata fisicamente, altrimenti si può rimuovere il gruppetto # senza problemi perché senza contenuto) old_entity.extract(old_entity.quantity, use_repop=False) # Prepara il lancio per il prossimo stage if choised_attr != "dead_entity" and new_entity.plant_type: new_entity.plant_type.start_growth(new_entity, "plant_type")