Darkj wrote:Ok i lost you, that doesn't look for cutomizable, it looks like I'll have to edit code everytime I add more bots, I was trying to avoid that.
You said you wanted to output the bots in pairs, I suggested a way. (not static in any way) Try to understand what that foreach does and you'll see what I mean.
Well, actually, I asked how to output an INI file (as seen above) to IRC, i just prefered the format of 2 bots per line, whether it still be 10 bots listed.
As for my debugging, it doesn't look like an array is going to work for me with the way the INI file is designed
the [BotName] being the actual bots name on IRC, char name is the character name in game. But in order for an array to work it looks like, is it needs some general same thing to look for. Which is where I'm stuck, I just wanted a simple list script, didn't realize it was gonna get this complicated.
EDIT: In order to use ini_write properly, the [] sections need to be different names.
Darkj wrote:Actually, I've kind of gone a different route now, and worked a little with the ini_read and ini_write functions. Here is my working code now.
...
See any typos or mess ups, would be great to know, but this code works exactly the way I want it
proc list_bots {nick uhost hand chan args} {
global nowhere mainchanbots inifilebots
# i took the liberty to rewrite this 'if' a bit..just to make it easier to read (the result is the same)
if {$chan != $mainchanbots} {return 0}
set i 0
foreach {name value} [parseIni bots.ini] {
set check [ini_read bots.ini ${name} location]
set displayname [ini_read $inifilebots ${name} display]
set botcharname [ini_read $inifilebots ${name} charname]
set botloc [ini_read $inifilebots ${name} location]
set botact [ini_read $inifilebots ${name} action]
# you should open the file outside the foreach loop and close it after the end..no point hammering the poor file that way :P
# but why are you writing it to a file in the first place? why not keep the lines in a variable?
set fs [open bots.tmp a+]
# this 'string match' should be replaced by a 'string equal' I guess.
# Although I don't get the point of ignoring one bot..why is it in the file if you don't want to know about it? And why go through all that hard work in the previous lines just to end up ditching the data gathered?
if {![string match $check $nowhere]} {
# here you write it as a string, but you later treat it as a list (using 'lindex' on it when reading it back in)
puts $fs "$displayname $botcharname $botloc $botact"
incr i
}
close $fs
}
# the number of bots can be determined without this counter if you use one of the examples from my previous post
if {$i <= 0} {
putserv "PRIVMSG $mainchanbots :\<\0032There are currently\003\0034\002 0 \002\003\0032bots logged in.\003\>"
}
if {$i > 0} {
putserv "PRIVMSG $mainchanbots :\<\0032There are currently\003\0034\002 $i \002\003\0032bot\(s\) logged in.\003\>"
}
# using a timer to delete the file doesn't make sense to me...why are you doing it?
utimer 5 deletefile
set fs [open bots.tmp r]
while {![eof $fs]} {
if {![gets $fs line]} {
# danger danger! :P by returning at this point you end up leaving the file channel open and eventually your interpreter will hang because of too many open files
return 0
# you did this check when creating the file
} elseif {[lindex $line 2] != $nowhere} {
# using 'lindex' on a string for the next 4 lines (will cause errors if your data contains special chars like [ and {)
set displayname [lindex $line 0]
set botcharname [lindex $line 1]
set botloc [lindex $line 2]
set botact [lrange $line 3 end]
# a little late to do this check now? :P
if {$displayname == ""} {
close $fs
return 0
}
putserv "PRIVMSG $mainchanbots :\002$displayname\:\002 \(\0032$botcharname\003\) \0034$botloc\003 \(\0036$botact\003\)"
}
}
close $fs
return 0
}
I imagine one of my previous examples would gain a very similar result with HUGE cpu savings and no possible errors, so you should consider at least trying one of them
while {[gets $fs line]>-1} {
if {![string len $line]} continue
# this makes it ignore empty lines and just skip to the next
# but you don't need that as you create the file and don't write any
# empty lines to it :)
# insert the rest of your code here
}
Darkj wrote:Basically I've changed the way I'm doing this
I'm pulling it out of the INI file and dumping in a tmp file, to make for easy formatting, then the bottom of the script is just outputting the file.
This bot is only used between 15-20 people on a private network, so I'm not too concerned with cpu etc.
But 'append'ing/'lappend'ing to a variable would be much easier...and the 3 examples I showed you earlier would just need color codes to be added to produce the exact same output. (saving alot of precious vertical space on your screen while debugging the code ,P)
bind pub n !test test
proc test {nick uhost hand chan arg} {
set defaults {charname none location none action none}
array set a [parseIni your.ini]
# plural ending (bot(s)) based on the number :P
putserv "PRIVMSG $chan :There are currently [array size a] bot[expr {[array size a]!=1?"s":""}] logged in."
foreach bot [lsort -dict [array names a]] {
array set b [concat $defaults $a($bot)]
putserv "PRIVMSG $chan :$bot: ($b(charname)) $b(location) ($b(action))"
}
}
That worked perfectly, well, except the auto counter, but I fixed it up a bit. Thanks for the help user, just glad someone stuck with me even though it was prolly like talkin to a brick wall.
Darkj wrote:That worked perfectly, well, except the auto counter.
Do you mean the grammatical errors in the line announcing the number of bots online or the fact that my code didn't subtract the bot(s) you're filtering out?
proc parseIni {file} {
array set arr {}
set f [open $file]
while {[gets $f l]>-1} {
set l [string trim $l]
if {[string match {\[*\]} $l]} {
set e [string range $l 1 end-1]
} elseif {[info exists e]&&[string match *?=?* $l]} {
regexp {^([^=]+)=(.+)$} $l a a b
lappend arr($e) [string trim $a] [string trim $b]
}
}
close $f
array get arr
}
Is that code fine without return's etc? I think this may be a problem.