devolution

Author Topic: Code review  (Read 7006 times)

0 Members and 1 Guest are viewing this topic.

Offline Xela

  • Global Moderator
  • *****
  • Posts: 6610
  • "It's like hunting cows"
Re: Code review
« Reply #30 on: June 30, 2013, 05:06:49 AM »
Damn, that devlog thing is useful, just traced a nasty error using it, we should do more of those :)

2 Errors fixed during the next day (Guard Job and guard event with a normal defeat result). Gonna start with shops soon.

Offline rudistoned

  • Full Member
  • ***
  • Posts: 229
Re: Code review
« Reply #31 on: June 30, 2013, 09:05:49 AM »
Because it still works, but feel free to remove it completely or turn it into an Error.
If the game still works at that point, we should not throw an Exception. However, since your comment states that the else condition should never be reached, reaching it indicates some programming error, so it should log an error message, or at least a warning (devlog.error or devlog.warning). Creating ingame text for a condition that should never be reached seems like wasted effort.

It's no problem of course. I just want to suggest we do it differently in the future  :)

Offline Xela

  • Global Moderator
  • *****
  • Posts: 6610
  • "It's like hunting cows"
Re: Code review
« Reply #32 on: June 30, 2013, 10:42:58 AM »
If the game still works at that point, we should not throw an Exception. However, since your comment states that the else condition should never be reached, reaching it indicates some programming error, so it should log an error message, or at least a warning (devlog.error or devlog.warning). Creating ingame text for a condition that should never be reached seems like wasted effort.

It's no problem of course. I just want to suggest we do it differently in the future  :)

Agree with you 110%. Like I've said, when that code was written, I didn't know that [item for item in items] might create a list of items...

Offline rudistoned

  • Full Member
  • ***
  • Posts: 229
Re: Code review
« Reply #33 on: June 30, 2013, 11:40:38 AM »
I think I had been programming Python for one or two years when I first read about list comprehension  :D

Offline rudistoned

  • Full Member
  • ***
  • Posts: 229
Re: Code review
« Reply #34 on: August 11, 2013, 11:17:52 AM »
Hey guys!


Here is the code I used in Pytherworld to load PyTFalls girl ressources, in case you want a new ressource loader that supports PyTFalls filename-based tagging and can read XMP tags. To use these classes, you need to import the tags package from Pytherworld or Image Tagger in your code. You do not need pyexiv2, because the tags package comes with an included XMP reader in pure python. This means that distributing it with renpy should be easy.  You will also have to adapt these classes a little to your applications needs and environment, of course. Just ask if anything gives you trouble :)


Code: [Select]
class PyTFallGirlDataRessourceMap(tags.resload.RessourceMap):
    '''Provides xml ressource files.'''
    def __init__(self, rootdir, picklepath="DEFAULT"):
        tags.resload.RessourceMap.__init__(self, ["data.xml"], rootdir,
                                           picklepath=picklepath)
        # maps pytfall character ids to character name tags
        self.idmap = {}


    def guess_tags(self, relpath):
        '''Returns a list of tags for this file based on relpath.'''
        abspath = os.path.join(self.rootdir, relpath)
        # parse XML
        tree = ET.parse(abspath)
        rootelem = tree.getroot()
        # remember which girls are described here in the tagmap
        nametags = []
        nametags.sort()
        for girlelem in rootelem.iterfind("girl"):
            charnametag = girlelem.attrib["name"]
            nametags.append(charnametag)
            # also rememeber the character folder for each girl
            self.idmap[girlelem.attrib["id"]] = charnametag
        return nametags




class PyTFallImageRessourceMap(tags.resload.ImageRessourceMap):
    '''Provides PyTFall image ressource files.'''
    def __init__(self, patternlist, rootdir, picklepath="DEFAULT"):
        tags.resload.ImageRessourceMap.__init__(self, patternlist, rootdir,
                                                picklepath=picklepath)
        self.girlxml = None
        self.guessmap = {"etiquette": ["learn etiquette"],
                          "dance": ["learn dancing"],
                          "nude.jpg": ["nude"],
                          "rest": ["resting"],
                          "battle_sprite": ["ignore"],
                          "combat": ["ignore"],
                          "date": ["ignore"],
                          "datebeach": ["ignore"],
                          "shop": ["ignore"],
                          "ent": ["ignore"],
                          "Quest": ["ignore"],
                          "quest": ["ignore"],
                          "0quest0": ["ignore"],
                          "0quest1": ["ignore"],
                          "0quest2": ["ignore"],
                          "quest1": ["ignore"],
                          "quest2": ["ignore"],
                          "questsad": ["sad"],
                          "questnormal": ["indifferent"],
                          "questneutral": ["indifferent"],
                          "questhappy": ["happy"],
                          "questangry": ["angry"],
                          "battle": ["ignore"],
                          "portrait.png": ["portrait"],
                          "maid.jpg": ["maid"],
                          "profilesad": ["sad"],
                          "profilehappy": ["happy"],
                          "profileneutral": ["indifferent"],
                          "profileangry": ["angry"],
                          "blowjob": ["+blowjob"],
                          "sex": ["-fuck"],
                          "Sex": ["-fuck"],
                          "anal": ["-anal"],
                          "bdsm": ["-bdsm"],
                          "mast": ["masturbate"],
                          "strip": ["undressing"],
                          "beauty": ["ignore"],
                          "les": ["ignore"],
                          "Les": ["ignore"],
                          "date.jpg": ["ignore"]}
        self.unknown = set()
        # initialize girl data resmap
        ppath = os.path.join(c.PATH.RESDIR, "pytfall", "pytfgirldata.res")
        self.girlxml = PyTFallGirlDataRessourceMap(self.rootdir,
                                                    picklepath=ppath)
        self.girlxml.load()


    def guess_tags(self, relpath):
        '''Returns a list of tags for this file based on its path and XMP tags.


        The filename is converted into a tag by splitting at whitespace and
        treating the first item of the resulting list as the tag.
        The remaining path is split at the path separator and translated into
        tags according to self.guessmap.
        '''
        guessedtags = []
        # split off filename and file extension
        base, fullfn = os.path.split(relpath)
        filename, ext = os.path.splitext(fullfn)
        # split the filename into words and assume the first word is the tag
        firstword = filename.split()[0]
        ##for encoding in ["ascii", "utf-8"]:
            ##try:
                ##firstword = firstword.decode(encoding)
            ##except UnicodeDecodeError:
                ##pass
        ##firstword.encode("utf-8")
        if firstword in self.guessmap:
            guessedtags.extend(self.guessmap[firstword])
        else:
            guessedtags.append(firstword)
            if firstword not in tags.default.known:
                logger.warning("unknown pytfall tag: %s" % firstword)
        # split the path and translate it into tags
        taglist = tags.resload.ImageRessourceMap.guess_tags(self, relpath)
        guessedtags.extend(list(taglist))
        # add tags based on the character
        base = relpath
        charnametag = None
        while base:
            base, dirname = os.path.split(base)
            if dirname in self.girlxml.idmap:
                charnametag = self.girlxml.idmap[dirname]
                guessedtags.append(charnametag)
                break
        if charnametag is None:
            msg = "could not identify charnametag for %s"
            logger.warning(msg % relpath)
        guessedtags.sort()
        # inform if there are untranslated parts
        if c.DEBUG:
            for pathpart in base.split(os.path.sep):
                if (pathpart not in self.guessmap and
                    pathpart not in self.unknown):
                    msg = "No translation for PyTFall path part: %s"
                    logger.info(msg % pathpart)
                    self.unknown.add(pathpart)
        return guessedtags




Here is one way to instantiate the classes above:


Code: [Select]
class PyTFallRessourceNamespace(object):
    '''Makes pytfall ressource loaders accessible via 'c.res.pytfall'.'''
    def __init__(self):
        self.gamedir = os.path.join(c.PATH.PYTFALL, "game")
        # provides images for character screens
        self.girls = None
        # --  initialize  -- #
        rootdir = os.path.join(self.gamedir, "content", "chars")
        # initialize girl image resmap
        picklefile = os.path.join(c.PATH.CACHE, "res_pytfall_girls.res")
        if os.path.exists(picklefile):
            msg = "loaded pytfall girl image metadata from pickled ressource"
            logger.info(msg)
            self.girls = PyTFallImageRessourceMap.from_pickle(picklefile)
        else:
            self.girls = PyTFallImageRessourceMap(["*.jpg", "*.png"], rootdir,
                                                  picklepath=picklefile)
            self.girls.load()
            logger.info("created new pytfall girl image metadata")
            self.girls.to_pickle()
« Last Edit: August 11, 2013, 11:21:22 AM by rudistoned »

Offline h3nta1fun

  • Newbie
  • *
  • Posts: 16
Re: Code review
« Reply #35 on: April 09, 2014, 03:00:11 PM »
Code: [Select]


# Other ----------------------
label interact_other:
    # It'll be up to me to write an occupation changer for other at the very least.
    menu:
        "What will it be?"
        "Ask her to change profession":
            menu:
                "Switch to:"
                "Prostitute" if chr.occupation != "Prostitute":
                    if chr.status == "slave" and chr.disposition > -500:
                        g "As you wish Master..."
                        if chr.occupation != "Stipper" and chr.disposition < 200:
                            "She doesn't look too happy about this..."
                            python:
                                chr.joy -= 40
                                chr.disposition -= 50                                chr.occupation = "Prostitute"


Just looking in the pyt - labels - girlinteractions.rpy file and found that "Stipper" that sould have been "Stripper".[size=78%]  [/size]

Offline Xela

  • Global Moderator
  • *****
  • Posts: 6610
  • "It's like hunting cows"
Re: Code review
« Reply #36 on: April 10, 2014, 06:33:15 AM »
Code: [Select]


# Other ----------------------
label interact_other:
    # It'll be up to me to write an occupation changer for other at the very least.
    menu:
        "What will it be?"
        "Ask her to change profession":
            menu:
                "Switch to:"
                "Prostitute" if chr.occupation != "Prostitute":
                    if chr.status == "slave" and chr.disposition > -500:
                        g "As you wish Master..."
                        if chr.occupation != "Stipper" and chr.disposition < 200:
                            "She doesn't look too happy about this..."
                            python:
                                chr.joy -= 40
                                chr.disposition -= 50                                chr.occupation = "Prostitute"


Just looking in the pyt - labels - girlinteractions.rpy file and found that "Stipper" that sould have been "Stripper".[size=78%]  [/size]

Tnx!