(* $Id: Idyll.scpt,v 1.1 2006/06/04 16:50:42 jmates Exp $ A /loadable ircle script that aids role playing games over Internet Relay Chat (IRC). Idyll provides prepared text dumping into a channel (or to a nick) and dice rolling support. Requires the RegEx Commands Scripting Addition. Unsupported since written in 1999. *) (* Constants *) -- where on disk files for readback live (change to suit your computer) property sayFolder : "Idyll:Say" property sayNickFolder : "Idyll:SayNick" property messagesFolder : "Idyll:Messages" -- limits on dice sides/times/mods property minTimes : 1 property maxTimes : 100 property minSides : 1 property maxSides : 1000 -- per die property minMod : -100 property maxMod : 100 -- per roll property globalMaxMod : 1000 property globalMinMod : -1000 -- minimum limits on die rolls property minModOnDie : 1 property minRollValue : 1 -- probably not needed, unless the die regex changes property defaultSidesOnDie : 20 (* Globals *) -- lists to put contents into property sayList : {} property messagesList : {} property sayNickList : {} (* Ircle Handlers *) -- called when /loaded on load() tell application "ircle 3.1.2 OS X" echo serverprefix & "Welcome to Idyll!" echo serverprefix & "Idyll loading file Index... (should flip to Finder)" end tell -- load up index of messages from disk for reference purposes set sayList to getTEXTFileList(sayFolder) set messagesList to getTEXTFileList(messagesFolder) set sayNickList to getTEXTFileList(sayNickFolder) tell application "ircle 3.1.2 OS X" activate echo serverprefix & "Idyll done loading." end tell end load -- when the user types something.. on input(con, target, thestring) set AppleScript's text item delimiters to " " set cmdList to text items of thestring -- public messages sent back to channel if item 1 of cmdList is ".say" and (length of cmdList) > 1 then set textToDisplay to getTextBlarb(sayList, items 2 thru end of cmdList as string) if textToDisplay ≠ {} then tell application "ircle 3.1.2 OS X" repeat with aLine in textToDisplay type aLine in channel target of connection con delay 1 -- to prevent flooding end repeat end tell return true -- suppress input to channel! end if -- private messages sent to a nick by the GM else if item 1 of cmdList is ".saynick" and (length of cmdList) > 2 then tell application "ircle 3.1.2 OS X" set tempUser to (item 2 of cmdList) if not (exists user tempUser of channel target of connection con) then return end if end tell set textToDisplay to getTextBlarb(sayNickList, items 3 thru end of cmdList as string) if textToDisplay ≠ {} then tell application "ircle 3.1.2 OS X" repeat with aLine in textToDisplay type "/msg " & tempUser & " " & aLine in connection con --delay 1 -- to prevent flooding end repeat end tell return true end if end if end input -- public channel message handler on pubmsg(con, source, sourcehost, target, thestring) -- see whether this is a die roll... return dicer(con, source, sourcehost, target, thestring, false) of me end pubmsg -- private message handler on privmsg(con, source, sourcehost, target, thestring) -- see whether this is a die roll, if so, exit out if dicer(con, source, sourcehost, target, thestring, true) is true then return true end if -- check whether their message requires a message back repeat with i from 1 to (length of messagesList) if (name of item i of messagesList) is equal to thestring then set textToDisplay to readFileToList(item i of messagesList as string) -- spit the results out into Ircle tell application "ircle 3.1.2 OS X" repeat with aLine in textToDisplay type "/msg " & source & " " & aLine in connection con --delay 1 -- to prevent flooding end repeat end tell return true end if end repeat end privmsg (* Idyll Handlers *) -- this custom subroutine handles the actual rolling and display of results on dicer(con, source, sourcehost, target, thestring, privateFlag) set AppleScript's text item delimiters to " " -- try to parse out a roll using a regular expression set resultList to text items of («event RegXRMat» thestring given «class rPat»:"^(\\d+)?d(\\d+)([+-]\\d+)? ?([+-]\\d+)?", «class rUsi»:"\\1 \\2 \\3 \\4") -- if there's something in the result, extract out individual values if length of resultList is 4 then if item 1 of resultList is not "" then set timesToRoll to item 1 of resultList as integer else set timesToRoll to 1 end if if item 2 of resultList is not "" then set sidesOnDie to item 2 of resultList as integer else -- shouldn't really hit here, but I'm paranoid set sidesOnDie to defaultSidesOnDie end if -- item 3 now the global mod, so if you need per-die mods, -- they've been shuffled to the ' +mod' space at the end if item 3 of resultList is not "" then set globalMod to item 3 of resultList as integer else set globalMod to 0 end if if item 4 of resultList is not "" then set eachDieMod to item 4 of resultList as integer else set eachDieMod to 0 -- otherwise rolling loop below complains end if else return false -- not a die roll end if -- bounds checking if timesToRoll < minTimes or sidesOnDie < minSides or timesToRoll > maxTimes ¬ or sidesOnDie > maxSides or eachDieMod < minMod or eachDieMod > maxMod ¬ or globalMod < globalMinMod or globalMod > globalMaxMod then tell application "ircle 3.1.2 OS X" to type "/msg " & source & " your roll was outside of the bounds set by the GM" in connection con return false end if -- over-ride minRollValue to a calculated value... set minRollValue to minModOnDie * timesToRoll -- call the roller thingy & parse results set rollResultList to doRoll(timesToRoll, sidesOnDie, eachDieMod, globalMod, minModOnDie, minRollValue) of me set rollRecord to item 1 of rollResultList set rollSum to item 2 of rollResultList set modSum to item 3 of rollResultList set rollResult to item 4 of rollResultList -- form up a string to send back if length of rollRecord < 11 then set resultStr to (rollRecord as string) else set resultStr to "(" & (length of rollRecord as string) & " dice)" end if if modSum ≠ 0 then set resultStr to resultStr & " sum: " & rollSum & " mods: " & modSum end if set resultStr to resultStr & " result: " & rollResult -- display the results tell application "ircle 3.1.2 OS X" -- log the roll locally echo serverprefix & " Idyll: " & resultStr -- and actually tell the user if privateFlag is false then type source & " rolls: " & resultStr in channel target of connection con else type "/msg " & source & " you rolled: " & resultStr in connection con end if end tell return true -- prevent ircle for displaying the text end dicer -- handles die rolling, bounds checking. Returns lots of info on the roll. on doRoll(timesToRoll, sidesOnDie, eachDieMod, globalMod, minModOnDie, minRollValue) set rollRecord to {} set rollSum to 0 set modSum to 0 -- do the die rolls repeat with i from 1 to timesToRoll set roll to (random number from 1 to sidesOnDie) -- form up a list of unmodified rolls for display later copy roll to end of rollRecord set rollSum to rollSum + roll -- figure out mods on this die if (roll + eachDieMod) ≤ minModOnDie then set modSum to modSum + minModOnDie - roll else set modSum to modSum + eachDieMod end if end repeat set rollResult to rollSum + modSum -- adjust result for the global mod if (rollResult + globalMod) ≤ minRollValue then set modSum to modSum + minRollValue - rollSum set rollResult to minRollValue else set modSum to modSum + globalMod set rollResult to rollResult + globalMod end if return {rollRecord, rollSum, modSum, rollResult} end doRoll -- This routine reads the text from the path passed to it -- Unadultured Source: http://cgi.skyweyr.com/applescript/general/files.html on readFileToList(thePath) try set theFileReference to open for access file thePath set theText to read theFileReference close access theFileReference on error errMsg number errNum try close access theFileReference end try error errMsg number errNum end try set AppleScript's text item delimiters to return set textList to text items of theText -- some text apps (BBEdit) like to tack on extra returns, strip them if last item of textList is "" then return items 1 thru ((length of textList) - 1) of textList else return textList end if end readFileToList -- returns list of files of type TEXT in the specified folder on getTEXTFileList(theFolder) set fileList to {} tell application "Finder" activate -- otherwise painfully slow! set folderList to contents of folder theFolder -- loop over context, extracting only proper files... repeat with i from 1 to (length of folderList) if file type of item i of folderList is "TEXT" then copy item i of folderList to end of fileList end if end repeat end tell return fileList end getTEXTFileList -- searches folder index vs. user input for a match on getTextBlarb(indexList, thestring) repeat with i from 1 to (length of indexList) if (name of item i of indexList) is equal to thestring then return readFileToList(item i of indexList as string) end if end repeat return {} end getTextBlarb