Trivia

From Second Life Wiki
Jump to: navigation, search
KBnote.png Note: Due to licensing issues, all contributions to this wiki have stopped and the articles that we posted are just being maintained. This is one of the projects that has gone further and for updates you are cordially invited to the project page on our wiki.

Created by Kira Komarov.

Introduction

Back again and providing you with free scripts; this time I have implemented a trivia engine (gosh, this brings me back) based on HamFon's original TriviaBot. This trivia script uses notecards as brain files with a specific syntax allowing it to be extended depending on the number of notecards you provide. I also supply a few notecards to get you going which are provided by HamFon and others. For a complete arsenal, download the full archive of text files from imatowns.com to supply to your trivia bot.

Features

  • Straight-forward operation: the script reads the notecards and starts the trivia engine. To turn the trivia game off, the owner must touch the prim once. To turn it back on again, touch the prim again.
  • Supports multiple notecards (careful, the notecards are read in and script memory consumption will go up depending on how many notecard brain files you have).
  • Supports a configurable time interval for answering the questions.
  • Keeps a score of all players. Anybody is free to enter the game as long as they give at least one valid answer. ;-)
  • Dumps a list of scores after a configurable multiple of questions.
  • The questions are randomised and removed from the pool of questions so the same question cannot come up in a session. When the trivia engine is out of questions, it resets itself and starts over.

Setup

Place some of the notecards from the next section and name them accordingly in a primitive. After that, drop the script from this page into the prim. That's it, you should be ready to go. If memory is an issue for your SIM, simply set the primitive scripts to not running. To start again, set the scripts to running.

Notecards

The trivia brain files you place in the prim containing the trivia engine must be named after the pattern: Trivia_Brain_1 for the first notecard, Trivia_Brain_2 for the second notecard, Trivia_Brain_3 for the third notecard... Trivia_Brain_N for the Nth notecard.

If you want more notecards you can download a bunch of files from from imatowns.com which will be compatible with this trivia engine. Download, unpack and just paste the contents into a notecard making sure you follow the naming convention for the notecard brain files.

Code

//////////////////////////////////////////////////////////
// [K] Kira Komarov - 2011, License: GPLv3              //
// Please see: http://www.gnu.org/licenses/gpl.html     //
// for legal details, rights of fair usage and          //
// the disclaimer and warranty conditions.              //
//////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////
// ------------------- CONFIGURATION ------------------ //
// The time alloted to answering a trivia question.
integer ANSWER_TIME = 20;
// What multiple of questions before a score will be sent
// out on the main chat.
integer SCORES_AFTER_QUESTIONS = 5;
//////////////////////////////////////////////////////////
// --------------------- INTERNALS -------------------- //
list user_scores = [];
list trivia_lines = [];
list trivia_cards = [];
key bQuery = NULL_KEY;
integer bLine = 0;
integer nRun = 0;
integer comHandle = 0;
list round_answers = [];
 
qNext(integer q) {
    if(!llGetListLength(trivia_lines)) {
        llSay(0, "All my questions have been exhausted... Resetting myself.");
        llResetScript();
    }
    list qaSplit = llParseString2List(llList2String(trivia_lines, q), ["//"], [""]);
    list caSplit = llParseString2List(llList2String(qaSplit, 0), ["/"], [""]);
    list answers = llDeleteSubList(caSplit, 0, 0);
    integer itra;
    for(itra=0, round_answers=[]; itra<llGetListLength(answers); ++itra) {
        round_answers += llToLower(llList2String(answers, itra));
    }
    trivia_lines = llDeleteSubList((trivia_lines=[]) + trivia_lines, q, q);
    llSay(0, "[" + llList2String(caSplit, 0) + "]" + " " + llList2String(qaSplit, 1));
    llSetTimerEvent(ANSWER_TIME);
}
 
init() {
    trivia_cards = [];
    trivia_lines = [];
    nRun = 0;
    bLine = 0;
    integer itra;
    for(itra=0; itra<llGetInventoryNumber(INVENTORY_NOTECARD); ++itra) {
        list bCard = llParseString2List(llGetInventoryName(INVENTORY_NOTECARD, itra), ["_"], [""]);
        if(llList2String(bCard, 0) != "Trivia" || llList2String(bCard, 1) != "Brain")
            jump continue;
        trivia_cards += llGetInventoryName(INVENTORY_NOTECARD, itra);
@continue;
    }
    llSay(0, "Reading trivia brain files... Please wait...");
    llSetTimerEvent(1.0);
    bQuery = llGetNotecardLine(llList2String(trivia_cards, nRun), bLine);
}
 
default
{
    state_entry()
    {
        init();
    }
 
    on_rez(integer num) {
        init();
    }
 
    changed(integer change) {
        if(change & CHANGED_INVENTORY)
            init();
    }
 
    timer() {
        if(nRun == llGetListLength(trivia_cards)) {
            llSetTimerEvent(0.0);
            llSay(0, "Read all brain files.");
            trivia_cards = [];
            bQuery = NULL_KEY;
            nRun = 0;
            state trivia;
        }
        if(!bLine) bQuery = llGetNotecardLine(llList2String(trivia_cards, nRun), bLine);
        llSetTimerEvent(1.0);
    }
    dataserver(key id, string data) {
        if(id != bQuery) return;
        if(data == EOF) {
            llSay(0, "Read brain file: " + llList2String(trivia_cards, nRun));
            ++nRun;
            bLine = 0;
            return;
        }
        if(data == "") jump next_line;
        trivia_lines += data;
@next_line;
        bQuery = llGetNotecardLine(llList2String(trivia_cards, nRun), ++bLine);
    }
}
 
 
state trivia
{
    state_entry() {
        llSay(0, "Staring trivia...");
        llSleep(5);
        comHandle = llListen(0, "", "", "");
        qNext((integer)llFrand(llGetListLength(trivia_lines)));
    }
    listen(integer chan,string name,key id,string mes) {
        if(!~llListFindList(round_answers, (list)llToLower(mes))) return;
        llSay(0, name + " is right! " + mes + " is the correct answer!");
        llSleep(10);
        integer itra;
        for(itra=0; itra<llGetListLength(user_scores); ++itra) {
            list usList = llParseString2List(llList2String(user_scores, itra), ["#"], [""]);
            if(llList2String(usList, 0) == name) {
                user_scores = llListReplaceList((user_scores=[]) + user_scores, (list)(name + "#" + (string)(llList2Integer(usList, 1)+1)), itra, itra);
                jump score_updated;
            }
        }
        user_scores += (list)(name + "#1");
@score_updated;
        qNext((integer)llFrand(llGetListLength(trivia_lines)));
    }
 
    touch_start(integer num) {
        if(llDetectedKey(0)!=llGetOwner()) return;
        if(bLine = !bLine) {
            llSetTimerEvent(0.0);
            llSay(0, "Stopping trivia. Touch me again to start...");
            llListenRemove(comHandle);
            return;
        }
        llSay(0, "Starting trivia. Touch me again to stop...");
        comHandle = llListen(0, "", "", "");
        qNext((integer)llFrand(llGetListLength(trivia_lines))); 
    }
 
    timer() {
        llSetTimerEvent(0.0);
        if(llGetListLength(trivia_lines)%SCORES_AFTER_QUESTIONS == 0) {
            integer itra;
            llSay(0, "------------------ SCORES ------------------");
            for(itra=0; itra<llGetListLength(user_scores); ++itra) {
                list usList = llParseString2List(llList2String(user_scores, itra), ["#"], [""]);
                llSay(0, llList2String(usList, 0) + "'s score is: " + llList2String(usList, 1));
            }
            llSay(0, "------------------ SCORES ------------------");
        }
        llSay(0, "A correct answer would have been: " + llList2String(round_answers, 0) + ".");
        llSleep(5);
        llSay(0, "Get ready for next question...");
        llSleep(10);
        qNext((integer)llFrand(llGetListLength(trivia_lines)));
        llSetTimerEvent(ANSWER_TIME);
    }
}

Notecard Syntax

If you are curious about the syntax, here is a description of the notecard syntax:

/<category>/<possible answer 1>/<possible answer 2>/.../<possible answer N>//<question>

where:

  • category represents a trivia category like "Arts" or "Sciences". This will prefix the question that the trivia engine will ask.
  • possible answer 1 through possible answer N represent the possible answers that the trivia engine will accept as being valid for the question.
  • question is simply the question that the trivia engine will ask on the main chat.

Example:

/Valentines/good luck//A white dove, also a symbol of Valentine's Day, symbolizes what?