You have good ideas for balancing the game in the first post. ButIn our case refinement is a knowledge about society and its customs and manners, not physical grace
Thanks for the input; Certainly that's a fair point, and if that is the case and intention of the 'purpose' of the game's refinement stat, then I'll agree that it shouldn't impact dirt generation, though I still feel that agility should help (It's really difficult to raise agility for slaves anyway since they are forbidden from participating in Combat Courses, and have to deal with very low success via Dance courses instead.)
The main reason I've been hesitant about going ahead with implementing any of my suggestions so far (and some of them are really easy, it looks like) is because anything I do would change the game's balance from what I assume was 'intended difficulty' you guys put out in the alpha. Anything I do would theoretically make it easier as guards and strippers level up faster, characters will be able to do a bit more / more effectively, taxes won't be so devastating (though I think if I
do change it to hit net income instead of gross, I'll raise the lower level tax rates to still slow early growth a bit,) and so on. Part of my post was somewhat testing to see what anyone would've probably agreed on to be a good change to balance. Honestly, of the character/job-related changes, guards are probably my highest priority, because once you get to 1000 security rating, there is literally no reason at all to even field a guard team, much less have 5 of them in that little guard house.
Thus, I'm currently just doing UI/QoL improvements instead.
On that note, I tweaked my course assignment screen a bit more and fiddled with the colors again. I think I'm pretty happy with it now (wording could probably still change, though.) I decided to change the logic to include 3 'scenarios' instead of 2: Instead of the "days left" counter next to the girls showing the static/absolute end time of that course - which is reflected on the course's 'card' already anyway) I made it provide two different counters.
- If a girl's already completed the course and gotten her bonus stats from it, it counts down to the absolute end day as normal, telling you how many more days she can continue participating in that class to get the regular bonuses, but making it clear she's already gotten the course bonus and won't be getting them again.
- If a girl has not yet completed the course, the counter will instead display either the number of days left until she completes the course to gain her bonus stats, or turn red and count down to the absolute end day of the course if there's not enough time for the girl to get to that point.
I find this has given me a very easy way to very quickly and at a glance tell what the status of all the girls I'm training are. Important for me when I have 8 girls working to pay for the course cost, upkeep and wages of 14 other girls taking classes simultaneously. I've attached an updated screenshot showing all three statuses now.
With that out of the way, as I mentioned before, I'd like to ask if anyone could suggest a way to improve the code a bit - it works, but I'm really going in blind here, especially with no experience with Python nor any knowledge of the setup of this game's data structures (lots of guessing what data is available based on looking at similar sections of existing code, as well as the functions that define those structures. It's apparent to me just how much I was used to using my
for k,v in pairs(t) do print(k,v) end loop in Lua to find the data available to me. Unfortunately, trying similar tactics here didn't go very well, because most things apparently aren't 'iterateable.' In short, I think there's probably more efficient methods of getting what I need, but the loops so far make logical sense to me.
Beginning with the course list name change to add in a numeric identifier, I altered this line of code:
The original:
text(u'{size=-5}%s'%course['action']) xalign 0.5
The modified line:
text(u'{size=-6}%s %d%02d'%(course['action'], int(course['Teacher Skill'] / 10), int(course['Teacher Knowledge'] / 10))) xalign 0.5
Apparently I can't really set any variables in this file, because I kept getting errors/complaints that it expected only layout code, or something, so I had to call the data repeatedly in-line instead in order to handle the logic. Either way, the number is simply truncating the teacher skill and knowledge values and concatenating them together with the original course name to create a semi-sensible 'numbering system' where higher numbers = roughly better courses. In this case, since the range of values for creating a course are 30-100 skill and 40-300 knowledge, the 'worst' course would be a 304 course, while the 'best' would be a 1030 course. I also had to reduce the text size because it started overflowing with the extra numbers.
Now the big stuff is on the left hand 'summary' pane:
The original code:
for entry in [girl for girl in hero.girls if girl.location == "-PyTFall Educators-"]:
hbox:
vbox:
xmaximum 180
xfill True
text (u"{size=-2}%s:"%entry.name)
vbox:
text (u"{size=-2}%s"%entry.action)
The modified block:
for girl in hero.girls:
if girl.location == "-PyTFall Educators-":
for course in schools['-PyTFall Educators-'].active_courses:
if course['id'] == girl.mech_relay['courseid']:
hbox:
vbox:
xmaximum 180
xfill True
text (u"{size=-3}%s:"%girl.name)
vbox:
#if girl has been in course longer than class completion length
if int(course['chars'][str(girl)]) >= int(course['Duration'] * 0.7):
text (u"{size=-4}{color=[royalblue]}%s %d%02d{/color} {color=[springgreen]}Completed!{/color} ({color=[firebrick]}%dd left{/color})"%(course['action'], int(course['Teacher Skill'] / 10), int(course['Teacher Knowledge'] / 10), int(course['Days Left'])))
#if not long enough to complete, but enough time remaining to do so
elif int((course['Duration'] * 0.7) - course['chars'][str(girl)]) <= int(course['Days Left']):
text (u"{size=-4}{color=[skyblue]}%s %d%02d{/color} on Day {color=[lawngreen]}%d{/color} / {color=[gold]}%d{/color} ({color=[lightgreen]}%dd left{/color})"%(course['action'], int(course['Teacher Skill'] / 10), int(course['Teacher Knowledge'] / 10), int(course['chars'][str(girl)]), int(course['Duration'] * 0.7), int((course['Duration'] * 0.7) - course['chars'][str(girl)])))
#if not long enough to complete, and not enough time to do so
else
text (u"{size=-4}{color=[darkslateblue]}%s %d%02d{/color} on Day {color=[lightcoral]}%d{/color} / {color=[goldenrod]}%d{/color} ({color=[red]}%dd left{/color})"%(course['action'], int(course['Teacher Skill'] / 10), int(course['Teacher Knowledge'] / 10), int(course['chars'][str(girl)]), int(course['Duration'] * 0.7), int(course['Days Left'])))
What's immediately apparent is that there appeared to be some shorthand occurring in the original code where it seems to be running multiple loops all at once in one line, but I have no idea how that worked, so I separated them into separate discrete loops instead. This would probably be where any optimization could come in, but as before, the bottom half looks like a nightmare because of my inability to define any variables in this file. Any suggestions, or is it basically fine as-is?
EDIT:
Somewhat unrelated, but if I will be training the girls I get from the slave market anyway, does it really matter what their work price and upkeep are? I ask because some are obviously more expensive than others there, but even going by the calculations in the code, I'm not coming up with the same upkeep costs, so I can't be sure that, all else being equal, two slaves bought at different starting costs would eventually come to have the same upkeep/work costs if I train them to make their stats identical to each other.
For example, there is a slave that has a work price of 49 and upkeep of 70, and another with a work price of 24 and upkeep of 75.
According to the code:
def get_upkeep(self):
if self.status == 'slave':
if self.occupation == 'Prostitute':
bu = 20 * self.rank
su = self.charisma/10 + self.refinement*1.5 + self.constitution/5 + self.reputation/2 + self.fame/2 # Stats Upkeep
ssu = self.anal/8 + self.normalsex/8 + self.blowjob/8 + self.lesbian/8
return int(bu + su + ssu + self.upkeep)
They are both rank 1, so that's a base of 20. The first one has 5 Charisma, 10 Refinement, 40 Constitution, 17 Reputation, 12 Fame, and 21/17/18/21 of the relevant skills.
The second one has 29 Charisma, 0 Refinement, 40 Constitution, 0 Reputation, 0 Fame, and 0/0/0/0 of the relevant skills.
Based on these stats, I would naturally prefer the first one, but I wanted to see if the price disparity still exists when they are trained up. Unfortunately, the base numbers don't match.
The first one would have upkeep of:
20 + 5/10 + 10*1.5 + 40/8 + 17/2 + 12/2 + 21/8 + 17/8 +18/8 + 21/8 =
64.625, or 64 gold, where the game claims she has an upkeep of 70.
The second one would have upkeep of:
20 + 29/10 + 0*1.5 + 40/8 + 0/2 + 0/2 + 0/8 + 0/8 + 0/8 + 0/8 =
27.9, or 27 gold, but the game says she has upkeep of 75! Granted, I don't know what value self.upkeep contains, but I can't be sure if it makes that large a difference, especially between the two girls.
The gist of it all is that I have no idea if I should be hiring these slaves hoping for the upkeep to not be insane later on. In the second slave's case, it would be a nightmare if I trained her up and her upkeep
still ends up being triple her work price.