Jump to content

quiz using dialog menu


testgenord1
 Share

You are about to reply to a thread that has been inactive for 1587 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

Hi!
I'm trying to build a multiple-choice quiz using dialog menus.
I'm running into three problems, which I can't seem to solve:

1. The dialog menu is supposed to automatically close down once all questions have been answered correctly, without clicking the "ignore" button
(might not be possible in SL; not the main issue).

2. the main issue: If the question is answered correctly, a new dialog menu is supposed to be opened.
If the question is answered wrongly, the dialog is supposed to go back to the initial menu, and so the player has to start all over again.
In order to achieve this, I need a way to define the false replies in a convenient manner,
without having to write down every single false answer.
I tried using "else" as an alternative, but this does not work, because now also correct replies end up being counted as "false".

3. Is there a way to open the dialog menus, and thus the questions, in a random fashion?
This would make the quiz more interesting.
(But I guess that's complicated.)

Since I'm still a beginner, I know the script is quite flawed.
I apologize for this in advance, but this is all I have been able to accomplish so far.

Here is the script:

integer listen_handle;
integer CHANNEL = -202; // dialog channel
list question1 = ["1/4", "2/4" ]; 
list question2 = ["1/6","2/6","3/6","4/6","5/6","6/6"]; // a submenu

default 
{
    state_entry() 
    {
        llListen(CHANNEL, "", NULL_KEY, ""); // listen for dialog answers (from multiple users)
    }
    
    touch_start(integer total_number) 
    {
        llSetTimerEvent(15);
        llDialog(llDetectedKey(0), "Which fraction equals 1/2?\n\n\n\n(Click 'ignore' to close the menu.)", question1, CHANNEL); // present dialog on click
    }
    listen(integer channel, string name, key id, string message) 
    {  
            if (message == "2/4")
            {  
                llPlaySound("ed124764-705d-d497-167a-182cd9fa2e6c ",1.0);
                llSay(0, "This is correct, " +name+ ".");
                llDialog(id, "Which fraction equals 1/3?\n\n\n\n(Click 'ignore' to close the menu.)", question2, CHANNEL);
                {
                if (message == "2/6")
                    { 
                    llPlaySound("ed124764-705d-d497-167a-182cd9fa2e6c ",1.0);
                    llSay(0, "This is correct, " +name+ ".");
                    llGiveInventory(id,llGetInventoryName(INVENTORY_OBJECT, 0));
                    llSetText(name+" has solved the quiz!",<1.0, 1.0, 1.0>,1.0);
                    llListenRemove(listen_handle);
                    }
                else
                    {
                    llSay(0, "This is wrong, " +name+ ".");
                    llDialog(id, "Which fraction equals 1/2?\n\n\n\n(Click 'ignore' to close the menu.)", question1, CHANNEL);
                    }
                }
            }        
    }
    timer()
    {
        llSetTimerEvent(0);
        llListenRemove(listen_handle);        
    }
}


 

Edited by testgenord1
Link to comment
Share on other sites

you are heading for a coding disaster with the elseif elseif approach.  Another way is to use calculation to keep everything in sync and allowing for easier expansion

essentially calculation allows us to add as many questions as we like to the quiz list without having to modify the code because of the additions

in the calculation case I would go with a strided list of 3 elements per 'record'

example is p-coded off the top my head. Shows the calculation method mostly. You can fill in the bits of code that you know already

list quiz = [
// question                     answer  picks (buttons) the pipe | is the delimiter 
   "What fraction equals 1/2?", "3/6", "1/6|2/6"|3/6|4/6|5/6|6/6",
   "What fraction equals 3/5?", "9/15", "3/15|6/15"|9/15|12/15|15/15",
   "What is 6 times 7?",        "42",  "36|42|67|76"
];

integer CHANNEL = -16;

integer index;
integer count;
string answer;



state_entry()
{
    count = llGetListLength(quiz);
}

touch_start(...)
{
   // get a question not the same as the last question
   //  this method is one way. Other methods of 'random' can be used also
   // index must be a value in range [0 < count]
   // 3 is the width of the stride. 0 * 3 = 0. 1 * 3 = 3. 2 * 3 = 6. etc
   index = (index + 1 + (integer)llFrand(count - 1)) % count * 3;
 
   // get the question
   string question = llList2String(quiz, index);
   // get the answer
   // 1 is the offest to the answer element. 0 + 1 = 1. 3 + 1 = 4. 6 + 1 = 7. etc
   answer = llList2String(quiz, index + 1);    
   // get the picks (buttons)
   // 2 is the offset to the picks element. 0 + 2 = 2. 3 + 2 = 5. 6 + 2 = 8. etc
   string picks = llList2String(quiz, index + 2);
   
   // parse the picks to a list on the pipe | delimiter
   // prepend a Dunno button
   list buttons = ["Dunno"] + llParseString2List(picks, ["|"], []);

   // display dialog
   llDialog(llDetectedKey(0), question, buttons, CHANNEL);
}

listen( ... string message)
{
   if (message == answer)
   {
      .. you the winner! ...
   }
   else if (message == "Dunno")
   {
      .. you egg ! ... 
   }
   else
   {
	.. totes wrong !!! ..
   }
}

 

edit add. the line in state_entry:  count = llGetListLength(quiz);  Should be count = llGetListLength(quiz) / 3;

divided by 3,  as 3 is the width of the stride

 

Edited by Mollymews
tpyeo
  • Like 1
Link to comment
Share on other sites

Thank you so much for your help!
This script is amazing.
I've already learnt a lot just from going through the explanations.

I seem to have gotten it to work.
I'm posting it below the way I ended up doing it.
Should there be some misunderstandings on my part, or should you find other possible improvements, feel free to comment more.
I might come back here in case I have some more detailed questions.

Thank you very much, again!😊👍

//by Mollymews, 10/16/2019

list quiz = [
// question                     answer  picks (buttons) the pipe | is the delimiter 
   "What fraction equals 1/2?", "3/6", "1/6|2/6|3/6|4/6|5/6|6/6",
   "What fraction equals 3/5?", "9/15", "3/15|6/15|9/15|12/15|15/15",
   "What is 6 times 7?",        "42",  "36|42|67|76"
];

integer CHANNEL = -16;

integer index;
integer count;
string answer;

default
{
state_entry()
{
    count = llGetListLength(quiz) / 3;
    llListen(CHANNEL, "", NULL_KEY, ""); // listen for dialog answers (from multiple users) 
}
touch_start(integer num)
{
   // get a question not the same as the last question
   //  this method is one way. Other methods of 'random' can be used also
   // index must be a value in range [0 < count]
   // 3 is the width of the stride. 0 * 3 = 0. 1 * 3 = 3. 2 * 3 = 6. etc
   index = (index + 1 + (integer)llFrand(count)) % count * 3;
 
   // get the question
   string question = llList2String(quiz, index);
   // get the answer
   // 1 is the offest to the answer element. 0 + 1 = 1. 3 + 1 = 4. 6 + 1 = 7. etc
   answer = llList2String(quiz, index + 1);    
   // get the picks (buttons)
   // 2 is the offset to the picks element. 0 + 2 = 2. 3 + 2 = 5. 6 + 2 = 8. etc
   string picks = llList2String(quiz, index + 2);
   
   // parse the picks to a list on the pipe | delimiter
   // prepend a Dunno button
   list buttons = ["Dunno"] + llParseString2List(picks, ["|"], []);

   // display dialog
   llDialog(llDetectedKey(0), question, buttons, CHANNEL);
}

listen(integer channel, string name, key id, string message)
{
   if (message == answer)
   {
      llSay(0, "you the winner!");
   }
   else if (message == "Dunno")
   {
      llSay(0, "you egg !"); 
   }
   else
   {
    llSay(0, "totes wrong !!!");
   }
}
}


 

Edited by testgenord1
  • Like 2
Link to comment
Share on other sites

as Rolig reminds us, coding is more about logic, flow and methodology than anything else. Which means choosing the better algorithm for a particular task

this post has been more about choosing/knowing what the better algorithm is for this problem case. I got a bit expansive, code typing wise with this, to better demonstrate how the algorithm works as it does

am happy that you have learned something, and happy coding going forward :)

 

Link to comment
Share on other sites

Hi again!
I made some additions to the script above, and partly ran into some new smaller problems:

- I added a counter for the correct answers.
Thus, the player is supposed to have won the complete quiz after 3 correct answers.
It seems to work.
(The dialog still has to be closed down by hand, now, through the "ignore" button.
Any ideas of how to close down the dialog automatically will be appreciated.)

- I also made the dialog repeat itself automatically after each correct reply.
(This is a work-around, I guess, so I'm open for suggestions of improvement.)

- Now the biggest problem: There was one little problem in the original script above, which is, the section preventing the repetition of the same question

index = (index + 1 + (integer)llFrand(count - 1)) % count * 3;
 
   

seems to prevent the first question in the list from being asked
(at least, the first question was never asked, when I tested it).
So I ended up changing it into

index = (index + 1 + (integer)llFrand(count)) % count * 3;
 
   

Now, all 3 questions are asked.
Unfortunately, this seems to enable the repetition of the same question again.
If you have ideas of how to change that, I will be very grateful for suggestions.

Thank you very much in advance!
Here is the script containing the counter:

//by Mollymews, 10/16/2019
integer counter;
list quiz = [
// question                     answer  picks (buttons) the pipe | is the delimiter 
   "What fraction equals 1/2?", "3/6", "1/6|2/6|3/6|4/6|5/6|6/6",
   "What fraction equals 3/5?", "9/15", "3/15|6/15|9/15|12/15|15/15",
   "What is 6 times 7?",        "42",  "36|42|67|76"
];

integer CHANNEL = -16;

integer index;
integer count;
string answer;

default
{
state_entry()
{
    count = llGetListLength(quiz) / 3;
    llListen(CHANNEL, "", NULL_KEY, ""); // listen for dialog answers (from multiple users) 
}
touch_start(integer num)
{
   // get a question not the same as the last question
   //  this method is one way. Other methods of 'random' can be used also
   // index must be a value in range [0 < count]
   // 3 is the width of the stride. 0 * 3 = 0. 1 * 3 = 3. 2 * 3 = 6. etc
   index = (index + 1 + (integer)llFrand(count)) % count * 3;
 
   // get the question
   string question = llList2String(quiz, index);
   // get the answer
   // 1 is the offest to the answer element. 0 + 1 = 1. 3 + 1 = 4. 6 + 1 = 7. etc
   answer = llList2String(quiz, index + 1);    
   // get the picks (buttons)
   // 2 is the offset to the picks element. 0 + 2 = 2. 3 + 2 = 5. 6 + 2 = 8. etc
   string picks = llList2String(quiz, index + 2);
   
   // parse the picks to a list on the pipe | delimiter
   // prepend a Dunno button
   list buttons = ["Dunno"] + llParseString2List(picks, ["|"], []);

   // display dialog
   llDialog(llDetectedKey(0), question, buttons, CHANNEL);
}

listen(integer channel, string name, key id, string message)
{
   if (message == answer)
   {
      llSay(0, "you the winner!");
    // get a question not the same as the last question
   //  this method is one way. Other methods of 'random' can be used also
   // index must be a value in range [0 < count]
   // 3 is the width of the stride. 0 * 3 = 0. 1 * 3 = 3. 2 * 3 = 6. etc
   index = (index + 1 + (integer)llFrand(count)) % count * 3;
 
   // get the question
   string question = llList2String(quiz, index);
   // get the answer
   // 1 is the offest to the answer element. 0 + 1 = 1. 3 + 1 = 4. 6 + 1 = 7. etc
   answer = llList2String(quiz, index + 1);    
   // get the picks (buttons)
   // 2 is the offset to the picks element. 0 + 2 = 2. 3 + 2 = 5. 6 + 2 = 8. etc
   string picks = llList2String(quiz, index + 2);
   
   // parse the picks to a list on the pipe | delimiter
   // prepend a Dunno button
   list buttons = ["Dunno"] + llParseString2List(picks, ["|"], []);

   // display dialog
   llDialog(id, question, buttons, CHANNEL);
   counter ++;
        if(counter == 3) 
        {
            llPlaySound("ed124764-705d-d497-167a-182cd9fa2e6c ",1.0);
            llSay(0, "You have won the quiz, " +name+ ".");
            llGiveInventory(id,llGetInventoryName(INVENTORY_OBJECT, 0));
            llSetText(name+" has solved the quiz!",<1.0, 1.0, 1.0>,1.0);
            llResetScript();
        }
   }
   else if (message == "Dunno")
   {
      llSay(0, "you egg !"); 
   }
   else
   {
    llSay(0, "totes wrong !!!");
   }
}
}


 

Edited by testgenord1
  • Like 1
Link to comment
Share on other sites

4 minutes ago, testgenord1 said:

(The dialog still has to be closed down by hand, now, through the "ignore" button.
Any ideas of how to close down the dialog automatically will be appreciated.)

There's no way to close the dialog automatically, but the easy solution is to simply open a final dialog box with 

llDialog( id, "Congratulations!  You won!", ["OK"], CHANNEL);

That will replace any previous dialog that may still be open and will encourage the user to close it manually.

 

  • Like 2
Link to comment
Share on other sites

2 hours ago, testgenord1 said:

- Now the biggest problem: There was one little problem in the original script above, which is, the section preventing the repetition of the same question


index = (index + 1 + (integer)llFrand(count - 1)) % count * 3;
 
   

seems to prevent the first question in the list from being asked
(at least, the first question was never asked, when I tested it).
So I ended up changing it into


index = (index + 1 + (integer)llFrand(count)) % count * 3;
 
   

Now, all 3 questions are asked.
Unfortunately, this seems to enable the repetition of the same question again.
If you have ideas of how to change that, I will be very grateful for suggestions.

 

oops! I should not have typed it all in one line

here is how this random method should be coded. Test example:

integer random;
integer count;

default
{
    state_entry()
    {
        count = 3;
    }

    touch_start(integer total_number)
    {
        random = (random + 1 + (integer)llFrand(count - 1)) % count;
        // random in [0, 1, 2] with count 3
        
        integer index = random * 3;
        // index in [0, 3, 6] 
        
        llOwnerSay("random: " + (string)random + " index: " + (string)index);
    }
}

i need more chemicals in my brains 😺

is a tiny issue with this as wrote. I show what that is and what the fix is

    state_entry()
    {
        count = 3;
        // seed random to the range so that the start value is in [0, 1, 2]
        // when we don't do this then the start value of random is 0
        //  0 + 1 + rnd(2) = 1 or 2. 0 will never generate as the 1st value
        random = (integer)llFrand(count);
        
    }

 

Edited by Mollymews
  • Like 2
Link to comment
Share on other sites

39 minutes ago, Rolig Loon said:

There's no way to close the dialog automatically, but the easy solution is to simply open a final dialog box with 

llDialog( id, "Congratulations!  You won!", ["OK"], CHANNEL);

That will replace any previous dialog that may still be open and will encourage the user to close it manually.

 

adding on to this as is quite good way to handle non-responses. We can  do the same when we make the non-response a part of the game mechanics

when we show the question dialog we start a timer like in OP original code.  When the player doesn't respond in the time allowed then we inform the player that is Game Over

example:

// globals
integer gameover;
key player;

touch_start(...)
{    
    if (gameover)
    {
        .. set up begin new game ..
 
        player = llDetectedKey(0);
        gameover = FALSE;
    }
    
    if (llDetectedKey(0) == player) // ignore touches from people not the player
    {
        ... calculate question ...    

        llSetTimerEvent(15.0);
        llDialog(...);
    }
}    
    
timer()
{
    gameover = TRUE;
    
    ... inform player about their results ...
    
    llDialog(player, "Game Over!", ["OK"], CHANNEL);    
}

listen( ... )
{
    ... check the answers ...
    
    counter++;
    if (counter == 3)
    {
       gameover = TRUE;
       
       ... inform player about their results ,,,
    }
}

 

  • Like 2
Link to comment
Share on other sites

Hi again.
I implemented Molly's and Roligloon's ideas.
I also added more questions.
This time it's a vocabulary quiz German - English and so it's partly German.
I'm posting it below.
Ideas of improvement, as always, are welcome.
Thanks again.
 

//by Mollymews, 10/16/2019
integer gameover;
key player;

integer counter;
list quiz = [
// question                     answer  picks (buttons) the pipe | is the delimiter 
   "\n\nWas heißt auf Englisch \n\n\n'weil'", "because", "now|also|but|because",
   "\n\nWas heißt auf Englisch \n\n\n'obwohl'", "although", "although|now|but|because",
   "\n\nWas heißt auf Englisch \n\n\n'auch'", "also",  "although|also|but|because",
   "\n\nWas heißt auf Englisch \n\n\n'aber'", "but",  "although|now|but|because",
   "\n\nWas heißt auf Englisch \n\n\n'jetzt'", "now",  "although|also|now|because",
   "\n\nWas heißt auf Englisch \n\n\n'heute'", "today",  "yesterday|tomorrow|now|today",
   "\n\nWas heißt auf Englisch \n\n\n'morgen'", "tomorrow",  "yesterday|tomorrow|now|today",
   "\n\nWas heißt auf Englisch \n\n\n'gestern'", "yesterday",  "yesterday|tomorrow|now|today",
   "\n\nWas heißt auf Englisch \n\n\n'immer'", "always",  "always|also|although|again",
   "\n\nWas heißt auf Englisch \n\n\n'wieder'", "again",  "always|also|although|again"
];

integer CHANNEL = -202;

integer index;
integer count;
string answer;

default
{
state_entry()
{
    count = llGetListLength(quiz) / 3;
    llListen(CHANNEL, "", NULL_KEY, ""); // listen for dialog answers (from multiple users) 
}
touch_start(integer num)
{
   key player = llDetectedKey(0);
   if (gameover)
    {
        gameover = FALSE;
    }
    
    if (llDetectedKey(0) == player) // ignore touches from people not the player
    {
   index = (index + 1 + (integer)llFrand(count)) % count * 3;
   // get the question
   string question = llList2String(quiz, index);
   answer = llList2String(quiz, index + 1);    
   string picks = llList2String(quiz, index + 2);
   list buttons = llParseString2List(picks, ["|"], []);
   llSetTimerEvent(60.0);
   llDialog(llDetectedKey(0), question, buttons, CHANNEL);
   }
}   
   
   timer()
{
    gameover = TRUE;
    llSay(0, "\n\nGame Over!\n\n\n");
    llResetScript(); 
}   

listen(integer channel, string name, key id, string message)
{
   if (message == answer)
   {
    llSay(0, "\n\nThat's correct, "+name+".\n\n\n");
   index = (index + 1 + (integer)llFrand(count)) % count * 3;
   string question = llList2String(quiz, index);
   answer = llList2String(quiz, index + 1);    
   string picks = llList2String(quiz, index + 2);
   list buttons = llParseString2List(picks, ["|"], []);
   
   counter ++;
         if(counter < 10) 
        {
            llDialog(id, question, buttons, CHANNEL);
        }
        if(counter == 10) 
        {
            gameover = TRUE;
            llDialog( id, "\n\nCongratulations!  You win!", ["OK"], CHANNEL);
            //llDialog( id, "Congratulations!  You won!\n\n\nUm das Menü zu schließen, klicke auf den Feldern auf 'ignore' ", buttons, CHANNEL);
            llPlaySound("ed124764-705d-d497-167a-182cd9fa2e6c ",1.0);
            llSay(0, "\n\nYou have won the quiz, " +name+ ".\n\n\n");
            llSetText(name+" has solved the quiz!",<1.0, 1.0, 1.0>,1.0);
            llSleep(4.0);
            llSay(0, "\n\nDies ist deine Medaille, " +name+ ".\n\n Klicke auf 'behalten'\n\n\n");
            llRezAtRoot(llGetInventoryName(INVENTORY_OBJECT, 1), llGetPos() + <1.0,3.0,1.0>,ZERO_VECTOR,llEuler2Rot(<0,90,0> * DEG_TO_RAD)*llGetRot(),0);
            llSleep(2.0);
            llGiveInventory(id,llGetInventoryName(INVENTORY_OBJECT, 0));
            llSleep(4.0);
            llSay(0, "\n\nHier ist der Basketball, " +name+ ".\n\n Klicke im Menü auf 'ja'\n\n\n");
            llRezAtRoot(llGetInventoryName(INVENTORY_OBJECT, 0), llGetPos() + <1.0,3.0,-1.0>,ZERO_VECTOR,llEuler2Rot(<0,0,0> * DEG_TO_RAD)*llGetRot(),0);
            llResetScript();
        }
   }
   
   else
   {
    llSay(0, "\n\nYou lose, "+name+".\n\nStart again.\n\n\n");
    llResetScript();
   }
}
}

 

Link to comment
Share on other sites

you don't need to put my name in your script.  As a body of work your script is your work, not mine. Is how copyright works, as it should

what code I have shown here, expressed in the language - lslish, are textual explanations of commonly-held and known algorithms, the roots of which go back  centuries in various mideast and eastern cultures.  If I were to show these algorithms in another language, like Spanish for example, it wouldn't make me the originator/proprietor/owner/holder of the algorithms

  • Like 1
Link to comment
Share on other sites

  • 1 month later...

Hi again.
Thank you all again for your support in building this script, which I'm still using.
There is just one little addition I would like to implement, which is, I would like to make sure the random questions in the dialog are only asked once in one round of playing,
so that the same questions don't show up again and again in the same round.

Somebody in a different forum suggested the following method, which probably makes a lot of sense, but I haven't been able to integrate it into the original script.
Do you maybe know how this could be done?
Thank you very much in advance.

Here is the suggestion from the other user:

 list questions = ["a", "b", "c", "d", "e"]; // The list "questions" is called "quiz" in the original script.

default
{
    state_entry()
    {
        llOwnerSay("Initialisation ...");
    }
    touch_start(integer number)
    {
        integer len = llGetListLength(questions); // see above.
        if (len <= 0) llResetScript();
        integer random = llRound(llFrand(len)) - 1; // The integer "random" seems to be similar to "count" in the original script.
        string question = llList2String(questions, random);.
        questions = llDeleteSubList(questions, random, random);.
    }
}

 

Link to comment
Share on other sites

If the questions list is strided, with the answers in there too, you could use llListRandomize to shuffle it at the start of a quiz, and then work through it sequentially.

If you have parallel question and answer lists, maybe you could create a third list for the order in which to ask the questions, starting of as [1, 2, 3, 4, …], use llListRandomize on that, and then work through it sequentially to get the numbers of the questions to ask.

 

  • Like 1
Link to comment
Share on other sites

Which method are you using? The strided list or the parallel question and answer lists, with the extra list with the order of the questions?

Edit:

Ok, so looking back I see you're using a strided list. Hopefully this minimalist script (which doesn't listen for the answers but just puts the questions up as a dialog using a throw-away channel) illustrates how it could be done:

list quiz = [
// question                     answer  picks (buttons) the pipe | is the delimiter 
   "\n\nWas heißt auf Englisch \n\n\n'weil'", "because", "now|also|but|because",
   "\n\nWas heißt auf Englisch \n\n\n'obwohl'", "although", "although|now|but|because",
   "\n\nWas heißt auf Englisch \n\n\n'auch'", "also",  "although|also|but|because",
   "\n\nWas heißt auf Englisch \n\n\n'aber'", "but",  "although|now|but|because",
   "\n\nWas heißt auf Englisch \n\n\n'jetzt'", "now",  "although|also|now|because",
   "\n\nWas heißt auf Englisch \n\n\n'heute'", "today",  "yesterday|tomorrow|now|today",
   "\n\nWas heißt auf Englisch \n\n\n'morgen'", "tomorrow",  "yesterday|tomorrow|now|today",
   "\n\nWas heißt auf Englisch \n\n\n'gestern'", "yesterday",  "yesterday|tomorrow|now|today",
   "\n\nWas heißt auf Englisch \n\n\n'immer'", "always",  "always|also|although|again",
   "\n\nWas heißt auf Englisch \n\n\n'wieder'", "again",  "always|also|although|again"
];

integer stride = 3;
integer quiz_length;
integer question_number;
string correct_answer; // so it's available in the listen event when the user has made their choice

default
{
    state_entry ()
    {
        quiz = llListRandomize (quiz, stride);
        quiz_length = llGetListLength (quiz);
    }

    touch_start (integer count)
    {
        if (question_number * stride >= quiz_length)
        {
            llDialog (llDetectedKey (0), "\n\nThat's all, folks!", [], -999);
            llResetScript ();
        }
        else
        {
            string question = llList2String (quiz, question_number * stride);
            correct_answer = llList2String (quiz, question_number * stride + 1);
            list choices = llParseString2List (llList2String (quiz, question_number * stride + 2), ["|"], []);
            llDialog (llDetectedKey (0), question, choices, -999);
            ++question_number;
        }
    }
}

 

Edited by KT Kingsley
Link to comment
Share on other sites

if you are using the strided list example. The stride is 3. So something like:
 

count = llListLength(quiz) / 3;
index = 0;



if (index++ == count)
{
   list quiz = llListRandomize(quiz, 3);
   index = 0;
}


string question = llList2String(quiz, 3 * index);
string answer = llList2String(quiz, 3 * index + 1);
string picks = llList2String(quiz, 3 * index + 2);

 

Link to comment
Share on other sites

Hi again!
Thank you very much for your ideas.
It looks as though I've been successful through your help.
I'm posting the script below.

The script does the following:

With each correct answer a part of a transparent linkset is made visible, which serves as a victory podium.
The linkset consists of 10 transparent childprims,
and one non-transparent childprim as starting button (childprim 11).
Once all childprims are visible, the user is teleported on top of the prim containing the script as a victory honoring.

There is always room for improvement, so feel free to comment (for example, the 3 different particle systems are a bit clumsy).

Here is the script:
Thank you very much again!

//https://community.secondlife.com/forums/topic/444235-quiz-using-dialog-menu/
integer gListen;
integer time;
integer seconds;
key user;
list lChildprims = [2,3,4,5,6,7,8,9,10,1];
integer iChildprim;
integer total;
integer countChildprims;
integer count;
integer gameover;
integer CHANNEL = -808;
integer index;
string answer;

list lSounds = [ "6e517cde-066f-455e-8c6b-f1c33be90dea", "611c9470-507e-4471-8ce2-5ed0962e4c85", "b1e78aa1-52b7-482f-a48a-57e3ddff81fc", "7b978d05-b3bd-4e6f-892f-92dc4845ddd8", "64319812-dab1-4e89-b1ca-5fc937b8d94a", "720ff3dd-8fc6-4523-9670-139df57527f3"];

list quiz = [
// question                     answer  picks (buttons) the pipe | is the delimiter 
   "\n \nWho lives in Buckingham Palace?\n \n \n", "Queen", "Queen|Ministers|Lords",
   "\n \nThe White House:\n \nHere lives the President of ...?\n \n \n", "USA", "Britain|Australia|USA",
   "\n \nWhich country is the biggest?\n \n \n", "Canada", "USA|Canada|Britain",
   "\n \nWhere can you find the 'Statue of Liberty'?\n \n \n", "New York City", "Los Angeles|New York City|Washington",
   "\n \nWhich is the capital of the United States?\n \n \n", "Washington", "New York City|Los Angeles|Washington",
   "\n \nWhat was found in California in 1849?\n \n \n", "gold", "oil|gold|natural gas",
   "\n \nWhat did Levi Strauss invent?\n \n
   The first ...", "blue jeans", "car|computer|blue jeans",
   "\n \nWhich material are blue jeans made of?\n \n \n", "cotton", "wool|silk|cotton",
   "\n \nWhat is the name of the 'Freiheits-Statue' in English?\n \n
   The 'Statue of ...'\n \n", "Liberty", "Life|Light|Liberty",
   "\n \nWhat is the capital of Great Britain?\n \n \n", "London", "Washington|London|Sidney"
];

integer stride = 3;
integer quiz_length;
integer question_number;
string correct_answer; // so it's available in the listen event when the user has made their choice
confetti()
        {
            llParticleSystem([PSYS_PART_FLAGS,
            PSYS_PART_EMISSIVE_MASK,
            PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_EXPLODE ,
            PSYS_PART_START_ALPHA,0.5,
            PSYS_PART_END_ALPHA,0.1,
            PSYS_PART_START_COLOR,<1,1,1> ,
            PSYS_PART_END_COLOR,<1,1,1> ,
            PSYS_PART_START_SCALE,<1,1,0>,
            PSYS_PART_END_SCALE,<1,1,0>,
            PSYS_PART_MAX_AGE,4.0,
            PSYS_SRC_MAX_AGE,1.0,
            PSYS_SRC_ACCEL,<0.10,-0.5,-5>,
            PSYS_SRC_BURST_PART_COUNT,1000,
            PSYS_SRC_BURST_RADIUS,1,
            PSYS_SRC_BURST_RATE,5.0,
            PSYS_SRC_BURST_SPEED_MIN,5,
            PSYS_SRC_BURST_SPEED_MAX,15,
            PSYS_SRC_ANGLE_BEGIN,PI,
            PSYS_SRC_ANGLE_END,PI,
            PSYS_SRC_OMEGA,<0,0,0>,
            PSYS_SRC_TEXTURE, llGetInventoryName(INVENTORY_TEXTURE, 0), 
            PSYS_SRC_TARGET_KEY, NULL_KEY
            ]);
        }
        
        confetti1()
        {
            llParticleSystem([PSYS_PART_FLAGS,
            PSYS_PART_EMISSIVE_MASK,
            PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_EXPLODE ,
            PSYS_PART_START_ALPHA,0.5,
            PSYS_PART_END_ALPHA,0.1,
            PSYS_PART_START_COLOR,<1,1,1> ,
            PSYS_PART_END_COLOR,<1,1,1> ,
            PSYS_PART_START_SCALE,<1,1,0>,
            PSYS_PART_END_SCALE,<1,1,0>,
            PSYS_PART_MAX_AGE,4.0,
            PSYS_SRC_MAX_AGE,1.0,
            PSYS_SRC_ACCEL,<0.10,-0.5,-5>,
            PSYS_SRC_BURST_PART_COUNT,1000,
            PSYS_SRC_BURST_RADIUS,1,
            PSYS_SRC_BURST_RATE,5.0,
            PSYS_SRC_BURST_SPEED_MIN,5,
            PSYS_SRC_BURST_SPEED_MAX,15,
            PSYS_SRC_ANGLE_BEGIN,PI,
            PSYS_SRC_ANGLE_END,PI,
            PSYS_SRC_OMEGA,<0,0,0>,
            PSYS_SRC_TEXTURE, llGetInventoryName(INVENTORY_TEXTURE, 1), 
            PSYS_SRC_TARGET_KEY, NULL_KEY
            ]);
        }
    
    confetti2()
        {
            llParticleSystem([PSYS_PART_FLAGS,
            PSYS_PART_EMISSIVE_MASK,
            PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_EXPLODE ,
            PSYS_PART_START_ALPHA,0.5,
            PSYS_PART_END_ALPHA,0.1,
            PSYS_PART_START_COLOR,<1,1,1> ,
            PSYS_PART_END_COLOR,<1,1,1> ,
            PSYS_PART_START_SCALE,<1,1,0>,
            PSYS_PART_END_SCALE,<1,1,0>,
            PSYS_PART_MAX_AGE,4.0,
            PSYS_SRC_MAX_AGE,1.0,
            PSYS_SRC_ACCEL,<0.10,-0.5,-5>,
            PSYS_SRC_BURST_PART_COUNT,1000,
            PSYS_SRC_BURST_RADIUS,1,
            PSYS_SRC_BURST_RATE,5.0,
            PSYS_SRC_BURST_SPEED_MIN,5,
            PSYS_SRC_BURST_SPEED_MAX,15,
            PSYS_SRC_ANGLE_BEGIN,PI,
            PSYS_SRC_ANGLE_END,PI,
            PSYS_SRC_OMEGA,<0,0,0>,
            PSYS_SRC_TEXTURE, llGetInventoryName(INVENTORY_TEXTURE, 2), 
            PSYS_SRC_TARGET_KEY, NULL_KEY
            ]);
        }    
default
{
    state_entry ()
    {
        quiz = llListRandomize (quiz, stride);
        quiz_length = llGetListLength (quiz);
        llSetClickAction(CLICK_ACTION_TOUCH);
        llSetLinkPrimitiveParamsFast(LINK_SET,[PRIM_COLOR, ALL_SIDES, <1.0, 1.0, 1.0>,0.0,PRIM_PHANTOM,TRUE]);
        llSetLinkPrimitiveParamsFast(11, [PRIM_COLOR, ALL_SIDES, <1.0, 1.0, 1.0>, 1.0]);
        //count = llGetListLength(quiz) / 3;
    }

    touch_start (integer num)
    {                
        gListen=llListen(CHANNEL, "", NULL_KEY, ""); // listen for dialog answers (from multiple users) 
        user = llDetectedKey(0);
        llRegionSayTo(user,0,"Hello, "+ (string)llDetectedName(0) + "!");
        llSetClickAction(8);
        if (llDetectedKey(0) == user) // ignore touches from people not the player
        {
        //index = (index + 1 + (integer)llFrand(count)) % count * 3;
        //}
            llSetTimerEvent(1.0);
            string question = llList2String (quiz, question_number * stride);
            correct_answer = llList2String (quiz, question_number * stride + 1);
            list choices = llParseString2List (llList2String (quiz, question_number * stride + 2), ["|"], []);
            llDialog (llDetectedKey (0), question, choices, CHANNEL);
            ++question_number;
        }
    }
        timer()
   {
    ++seconds;
    time=60-seconds;
    llSetText("time left (seconds): "+(string)time, <1.0, 1.0, 1.0>, 1.0);
    if(time == 0)
    {
        llSay(0, "\n \nYour time is up!\n \n \n");
        llResetScript();
    }
    }   
        listen(integer channel, string name, key id, string message)
{
   if (message == correct_answer)
   {
    llPlaySound("ed124764-705d-d497-167a-182cd9fa2e6c ",1.0);
    llSay(0, "\nThat's correct, " + name + "!" + "\n \n \n");
    total = llGetListLength(lChildprims);
    integer iChildprim=llList2Integer(lChildprims,countChildprims++);
    llSetLinkPrimitiveParamsFast(iChildprim, [PRIM_COLOR, ALL_SIDES, <1.0, 1.0, 1.0>, 1.0,PRIM_PHANTOM,TRUE]);
    //if (question_number * stride == quiz_length)
    if (countChildprims == total) 
        {
            llListenRemove(gListen);
            countChildprims = 0;
            llSetLinkPrimitiveParamsFast(LINK_SET, [PRIM_PHANTOM,FALSE]);
            llSetText(name + " has won the quiz!", <1.0, 1.0, 1.0>, 1.0);
            llDialog( id, "\n \nGlückwunsch!  Du hast gewonnen!", ["OK"], CHANNEL);
            //llDialog (id, "\n\nThat's all, folks!", ["OK"], CHANNEL);
            //llRezAtRoot(llGetInventoryName(INVENTORY_OBJECT, 0), llGetPos() + <-8.0,5.0,-2.0>,ZERO_VECTOR,llEuler2Rot(<90,0,0> * DEG_TO_RAD)*llGetRot(),0);
            llGiveInventory(id,llGetInventoryName(INVENTORY_OBJECT,0));
            llPlaySound("ed124764-705d-d497-167a-182cd9fa2e6c ",1.0);
            llSay(0, "\n \nDies ist deine Medaille. \n \n Klicke auf 'Behalten', um sie zu behalten.\n \n \n");
            //llSay(0, "\n \nDu hast das Quiz gewonnen, " +name+ ".\n \n \nBerühre die Statue.");
            vector det_pos = llGetPos();
            llSleep(5.0);
            llTeleportAgent(user,"", det_pos+<0.0,0.0,1.5>, <0.0,1.0,0.0>);              
            llSleep(3.0); 
            llPlaySound("cheer-hooter-01",1.0);
            llSleep(2.0);
            confetti(); 
            llSleep(3.0);
            llPlaySound("cheer-hooter-01",1.0);
            llSleep(2.0);
            confetti1();
            llSleep(3.0);
            llPlaySound("cheer-hooter-01",1.0);
            llSleep(2.0);
            confetti2(); 
            llSleep(10.0);
            llParticleSystem([]);
            llResetScript();
        }       
    else
    {    
      string question = llList2String (quiz, question_number * stride);
      correct_answer = llList2String (quiz, question_number * stride + 1);
      list choices = llParseString2List (llList2String (quiz, question_number * stride + 2), ["|"], []);
      llDialog (id, question, choices, CHANNEL);
      ++question_number;
    }
    }
    else
    {
    llSetText("time left (seconds): 60", <1.0, 1.0, 1.0>, 1.0);
    llSay(0, "\n \nThat's wrong. \n \nYou lose, "+name+".\n \nStart the quiz again.\n \n \n");
    integer iWhichOne = (integer) llFrand( llGetListLength( lSounds ) );
    llPlaySound( llList2String(lSounds, iWhichOne), 1.0);
    llResetScript();
    }
    }
    }
Edited by testgenord1
  • Like 1
Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 1587 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...