; Acronym Game
; Author: ratmatix
; Email: ratmatix+hawkee [at] gmail (dot) com
; =============================================================================================
; Settings
; =============================================================================================
on *:load: {
acro.loadSettings
}
on *:start: {
acro.removeSettings
acro.loadSettings
}
alias acro.loadSettings {
; Sets if the bot is active; if a game can be started
set %ACROSETTING.active 1
; Bot name
set %ACROSETTING.botname acrobot
; Name of channel in which the game can be played
set %ACROSETTING.chan #acro
; Number of rounds
set %ACROSETTING.rounds 5
; Time to wait for players to !join
set %ACROSETTING.joinTime 30
; Time to wait for players to !submit acros
set %ACROSETTING.submitTime 90
; Time to wait for players to !vote acros
set %ACROSETTING.voteTime 30
; Weighted string for acronym
set %ACROSETTING.weighted AAABBBCCCDDDEEEFFFGGGHHHIIIJJKKLLLMMMNNNOOOPPPQRRRSSSTTTUUUVVVWWXYYZ
}
alias -l acro.removeSettings {
.timeracro.* off
unset %ACRO.*
}
; =============================================================================================
; Game Timeline (with default timings)
; =============================================================================================
; !start
; -> 30 seconds for players to join with !join
; startGame
; playRound x | x <- 1..10
; -> maximum of 120 seconds per round (All phases are ended prematurely if all players submit or vote)
; -> Bot generates and displays a string of random letters
; -> 90 seconds for players to submit acros with !submit <acro>
; -> Bot displays the submitted acronyms, anonymously
; -> 30 seconds for players to vote for acros with !vote <acroNum>
; -> Bot displays round results
; endGame
; -> Bot displays game results
; cake
; =============================================================================================
; Game aliases/identifiers (in order of game flow)
; =============================================================================================
on *:TEXT:!start*:%ACROSETTING.chan: {
if ($me == %ACROSETTING.botname) {
if (%ACROSETTING.active) {
if ((!%ACRO.starting) && (!%ACRO.started)) {
acro.loadSettings
msg %ACROSETTING.chan Game of acro starting!
msg %ACROSETTING.chan Type 4!join to join within the next %ACROSETTING.joinTime seconds.
unset %ACRO.*
set -u $+ [ %ACROSETTING.joinTime ] %ACRO.starting 1
.timerACRO.start 1 %ACROSETTING.joinTime acro.startGame
}
else {
notice $nick A game has already started!
}
}
else {
msg %ACROSETTING.chan acrobot has been disabled. Probably for upgrades... Like laz0rs! Try again later :)
}
}
}
on *:TEXT:!join*:%ACROSETTING.chan: {
if ($me == %ACROSETTING.botname) {
if (%ACRO.starting) || (%ACRO.started) {
if (!$acro.isPlayer($nick)) {
acro.addPlayer $nick
msg %ACROSETTING.chan 4 $+ $nick $+ has joined the game
}
else {
notice $nick You're already in the game!
}
}
else {
notice $nick No game to join. Type 4!start to start one.
}
}
}
; addPlayer <nick> adds that player to the current game
alias -l acro.addPlayer {
set %ACRO.playerNames $addtok(%ACRO.playerNames, $1, 32)
set %ACRO.playerPoints $instok(%ACRO.playerPoints, 0, $acro.numPlayers, 32)
set %ACRO.playerVotes $instok(%ACRO.playerVotes, 0, $acro.numPlayers, 32)
set %ACRO.playerVoted $instok(%ACRO.playerVoted, 0, $acro.numPlayers, 32)
}
alias -l acro.startGame {
if ($acro.numPlayers > 0) {
unset %ACRO.starting
set %ACRO.started 1
msg %ACROSETTING.chan Game starting with players:4 %ACRO.playerNames
set %ACRO.roundNum 0
acro.playRound
}
else {
acro.stop Nobody joined 4:(
}
}
alias -l acro.playRound {
inc %ACRO.roundNum
set %ACRO.acro $acro.generateAcro
set %ACRO.submitting 1
msg %ACROSETTING.chan Acronym for round %ACRO.roundNum of %ACROSETTING.rounds $+ :4 %ACRO.acro
msg %ACROSETTING.chan Submit acronyms to the bot with: 4/notice %ACROSETTING.botname submit <acronym> within the next %ACROSETTING.submitTime seconds
acro.resetRound
.timerACRO.beginVoting 1 %ACROSETTING.submitTime acro.beginVoting
}
; $generateAcro returns a random acronym of length 3 to 7
alias -l acro.generateAcro {
var %ACRO.c = 0
var %ACRO.length = $rand(3,7)
while (%ACRO.c < %ACRO.length) {
var %ACRO.d = %ACRO.d $mid(%ACROSETTING.weighted, $rand(1,$len(%ACROSETTING.weighted)), 1)
inc %ACRO.c
}
return %ACRO.d
}
alias -l acro.resetRound {
var %ACRO.b 1
unset %ACRO.playerVotes
unset %ACRO.playerVoted
unset %ACRO.playerAcros
unset %ACRO.playerAcrod
while (%ACRO.b <= $acro.numPlayers) {
set %ACRO.playerVotes $instok(%ACRO.playerVotes, 0, %ACRO.b, 32)
set %ACRO.playerVoted $instok(%ACRO.playerVoted, 0, %ACRO.b, 32)
inc %ACRO.b
}
}
on *:NOTICE:submit*:*: {
if ($me == %ACROSETTING.botname) {
if ($acro.isPlayer($nick)) {
if (!$acro.hasAcrod($nick)) {
if ($acro.checkAcro($strip($2-))) {
acro.addAcro $acro.playerNum($nick) $strip($2-)
notice $nick Acro submitted successfully.
if ($acro.allSubmitted) {
.timerACRO.beginVoting off
;msg %ACROSETTING.chan All players have submitted an acronym!
acro.beginVoting
}
}
else {
notice $nick Not a valid acro!
}
}
else {
notice $nick You've already submitted an acro!
}
}
else {
notice $nick You're not playing this game!
}
}
}
alias -l acro.hasAcrod {
return $istok(%ACRO.playerAcrod, $acro.playerNum($1), 32)
}
; $checkAcro(<player submitted acro>) returns true if it is a valid acro for that round
alias -l acro.checkAcro {
var %ACRO.e $numtok(%ACRO.acro, 32)
var %ACRO.f $numtok($1, 32)
if (%ACRO.e != %ACRO.f) {
return $false
}
while (%ACRO.e >= 1) {
if ($left($gettok($1-, %ACRO.e, 32), 1) != $left($gettok(%ACRO.acro, %ACRO.e, 32), 1)) {
return $false
}
dec %ACRO.e
}
return $true
}
; addAcro <player num> <acro>
alias -l acro.addAcro {
set %ACRO.playerAcrod $instok(%ACRO.playerAcrod, $1, $calc($numtok(%ACRO.playerAcrod, 32) + 1), 32)
set %ACRO.playerAcros $instok(%ACRO.playerAcros, $2-, $calc($numtok(%ACRO.playerAcros, 96) + 1), 96)
}
alias -l acro.allSubmitted {
if ($numtok(%ACRO.playerAcrod, 32) == $ACRO.numPlayers) {
return $true
}
else {
return $false
}
}
alias -l acro.beginVoting {
unset %ACRO.submitting
set %ACRO.voting 1
msg %ACROSETTING.chan Time to 4start voting!
msg %ACROSETTING.chan Vote for the best acro with 4/notice %ACROSETTING.botname vote <acro number> within the next %ACROSETTING.voteTime seconds
msg %ACROSETTING.chan Acronyms in order of submission:
var %ACRO.g 1
while (%ACRO.g <= $numtok(%acro.playerAcrod, 32)) {
msg %ACROSETTING.chan [4 $+ %ACRO.g $+ ] $gettok(%ACRO.playerAcros, %ACRO.g, 96)
inc %ACRO.g
}
.timerACRO.endRound 1 %ACROSETTING.voteTime acro.endRound
}
; players vote by sending a notice to the bot. The voting notice should be formed like this: !vote <acroNum>
on *:NOTICE:vote*:*: {
if ($me == %ACROSETTING.botname) {
if (%ACRO.voting) {
if ($acro.isPlayer($nick)) {
if (!$acro.hasVoted($nick)) {
if ($acro.checkAcroNum($2)) {
$acro.incVote($nick, $2)
notice $nick Vote submitted successfully.
if ($acro.allVoted) {
.timerACRO.endRound off
;msg %ACROSETTING.chan All players have voted!
acro.endRound
}
}
else {
notice $nick That's not a valid acro number!
}
}
else {
notice $nick You've already voted this round!
}
}
else {
notice $nick You're not playing this game!
}
}
else {
notice $nick It's not time to vote yet!
}
}
}
alias -l acro.hasVoted {
return $gettok(%ACRO.playerVoted, $acro.playerNum($1), 32)
}
; $checkAcroNum(<acroNum>) returns true if that acro number is valid. i.e. Was submitted.
alias -l acro.checkAcroNum {
var %ACRO.g $numtok(%ACRO.playerAcros, 96)
return $iif(($1 > 0) && ($1 <= $numtok(%ACRO.playerAcros, 32)), $true, $false)
}
; $incVote(<voting player name>, <acroNum>) increments the player's vote score
alias -l acro.incVote {
var %ACRO.acroOwner $gettok(%ACRO.playerAcrod, $2, 32)
set %ACRO.playerVoted $puttok(%ACRO.playerVoted, 1, $acro.playerNum($1), 32)
set %ACRO.playerVotes $puttok(%ACRO.playerVotes, $calc($gettok(%ACRO.playerVotes, %ACRO.acroOwner, 32) + 1), %ACRO.acroOwner, 32)
}
alias -l acro.allVoted {
var %ACRO.m 1
while (%ACRO.m <= $acro.numPlayers) {
if (!$acro.hasVoted($acro.playerName(%ACRO.m))) {
return $false
}
inc %ACRO.m
}
return $true
}
alias -l acro.endRound {
unset %ACRO.voting
var %ACRO.h 1
var %ACRO.mostVotes 0
msg %ACROSETTING.chan 4Results for round %ACRO.roundNum $+:
while (%ACRO.h <= $numtok(%ACRO.playerAcros, 96)) {
var %ACRO.acroOwner $gettok(%ACRO.playerAcrod, %ACRO.h, 32)
msg %ACROSETTING.chan [4 $+ %ACRO.h $+ ] $gettok(%ACRO.playerAcros, %ACRO.h, 96) - $iif($acro.numVotes(%ACRO.acroOwner) == 1, 1 vote, $ifmatch votes)
if ($acro.numVotes(%ACRO.acroOwner) > %ACRO.mostVotes) {
var %ACRO.mostVotes $ifmatch
}
inc %ACRO.h
}
if (%ACRO.mostVotes != 0) {
acro.incPoint %ACRO.mostVotes
}
else {
msg %ACROSETTING.chan 4Nobody voted. :'(
}
if (%ACRO.roundNum < %ACROSETTING.rounds) {
acro.playRound
}
else {
acro.endgame
}
}
; $numVotes(<player Num>) returns the number of votes that acro received
alias -l acro.numVotes {
return $gettok(%ACRO.playerVotes, $1, 32)
}
; incPoint <points> - finds the acros with that many votes and awards their owners with 1 point
alias -l acro.incPoint {
var %ACRO.j 1
msg %ACROSETTING.chan Round Winner(s):
while (%ACRO.j <= $acro.numPlayers) {
if ($gettok(%ACRO.playerVotes, %ACRO.j, 32) == $1) {
msg %ACROSETTING.chan [4 $+ %ACRO.j $+ ] belonged to4 $acro.playerName(%ACRO.j)
set %ACRO.playerPoints $puttok(%ACRO.playerPoints, $calc($gettok(%ACRO.playerPoints, %ACRO.j, 32) + 1), %ACRO.j, 32)
}
inc %ACRO.j
}
}
alias -l acro.endgame {
msg %ACROSETTING.chan Game finished!
msg %ACROSETTING.chan Final Scores:
var %ACRO.i 1
var %ACRO.mostPoints 0
while (%ACRO.i <= $acro.numPlayers) {
msg %ACROSETTING.chan $acro.playerName(%ACRO.i) - $iif($acro.numPoints(%ACRO.i) == 1, 1 point, $ifmatch points)
if ($acro.numPoints(%ACRO.i) > %ACRO.mostPoints) {
var %ACRO.mostPoints $ifmatch
}
inc %ACRO.i
}
acro.winners %ACRO.mostPoints
acro.removeSettings
}
alias -l acro.numPoints {
return $gettok(%ACRO.playerPoints, $1, 32)
}
; winners <points> - finds the players with that many points and call them the winner(s)! :D
alias -l acro.winners {
var %ACRO.k 1
while (%ACRO.k <= $acro.numPlayers) {
if ($gettok(%ACRO.playerPoints, %ACRO.k, 32) == $1) {
var %ACRO.winners %ACRO.winners $acro.playerName(%ACRO.k)
}
inc %ACRO.k
}
msg %ACROSETTING.chan The $iif($numtok(%ACRO.winners, 32) == 1, winner is4 %ACRO.winners , winners are:4 %ACRO.winners )
}
; =============================================================================================
; Utility identifiers or events
; =============================================================================================
; $isPlayer(<name>) returns $true if <name> is a player in the current game, else $false.
alias -l acro.isPlayer {
return $istok(%ACRO.playerNames, $1, 32)
}
; $playerNum(<name>) returns the player's player number. This means they are the nth token in playerNames, playerPoints
alias -l acro.playerNum {
return $findtok(%ACRO.playerNames, $1, 32)
}
; $playerName(<player number>) returns the player name who is the nth player number
alias -l acro.playerName {
return $gettok(%ACRO.playerNames, $1, 32)
}
; $numPlayers returns the number of players who joined this game
alias -l acro.numPlayers {
return $numtok(%ACRO.playerNames, 32)
}
on *:TEXT:!stop:%ACROSETTING.chan: {
if ($me == %ACROSETTING.botname) {
if ((%ACRO.starting) || (%ACRO.started)) {
if ($acro.isPlayer($nick)) {
acro.stop Game 4stopped! :(
}
else {
notice $nick Only players can stop the game!
}
}
else {
notice $nick There isn't a game to stop!
}
}
}
on *:TEXT:!leave:%ACROSETTING.chan: {
if ($me == %ACROSETTING.botname) {
msg %ACROSETTING.chan 4 $+ $nick has left the game.
acro.removePlayer $nick
}
}
on *:TEXT:!forcestart:%ACROSETTING.chan: {
if ($me == %ACROSETTING.botname) {
if (%ACRO.starting) {
if ($acro.isPlayer($nick)) {
.timerACRO.start off
acro.startGame
}
else {
notice $nick Only players can !forcestart a game
}
}
else {
notice $nick !forcestart can only be used when waiting for players to join
}
}
}
on *:TEXT:!kick*:%ACROSETTING.chan: {
if ($me == %ACROSETTING.botname) {
if (%ACRO.starting) || (%ACRO.started) {
if ($isPlayer($2)) {
if ($nick isop $chan) {
msg %ACROSETTING.chan 4 $+ $2 has been kicked from the game.
acro.removePlayer $2
}
else {
notice $nick !kick can only be used by OPs. OPs have been notified.
notice %ACROSETTING.botname $nick wants to kick $2
}
}
else {
notice $nick You can only kick players from the current game!
}
}
else {
notice $nick You can only kick people if there is a game in play!
}
}
}
; removePlayer <nick> removes the player from the game.
alias -l acro.removePlayer {
var %ACRO.m $acro.playerNum($1)
set %ACRO.playerNames $deltok(%ACRO.playerNames, %ACRO.m, 32)
set %ACRO.playerPoints $deltok(%ACRO.playerPoints, %ACRO.m, 32)
set %ACRO.playerVotes $deltok(%ACRO.playerVotes, %ACRO.m, 32)
set %ACRO.playerVoted $deltok(%ACRO.playerVoted, %ACRO.m, 32)
set %ACRO.playerAcros $deltok(%ACRO.playerAcros, %ACRO.m, $asc(`))
set %ACRO.playerAcrod $deltok(%ACRO.playerAcrod, %ACRO.m, 32)
if ($acro.numPlayers == 0) && (%acro.started) {
acro.stop 4Game stopped due to lack of players :(
}
}
; stop <text to be displayed>
alias -l acro.stop {
msg %ACROSETTING.chan $1-
acro.removeSettings
}
on *:JOIN:%ACROSETTING.chan: {
if ($me == %ACROSETTING.botname) {
if (%ACRO.starting) {
msg %ACROSETTING.chan Hey $nick $+ ! A game is starting now; type 4!join to join!
}
else if (%ACRO.started) {
msg %ACROSETTING.chan Hey $nick $+ ! A game has started, but you can still join with 4!join
}
}
}
on *:TEXT:!help:%ACROSETTING.chan: {
if ($me == %ACROSETTING.botname) {
notice $nick !start to begin a game
notice $nick !join to join a started game
notice $nick !forcestart to force a game to start if it is still in the joining phase
notice $nick !leave to leave a game you are currently playing
notice $nick !kick to kick a player from the current game. Can only be used by OPs.
notice $nick To submit an acronym, send a notice to the bot: /notice %ACROSETTING.botname submit <acronym>
notice $nick To vote for an acronym, send a notice to the bot: /notice %ACROSETTING.botname vote <nubmer>
}
}