Can I copy a random character into another character?

Discuss how to use the Ren'Py engine to create visual novels and story-based games. New releases are announced in this section.
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
Post Reply
Message
Author
arlj11
Regular
Posts: 35
Joined: Mon Jan 06, 2020 12:30 pm
Projects: 4Wins
Deviantart: arlj11
Github: arlj11
Contact:

Can I copy a random character into another character?

#1 Post by arlj11 »

Here is my challenge

The story I'm thinking of making is about what goes on behind the scenes in a film production.
I want to have a part where you are hiring actors and actresses to play parts in the film. But I want them to be sort of random and have different skills, then have the player select the character they want to be in the film. I also want different outcomes depending on who you pair up.

I want the characters in a list. That way, I can choose the actor and actress using a random number.

I am hoping to reuse as much code as possible and not have to create scenes for every combination.

I'm thinking something like this.

Code: Select all

Actress = chosen Actress
Actor = chosen Actor

Actress "Lines"
Actor "Lines"
If Actress skill > skill points needed
	Actress "Good lines delivered"
Else
	Actress "Bad lines delivered"
So, depending on the Actor/Actress's Skills, she may cause the scene to work or fail.

Also can I expand the Character Class to add Stats and Skills?

User avatar
enaielei
Miko-Class Veteran
Posts: 551
Joined: Fri Sep 17, 2021 2:09 am
Organization: enaielei
Tumblr: enaielei
Deviantart: enaielei
Github: enaielei
Skype: enaielei
Soundcloud: enaielei
itch: enaielei
Discord: enaielei#7487
Contact:

Re: Can I copy a random character into another character?

#2 Post by enaielei »

Better not subclass the Character class.
Create another class for the stats and stuff, and use the character namespace to isolate the character objects.

Code: Select all

init python:
  class Actor(): # This will be your mutable object, instead of mutating the Character object
    def __init__(self, name, aliases):
      self.name = name
      self.aliases = aliases
    def copy():
      return type(self)(self.name, self.aliases[:]) # create a new Actor instance from this template and shallow copy the list aliases using [:]

define preset_actors = [
  Actor("Michael", ["Mich"])
]

default actor = None
define character.actor = Character("actor.name", dynamic=True)

label start:
  $ actor = preset_actors[0].copy()
  actor "My name is [actor.name]"
Please consider supporting me if you like what I do :D
https://paypal.me/enaielei?country.x=PH&locale.x=en_US

arlj11
Regular
Posts: 35
Joined: Mon Jan 06, 2020 12:30 pm
Projects: 4Wins
Deviantart: arlj11
Github: arlj11
Contact:

Re: Can I copy a random character into another character?

#3 Post by arlj11 »

I think I understand your code. But I have a few questions.

How do I add an Image tag to the character? Would I define it in the class, then in the preset with the Character class like this...

Code: Select all

init python:
  class Actor(): # This will be your mutable object, instead of mutating the Character object
    def __init__(self, name, aliases, image):
      self.name = name
      self.aliases = aliases
      self.image = image
    def copy():
      return type(self)(self.name, self.aliases[:], self.image[:]) # create a new Actor instance from this template and shallow copy the list aliases using [:]

define preset_actors = [
  Actor("Michael", ["Mich", "Michael"])
]

default actor = None
define character.actor = Character("actor.name", "actor.image", dynamic=True)

label start:
  $ actor = preset_actors[0].copy()
  actor "My name is [actor.name]"
And I add stats to the Actor Class and call the stats like this...

Code: Select all

actor[0].int
actor[0].str

philat
Eileen-Class Veteran
Posts: 1958
Joined: Wed Dec 04, 2013 12:33 pm
Contact:

Re: Can I copy a random character into another character?

#4 Post by philat »

My preferred solution in these cases is to generate a new Character with the relevant attributes and refer to it in the Actor class. Theoretically there may be some save/load issues but I haven't really had any so far tbh.

Code: Select all

class Actor():
    def __init__(self, name, image):
           self.character = Character(name, image=image)
           #other stats and attribute as needed

arlj11
Regular
Posts: 35
Joined: Mon Jan 06, 2020 12:30 pm
Projects: 4Wins
Deviantart: arlj11
Github: arlj11
Contact:

Re: Can I copy a random character into another character?

#5 Post by arlj11 »

And how would that work with the previous code?

User avatar
enaielei
Miko-Class Veteran
Posts: 551
Joined: Fri Sep 17, 2021 2:09 am
Organization: enaielei
Tumblr: enaielei
Deviantart: enaielei
Github: enaielei
Skype: enaielei
Soundcloud: enaielei
itch: enaielei
Discord: enaielei#7487
Contact:

Re: Can I copy a random character into another character?

#6 Post by enaielei »

arlj11 wrote: Mon Apr 28, 2025 12:31 am How do I add an Image tag to the character? Would I define it in the class, then in the preset with the Character class like this...
You can use Dynamic Displayables to dynamically display the appropriate image depending on the actor selected.
https://www.renpy.org/doc/html/displaya ... tionSwitch
Full example using image tag + side images:

Code: Select all

init python:
  class Actor(): # This will be your mutable object, instead of mutating the Character object
    def __init__(self, id_, name, aliases):
      self.id = id_ # added this for dynamic image identification
      self.name = name
      self.aliases = aliases

    def copy(self):
      return type(self)(self.id, self.name, self.aliases[:]) # create a new Actor instance from this template and shallow copy the list aliases using [:]

define preset_actors = [
  Actor("mich", "Michael", ["Mich"]),
  Actor("andr", "Andrea", []),
]

default actor = None
define character.actor = Character("actor.name", image="actor", dynamic=True)

# use dynamic displayables to show dynamic side images depending on the value of the actor
# replace the Text() displayables with your actual images
image side actor = ConditionSwitch(
    "actor.id == 'mich'", Text("Michael side image", xysize=(300, 300)),
    "actor.id == 'andr'", Text("Andrea side image", xysize=(300, 300)),
)
image side actor happy = ConditionSwitch(
    "actor.id == 'mich'", Text("Michael happy side image", xysize=(300, 300)),
    "actor.id == 'andr'", Text("Andrea happy side image", xysize=(300, 300)),
)

label start:
  $ actor = preset_actors[0].copy()

  actor "My name is [actor.name]"
  actor happy "Yehey!!!"

  "Let's try again but with a different actor."
  scene black

  $ actor = preset_actors[1].copy()

  actor "My name is [actor.name]"
  actor happy "Yehey!!!"
arlj11 wrote: Mon Apr 28, 2025 12:31 am And I add stats to the Actor Class and call the stats like this...

Code: Select all

actor[0].int
actor[0].str
I'm assuming you're talking about the preset_actors here because you're using indices in your example. If that's the case, then no.
This line "actor = preset_actors[1].copy()" creates a new instance of the current actor based on the preset.
So any changes should be made on that new instance which is stored in the "actor" variable.
Please consider supporting me if you like what I do :D
https://paypal.me/enaielei?country.x=PH&locale.x=en_US

arlj11
Regular
Posts: 35
Joined: Mon Jan 06, 2020 12:30 pm
Projects: 4Wins
Deviantart: arlj11
Github: arlj11
Contact:

Re: Can I copy a random character into another character?

#7 Post by arlj11 »

I don't like the idea of using ConditionSwitch for the images. But I'll try it.

arlj11
Regular
Posts: 35
Joined: Mon Jan 06, 2020 12:30 pm
Projects: 4Wins
Deviantart: arlj11
Github: arlj11
Contact:

Re: Can I copy a random character into another character?

#8 Post by arlj11 »

Okay, now I'm trying to randomize the list and have only 3 actors selectable.

Here is my code so far

Code: Select all

label ActorSelection:
    call ActorRandomizer
    menu:
        "[preset_actors[int(RandomActor1)].fname]":
            $ actor = preset_actors[int(RandomActor1)].copy()
        "[preset_actors[int(RandomActor2)].fname]":
            $ actor = preset_actors[int(RandomActor2)].copy()
        "[preset_actors[int(RandomActor3)].fname]":
            $ actor = preset_actors[int(RandomActor3)].copy()
    call InterviewActor
    return

label ActorRandomizer:
    call RandomizeActor1
    call RandomizeActor2
    call RandomizeActor3

label RandomizeActor1:
    $ RandomActor1 = renpy.random.randint(0, len(preset_actors))
    if RandomActor1 == RandomActor2 or RandomActor1 == RandomActor3:
        call RandomizeActor1
    return

label RandomizeActor2:
    $ RandomActor2 = renpy.random.randint(0, len(preset_actors))
    if RandomActor2 == RandomActor1 or RandomActor2 == RandomActor3:
        call RandomizeActor2
    return

label RandomizeActor3:
    $ RandomActor3 = renpy.random.randint(0, len(preset_actors))
    if RandomActor3 == RandomActor2 or RandomActor3 == RandomActor1:
        call RandomizeActor3
    return
But I get this error

Code: Select all

I'm sorry, but an uncaught exception occurred.

While running game code:
  File "game/script.rpy", line 90, in script call
    call PreProduction
  File "game/PreProduction.rpy", line 4, in script call
    call CastingCall
  File "game/CastingCall.rpy", line 7, in script call
    call ActorSelection
  File "game/CastingCall.rpy", line 13, in script
    menu:
  File "game/screens.rpy", line 207, in execute
    screen choice(items):
  File "game/screens.rpy", line 207, in execute
    screen choice(items):
  File "game/screens.rpy", line 210, in execute
    vbox:
  File "game/screens.rpy", line 211, in execute
    for i in items:
  File "game/screens.rpy", line 212, in execute
    textbutton i.caption action i.action
IndexError: list index out of range

-- Full Traceback ------------------------------------------------------------

Full traceback:
  File "game/script.rpy", line 90, in script call
    call PreProduction
  File "game/PreProduction.rpy", line 4, in script call
    call CastingCall
  File "game/CastingCall.rpy", line 7, in script call
    call ActorSelection
  File "game/CastingCall.rpy", line 13, in script
    menu:
  File "C:\Renpy\renpy\ast.py", line 1632, in execute
    choice = renpy.exports.menu(choices, self.set, args, kwargs, item_arguments)
  File "C:\Renpy\renpy\exports\menuexports.py", line 134, in menu
    rv = renpy.store.menu(new_items)
  File "C:\Renpy\renpy\exports\menuexports.py", line 424, in display_menu
    rv = renpy.ui.interact(mouse='menu', type=type, roll_forward=roll_forward)
  File "C:\Renpy\renpy\ui.py", line 301, in interact
    rv = renpy.game.interface.interact(roll_forward=roll_forward, **kwargs)
  File "C:\Renpy\renpy\display\core.py", line 2218, in interact
    repeat, rv = self.interact_core(preloads=preloads, trans_pause=trans_pause, pause=pause, pause_start=pause_start, pause_modal=pause_modal, **kwargs) # type: ignore
  File "C:\Renpy\renpy\display\core.py", line 2748, in interact_core
    root_widget.visit_all(lambda d : d.per_interact())
  File "C:\Renpy\renpy\display\displayable.py", line 434, in visit_all
    d.visit_all(callback, seen)
  File "C:\Renpy\renpy\display\displayable.py", line 434, in visit_all
    d.visit_all(callback, seen)
  File "C:\Renpy\renpy\display\displayable.py", line 434, in visit_all
    d.visit_all(callback, seen)
  File "C:\Renpy\renpy\display\screen.py", line 480, in visit_all
    callback(self)
  File "C:\Renpy\renpy\display\core.py", line 2748, in <lambda>
    root_widget.visit_all(lambda d : d.per_interact())
  File "C:\Renpy\renpy\display\screen.py", line 491, in per_interact
    self.update()
  File "C:\Renpy\renpy\display\screen.py", line 700, in update
    self.screen.function(**self.scope)
  File "game/screens.rpy", line 207, in execute
    screen choice(items):
  File "game/screens.rpy", line 207, in execute
    screen choice(items):
  File "game/screens.rpy", line 210, in execute
    vbox:
  File "game/screens.rpy", line 211, in execute
    for i in items:
  File "game/screens.rpy", line 212, in execute
    textbutton i.caption action i.action
  File "C:\Renpy\renpy\ui.py", line 1015, in _textbutton
    text = renpy.text.text.Text(label, style=text_style, substitute=substitute, scope=scope, **text_kwargs)
  File "C:\Renpy\renpy\text\text.py", line 2079, in __init__
    self.set_text(text, scope, substitute) # type: ignore
  File "C:\Renpy\renpy\text\text.py", line 2216, in set_text
    i, did_sub = renpy.substitutions.substitute(i, scope, substitute) # type: ignore
  File "C:\Renpy\renpy\substitutions.py", line 373, in substitute
    s = interpolate(s, variables) # type: ignore
  File "C:\Renpy\renpy\substitutions.py", line 86, in interpolate
    raise e
  File "C:\Renpy\renpy\substitutions.py", line 78, in interpolate
    value = renpy.python.py_eval(code, {}, scope)
  File "C:\Renpy\renpy\python.py", line 1218, in py_eval
    return py_eval_bytecode(code, globals, locals)
  File "C:\Renpy\renpy\python.py", line 1211, in py_eval_bytecode
    return eval(bytecode, globals, locals)
  File "<none>", line 1, in <module>
  File "C:\Renpy\renpy\revertable.py", line 214, in __getitem__
    rv = list.__getitem__(self, index)
IndexError: list index out of range

Windows-10-10.0.26100 AMD64
Ren'Py 8.3.7.25031702
PorMa 1.0
Thu May 15 15:49:54 2025
What am I doing wrong and how do I do it correctly?

User avatar
enaielei
Miko-Class Veteran
Posts: 551
Joined: Fri Sep 17, 2021 2:09 am
Organization: enaielei
Tumblr: enaielei
Deviantart: enaielei
Github: enaielei
Skype: enaielei
Soundcloud: enaielei
itch: enaielei
Discord: enaielei#7487
Contact:

Re: Can I copy a random character into another character?

#9 Post by enaielei »

https://www.renpy.org/doc/html/other.html#renpy-random wrote:
  • renpy.random.randint(a, b)
Return a random integer such that a <= N <= b.
Meaning the range is inclusive, so it should be "renpy.random.randint(0, len(preset_actors) - 1)"

Also, randint already returns an integer, so no need to type cast the stored value using "int()"

I'm still unsure of what you're doing in your example, but it seems like it can be improved.
Please consider supporting me if you like what I do :D
https://paypal.me/enaielei?country.x=PH&locale.x=en_US

giorgi1111
Veteran
Posts: 306
Joined: Sat May 04, 2024 10:40 pm
Contact:

Re: Can I copy a random character into another character?

#10 Post by giorgi1111 »

maybe this ll help with chars: https://github.com/Habitacle/battle-engine


what exactly you need? when you randomly choose char it must have other chars stats and skills? (if choosen is char 1 it must have some stats from char 2 and and some stats from char3?)

Post Reply