Author Topic: Code review  (Read 80481 times)

0 Members and 1 Guest are viewing this topic.

Offline Xela

  • Global Moderator
  • *****
  • Posts: 6893
  • "It's like hunting cows"
Re: Code review
« Reply #15 on: June 26, 2013, 09:00:05 AM »
Do you remember the symptoms of the problem you observed?

There is no call to "remember", it becomes obvious the moment you change iterator name back to brothel and buy more than one brothel.

Try actually setting girls working in the brothels :)
Like what we're doing?

Offline rudistoned

  • Full Member
  • ***
  • Posts: 229
Re: Code review
« Reply #16 on: June 26, 2013, 09:43:15 AM »
I checked out revision c4ba128 (- Updated Traits File)
I bough two extra buildings
I set girls to work in these buildings
I clicked trough all events on next day

Nothing out of the ordinary happened.
« Last Edit: June 26, 2013, 10:00:17 AM by rudistoned »

Offline Xela

  • Global Moderator
  • *****
  • Posts: 6893
  • "It's like hunting cows"
Re: Code review
« Reply #17 on: June 26, 2013, 09:56:48 AM »
I checked out revision c4ba128 (- Updated Traits File)
I bough two extra buildings
I set girls to work in these buildings
I clicked trough all events on next day

Nothing out of the ordinary happened.

After you buy several brothels:

Note that if iterator name in the girls assign screen is 'brothel':

1) When you set girls to work, tooltip displays faulty data.
2) Jobs available for girls in the brothel of your choice is not being updated either (Stripper job should be available to Mei in that brothel).

Note that problem disappears if you iterate with brtl (or anything else on the screen) with rest of the code being exactly the same, job is available, tooltip is functioning correctly.
« Last Edit: June 26, 2013, 09:58:31 AM by Xela »
Like what we're doing?

Offline rudistoned

  • Full Member
  • ***
  • Posts: 229
Re: Code review
« Reply #18 on: June 26, 2013, 10:00:30 AM »
Now I checked out the newest revision of master and changed "brtl" back to "brothel". Something should be wrong because the "brothel" variable of the label is used in the screen here:

Code: [Select]
    if brothel_selected:
        frame background Frame("content/gfx/bg/pergament.jpg",10,10):
            align (0,0.65)
            side "c r":
                viewport id "girlaction_vp":

<...>

                        if brothel.free_rooms() > 0 or chr.location == brothel:

                            for entry in brothel.actions:
                                    if entry == 'Stripper':

If "brothel" is used in the for loop in the screen code before my quoted code is executed, it would change which actual brothel the "brothel" variable in the quoted code refers to. I suppose that is the root of the problems you saw.
« Last Edit: June 26, 2013, 10:06:06 AM by rudistoned »

Offline Xela

  • Global Moderator
  • *****
  • Posts: 6893
  • "It's like hunting cows"
Re: Code review
« Reply #19 on: June 26, 2013, 10:05:45 AM »
If "brothel" is used in the for loop in the screen code before my quoted code is executed, it would change which actual brothel the "brothel" variable in the quoted code refers to. I suppose that is the root of the problems you saw.

Prolly is the case.
Like what we're doing?

Offline rudistoned

  • Full Member
  • ***
  • Posts: 229
Re: Code review
« Reply #20 on: June 26, 2013, 10:06:13 AM »
This kind of bug could appear in any python script. However, it is IMHO more difficult to spot in renpy scripts due to the many levels of indentation. Pytfalls code makes it even more difficult because some lines of code are extremely long, so you have to scroll sideways to see all the code.

To avoid it, we should use more functions and classes, so less code is executed in the global namespace.

UPDATE: Does renpys screen language support functions and/or classes? They might call it custom widgets.
« Last Edit: June 26, 2013, 10:12:20 AM by rudistoned »

Offline Xela

  • Global Moderator
  • *****
  • Posts: 6893
  • "It's like hunting cows"
Re: Code review
« Reply #21 on: June 26, 2013, 10:19:46 AM »
UPDATE: Does renpys screen language support functions and/or classes? They might call it custom widgets.

Supports pretty much anything. The entire screen can even be constructed in pure Python (if you wish to use the same paradigm as you've used in your Python OW port).
Like what we're doing?

Offline rudistoned

  • Full Member
  • ***
  • Posts: 229
Re: Code review
« Reply #22 on: June 26, 2013, 10:24:27 AM »
That's great :-)

Offline Xela

  • Global Moderator
  • *****
  • Posts: 6893
  • "It's like hunting cows"
Re: Code review
« Reply #23 on: June 26, 2013, 10:37:50 AM »
That's great :-)

Yeap, having options is always a good thing. I personally prefer the looks of screen language itself, it's a lot less confusing once you get used to it. Running anything python in the screen language is also possible.
Like what we're doing?

Offline rudistoned

  • Full Member
  • ***
  • Posts: 229
Re: Code review
« Reply #24 on: June 28, 2013, 08:17:59 AM »
Quote
+            '''On Rudi's advice, I'll try to code some screen control into pure Python classes
+            This method enables/disables security bar, and sets max value depending on brothel upgrades
+            Index 0 = Show/No show of bar, index 1 = max value of bar
+            '''

 ???
 :D
What I meant to convey with my advise is that we should package GUI code up in classes and functions, so we don't overwrite global variables with variables that look "local", when in fact they are in the global namespace. Putting GUI code in game logic classes (anything else than GUI code) is quite the opposite of what I want  ;)

With that being said, lets look at the complete method:
Code: [Select]
+        def gui_security_bar(self):
+            '''On Rudi's advice, I'll try to code some screen control into pure Python classes
+            This method enables/disables security bar, and sets max value depending on brothel upgrades
+            Index 0 = Show/No show of bar, index 1 = max value of bar
+            '''
+            result = []
+           
+            if len([girl for girl in self.get_girls() if girl.action == 'Guard']) > 0:
+                result.append(True)
+            else: result.append(False)
+           
+            if self.upgrades['mainhall']['2']['active']:
+                result.append(100)
+            elif self.upgrades['mainhall']['1']['active']:
+                result.append(50)
+            else: result.append(20)
+           
+            return result

Basically, this method answers two questions:
1) Is there a guard?
2) What's the maximum value for security at the bar?

So this method actually describes its instance and should therefore be part of the class. I would not consider that GUI code  :)

Here's another, IMHO clearer, way to answer the two questions:
Code: [Select]
        def is_guarded(self):
            '''Returns True if there is at least one guard here.
            '''
            guards = [girl for girl in self.get_girls() if girl.action == 'Guard']
            return bool(guards)

        def get_bar_security_max(self):
            '''Returns the maximum value for bar security (20 - 100).
            '''
            if self.upgrades['mainhall']['2']['active']:
                maxsec = 100
            elif self.upgrades['mainhall']['1']['active']:
                maxsec = 50
            else:
                maxsec = 20
            return maxsec

UPDATE: After reading Xelas post in the General discussion, I realize that "bar" probably refers to a GUI element. Well, my bad. It does not change anything important.
« Last Edit: June 28, 2013, 08:34:09 AM by rudistoned »

Offline Xela

  • Global Moderator
  • *****
  • Posts: 6893
  • "It's like hunting cows"
Re: Code review
« Reply #25 on: June 28, 2013, 09:50:52 AM »
What I meant to convey with my advise is that we should package GUI code up in classes and functions, so we don't overwrite global variables with variables that look "local", when in fact they are in the global namespace. Putting GUI code in game logic classes (anything else than GUI code) is quite the opposite of what I want  ;)

One of the things I like about RenPy is screen language and how it's setup. I figured you were in favor of cleaning screens up, not recoding them in pure Python.
Like what we're doing?

Offline rudistoned

  • Full Member
  • ***
  • Posts: 229
Re: Code review
« Reply #26 on: June 28, 2013, 10:31:03 AM »
I am in favour of cleaning the current screens up and I'm probably also in favour of using renpys screen language.


Is there any way to package screen language code into a separate namespace? Something like a subscreen or custom widget?



What I don't like is code that does something for screens in classes that contain game logic. Rule of thumb: if the class is in any of our current "classes - *.rpy" files, it should not contain GUI code. GUI code should IMHO be in the label that shows the screen, or in separate classes and functions.

Offline Xela

  • Global Moderator
  • *****
  • Posts: 6893
  • "It's like hunting cows"
Re: Code review
« Reply #27 on: June 28, 2013, 10:49:52 AM »
I am in favour of cleaning the current screens up and I'm probably also in favour of using renpys screen language.

Is there any way to package screen language code into a separate namespace? Something like a subscreen or custom widget?

One or the other, you can't have both, would be to convenient.

What I don't like is code that does something for screens in classes that contain game logic. Rule of thumb: if the class is in any of our current "classes - *.rpy" files, it should not contain GUI code. GUI code should IMHO be in the label that shows the screen, or in separate classes and functions.

I honestly have no problem with it.
Like what we're doing?

Offline rudistoned

  • Full Member
  • ***
  • Posts: 229
Re: Code review
« Reply #28 on: June 30, 2013, 02:57:42 AM »
Code: [Select]
            # Should not be called (ever)
            else:
                txt += "Brothel is reasonably clean and there are no clients left to serve! "

This is a snippet from ServiceJob.set_task.

If the else condition should only be reached when something went wrong, why does it output ingame text instead of logging an error message?

Offline Xela

  • Global Moderator
  • *****
  • Posts: 6893
  • "It's like hunting cows"
Re: Code review
« Reply #29 on: June 30, 2013, 03:58:05 AM »
If the else condition should only be reached when something went wrong, why does it output ingame text instead of logging an error message?

Because it still works, but feel free to remove it completely or turn it into an Error. Things like that are in many places in the code, especially in part that I've programmed close to when the project was started (Not having any previous coding experience of any serious kind).
Like what we're doing?