All pastes #2099952 Raw Edit

acrobot for mirc

public text v1 · immutable
#2099952 ·published 2012-01-06 05:12 UTC
rendered paste body


; 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>
  }
}