I Have Over 1000 Variables And Need To Speed Up My Game Using Twine Harlowe 3.1.0

Im using twine in the harlowe 3.1.0 language and I need to speed up my game! Can anyone help me? Im pretty sure the way to fix this is to find away to get the engine to stop cloning variables but not sure. Plz help ASAP.

I’ve not heard of Twine cloning variables before. Could you post a snippet of your code that you think may be causing this behavior?

If you’re worried that posting parts of your game might be spoiler-ish, you can use a lorem ipsum generator to make some nonsense placeholder text.

1 Like

Harlowe doesn’t currently have any way to limit the amount of game history that is stored, unfortunately.

1 Like

I believe that they’re talking about how variables get copied in the game’s history on every passage transition.

1 Like

Yea thats what I mean, my game takes 5-10 second to load per link, also this is my first post since I have been finding most of my answers on already made forums. Do you know how I could make snippets of code?

Is there anyway I could split it into multiple games using external links if I can’t stop the cloning proccess?

By “snippet” they just meant copy and paste some of your code that uses the variables here. We can’t suggest fixes without seeing the problem. When you do post the code, be sure to use the little </> button in the editor to format your code (it preserves spaces, tabs, and HTML tags that way).

I find it really hard to believe that your game actually needs 1000 variables. There must be something you’re doing that can be optimized to reduce the number.

1 Like

Im having to make multiple variables for over 50 characters, 10 seperate times.

(set: $QB1ARMSTRENGTH1 to  (random: 6,10))
(set: $QB1ACCURACY1 to  (random: 4,10))
(set: $QB1SCRAMBLING1 to  (random: 1,10))
(set: $QB2ARMSTRENGTH1 to  (random: 4,10))
(set: $QB2ACCURACY1 to  (random: 2,7))
(set: $QB2SCRAMBLING1 to  (random: 1,10))
(set: $HB1SPEED1 to  (random: 5,10))
(set: $HB1POWER1 to  (random: 1,10))
(set: $HB1CATCH1 to  (random: 3,10))
(set: $HB2SPEED1 to  (random: 3,10))
(set: $HB2POWER1 to  (random: 1,8))
(set: $HB2CATCH1 to  (random: 2,10))
(set: $HB3SPEED1 to  (random: 2,8))
(set: $HB3POWER1 to  (random: 1,6))
(set: $HB3CATCH1 to  (random: 1,8))
(set: $WR1SPEED1 to  (random: 5,10))
(set: $WR1CATCH1 to  (random: 7,10))
(set: $WR2SPEED1 to  (random: 3,10))
(set: $WR2CATCH1 to  (random: 4,10))
(set: $WR3SPEED1 to  (random: 7,10))
(set: $WR3CATCH1 to  (random: 2,8))
(set: $WR4SPEED1 to  (random: 2,9))
(set: $WR4CATCH1 to  (random: 1,6))
(set: $WR5SPEED1 to  (random: 1,7))
(set: $WR5CATCH1 to  (random: 1,5))
(set: $TE1SPEED1 to  (random: 5,8))
(set: $TE1CATCH1 to  (random: 4,7))
(set: $TE1BLOCK1 to  (random: 2,10))
(set: $TE2SPEED1 to  (random: 2,7))
(set: $TE2CATCH1 to  (random: 2,5))
(set: $TE2BLOCK1 to  (random: 1,7))
(set: $OG1SPEED1 to  (random: 4,10))
(set: $OG1POWER1 to  (random: 6,10))
(set: $OG2SPEED1 to  (random: 4,10))
(set: $OG2POWER1 to  (random: 6,10))
(set: $OG3SPEED1 to  (random: 2,7))
(set: $OG3POWER1 to  (random: 4,9))
(set: $OG4SPEED1 to  (random: 2,7))
(set: $OG4POWER1 to  (random: 4,9))
(set: $OT1SPEED1 to  (random: 6,10))
(set: $OT1POWER1 to  (random: 5,10))
(set: $OT2SPEED1 to  (random: 6,10))
(set: $OT2POWER1 to  (random: 5,10))
(set: $OT3SPEED1 to  (random: 2,6))
(set: $OT3POWER1 to  (random: 5,7))
(set: $OT4SPEED1 to  (random: 2,6))
(set: $OT4POWER1 to  (random: 5,7))
(set: $C1SPEED1 to  (random: 7,10))
(set: $C1POWER1 to  (random: 6,10))
(set: $C2SPEED1 to  (random: 4,8))
(set: $C2POWER1 to  (random: 3,7))
(set: $QB1one to (either: "Luke","Donald","Conner","Alex","Taylor","Kaden","Trey","Tracey"))
(set: $QB2one to (either: "Luke","Donald","Conner","Alex","Taylor","Kaden","Trey","Tracey"))
(set: $HB1one to (either: "Luke","Donald","Conner","Alex","Taylor","Kaden","Trey","Tracey"))
(set: $HB2one to (either: "Luke","Donald","Conner","Alex","Taylor","Kaden","Trey","Tracey"))
(set: $HB3one to (either: "Luke","Donald","Conner","Alex","Taylor","Kaden","Trey","Tracey"))
(set: $WR1one to (either: "Luke","Donald","Conner","Alex","Taylor","Kaden","Trey","Tracey"))
(set: $WR2one to (either: "Luke","Donald","Conner","Alex","Taylor","Kaden","Trey","Tracey"))
(set: $WR3one to (either: "Luke","Donald","Conner","Alex","Taylor","Kaden","Trey","Tracey"))
(set: $WR4one to (either: "Luke","Donald","Conner","Alex","Taylor","Kaden","Trey","Tracey"))
(set: $WR5one to (either: "Luke","Donald","Conner","Alex","Taylor","Kaden","Trey","Tracey"))
(set: $TE1one to (either: "Luke","Donald","Conner","Alex","Taylor","Kaden","Trey","Tracey"))
(set: $TE2one to (either: "Luke","Donald","Conner","Alex","Taylor","Kaden","Trey","Tracey"))
(set: $OG1one to (either: "Luke","Donald","Conner","Alex","Taylor","Kaden","Trey","Tracey"))
(set: $OG2one to (either: "Luke","Donald","Conner","Alex","Taylor","Kaden","Trey","Tracey"))
(set: $OG3one to (either: "Luke","Donald","Conner","Alex","Taylor","Kaden","Trey","Tracey"))
(set: $OG4one to (either: "Luke","Donald","Conner","Alex","Taylor","Kaden","Trey","Tracey"))
(set: $OT1one to (either: "Luke","Donald","Conner","Alex","Taylor","Kaden","Trey","Tracey"))
(set: $OT2one to (either: "Luke","Donald","Conner","Alex","Taylor","Kaden","Trey","Tracey"))
(set: $OT3one to (either: "Luke","Donald","Conner","Alex","Taylor","Kaden","Trey","Tracey"))
(set: $OT4one to (either: "Luke","Donald","Conner","Alex","Taylor","Kaden","Trey","Tracey"))
(set: $C1one to (either: "Luke","Donald","Conner","Alex","Taylor","Kaden","Trey","Tracey"))
(set: $C2one to (either: "Luke","Donald","Conner","Alex","Taylor","Kaden","Trey","Tracey"))

I have 10 of these and then even more code.

It looks like most of this could be replaced with datamaps, which would probably cut your amount of variables to between 10 to 100, depending on how you want to divide it up (either by assigning a datamap to each player or each team). But I’m not very familiar with Harlowe, so I don’t know whether a datamap of 100 items is faster than 100 variables.

Either way, take a look at the reference and see if it’s something that’ll work for you.

1 Like

Sorry for bothering you again but could you give me a small example of this using a few variables from my code because I don’t understand how this would work? Thanks for the help either way.

(set: $team1 to (dm: 
		"QB1ARMSTRENGTH1", (random: 6,10),
		"QB1ACCURACY1", (random: 4,10)
	)
)
(print: $team1's "QB1ARMSTRENGTH1")

Like that, I believe. I don’t use Harlowe except for occasionally trying to help people out, so hopefully the syntax is correct.

1 Like

Wait what would I replace with that code? The either code?

(set: $QB1ARMSTRENGTH1 to  (random: 6,10))
(set: $QB1ACCURACY1 to  (random: 4,10))

becomes

(set: $team1 to (dm: 
		"QB1ARMSTRENGTH1", (random: 6,10),
		"QB1ACCURACY1", (random: 4,10)
	)
)

I only showed two of them to keep the example short, but you can add the rest below those two using the same format. Be sure to end each line with a comma (with the exception of the final line) or else it’ll error.

Edit: Oh, and like in the print statement in the first example, instead of accessing the value using $QB1ARMSTRENGTH1, you’ll now access it using $team1's "QB1ARMSTRENGTH1".

1 Like

I could be wrong here, but I don’t think replacing a number of variables storing primitives with datamaps will be faster in Harlowe. Cleaner, perhaps, but not faster. Each time you modify any value within a datamap, the entire map will be copied rather than a single primitive value.

I wouldn’t think that Harlowe should have issues with a large number of variables—especially that mostly hold primitives. Harlowe also does not clone on passage transitions, AFAIK, but on access, so it’s curious that you’re seeing the slowdown on activating passage links. Are you doing something involved each turn? E.g., looping, lots of calculations, etc.

1 Like

Harlowe’s Passage Transition process and associated History system works a little different to that of SugarCube, and is based on Object Prototype inheritance instead of a collection of Moments.

eg. the following is a very basic representation of how Harlowe’s History is structured.

/* 1st Moment... */
state: {
	name: "Jane Doe",
	age: 21,
	tags: ["aaa", "bbb", "ccc"]
}

/* 2nd Moment... */
state: {
	prototype: {
		name: "Jane Doe",
		age: 21,
		tags: ["aaa", "bbb", "ccc"]
	}
}
/* 3rd Moment... , variable 'location' is created */
state: {
	prototype: {
		prototype: {
			name: "Jane Doe",
			age: 21,
			tags: ["aaa", "bbb", "ccc"]
		}
	},
	location: "Home"
}
/* 4th Moment, new tag is added. */
state: {
	prototype: {
		prototype: {
			prototype: {
				name: "Jane Doe",
				age: 21,
				tags: ["aaa", "bbb", "ccc"]
			}
		},
		location: "Home"
	}
	tags: ["aaa", "bbb", "ccc", "ddd"]
}

note: The cloning of the ‘tags’ collection in the 4th Moment is actually performed by the (set:) macro that added the “ddd” value to the collection. eg. (set: $tags to it + (a: "ddd"))
And that cloning action is performed every time a collection object (like an Array or Data-Map) is modified using the (set:) family of macros.

2 Likes

Right now I’m just loading a ton of values for future use, almost no work in the game, just a basic interface.

1 Like

Just a thought: you don’t need to initialize all the variables that you’re ever going to need right at the beginning. You can simply create a variable by using it. – i.e.

(set: $myNewVariable to "whatever")

Obviously it’s a good idea to keep a separate note of where you first used a variable for debugging purposes. (Or, in my case, coding paranoia.)

So how about initializing only the absolutely essential variables right at the start? I know it seems like you’re only putting off the evil hour – but that’s life! :wink:

I found out I can just make a twine game and then make new passages with it but the rest I do in notes by exporting file because it increases performance in every aspect including editing code and loading passages with most being instant and some being up to 5 times faster. But thanks for the help anyways!

1 Like