Skip to main content

Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

Questionnaire contraption failure

A topic by A.C. Danvers created Jul 03, 2025 Views: 468 Replies: 5
Viewing posts 1 to 4
(4 edits) (+2)

I've been working on a project for the jam, and at the moment I am rather stuck on a prototype/contraption design. The behavior seems unexpected but I'm new to this and feel like I'm probably just missing something.

The idea was to make a prefab "question" box, akin to those weird psych questionnaires where you have to answer a series of questions to varying degrees of affirmative/negative. The current design looks like this:



The buttons on the right are meant to act not unlike a radio button: you click one, it goes inverted, uninverts the other two, and stores the new value (1, 0, or -1) in the hidden field above.

The prototype code looks like this:

on get_question do
 questionText.text
end
on set_question v do
 questionText.text:v
end
on get_answer do
 answerVal.text
end
on set_answer v do
 answerVal.text:v
end

With each button having a variant on this script: 


on click do
 me.parent.widgets.answerVal.text:1
 me.show:"invert"
 zeroB.show:"solid"
 minusB.show:"solid"
end

`answerVal` here is the invisible field. `answer` is set up as an attribute with the "number" type.

This works fine when testing within the prototype editor. I can click on the buttons, they toggle as expected, and if I peek at the value in the hidden field, it has the correct one for the currently depressed button.

If I make one of these contraptions on an actual card, though, it breaks. It looks like it's working, but `answer` doesn't actually get updated. Since the goal is to be able to sum the answers from a bank of these contraptions, that is obviously not useful, but I've tried a number of variations on how to handle the stored value and none of them seem to work.
Any ideas?

(+3)

So I'm not sure why you're using the "me.parent.widgets" method to access answerVal - you should just be able to refer to it like "answerVal.text:1" I think. Not sure if this would make a difference but there might be some weird edge case?

Another possibility (and I think this is more likely), would "answer" having a number type be a problem when it's being fed a text value from answerVal.text? You may need to convert it to a number as part of the "get" function. Alternatively, since you're storing an integer that can only take 3 possible values, instead of using a field it might be neater to use a slider with a minimum value of -1 and a maximum value of 1, then you can refer to that with slider1.value. Then as the value is numeric you wouldn't have to worry about conversion.

Developer (1 edit) (+3)

I had a go at creating this contraption as described:

as a paste-able example:

%%WGT0{"w":[{"name":"q1","type":"contraption","size":[185,24],"pos":[100,84],"def":"questionAsker","widgets":{"questionText":{"value":"A hotdog is a sandwich?"},"bp":{},"bz":{},"bn":{},"answerVal":{"value":"-1"}}}],"d":{"questionAsker":{"name":"questionAsker","size":[185,24],"resizable":1,"margin":[3,3,71,4],"description":"Your choices will be recorded for quality-assurance purposes.","version":1,"script":"on get_question do\n questionText.text\nend\non set_question v do\n questionText.text:v\nend\non get_answer do\n answerVal.data\nend\non set_answer v do\n answerVal.data:v\n view[]\nend\non view do\n each val wid in (bp,bz,bn) dict 1,0,-1\n  wid.show:(\"solid\",\"invert\")[answerVal.data~val]\n end\nend","attributes":{"name":["question","answer"],"label":["Question","Answer"],"type":["string","number"]},"widgets":{"questionText":{"type":"field","size":[115,20],"pos":[2,2],"locked":1,"border":0,"value":"Question?"},"bp":{"type":"button","size":[19,20],"pos":[120,2],"script":"on click do\n answerVal.data:1\n view[]\nend","text":"+","style":"rect"},"bz":{"type":"button","size":[19,20],"pos":[142,2],"script":"on click do\n answerVal.data:0\n view[]\nend","show":"invert","text":"0","style":"rect"},"bn":{"type":"button","size":[19,20],"pos":[164,2],"script":"on click do\n answerVal.data:-1\n view[]\nend","text":"-","style":"rect"},"answerVal":{"type":"field","size":[63,20],"pos":[120,-38],"show":"none","style":"plain","value":"0"}}}}}

Millie's on the right track with respect to using "me.parent.widgets". The Prototype interface has a ".widgets" attribute, so this works in the design preview, but the Contraption interface does not (otherwise there'd be no "abstraction barrier" and anything could freely fiddle with the innards of contraption instances).

I use the answerVal.data attribute for reading and writing the contents of the inner field so that the .answer attribute is exposed as a number, rather than a string. I do like Millie's suggestion to use a Slider instead; fewer possibilities for using it wrong. I also modified set_answer[] to call a contraption-level view[] function that updates the highlighting status of each button; otherwise writes to this attribute won't appear visually:

on set_answer v do
 answerVal.data:v
 view[]
end
on view do
 each val wid in (bp,bz,bn) dict 1,0,-1
  wid.show:("solid","invert")[answerVal.data~val]
 end
end

The buttons themselves now just set AnswerVal.data and invoke view[]:

on click do
 answerVal.data:1
 view[]
end

Does that help clear things up?

(+3)

Oh that is a much less clunky solution for handling the toggle effect! Will definitely have to borrow that as well.

Simpler question, how does one utilize the serialized contraptions like your paste? 

Developer (1 edit) (+3)

If you copy the blob of text starting with "%%WGT0" and ending in the final "}" to your operating system's clipboard, and then within Decker choose "Edit -> Paste Widgets" (or "Edit -> Paste" in web-decker), the sample contraption instance along with its prototype will be added to the current card. If you already have a prototype with an identical name and a lower "version" number, the revised prototype will upgrade any existing contraption in place.

The "%%WGT0{...}" format is literally how widgets (and their dependencies; referenced fonts and prototypes) are represented in the system clipboard by Decker.

(+2)

The "me.parent.widgets" thing is a mix of my understanding of the namespacing still being a little fuzzy, and also probably me just trying anything I could think of.

In any case: you were correct, re: converting to a number. That sparked off a memory of wondering why there was a "+0" in the "get_value" function in the counter example from the docs, and it seems the answer is that's the quickest way to make sure the text casts to a number. Once I did the same with the result of "answer", the widget works as intended now.

Thanks!