+1 vote
by (1.1k points)
retagged by

So, I managed to confuse the heck out of myself while trying code one. Not sure why, I've done things which seem much more complicated.

The goal is to have a datamap of locations, such as.

(set: $boxes to (datamap: "green" , 0 , "blue" , 0 , "red" , 0 , "purple" , 0 , "yellow" , 0 , "neon paisley" , 0))

And have a count of items,

(set: $marbles to 23)

Then assign a marble to randomly picked boxes until out of marbles. It's okay if a box receives multiple marbles or if boxes receive none.

This one is breaking my head. o_O

2 Answers

0 votes
by (1.1k points)
 
Best answer

Okay, I figured out the missing piece: the (range:) macro to control the number of iterations.

 

{
(set: $boxes to (datamap: "green" , 0 , "blue" , 0 , "red" , 0 , "purple" , 0 , "yellow" , 0 , "neon paisley" , 0))
(set: $marbles to 12)
(for: each _drop , ...(range: 1 , $marbles))[
	(set: $boxes's (either: ...(datanames: $boxes)) to it + 1)
	]
}

 

+1 vote
by (159k points)

You need to state the name and full version number of the Story Format you are using, as answers can be different for each one. As you have not stated if you are using Harlowe v1.2.4 or v2.0.1 I will assume you are using the default Harlowe v1,2,4, which unfortunately does not have a built-in looping feature nor temporary variables..

1. Randomly determining the name of a box.
You can use the (datanames: ) macro to obtain the names of each of the boxes within your datamap, then use the (shuffled: ) macro to randomly sort those names, and then use the first name from the sorted list to access and update a box.

(set: $boxes to (datamap: "green" , 0 , "blue" , 0 , "red" , 0 , "purple" , 0 , "yellow" , 0 , "neon paisley" , 0))

boxes: (print: $boxes)

(set: $boxNames to (datanames: $boxes))
(set: $shuffledNames to (shuffled: ...$boxNames))
(set: $firstBox to $shuffledNames's 1st)

firstBox: firstBox

(set: $boxes's ($firstBox) to it + 1)

boxes: (print: $boxes)

 

2. Looping in Harlowe v1.2.4.
There are a number of way you can emulate this functionality, although each one it's downside. The following solution uses the conditionally replacing the contents of a named hook method.

2a, Setup the loop framework.

(set: $boxes to (datamap: "green" , 0 , "blue" , 0 , "red" , 0 , "purple" , 0 , "yellow" , 0 , "neon paisley" , 0))
(set: $marbles to 23)

boxes: (print: $boxes)
marbles: (print: $marbles)

[(display: "Increment Random Box Count")]<workarea|

boxes: (print: $boxes)
marbles: (print: $marbles)

... the above defines a workarea named hook which is used to contain the code being executed for each iteration of the loop.

2a. Define the content you want to execute for each iteration within a child passage, in this example that passage is named Increment Random Box Count

(if: $marbles > 0)[
	(set: $box to (shuffled: ...(datanames: $boxes))'s 1st)
	(set: $boxes's ($box) to it + 1)
	(set: $marbles to it - 1)
	(if: $marbles > 0)[
		(replace: ?workarea)[(display: "Increment Random Box Count")]
	]
]

... the above first checks to see if there are any marbles left and if there are it randomly selects a box to add one to, it then decreases the number of available marbles by one and if there are still some left to allocate it uses a (replace:) macro to refresh the workarea.

2c. CSS used to hide the contents of the workarea, this is placed within the Story Stylesheet area.

tw-hook[name="workarea"] {
	display: none;
}

 

by (1.1k points)
I've updated the question, tagging the version numbers. Sorry about that!

The shuffled macro, I'd forgotten completely about. I also see some things in this I can use later... I'm not too good with <tags| yet. It's really fascinating to see examples of their use.

And good grief, the difference the for: loop makes!
This site has been placed in read-only mode. Please use the Interactive Fiction Community Forum instead.
...