-- -- [BottleBot] - v0.451 -- -- Spin the bottle! -- Written by bonki 2003 -- -- ABOUT: -- Just an average SPIN THE BOTTLE game =) -- -- CREDITS/THANKS: -- Manic_Depresiv_Santa (I've taken the sentences from his VB-version) -- RabidWombat (thanks to you mate :)) -- -- USED FILES (don't forget to create the "scripts/txt" folder!!!): -- txt/BottleBot.template.txt (optional!): template file where you can change the sentences :) -- -- [nick1] / [nick2] will be replaced with the users' nicks -- [num1] / [num2] -||- [nickx]'s "number" -- -- AVAILABLE COMMANDS: -- Type !bb.help for further details. -- -- TODO: -- any suggestions? -- -- BUGS/LIMITATIONS: -- o) reconnecting may cause a user to be removed from the list only -- o) only user who connect after the bot will be added to the list -- -- CHANGELOG: -- v0.451: Bugfix: Interval now in seconds, not milliseconds -- v0.45: Optimized: code rewritten module-alike :) -- v0.4: Added: !spinrandom{start/stop} -- v0.31: Bugfix: fixed add/remove user bug -- v0.3: Bugfix: fixed several bugs -- v0.25: Optimized: replaced table algorithm (thx RabidWombat :) -- v0.2: Added: added template file support -- iInterval = 30; -- seconds -- You may change sBotName but PLEASE leave the rest as it is, thx :-) bot = { sBotName = "BottleBot", sBotVer = "v0.451", sBotEmail = "bonki@no-spam.net", sBotSpeed = "Sol", sBotDescr = "BottleBot - v0.451 - written by bonki 2003", iBotShare = 0 }; sCrLf = "rn"; sOpHelpOutput = sCrLf..sCrLf.."OP Commands:"..sCrLf..sCrLf; sHelpOutput = sCrLf.."Commands:"..sCrLf..sCrLf; sBotInfo = "" sTemplateFile = "txt/"..bot.sBotName..".template.txt"; tUsers = {}; s = {}; function Main() frmHub:RegBot(bot.sBotName); UpdateBotInfo(); ReadTemplate(); randomseed(clock()); tCommands = { [ "!bb.help" ] = { CmdShowHelp, 0, "Display this help message" }, [ "!bb.spin" ] = { CmdSpin, 0, "Spin the bottle!" }, [ "!bb.startrandom" ] = { CmdSpinRandomStart, 1, "Start random spinning!" }, [ "!bb.stoprandom" ] = { CmdSpinRandomStop, 1, "Stop random spinning!" }, }; for sCmd, tCmd in tCommands do if(tCmd[2] == 1) then sOpHelpOutput = sOpHelpOutput..sCmd.."t: "..tCmd[3]..sCrLf; else sHelpOutput = sHelpOutput..sCmd.."tt: "..tCmd[3]..sCrLf; end end end ------------------------------------------------------------------------------- function CmdSpin(curUser) local sUserName1, iUserNum1 = nil; local sUserName2, iUserNum2 = nil; repeat iUserNum2, sUserName2 = tGetRandomUser(tUsers); if (iUserNum2 == -1) then if (curUser) then SendToAll(bot.sBotName, "There's nobody to play with :("); end; return; end; if (curUser) then iUserNum1 = tGetUserIndex(tUsers, curUser); sUserName1 = curUser.sName; else iUserNum1, sUserName1 = tGetRandomUser(tUsers); end; until (sUserName1 ~= sUserName2); local iRndNum = random(getn(s)); local sSentence = s[iRndNum]; if (strfind(sSentence, "%[nick1%]")) then sSentence = gsub(sSentence, "%[nick1%]", sUserName1); end; if (strfind(sSentence, "%[nick2%]")) then sSentence = gsub(sSentence, "%[nick2%]", sUserName2); end; if (strfind(sSentence, "%[num1%]")) then sSentence = gsub(sSentence, "%[num1%]", iUserNum1); end; if (strfind(sSentence, "%[num2%]")) then sSentence = gsub(sSentence, "%[num2%]", iUserNum2); end; SendToAll(bot.sBotName, sSentence); end ------------------------------------------------------------------------------- function CmdSpinRandomStart() SetTimer(iInterval * 1000); StartTimer(); SendToAll(bot.sBotName, "Random spinning started!"); end ------------------------------------------------------------------------------- function CmdSpinRandomStop() StopTimer(); SendToAll(bot.sBotName, "Random spinning stopped!"); end function CmdShowHelp(curUser) curUser:SendData(bot.sBotName, sOpHelpOutput..sHelpOutput); end ------------------------------------------------------------------------------- function OnTimer() CmdSpin(); end ------------------------------------------------------------------------------- function DataArrival(curUser, sData) local _, _, cmd, args = strfind(sData, "%b<>%s+(%S+)%s*([^%|]*)%|$"); if(cmd == nil) then return 0; end cmd = strlower(cmd); if (tCommands[cmd]) then curUser:SendData(sData); if (tCommands[cmd][2] == 0 or curUser.bOperator) then tCommands[cmd][1](curUser, args); else curUser:SendData(bot.sBotName, "You do not have sufficient rights to run that command!"); end return 1; end end ------------------------------------------------------------------------------- function OpConnected(curUser) curUser:SendData(sBotInfo); tAddUser(tUsers, curUser); end ------------------------------------------------------------------------------- function OpDisconnected(curUser) tRemoveUser(tUsers, curUser); end ------------------------------------------------------------------------------- function NewUserConnected(curUser) curUser:SendData(sBotInfo); tAddUser(tUsers, curUser); end ------------------------------------------------------------------------------- function UserDisconnected(curUser) tRemoveUser(tUsers, curUser); end ------------------------------------------------------------------------------- function UpdateBotInfo() sBotInfo = "$MyINFO $ALL "..bot.sBotName.." "..bot.sBotDescr.."$ $"..bot.sBotSpeed..strchar(1).."$"..bot.sBotEmail.."$"..bot.iBotShare.."$" ; end ------------------------------------------------------------------------------- function ReadTemplate() local flTemplateFile = openfile(sTemplateFile, "r"); if (flTemplateFile) then local line = read(flTemplateFile); while (line) do tinsert(s, 1, line); line = read(flTemplateFile); end closefile(flTemplateFile); else s = { "< * The bottle lands on [num2] and [num2] faints at the site of [nick1] * >", "< * [nick1] tackle huggles [nick2] and faits from all the excitement * >", "< * [nick2] is kissed passionately by [nick1] * >", "< * [nick2] and [nick1] giggle and run towards the closet holding hands * >", "< * [nick2] picks up the bottle and breaks it on [nick1]'s head * >", "< * [nick2] picks up and throws [nick1] across the room * >", "< * [nick2] doesn't want to be kissed so gives [nick1] a cactus in place * >", "< * [nick2] runs home crying * >", "< * [nick2] *kneels*. If you wish to kiss me you have to ask my parents, [nick1]. * >", "< * [nick2] and [nick1] interlock eyes and run towards eachother while the cellos play * >", "< * [nick2] gets restraining order against [nick1] * >", "< * [nick2] and [nick1] sitting in a tree, K I S S I N G... * >", "< * This is the spin that doesnt end, yes it goes on and on my friend, some people started spinning me without knowing where I'd land. Now I'll continue spinning forever just because... * >", "< * [nick1] spins the bottle and it lands on [nick1]. [nick1] goes and hides in the closet * >", "< * The bottle lands on [num2]. [num2] then looks at [nick1]. Then stares at the bottle again. Eventually [num2] chooses the bottle over [nick1]. And they all live happily ever after! * >"; }; end end ------------------------------------------------------------------------------- function tGetUserIndex(tTable, uUser) local iFind = tBinarySearch(tTable, uUser.sName); if(iFind ~= -1) then return -1; else return iFind; end end ------------------------------------------------------------------------------- function tGetRandomUser(tTable) local n = getn(tTable); if (n < 2) then return -1, nil; else local iRnd = random(n); return iRnd, tTable[iRnd]; end end ------------------------------------------------------------------------------- function tAddUser(tTable, uUser) local iFind, iInsert = tBinarySearch(tTable, uUser.sName); if(iFind == -1) then tinsert(tTable, iInsert, uUser.sName); return 1; else return 0; end; end ------------------------------------------------------------------------------- function tRemoveUser(tTable, uUser) local iFind = tBinarySearch(tTable, uUser.sName); if(iFind ~= -1) then tremove(tTable, iFind); return 1; else return 0; end; end ------------------------------------------------------------------------------- function tBinarySearch(tTable, SearchVar) assert(tTable and SearchVar); local iBot, iMid, iTop = 1, nil, getn(tTable); local CompVal = nil; if(getn(tTable) == 0) then return -1, 1; end; while(iBot <= iTop) do iMid = floor((iTop + iBot) / 2); CompVal = tTable[iMid]; if(CompVal == nil) then return -1, -1; end; if(SearchVar < CompVal) then iTop = iMid - 1; elseif(SearchVar > CompVal) then iBot = iMid + 1; else return iMid, -1; end end if(SearchVar > CompVal) then iMid = iMid + 1; end; return -1, iMid; end