This is the new home of the egghelp.org community forum.
All data has been migrated (including user logins/passwords) to a new phpBB version.


For more information, see this announcement post. Click the X in the top right-corner of this box to dismiss this message.

how to optimize that proc

Old posts that have not been replied to for several years.
Locked
e
eiSi
Halfop
Posts: 70
Joined: Thu Mar 07, 2002 8:00 pm

how to optimize that proc

Post by eiSi »

hi there!

some of you know the fishbot on quakenet.. he just gives silly answers to people saying a certain sentence.

I coded that in tcl, but how to optimize:

setudef flag fish
bind pubm -|- * fishbot

Code: Select all

proc fishbot {nick uhost handle chan text} {
  if {![string match "*+fish*" [channel info $chan]]} { return 0 }
  
  set fish1 "you can't just pick people at random!"  
  set fish2 "wertle"
  
  if {[string match "$fish1" $text]} { putserv "PRIVMSG $chan : I can do anything I like, $nick, I'm eccentric! Rrarrrrrgh! Go!" }
  if {[string match "$fish2" $text]} { putserv "PRIVMSG $chan : moo" }
}
the list goes on that way.. fish3, fish4... and the responses do aswell.

what's the best way to solve this? with 2 arrays? (questions <--> answers)

thanks for any suggestions!
User avatar
user
&nbsp;
Posts: 1452
Joined: Tue Mar 18, 2003 9:58 pm
Location: Norway

Post by user »

A list and a foreach loop would speed it up some i recon...

Code: Select all

set crap {
"question" "answer"
"blah*" "$nick is verbose!"
"* bleh *" "no."
"bluh" "i hate $chan"
}

foreach {m a} $crap {
  if {[string match $m $text]} {
    # the 'subst' takes care of variable/command/backslash substitution
    # in the string contained in 'a'.
    putserv "PRIVMSG $chan :[subst $a]"
    # then we 'break' to avoid answering more than once to each line
    # of text and also cut down on the cpu usage
    break
  }
}
You could of course store the mask/reply pairs in an array and loop through 'array names' or 'array get' instead.

Also make sure you put the most commonly matched masks first.

If you plan to have thousands of elements the best thing would probably be to sort them some way and use a binary search approach to decrease the number of mask having to be matched.
Last edited by user on Wed Jun 11, 2003 8:59 am, edited 1 time in total.
e
eiSi
Halfop
Posts: 70
Joined: Thu Mar 07, 2002 8:00 pm

Post by eiSi »

all right!

thanks for your help!

I'll try it!
User avatar
user
&nbsp;
Posts: 1452
Joined: Tue Mar 18, 2003 9:58 pm
Location: Norway

Post by user »

Here's another idea that might speed things up further when you have alot of answers:

Code: Select all

# outside the proc:
# array of masks/answers
array set fishA {
  "question" "answer" 
  "blah*" "$nick is verbose!" 
  "* bleh *" "no." 
  "bluh" "i hate $chan" 
}

# array containing lists of masks starting with a certain char
array unset fishM
foreach e [array names fishA] {
  lappend fishM([string index $e 0]) $e
}
# and a sorted list of the chars
set fishC [lsort -dict [array names fishM]]

proc fishbot {nick uhost handle chan text} {
  # converting $text to lowercase and making sure all your masks also are 
  # in lowercase might be a good idea to avoid multiple case conversions
  global fishA fishM fishC
  # first we make a list of masks that might match $text
  # (based on the first char)
  set masks {}
  foreach e $fishC {
    if {[string match $e* $text]} {
      set masks [concat $masks $fishM($e)]
    }
  }
  # then we do the actual matching
  foreach m $masks {
    if {[string match $m $text]} {
      putserv "PRIVMSG $chan :[subst $fishA($m)]"
      break
    }
  }
}
e
eiSi
Halfop
Posts: 70
Joined: Thu Mar 07, 2002 8:00 pm

Post by eiSi »

wow!

that's really great :)

I'll try it later on, but I think it's exactly what I meant! :)

Thanks again!
Locked