How to change position of object/datamap inside of an array

If you are requesting technical assistance with Twine, please specify:
Twine Version: 2.3.14
Story Format: Sugarcube 2.34.1

in my project the position of a unit inside the party is very important, so i want the player to be able to change them around at will.
the code parts look like this.

example unit defined as object/datamap (don’t know the difference):

<<set $Healer1 = {
	"name" : "Jennifer",
	"skill1": "Heal",
	"skill2": "Staff",
	"HP": "90",
	"Atk": "70",
	"Def": "60",
	"SpA": "70",
	"SpD": "80",
	"Spe": "110",
	"weapon1": "WoodStaff",
	"weapon2": "ManaRing",
	"friendship": "0",
	"pic":
	"<img src='https://i.ytimg.com/vi/LyOOf3GrpcQ/mqdefault.jpg'
			style='width:200px;height:200px;' />",
}>>

i then push that object (and others like it) into an array called “$PlayerParty”
and this is the loop that i use to display the current party setup:

<<nobr>>

<<for _i = 0; _i < $PlayerParty.length; _i++>>
	<div class="twocolumn">
		<div style="text-align: left">
			$PlayerParty[_i].pic
		</div>

		<div style="text-align: left">
			''$PlayerParty[_i].name''
				<br>
				<br>
			<<if $PlayerParty.length gt 1>>
				<<capture _i>>
					<<link "''take $PlayerParty[_i].name out''
							<br><br>">>
						<<set $PlayerBank.push($PlayerParty[_i])>>
						<<set $PlayerParty.deleteAt(_i)>>
						<<goto "Player Party">>
					<</link>>
				<</capture>>
			<</if>>
			''$PlayerParty[_i].skill1''
				<br>
				<br>
			''$PlayerParty[_i].skill2''
				<br>
				<br>
		</div>
	</div>
<</for>>

<</nobr>>

i want to add an option where theres a second link under the first one that allow the player to move that unit to a specific place in the array,
because certain skills will will bahave differently depending on the position of the unit, like a “shield” skill is supposed to be most effective in the front.

i also want it to change inside the array beacuse that way the loop above serves as a visual represantation of the units order.

For the record, that’s a generic JavaScript object, not a JavaScript Map object (a “datamap” is a similar Harlowe concept).

Anyways, if you want to swap two array elements, then it’s just a three step shuffle of data. Simply copy one array element to a temporary variable, then overwrite that element with the value in the other element, and then overwrite the element that wasn’t overwritten yet with the value in the temporary variable.

Your code for that within your <<for>> loop might look something like this:

<<if _i > 0>>
	<<capture _i>>
		<<link "Move up" "Player Party">>
			<<set _tempMember = $PlayerParty[_i]>>
			<<set $PlayerParty[_i] = $PlayerParty[_i - 1]>>
			<<set $PlayerParty[_i - 1] = _tempMember>>
		<</link>>
	<</capture>>
<</if>>
<<if _i < $PlayerParty.length - 2>>
	<<capture _i>>
		<<link "Move down" "Player Party">>
			<<set _tempMember = $PlayerParty[_i]>>
			<<set $PlayerParty[_i] = $PlayerParty[_i + 1]>>
			<<set $PlayerParty[_i + 1] = _tempMember>>
		<</link>>
	<</capture>>
<</if>>

That should give you a rough idea of how the code should look.

Enjoy! :slight_smile:

This works exactly like i wanted it to, thank you!
It does mess with my .twocolumn setup but i wanted to replace that with a table anyway, so i guess i’ll work on that next.

No problem. Glad to help.
 

Ah, then I should mention that SugarCube doesn’t make it easy to build tables using a <<for>> loop. The trick to get around the problem is to simply build the whole table as a string within a temporary variable and then, once the table is complete, simply print out that string.

Have fun! :wink:

1 Like

If you’re referring to line-breaks interspersed with <table> elements’ own children, then that hasn’t been an issue since v2.31.0.

Updated the HTML parser to ignore line-breaks where appropriate. E.g., removes the need to use a line-break control feature within <table> tags.

No, I’m referring to the fact that SugarCube complains if you create an HTML element like <tr> without also creating a </tr> at the exact same time. That can make building up complex HTML objects (like tables) from pieces difficult. That’s why it’s easier to just add it all to a string and then print that string out, since it builds the whole table at once.

I understand the point of the validation check, but it can be annoying when, instead of helping, it gets in the way of things and you have to do workarounds like this.

I’m unsure why you’d ever need to reasonably do that.

Using the original example from the OP.

Simple two cell:

<table>
<<for _i = 0; _i < $PlayerParty.length; _i++>>
	<tr>
		<td>
			$PlayerParty[_i].pic
		</td>
		<td>
			''$PlayerParty[_i].name''
				<br><br>
			<<if $PlayerParty.length gt 1>>
				<<capture _i>>
					<<link "''take $PlayerParty[_i].name out''" "Player Party">>
						<<run $PlayerBank.push($PlayerParty[_i])>>
						<<run $PlayerParty.deleteAt(_i)>>
					<</link>>
				<</capture>>
					<br><br>
			<</if>>
			''$PlayerParty[_i].skill1''
				<br><br>
			''$PlayerParty[_i].skill2''
				<br><br>
		</td>
	</tr>
<</for>>
</table>

With row spanning:

<table>
<<for _i = 0; _i < $PlayerParty.length; _i++>>
	<tr>
		<td @rowspan="$PlayerParty.length gt 1 ? 4 : 3">
			$PlayerParty[_i].pic
		</td>
		<td>
			''$PlayerParty[_i].name''
		</td>
	</tr>
	<<if $PlayerParty.length gt 1>>
		<tr>
			<td>
				<<capture _i>>
					<<link "''take $PlayerParty[_i].name out''" "Player Party">>
						<<run $PlayerBank.push($PlayerParty[_i])>>
						<<run $PlayerParty.deleteAt(_i)>>
					<</link>>
				<</capture>>
			</td>
		</tr>
	<</if>>
	<tr>
		<td>
			''$PlayerParty[_i].skill1''
		</td>
	</tr>
	<tr>
		<td>
			''$PlayerParty[_i].skill2''
		</td>
	</tr>
<</for>>
</table>

I’m not saying that there aren’t ways around it, and I don’t remember specific circumstances of the times where this has happened in the past off the top of my head, but it’s still annoying when you’re trying to do something which is the equivalent of:

<<= "<label>test">>
<<= "</label>">>

and you can’t, because it throws a “Error: cannot find a closing tag for HTML <label>” error message when trying to run the first line. When that happens it’s like, “Hey! Just run the next line of code! It’s right there!” It’s frustrating.

If I come across one of the cases where this was a problem I encountered, then I’ll let you know, but it’s still annoying, IMHO.

1 Like