0
\$\begingroup\$

before you mark it as duplicate, I want to say I have read this: I want to make a moddable game. How does this affect my programming language choice?

And it did not help me. Just for proof of concept, what would I add to

# main.py
import turtle as t
screen = t.Screen()
turt = t.Turtle()
for i in range(8):
    t.forward(100)
    t.right(45)
    t.backward(75)
screen.exitonclick()

to make it so that in another file, you could add something like

import main
main.t.color("red")

to make the turtle a different color.

Basically, what would I add to main.py to make it run the mod settings?

\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

Haha. Solved my own problem in less than 10 minutes.

So what I really wanted to do was to make a simple game modifiable.

So I created this (not necessarily smart or safe) method of making a configuration file that could be used for "modding".

This is what it looks like:

# main.py
import turtle as t
screen = t.Screen()
turt = t.Turtle()
cfg = open("mods.py","r")
cfg = cfg.read()
cfg = cfg.split("\n")
for i in range(len(cfg)):
    if i < len(cfg):
            exec(cfg[i])

for i in range(8):
    turt.forward(100)
    turt.right(45)
    turt.backward(75)
screen.exitonclick()

and in mods.py:

turt = t.Turtle()
turt.color("red")

Now before everyone gets all up in my face for using exec, let me just say that for a solution that was thought of quickly, I am okay with it. Plus, it wouldn't be that hard to add some sort of portection, ie if "os" not in cfg[i]: exec(cfg[i]) and all of that would really just be a matter of time consumption.

I had to add if i <len(cfg): because when I split at the \n that was adding a blank element at the end of the list it generated. I doubt that would raise an error, but no harm in being a little extra cautious.

Overall, I'm glad with my solution... I'll add security detection and stuff but as of right now it will work, because the game I am working on will not be a public game.

\$\endgroup\$
2
  • \$\begingroup\$ When you want to allow mods which implement logic in program code, you are always going to execute untrusted code in the context of your game program. That's simply a matter of fact. So the "don't use exec" arguments don't apply here. You are aware of the risks and taking them is part of your requirement. The only workarounds are to either limit modding to only changing the data files of the game or to add an interpreter for an own scripting language to your game which is too limited in functionality to cause any damage. Both options are very limiting to the modders. \$\endgroup\$ Commented Mar 11, 2017 at 10:42
  • \$\begingroup\$ This is extremely restrictive in terms of the code you can write in the mod file--if you add a loop or function in the mods.py file, it'll fail with an IndentationError. \$\endgroup\$ Commented Nov 8 at 21:43
0
\$\begingroup\$

Even if we're OK with the approach being totally unsafe, OP's answer still doesn't offer a sensible solution, since loops and functions, or anything multi-line can't be used in the mods file, and the mods file has to know about the existence of certain magic globals like t.

Here's a solution that lets you run a fully legitimate Python file. Note that this is completely unsafe and not suitable in any sort of public environment.

main.py:

import importlib.util
import pathlib
from turtle import Screen, Turtle

mods_path = pathlib.Path("mods.py")
spec = importlib.util.spec_from_file_location("mods", mods_path)
mods = importlib.util.module_from_spec(spec)
spec.loader.exec_module(mods)

turt = Turtle()
turt.color("green")

for _ in range(5):
    turt.forward(40)
    turt.left(46)

Screen().exitonclick()

mods.py:

from turtle import Screen, Turtle

t = Turtle()
t.color("red")
t.pensize(3)
Screen().bgcolor("black")

for _ in range(5):
    t.forward(50)
    t.right(26)

The turtle module is basically a global singleton, which facilitates this nicely. All drawing will occur on the same window. You can expose variables to the module from main.py if desired, via mods.t = t, in OP's example.

\$\endgroup\$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.