Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Auto-Raffler

Neo Rebus
Registered User
Join date: 10 Apr 2004
Posts: 59
05-13-2004 22:32
CODE

// AUTORAFFLER version 1.1a
// by Neo Rebus
// Copyright (c) 2004 by Johnson Earls, All Rights Reserved
// See end of file for license information
//
// This is an automatic raffling system. Once started, it will
// periodically conduct a raffle on its own and give the prize to the
// winner. The winner must accept the prize within 15 seconds or the
// autoraffler will choose a different winner. (This allows the owner
// of the object or property to decline accepting a prize)
//
// SETUP:
//
// Create an object that fills the volume in which the raffle attendees
// will be standing. The object can consist of multiple prims. Once
// the autoraffle script is put on the object, it will become phantom.
// The object should be named something descriptive (as it will say
// things to the world), and should be transparent since people will be
// standing inside it.
//
// Put the autoraffle script into the raffler object, then put the
// objects to be raffled in. Everything being raffled must be an
// *object*, not a texture or landmark or anything. If you want to
// raffle other types of things off, put them inside their own object
// and raffle that object. If you want to raffle money, make an object
// named "L$### ..." and the winner will be given ### linden dollars
// rather than the object itself.
//
// at this point, the autoraffler accepts voice commands to control it:
//
// autoraffle reset
// to reset the script
// autoraffle list
// to list the people entered in the raffle
// autoraffle list winners
// to list people who have won the raffle since it was reset
// autoraffle stop
// to stop an ongoing raffle
// autoraffle start [ <interval> [ <count> ] ]
// to start a raffle. <interval> and <count> are optional. If
// interval is not given, it will default to about 30 seconds.
// If count is not given, it will raffle off all the objects in
// the autoraffler's inventory.
//
// example: autoraffle start 20 5
// this will start the autoraffler with a raffle every 20 minutes
// (starting 20 minutes from now), raffling off 5 random prizes.
//

integer raffleAcceptTimeout = 15;

integer runningRaffleCount = 0;
integer runningRaffleInterval = 0;

integer runningRaffleListenerChat = 0;
integer runningRaffleListenerPrivate = 0;

list runningRaffleEntrants = [];
list runningRaffleWinners = [];

key thisRafflePrize = NULL_KEY;
string thisRafflePrizeName = "";
key thisRaffleWinner = NULL_KEY;
string thisRaffleWinnerAccepted = "";
list thisRaffleEntrants = [];

integer PRIVATE_CHAT = 1316110706 ;

list remove_from_list(list src, list what)
{
// find 'what'
integer idx = llListFindList(src, what);
if (idx > -1)
{
list pfx; // the list before 'what'
list sfx; // the list after 'what'
if (idx > 0)
{
pfx = llList2List(src, 0, idx - 1);
} else {
pfx = [];
}
if (idx < llGetListLength(src) - llGetListLength(what))
{
sfx = llList2List(src, idx + llGetListLength(what), -1);
} else {
sfx = [];
}
return pfx + sfx;
} else {
return src;
}
}

raffleWinner(key winner)
{

// if the winner is not NULL_KEY, give them the prize.
// if the winner *is* NULL_KEY, give the script owner the prize.
// remove the prize from the inventory, decrement the raffle count, and call nextRaffle().

if (winner == NULL_KEY)
{
llSay(0, "No one accepted the prize!");
if (llGetSubString(thisRafflePrizeName, 0, 1) != "L$")
{
llGiveInventory(llGetOwner(), thisRafflePrizeName);
}
} else {
if (llGetSubString(thisRafflePrizeName, 0, 1) == "L$")
{
llGiveMoney(winner, llList2Integer(llParseString2List(thisRafflePrizeName, [" ", "$"], []), 1));
} else {
llGiveInventory(winner, thisRafflePrizeName);
}
runningRaffleWinners = runningRaffleWinners + [ winner ];
}

llRemoveInventory(thisRafflePrizeName);

thisRafflePrize = NULL_KEY;
thisRafflePrizeName = "";
thisRaffleWinner = NULL_KEY;

runningRaffleCount -= 1;

nextRaffle();
}

nextRaffle()
{
llSetTimerEvent(0.0); // just in case

// if the raffle count is 0, announce the end of the raffle and reset running variables.
if (runningRaffleCount == 0)
{

runningRaffleInterval = 0;
thisRafflePrize = NULL_KEY;
thisRafflePrizeName = "";
thisRaffleWinner = NULL_KEY;
thisRaffleWinnerAccepted = "";
thisRaffleEntrants = [];
llSay(0, "The raffle is over! Thank you for attending!");

} else {

// compute the timer value. if < 5, set it to 5.
float timer_value = runningRaffleInterval - llGetTime();
if (timer_value < 30.0)
{
timer_value = 30.0;
}
if (timer_value > 120)
{
timer_value -= 120; // give a 2 minute warning
}
llSetTimerEvent(timer_value);

// initialize raffle params.
thisRaffleWinner = NULL_KEY;
thisRafflePrize = NULL_KEY;
thisRafflePrizeName = "";

// announce the raffle.
if (timer_value < 120)
{
llSay(0, "The next raffle is coming up!");
} else {
llSay(0, "The next raffle will be in " + (string)(llFloor(timer_value / 60.0)) + " minutes.");
}

}
}

chooseWinner()
{

integer nument = llGetListLength(thisRaffleEntrants);

// if no valid entrants, call raffleWinner(NULL_KEY) to give item back to owner.
if (nument == 0)
{
raffleWinner(NULL_KEY);
} else {

// pick a random person from the entrants. Announce that they won.
// give them a dialog to allow them to decline the prize, and set a
// timer for the timeout.

integer winner = llCeil(llFrand(nument)) - 1;

thisRaffleWinner = llList2Key(thisRaffleEntrants, winner);
llSay(0, "The winner is " + llKey2Name(thisRaffleWinner) + "!");
llSetTimerEvent(raffleAcceptTimeout);
llDialog(thisRaffleWinner, "Do you wish to accept the raffle prize " + thisRafflePrizeName + "?", [ "Yes", "No" ], PRIVATE_CHAT);

}

}

default
{

state_entry()
{
// turn off the timer
llSetTimerEvent(0.0);

// get permission to give money
llRequestPermissions(llGetOwner(),PERMISSION_DEBIT);

// reset the running raffle parameters
runningRaffleCount = 0;
runningRaffleInterval = 0;
runningRaffleEntrants = [];
runningRaffleWinners = [];

thisRafflePrize = NULL_KEY;
thisRafflePrizeName = "";
thisRaffleWinner = NULL_KEY;

// turn volume detect off, then back on, to force collision_start events
llVolumeDetect(FALSE);
llSleep(0.1);
llVolumeDetect(TRUE);

// remove listeners and re-add them
llListenRemove(runningRaffleListenerChat);
llListenRemove(runningRaffleListenerPrivate);
runningRaffleListenerChat = llListen(0, "", NULL_KEY, "");
runningRaffleListenerPrivate = llListen(PRIVATE_CHAT, "", NULL_KEY, "");
}

on_rez(integer start_code)
{
// reset script
llResetScript();
}

collision_start(integer total_number)
{
integer i;
for (i=0; i<total_number; i++)
{
// in order to be an avatar, the detected item's key must = the item's owner.
if (llDetectedKey(i) == llDetectedOwner(i))
{
// check if the detected person is already in Entrants. if not, add them.
if (llListFindList(runningRaffleEntrants, [ llDetectedKey(i) ]) == -1)
{
runningRaffleEntrants = runningRaffleEntrants + [ llDetectedKey(i) ];
}
}
}
}

collision_end(integer total_number)
{
integer i;
for (i=0; i<total_number; i++)
{
// remove the person from Entrants
runningRaffleEntrants = remove_from_list(runningRaffleEntrants, [ llDetectedKey(i) ]);
}
}

listen(integer channel, string name, key id, string msg)
{

// convert msg to lowercase
msg = llToLower(msg);

// on chat channel, listen for "autoraffle" commands.
if ((channel == 0) && (id == llGetOwner()) && (llGetSubString(msg, 0, 10) == "autoraffle "))
{

if (msg == "autoraffle stop")
{

// turn autoraffle off by setting the runningRaffleCount to 0 and calling nextRaffle()
runningRaffleCount = 0;
nextRaffle();

} else if (msg == "autoraffle list")
{

// generate comma-separated list of entrants with 'and' between last two
integer i;
integer num;
string entrants = "";
num = llGetListLength(runningRaffleEntrants);
for (i=0; i<num; i++)
{
string name = llKey2Name(llList2Key(runningRaffleEntrants, i));
if (i == 0)
{
entrants = name;
} else if (i == num - 1)
{
if (i > 1)
{
entrants = entrants + ",";
}
entrants = entrants + " and " + name;
} else {
entrants = entrants + ", " + name;
}
}
llSay(0, "The current raffle entrants are " + entrants);

} else if (msg == "autoraffle list winners")
{

// generate comma-separated list of entrants with 'and' between last two
integer i;
integer num;
string winners = "";
num = llGetListLength(runningRaffleWinners);
for (i=0; i<num; i++)
{
string name = llKey2Name(llList2Key(runningRaffleWinners, i));
if (i == 0)
{
winners = name;
} else if (i == num - 1)
{
if (i > 1)
{
winners = winners + ",";
}
winners = winners + " and " + name;
} else {
winners = winners + ", " + name;
}
}
llSay(0, "The raffle winners so far have been " + winners);

} else if (msg == "autoraffle reset")
{

// reset script
llResetScript();

} else if ((msg == "autoraffle start") || (llGetSubString(msg, 0, 16) == "autoraffle start "))
{

// split message into params, set interval and count, and call nextRaffle()
list params = llParseString2List(msg, [" "], []);
integer npar = llGetListLength(params);
if (npar > 2)
{
runningRaffleInterval = llList2Integer(params, 2);
} else {
runningRaffleInterval = 0;
}
if (npar > 3)
{
runningRaffleCount = llList2Integer(params, 2);
} else {
runningRaffleCount = llGetInventoryNumber(INVENTORY_OBJECT);
}
llResetTime();
nextRaffle();

}
}

if ((channel == PRIVATE_CHAT) && (id == thisRaffleWinner))
{

// on the private chat, set the Accepted string and reset the timer to go off as quickly as possible
thisRaffleWinnerAccepted = msg;
llSetTimerEvent(0.1);

}

}

timer()
{

// unset the timer
llSetTimerEvent(0.0);

// if we don't have a winner, then we're still selecting one.
if (thisRaffleWinner == NULL_KEY)
{

// if we don't have a prize key, then we need to announce it.
if (thisRafflePrize == NULL_KEY)
{

// if we haven't gotten to the raffle yet, call nextRaffle() again.
if (llGetTime() < runningRaffleInterval)
{
nextRaffle();
} else {

// reset the time so the next raffle is based on this time.
llResetTime();

integer n = llGetInventoryNumber(INVENTORY_OBJECT);
n = llCeil(llFrand(n)) - 1;
thisRafflePrizeName = llGetInventoryName(INVENTORY_OBJECT, n);
thisRafflePrize = llGetInventoryKey(thisRafflePrizeName);
llSetTimerEvent(10.0);
llSay(0, "Now raffling: " + thisRafflePrizeName);

}

} else {

// we have a prize key, find a winner.
thisRaffleEntrants = runningRaffleEntrants;
chooseWinner();

}
} else {

// we have a winner. therefore they've already been offered
// the win dialog. if they accept, call raffleWinner(); otherwise,
// remove them from thisRaffleEntrants and call chooseWinner() again.
if (thisRaffleWinnerAccepted == "yes")
{
raffleWinner(thisRaffleWinner);
} else {
llSay(0, llKey2Name(thisRaffleWinner) + " has declined the raffle prize.");
thisRaffleEntrants = remove_from_list(thisRaffleEntrants, [ thisRaffleWinner ]);
chooseWinner();
}
}

}

}


////////////////////////////////////////////////////////////////////////
//
// Auto-Raffler version 1.1a
// by Neo Rebus
// Copyright (c) 2004 by Johnson Earls
// All Rights Reserved
//
// Permission to Use and Redistribute
//
// Permission to use and redistribute the Auto-Raffler code, with or
// without modifications, is granted under the following conditions:
//
// + All redistributions must include this copyright notice and license.
// + All redistributions must give credit to the author, by real name
// (Johnson Earls) and by SL name (Neo Rebus). If distributed in a
// modified form, credit must still be given to Neo Rebus (Johnson
// Earls) as the original author.
// + All redistributions *should* include the setup information at the
// beginning of the script.
//
////////////////////////////////////////////////////////////////////////


Version 1.1a: Fixed the code to skip a raffle when no one's around. Whoops.

Version 1.1: Automatically skips a raffle attempt if there's no one around to raffle to. Notifies the owner if there are no items left to raffle.
Aaron Levy
Medicated Lately?
Join date: 3 Jun 2004
Posts: 2,147
"L$### ..."
06-28-2004 00:04
"L$### ..."

So, to give L$100 I'd name it:

L$100 ...

Is the "..." literal?
Neo Rebus
Registered User
Join date: 10 Apr 2004
Posts: 59
07-14-2004 08:31
L$<amount> <descriptive-text>

For example:

"L$100 donated by Neo Rebus"

The full name will be used in the output from the auto-raffler. When the prize is handed out, it will see the initial L$ and grab the number between the $ and the first space.

- Neo
Jack Lambert
Registered User
Join date: 4 Jun 2004
Posts: 265
07-16-2004 15:51
Hmmm....

This uses an llSetTimerEvent(timer_value) for an X number of seconds...

Unfortunately those things seem to lag out at times when there are a lot of people present...like raffles...the timer will count verrry sloowwly.

Wouldn't something like llSetTimerEvent(1)

timer()
{
if (llGetTime() < timer_value)
{
... <process winner>
llResetTime();
}
}

work a bit better in high people count situations?

--Jack Lambert
Sensual Casanova
Spoiled Brat
Join date: 28 Feb 2004
Posts: 4,807
07-17-2004 18:35
I tried this the other day at an event but for some reason it kept saying no one was entered...
Neo Rebus
Registered User
Join date: 10 Apr 2004
Posts: 59
07-20-2004 08:15
I'll admit that I haven't used this code for a real raffle, but in my test runs it seemed to work just fine.

All raffle entrants must be intersecting the raffler object.
Aestival Cohen
half pint half drunk up
Join date: 2 Sep 2004
Posts: 311
11-02-2004 13:56
Could you make a modification where participants would just have to "touch" something to be entered in the raffle? Seems maybe less crowded?
_____________________
=^.^= =^.^= =^.^= =^.^= =^.^= =^.^= =^.^= =^.^= =^.^= =^.^=
Luverly FLICKR photos!
=^.^= =^.^= =^.^= =^.^= =^.^= =^.^= =^.^= =^.^= =^.^= =^.^=
Neo Rebus
Registered User
Join date: 10 Apr 2004
Posts: 59
11-03-2004 19:41
From: Aestival Cohen
Could you make a modification where participants would just have to "touch" something to be entered in the raffle? Seems maybe less crowded?


Well, it's not quite what the original program was designed for, but I can look into it.

(The program was designed to be left running over a long period of time and automatically raffle to anyone who is within the right area - the "right area" being determined by the volume of the object containing the autoraffle script)

If modified to accept a touch, would you want people to still be elligible for the raffle if they are disconnected? if they are not "close" (for some definition of close)?

- Neo
Lee Callahan
Registered User
Join date: 2 Aug 2004
Posts: 11
Range instead of area prim
11-08-2004 13:33
How would one modify the script to include persons within a certain range instead of persons standing in the prim? I would like to cover a large area (too big to link into a single object).
Lee Callahan
Registered User
Join date: 2 Aug 2004
Posts: 11
Range instead of prim
11-08-2004 13:36
Can anyone offer changes to thisscript to include persons within a specific range as opposed to standing within an object? I would like it to include persons in a range of like 60 meters (too large an area to link).

Thanks
Neo Rebus
Registered User
Join date: 10 Apr 2004
Posts: 59
11-09-2004 07:24
From: Lee Callahan
How would one modify the script to include persons within a certain range instead of persons standing in the prim? I would like to cover a large area (too big to link into a single object).


That's a difficult problem. The reason I chose to go with the volume-detect prim is that the llSensor() calls will only return 16 detected "things". i suppose one could do very small slices and rotate a sensor around continuously, but that's not easy either.

Another possibility would be to make it so several autorafflers could all talk to each other, with one "master" autoraffler controlling the list of prizes and entrants.

I've not had a lot of time to look at this recently, but when I get a chance, I will look at doing the touch-to-enter version and the extendible version (multilpe autorafflers working together)
Water Rogers
Registered User
Join date: 1 May 2003
Posts: 286
11-14-2004 11:19
From: Neo Rebus
That's a difficult problem. The reason I chose to go with the volume-detect prim is that the llSensor() calls will only return 16 detected "things". i suppose one could do very small slices and rotate a sensor around continuously, but that's not easy either.

Another possibility would be to make it so several autorafflers could all talk to each other, with one "master" autoraffler controlling the list of prizes and entrants.

I've not had a lot of time to look at this recently, but when I get a chance, I will look at doing the touch-to-enter version and the extendible version (multilpe autorafflers working together)

Just have the person touch an object to be involved in the raffle if they choose --> put their name into a list. When it comes time to raffle of prize(s), run a single llSensor("NAME FROM LIST", "", AGENT, YOUR RANGE, PI); call to look for the person --> if person isn't in the area, remove person from the list, and relook until a match is found --> give prize to winner.

OR if you don't mind giving prizes to people not within the area or even logged out, store their KEYS in a list and don't even bother running the sensor

If you'd like me to post an example let me know.

--Water
_____________________
From: Philip Linden

For the more technically minded - the problem is actually NOT the asset server (or 'asshat' as you prefer to affectionately call it herein).
Patrick Playfair
Registered User
Join date: 19 Jul 2004
Posts: 328
???
02-20-2005 10:08
is anyone using this? I am attempting to use it, but in testing all it does is keep saying "Next raffle coming up". It never actually does anything. Anyone else encountered this problem?

Thanks... Patrick playfair
_____________________
The meek shall inherit the earth (after I'm through with it).

Patrick Playfair
Jack Lambert
Registered User
Join date: 4 Jun 2004
Posts: 265
02-21-2005 13:42
Patrick, give me a shout in-game. I have several rafflers you can play with that are working.

--Jack
Huns Valen
Don't PM me here.
Join date: 3 May 2003
Posts: 2,749
02-22-2005 22:17
I may have missed it, but I don't think you are shuffling the list of entrants. SL's random number generator is notorious for not being very random. When Xylor did the Mah Jong board last year, I think he was shuffling at least seven times in order to make sure the result set was at least somewhat random. Forgive me if you are shuffling and I missed it.
Francis Chung
This sentence no verb.
Join date: 22 Sep 2003
Posts: 918
02-25-2005 02:51
From: Huns Valen
. SL's random number generator is notorious for not being very random. When Xylor did the Mah Jong board last year, I think he was shuffling at least seven times in order to make sure the result set was at least somewhat random.


What do you mean when you say "SL's random number generator?" Not random in what way?

I've never tested the list shuffle, but I went to the trouble of histogramming the results of llFrand() a few times. The results definately looked Poisson to me.
_____________________
--
~If you lived here, you would be home by now~