Wow... What the hell is this?
I have the answer to your question, but first a bit of code 101, it will be useful for the future. If you don't want to learn, just jump at the end of the post...
First thing first, why the fuck this:
Code:
for i in ['[player_name]','[player_name!c]','[player_name!t]','[player_name!ct]','[player_name!tc]'] :
text = text.replace( i , "pielustous".capitalize())
text = text.replace('[player_name!u]', "pielustous".upper())
You replace all occurrence of Ren'Py displaying the
content of the variable named "player_name", by a text, that will always be the same...
Therefore I have a question for you:
Why something so complex when a basic
player_name = "pielustous"
in the console would have the exact same result, and wouldn't need to be done more than once by playthrough?
It's not like enabling the console is more complex than adding
config.console = True
in your rpy file.
Note that the same apply for the three following lines, that address "xlasname".
There's also this part:
Code:
for i in [
"Cum inside me","cum inside me","Cumming inside me","cumming inside me", [...] "Bang us", "bang us", "Bang me", ] :
text = text.replace( i , randxcolor+(i).title()+ "{/b}{/color}")
That have a hell big list...
Since you already use
title()
, you can perfectly make it way smaller by normalizing the input:
Code:
for i.lower() in [
"cum inside me", "cumming inside me", [...] "bang us", "bang me", ] :
text = text.replace( i , randxcolor+(i).title()+ "{/b}{/color}")
But this is secondary, because I guess that it's your fix for the issue you describe. Just know that it's totally possible and can significantly lower your lists.
And this part:
Code:
x_cl = renpy.random.randint(1,5)
if x_cl == 1:
prefix = "{color=#EF1221}{b}"
elif x_cl == 2:
prefix = "{color=#FE12EF}{b}"
elif x_cl == 3:
prefix = "{color=#12FEEF}{b}"
elif x_cl == 4:
prefix = "{color=#FF7712}{b}"
else:
prefix = "{color=#12EF21}{b}"
suffix = "{/b}{/color}"
Why something so complex, when you already did this:
Code:
randxcolor = renpy.random.choice(['{color=#EF1221}{b}', '{color=#FE12EF}{b}', '{color=#12FEEF}{b}', '{color=#FF7712}{b}', '{color=#12EF21}{b}'],)
[...]
text = text.replace( i , randxcolor+(i)+ "{/b}{/color}")
That you want another color than the one already picked, okay, why not, but why pass through an
if
structure since you already know a better way to do it?
And there this part:
Code:
replace_dict = {
'pielustous': "pielustous",
'weincestt': "weincestt",
'the goddesses': "the goddesses",
'the goddess': "the goddess",
[...]
if match.group(0).isupper():
value = replace_dict[key].upper()
elif match.group(0).istitle():
value = replace_dict[key].title()
else:
value = replace_dict[key].title()
I can have missed some, but in your near to 2000 entries dictionary, there's less than two dozen times where the value do not correspond to the key...
Make them an exception, and use a list for the rest:
Code:
replace_list = [
'pielustous', 'weincestt',
'the goddesses', 'the goddess',
[...]
replace_dict = {
'brother and sisters': "siblings",
'brother and sister': "siblings",
'sisters and brother': "siblings",
'sister and brother': "siblings",
[...]
Then you modify a bit your "translate" function:
Code:
def translate(match):
key = match.group(0).lower()
x_cl = renpy.random.choice( [...]
suffix = "{/b}{/color}"
value = ""
if match.group(0).isupper():
if key in replace_dict: # Update the value if it's parts of the exceptions.
key = replace_dict[key]
value = key.upper()
elif match.group(0).istitle():
if key in replace_dict: # Update the value if it's parts of the exceptions.
key = replace_dict[key]
value = key.title()
else:
if key in replace_dict: # Update the value if it's parts of the exceptions.
key = replace_dict[key]
value = key.title()
return prefix + value + suffix
Then you use this:
Code:
# Proceed to the default substitutions
rc = re.compile('\\b|\\b'.join(map(re.escape, replace_list)), re.I)
text = rc.sub(translate, text)
# Then deal with the exceptions.
rc = re.compile('\\b|\\b'.join(map(re.escape, replace_dict)), re.I)
return rc.sub(translate, text)
Regarding the "replace_dict", there's also the struggle with all those:
Code:
### ----------------------------------------------------
'the queens': "the queens",
'your queens': "your queens",
'our queens': "our queens",
'his queens': "his queens",
'my queens': "my queens",
'queens': "queens",
### ----------------------------------------------------
'the queen': "the queen",
'your queen': "your queen",
'our queen': "our queen",
'his queen': "his queen",
'my queen': "my queen",
'queen': "queen",
### ----------------------------------------------------
'the princesses': "the princesses",
'your princesses': "your princesses",
'our princesses': "our princesses",
'his princesses': "his princesses",
'my princesses': "my princesses",
'princesses': "princesses",
### ----------------------------------------------------
'the princess': "the princess",
'your princess': "your princess",
'our princess': "our princess",
'his princess': "his princess",
'my princess': "my princess",
'princess': "princess",
Since you use regEx, and like you don't need a dict here, use the regEx totally.
Code:
"(?:(?:the|y?our|his|my) )?queen(?:s)?"
"(?:(?:the|y?our|his|my) )?princess(?:es)?"
1 line for each group of 12 entries...
It would help to clear up a bit your code and, despite the fact that the regEx is now more complex, it would be a bit faster. This without changing the result since you'll still get, and works with, the string as it is written.
All this being said...
A translation file should do exactly the same than your long list, while also getting rid of your problem:
Code:
translate None strings:
old 'the goddesses'
new "{color=#EF1221}{b}the goddesses{/b}{/color}"
old 'the goddess'
new "{color=#EF1221}{b}the goddess{/b}{/color}"
old 'my goddesses'
new "{color=#EF1221}{b}my goddesses{/b}{/color}"
old 'brother and sisters'
new "{color=#EF1221}{b}siblings{/b}{/color}"
[...]
Name it "myFix.rpy", drop it in the "game" directory (I don't see why it would need to be in the "tl" one), and normally it should works.
It remove the randomness for the color, but is it really this important? Anyway there's a way to also deal with this, but it's more advanced.
Now, for the problem you encounter...
You use a dictionary as entry, and the fact is that dictionaries are
not ordered.
You've this:
Code:
'banged you': "banged you",
'banged her': "banged her",
'banged me': "banged me",
'bang you': "bang you",
'bang her': "bang her",
'bang me': "bang me",
'banging': "banging",
'banged': "banged",
'bangs': "bangs",
'bang': "bang",
In the source, it looks good, "bang" will be the last tested value. But it happen that when the code will come to:
Code:
rc = re.compile('\\b|\\b'.join(map(re.escape, replace_dict)), re.I)
The order will be different. This will make "bang" appear sooner in the list, before the entries for "bang me", "bang them" and "bang her". Therefore, the regEx will never test those three, because it already have a match for "bang".
It's the reason why using a list is preferable, in addition to the fact that a dictionary isn't needed.
As well as the reason why using actual regEx in place of just a list of word is also preferable, in addition to the fact that it lower the number of entries.
List are ordoned, therefore "bang me", "bang them", and "bang her" will
always appear before "bang", what solve your issue.
And something like
"bang(?:(?:ing|ed) )?(?:you|her|me)?"
will always catch the biggest match, therefore it will catch "bang me" and "bang her" when they are present.
Side note: You have no entries for "bang them", whatever the declinaison for "bang".