[00:00] heh. [00:00] Plus, you can always generate the code [00:01] Yes, I probably have to. For '88 I've done everything manually, but ran into several problems because of typos [00:01] Now I've replaces everything with macros to prevent such problems [00:01] heh [00:01] *replaced [00:01] only one more step to generate the code then [00:03] yes, but I still have a lot of special cases [00:03] for instance for spl < x, < y I don't have to fully evaluate the B operand [00:04] and such things I still have to do by hand [00:04] not necessarily [00:04] could have a redcode description DSL that'd compile down to C ;) [00:04] or you could rely on GCC to eliminate dead code [00:06] I cannot reply on GCC, because I want the code to be at least a little bit portable [00:07] I think, that I have so far done everything according to the Python coding standards and want to keep it that way [00:07] *rely [00:07] no computed goto without GCC [00:08] and there go the Python coding standards ... [00:09] heh [00:09] if you want performance, you're gonna have to use some gcc extension. [00:09] (or drop down to some inline asm, which is even less portable) [00:11] I'm already amazed, that the current version is so near to fmars [00:11] Just by writing a big switch on opcode/amode/bmode [00:12] yeah, that's clearly the lowest hanging fruit [00:12] At least now I know the icws'88 by heart [00:12] (or think, I do) [00:12] heh [00:13] I probably really on think, that I do [00:13] *only [00:16] btw, I think I can write a quick mod-8000 for 2 numbers w/ SSE or MMX. [00:16] SSE2 preferably, but you don't have it on your C500 ;) [00:18] No, but so far my two cute C500 have never failed me [00:22] Hey, koth.org seems to be up and running again :) [00:22] I've just got some challenge results :) [00:23] MSG: Quit: humhum [00:23] But the results really torture me [00:24] HFB is always a tiny bit before being pushed off [00:31] err ... maybe I should look at the clock from time to time [00:31] It is a little bit late now and I really need to sleep [00:31] * Fluffy waves [00:32] Part: Fluffy left #corewars [03:45] hrm [04:12] Part: Core29 left #corewars [10:35] Join: Fluffy joined #corewars [10:35] :) [11:30] Anybody here? [11:30] I've got a little problem with the redcode standard [11:39] Seems, that nobody is here. So I've posted my problem to r.g.c. [12:03] Join: Judodudo joined #corewars [12:04] fluff: I didn't know you still played on 94b [12:05] I don't play 94b. Yatima v2.0.5 was from the time I've learned cw. [12:05] I've simply kileed it [12:05] *killed [12:06] Anyway: Hi Judodudo :-) [12:06] Never mind [12:06] Hi [12:07] You are Jens Gutzeit, aren't you? [12:07] Who is that ;-) [12:07] ? [12:09] Only a warrior popped up on 94b by Jens, and I thought that was you [12:09] nicks are confusing [12:09] Yes, it was me [12:09] (killer) was for killing Yatima v2.0.5 [12:10] ahh [12:11] that makes sense [12:11] Originally I thought to leave one warrior on 94b to monitor it, but several people do that. So I think it is a little bit unfair for beginners to fight on a hill filled with "monitor warriors" [12:11] Anyway SAL has a good history. So there is no need to leave a warrior on 94b [12:11] when is the age limit being imposed? [12:17] Don't ask me :-) The current answer is "soon", but that was one or two months ago [12:29] lol [12:33] MSG: Ping timeout: 252 seconds [12:54] Join: Philb joined #corewars [12:54] Hi Philb! [12:55] Hi [12:55] How well do you know the ICWS'88 rules? [12:55] I've go a little problem with them [12:55] *got [12:56] Probably not that well anymore. 94 is my native cw :) [12:57] * Philb waits [12:57] One warrior on '88 Koenigstuhl contains "SLT $ x, # y". "pmars -8" says it is value '88, but as far as I know, SLT isn't allowed with immediate B-mode [12:57] *value->valid [13:01] Sorry, you'll need check the 88 specs [13:02] Part: Philb left #corewars [13:02] Yes, according to my copy of the '88 rules it is invalid, but it says "Core War '88 - A *Proposed* Standard" and I'm not sure, whether it is final [13:02] hmm [13:17] Join: Roy joined #corewars [13:17] Hi Roy! [13:18] Hey Fluff, isn't pMars just the standard? ;-) [13:18] That is the question :) [13:18] At the moment I would say, it is a pMARS bug, but I'm still not sure [13:20] Under '94 rules I wouldn't have this problem, because every possible instruction is also a valid instruction [13:28] Hmm yes, except 94nop :) [13:29] Big prime, but not big enough (by far)... :-( [13:29] How did the big big speed test go? [13:29] hehe ... just the moment I've found a bug, you ask [13:30] :( [13:30] Bug :-O :-( [13:30] Corewar primes: [13:30] 6557*2^102991 + 1 -----> Prime of 31008 digits [13:30] 6557*2^161011 + 1 -----> Prime of 48473 digits [13:30] yes, pmars returns a different result than pycorewar [13:30] Ah.. :( [13:30] Unfortunately only a slightly different [13:30] pmars: 0, 22, 478 - pycorewar 0, 14, 486 [13:31] 8 losses or ties, you can look those up easily [13:31] How should I do this? [13:32] No idea.. :) [13:32] Yes, then it must be very easy ;-) [13:32] hmm ... maybe it isn't a bug of the MARS, but only of the warrior positioning algorithm [13:33] That would be easier to check, just printout the starting positions [13:33] already working on that [13:34] Otherwise you can let pmars print out when (which fight) the warriors losses are (22 numbers) and pycorewar too, then you know when it went wrong :P [13:34] Now I let the warriors fight with -P [13:35] If there is no difference then it must be a bug in the warrior positioning [13:36] And I already thought I could start to implement the ideas, pkhuong talked about yesterday [13:37] Nice, I didn't follow it one bit, sounded a bit complicated [13:37] it is quite easy actually [13:37] At the moment I have a big switch statement. [13:37] and I switch on opcode/amode/bmode [13:37] fmars goes one step further [13:38] it has a table (indexed with opcode/amode/bmode), where the table entries point to the the appropriate code to execute [13:39] so you can simply run: do { goto[table[instruction]] } while (...) [13:39] Ah yes, now I understand it a little [13:39] But there is more [13:39] and fmars does goto instruction with all instructions unrolled [13:39] yes [13:40] If I store the address of the appropiate function directly in the core I could do [13:40] do { goto[insn] } while (...) [13:40] which eliminates the need of a table lookup [13:41] hmm ... it seems to be a problem of the MARS itself, because with -P I still have different results :-( [13:42] Ah yes, nice... hmm Mars problem not nice [13:42] And if I've understood pkhuong correctly there is yet another way to improve that [13:43] do { ... } while (...) do some unnecessary jumps [13:43] I could replace the loop, if I would determine the at each point, which instruction to execute next and then directly goto there [13:44] That would eliminate the need to jump to the start and the end of the loop for each executed instruction [13:44] Hm yes, but that'll need a big rehaul [13:44] no :-) [13:45] I only have to add the same code at the end of each "part" [13:45] it is just a copy&paste [13:45] Hmm, well, it might be worth trying, BUT you have a MARS problem :-P [13:45] yes, yes, I know :-( [13:46] Always hit the sore spot again :-( [13:49] Heh, I'm very proud of you already! [13:49] There might be nothing to be proud of [13:49] I might have a lof of fun PRETENDING to write a MARS [13:50] anyway I've now started to review every instruction of my MARS (codename "VAPORWARE" ;-) [13:56] I was just thinking, what if I have hit a bug in pMARS and my MARS is correct ... [14:08] Download another MARS, but its unlikely because more marses have been created using pmars as benchmark [14:08] already done ... they all show the same results as pMARS [14:10] Then its probably something in the mars.. :( [14:10] Maybe you can send it to me for b3ta testing..? [14:10] I've just noticed, that one of warriors I have problems with is named "Annoying" [14:10] Analyzing warriors could point out to a single instruction not working right [14:11] I've already checked the instruction of both warriors, but couldn't find anything. Maybe I've simply overoptimized it and now the the A or B operand isn't any longer evaluated correctly [14:11] you want the code, Roy? [14:12] Sure [14:12] one mo [14:13] Does it have a form of GUI? or is it just commandline [14:14] just a commandline [14:14] k [14:14] you have to install it as root [14:14] with "python setup.py install" [14:14] k [14:14] the you can run "./testsuite" and "./benchmark" [14:15] but the second part of the benchmark is likely to segfault, because there is yet another bug [14:15] but that is the multiwarrior-code, which I haven't edited for a while [14:16] error: The .NET Framework SDK needs to be installed before building extensions f [14:16] or Python. [14:16] grr :) [14:16] NET? [14:16] * Roy doesn't have .NET [14:16] you only need Python and a C compiler [14:17] Hehe ... you run XP, right? [14:17] It errors out during the build_ext [14:17] What does it say? [14:17] Yup, XP [14:17] I've only tested it under Linux so far [14:17] (LFS and Debian) [14:17] It says what I copied :P [14:18] Could you please copy&paste the output :-) [14:18] running install [14:18] running build [14:18] running build_py [14:18] creating build\lib.win32-2.4 [14:18] creating build\lib.win32-2.4\Corewar [14:18] copying corewar\__init__.py -> build\lib.win32-2.4\Corewar [14:18] copying corewar\Debugging.py -> build\lib.win32-2.4\Corewar [14:18] copying corewar\Parser.py -> build\lib.win32-2.4\Corewar [14:18] running build_ext [14:18] error: The .NET Framework SDK needs to be installed before building extensions f [14:18] or Python. [14:18] Like I said :-) [14:18] Strange [14:19] But if you want, you can play with the C-code [14:19] the MARS is in src/BenchMARS88.c [14:19] Heh, I'll check it ou [14:20] Yup, thats a big switch :) [14:21] And the final version will include 3 almost identical switches [14:21] one for normal, one for -P, one for multiwarrior [14:27] Damn :( [14:27] what? [14:27] I can't find the bug [14:27] Maybe I should write a Python-script, that generates the big switch. That way I can be sure to have no typos [14:27] * Roy neither, I can't compile it now :) [14:28] Heh, typos in switch.. thats hard to find [14:28] yes and now think of what happens, if I do the same for '94 [14:28] there are way more combinations [14:29] Join: fiveop joined #corewars [14:30] Roy: I start to write the Python-script, which then generates the big switch. Should be safer anyway [14:30] Yeah, and easier if someday you implement 94 :) [14:31] * Fluffy sighs [14:45] I should have done this right from the beginning [14:45] Especially after I've decided to unroll almost everything [14:48] Join: Mizcu joined #corewars [14:48] Hi Mizcu! [14:49] hi Fluff [14:49] How well do you know the ICWS '88 rules, Mizcu? [14:49] not really [14:49] ok, then forget the question :) [15:01] Join: fiveop_ joined #corewars [15:03] MSG: Ping timeout: 252 seconds [15:21] MSG: [15:53] Part: Fluffy left #corewars [16:04] Join: Metcalf joined #corewars [16:04] Hi [16:28] hi met [16:28] Wow, a potential sign of life :-) [16:28] not really.. I just woke up.. [16:30] Only just? I never get up that late! [16:31] I'm on holidays for 3 more days :) and my neighbors were loud at 3am.. [16:31] Didn't they invite you to the party? [16:32] heh.. [16:32] no [16:32] they think we're too old. [16:33] :-( [16:35] how about you? [16:35] good day? [16:36] Hmmm... busy [16:36] how about you? [16:36] how have the 5 minutes you have been awake been? [16:36] just organizing the house is the plan.. [16:36] I got a huge copper heatsink for my graphics card yesterday.. [16:36] now its *DEFINATELY* not overheating.. [16:37] went from an idle temp of 60C->44C and the fan on the new heatsink doesn't run unless its hot! [16:37] :-) [16:39] almost bought an athlon 64 x2 4000+.. [16:39] but my wife was hinting a little too much that my birthday was coming.. so I think thats what I'm getting.. [16:39] That would be handy for evolving :-) [16:40] Maybe your wife just means she doesn't want you to have it! [16:40] Does she understand you having so much computer stuff? [16:40] yeah.. [16:41] and she knows she'll get the old one for her windows box :).. [16:41] :-) [16:41] The Sci Am publication date has now been resolved [16:42] she's mostly just happy I keep it to one desktop, a firewall and notebooks in here.. [16:42] I had a good 30 computers in the last house we were living in.. [16:42] I can beat that, 42 :-P [16:42] she was getting mad because she couldn't vaccuum without prior notice.. [16:42] heh [16:42] mine were all current at the time tho :) [16:50] how'd you end up with 42 computers met? [16:51] I just kept buying them to play with! [16:51] hhe [17:06] time to go [17:06] * Metcalf waves [17:06] MSG: Quit: mov.i #1,1 [17:11] MSG: Ping timeout: 252 seconds [17:21] Join: Core29 joined #corewars [17:29] Join: Fluffy joined #corewars [17:30] :) [17:41] Join: pkhuong joined #corewars [17:41] hi pkhuong :) [17:42] hi [17:42] how goes the code generation? [17:42] bad :( [17:42] I still have the same bug, even with the generated code. [17:43] I probably understand sth. differently than it is described in the standards :( [17:43] in-register evaluation's where it hurts, usually, iirc. [17:44] Yes, I've already checked it and think, it is ok, but it isn't :( [17:46] want me to have a look? :/ [17:46] would be nice, but give me 5 minutes to finish the current test run [17:46] :) [17:47] k [17:47] YIPPIE [17:47] I'M SO STUPID! [17:48] erh [17:48] good, i suppose [17:48] And of course it was the in-register evaluation [17:49] When using CMP/SLT I've compared the values found in the memory, not in the register [17:50] I will try to fix that bug in the handwritten code, because it is faster [17:50] hrm [17:50] heya pk [17:50] twice as fast :) [17:50] we've broken 42.7 today pk :) [17:50] hey [17:50] ok nice :) [17:50] But if you don't mind I'll send you then code then nonetheless, pkhuong :) [17:50] sure [17:50] Hi bvowk! [17:50] my nick at gmail [17:50] ok [17:50] do you actually hold 2e by hand or is it mostly fire and forget now? [17:50] no.. its mostly fire and forget.. [17:51] k. [17:51] I update the commandlines every 4->8 hours [17:51] bvowk: And 42.7 translates into which place? [17:51] and submit the new results.. [17:51] 5th still.. [17:51] and 1st has what? [17:51] 45 [17:51] ? [17:51] 44.5 [17:51] right now.. [17:52] we need a new method, but :/ [17:52] even triggered sim looks like the last thing on my list. [17:53] *event [17:53] yeah.. [17:53] let me commit f and you can peek at it.. [17:54] ok.. gotta eat.. [17:54] bbiab [17:58] hmm ... one day to find the bug and only 3 times the same two lines to fix the bug [17:58] At least it is nowhere near my record [17:59] one week to find a missing dot :) [17:59] :/ [18:01] By the way it seems, that fmars does more than a simple table lookup. But what exactly I don't understand. [18:18] pkhuong: I've sent it [18:19] k [18:22] please ignore the methods p_run (same but, but not yet fixed) and mw_run (segfaults for unknown reason), but the run-method should work as expected [18:22] *but->bug [18:22] those if's to implement modulo can be optimised if you stick to a single coresize. [18:22] no branch, etc. [18:22] which if's are you talking about? [18:23] in BenchMARS88.c [18:23] if foo > coresize foo -= coresize; [18:23] ahh [18:24] But unfortunately I cannot stick to one coresize [18:24] heh why? [18:24] well, for additive you can still do it, actually. [18:24] just that it gets more complicated when you don't know for sure that x is <= 2*coresize [18:24] PyCorewar should sth. like a libraray. So it should support all coresizes [18:25] :/ [18:25] But I could implement special versions for coresize = 8000 as it is quite common [18:26] what is it an instruction's struct, apart from insn, a, b? [18:26] nothing [18:27] typedef struct { [18:27] u32_t insn; /* opcode, (modifier), A-mode, B-mode */ [18:27] field_t a; /* A-field */ [18:27] field_t b; /* B-field */ [18:27] } insn_t; [18:27] can't you use *bAddr = *aAddr, then, for example? [18:27] might let the compiler do a better job. [18:28] i beleive fmars uses MMX or SSE to move 64 or 128 bits in one go [18:28] you mean *bAddr = *aAddr to copy the an instruction? [18:28] yes [18:29] yes, it should work [18:29] I'll test it with my little benchmark [18:29] unlikely to change anything, but a sort of smart but not that smart compiler might compile it better [18:29] (i doubt) [18:30] hehe ... I like that: *bAddr++ = *aAddr++ [18:30] hehe [18:30] yeah, we can convert most of the branches to use more boolean&pointer arithmetic [18:30] you mean with a fixed size of the core? [18:31] no [18:31] even with a variable coresize [18:31] should help with the pipeline of death CPUs we have nowadays [18:31] maybe I should actually read, what you've written [18:32] Don't think I describe that one in the wiki [18:32] it's sort of a common knowledge trick for low level hackers [18:32] (a - b)>>31 gives -1 if a < b, 0 otherwise [18:32] So far I've only played a little bit with optimization, but never got that far [18:33] most of your branches are of the form if (a < b) x += y; [18:33] they can easily be converted to not branch. [18:34] (without having to rely on the compiler to convert it to a predicated instruction, which are pretty slow anyway) [18:34] heck, you should ask metcalf ;) [18:36] I will :) [18:36] benchmark is now running [18:38] bad idea ... as usual I've overoptimized [18:39] at least the testsuite has catched the error [18:39] :/ [18:40] hmm ... testsuite says it is ok, running benchmark again ... [18:44] mmm.. am now abusing my graph pattern matcher like a full-blown backtracking lazy language, so it can parse strings sanely... [18:45] hmm ... benchmark is still the same, but I will keep the new version, because it is shorter :) [18:45] lol [18:46] Unfortunately my current benchmark seems to have an error margin of about +/-0.2 MIPS and the new result in still within [18:47] heh. lemme rewrite your mod-coresize macros [18:48] :) [18:48] You might notice, that I've been lazy and copied them from exhaust-ma [18:48] but in DECMOD! [18:48] *bug [18:48] where? [18:48] how? [18:48] who? [18:48] #define DECMOD(x) do { if ((x)-- == 0) (x) = coresize - 1; \ [18:49] oh wait [18:49] damn [18:49] fucking variable length onts [18:49] gurh [18:49] pasting that in emacs [18:49] what's wrong with it? [18:49] yeah [18:49] if x was zero, it becomes -1 (= coresize -1) [18:49] it showed as an emdash [18:49] instead of -- [18:49] ah, ok [18:54] #define INCMOD(x, coresize) do { (x)++; (x) &= ((x) - (coresize)) >> 31; } while 0; [18:54] for example [18:55] will try it [18:55] totally untested ;) [18:55] Unfortunately it won't have an effect [18:55] It is hardly used :( [18:55] lol [18:55] well, that's an example [18:56] in '94 that would be different [18:56] all the MOD macros can be changed that way [19:00] naw, buggy [19:00] 2 sec [19:00] not buggy [19:00] :) [19:00] ? [19:01] Don't confuse me even more. [19:01] I've looked the whole day at my code. [19:01] And I know how hard it is to read my own code [19:01] ;-) [19:02] lol [19:03] yeha, let me spend a few minutes testing the thing before wasting time on the bench [19:03] wait [19:03] there is a bug in SLT [19:03] I mail you the new version [19:05] email is out [19:05] but be sure to delete the build directory [19:06] Again I've start the big comparison with all warriors on the '88 Koenigstuhl [19:06] k. [19:06] *started [19:06] I haven't built anything [19:06] got the file on windows, dev'ing in my linux VM [19:07] will scp later ;) [19:08] there seems to be confusion as to whether coresize should be a global or an argument to the macros, btw [19:08] I feel like in the "old days" when I tried to make my prime number generator as fast as possible [19:09] (compare INCMOD and DECMOD) [19:09] yes I was in the process of removing coresize when I discovered the bug [19:09] coresize isn't globally defined, but will be removed form the macros nonetheless [19:09] because it everywhere has the same name [19:16] going, going [19:16] now at SUBMOD [19:16] :) [19:17] bug in SUBMOD' btw [19:17] ? [19:17] if ( (z) >= coresize ) (z) += coresize; [19:17] should be if ((z) < 0) [19:17] no [19:17] z is unsigned long [19:17] ah k. [19:17] yuck :p [19:17] I was working with ints. [19:17] damn. [19:18] It made things easier, with unsigned long -1 becomes MAXINT - 1 and + pointer it is very likely to segfault [19:18] which makes it easy to recognize such bugs [19:19] at least for me, who has created a lot of such bug [19:19] k. [19:19] I'm casting in the macro [19:19] Yippie! The first step of the comparison is complete. I now had every warrior from Koenigstuhl once in the core [19:20] and there have been no differences [19:20] :) [19:20] is there no way to have a signed arithmetic shift on unsigned? [19:21] Not that I know of, but you are probably asking the wrong person [19:21] Try pkhuong, he seems to know more than me :) [19:21] :p [19:22] I'm a C as a second language programmer ;) [19:22] I've started with BASIC, moved to Forth, had to do Modula-2 and then learned C [19:24] basic, redcode, common lisp, C, Java ;) [19:24] some asm on the size [19:24] (side [19:26] I've done asm mostly on my first computer [19:26] a KC85/4 [19:26] but that have been different times [19:26] I know every bit personally [19:26] with 64 KByte it wasn't such a big problem [19:30] http://en.wikipedia.org/wiki/KC_85 :-) [19:31] Try the German version for a picture [19:34] btw, you do realize that depending on unsigned to wrap around is utterly non portable [19:34] (it just so happens that it's portable to nearly every modern arch ;) [19:35] That is sth. to think about. Apart from my tendency to not create that much bugs with the current version, there is no reason to use signed values. [19:36] It would only limit the maximal size of the core from 2**31 to 2**30, which shouldn't be a problem [19:37] err ... that is wrong, the limit would stay the same: 2**31 [19:37] since you depend on wrap-around, yeah, probablu [19:37] y [19:53] now to IPINCMOD [19:56] you got weird pointer arithm going on from there [19:56] I'll leave it at that :) [20:04] * Fluffy is back again [20:05] I'll try your new macros and benchmark them ... [20:05] Join: fiveop joined #corewars [20:09] MSG: Ping timeout: 252 seconds [20:13] pkhuong: With only the DECMOD macro now change, but seems to work. Now adding ADDMOD [20:15] k. [20:15] *now->no [20:17] The ADDMOD macro results in an error message, when used: [20:18] *** glibc detected *** free(): invalid pointer: 0x081dbe80 *** :-( [20:20] :# [20:20] do you use ADDMOD with pointer arithm? [20:20] that'd be a bad thing, since it does bitwise stuff [20:21] I can't remember where, but it seems probable [20:21] :/ [20:21] no, no pointer arith [20:21] weird... [20:21] SUBMOD seems to work [20:24] hmm ... have to leave for about 15 mins to run the benchmark without X windows running ... [20:24] Part: Fluffy left #corewars [20:30] Join: Fluffy joined #corewars [20:30] Sorry, but the new macros don't seem to have an effect. I'm still at 9.3 MIPS [20:31] Maybe you a Celery CPU is too old to see differences [20:31] I now start to implement the first goto-version [20:32] i.e. do { goto[table[insn]] } while (...) [20:32] yeah, on a P4, otoh, that should make a difference [20:32] well, for SUBMOD, anyway [20:33] INCMOD and DECMOD are pretty easy to predict right 9x% of the time [20:33] Yes, and the opcodes SUB/ADD aren't that often executed [20:35] heh. [20:36] otoh, < empty core VS nonempty core should make DECMOD hardish to predict [20:36] I guess more modern code might act differently [20:36] I simply have to wait two more months. [20:37] Then it is time for a new computer [21:30] Hmm ... converting the big switch into a goto[insn] doesn't improve the performance [21:30] probably GCC already does sth. similar [21:35] ok ... that's all for today [21:36] and tomorrow [21:36] To all a Happy New Year! [21:36] * Fluffy waves [21:36] Part: Fluffy left #corewars [22:11] Join: Roy joined #corewars [22:11] Hi..! [22:11] Nice talk about optimization etc, I can learn from that ;-) [22:12] I don't know much about that, but I'll have to learn programming on a mobile phone (preformance is bad there) [22:13] :| [22:13] ..? [22:13] :) [22:14] Things like integer division, never use X/2 but X>>1 [22:16] ah, that should be automagic compiler optimisations [22:16] same for mul-div conversion to add, shift and muls [22:17] yeah, but java (boo!) doesn't do that sort of stuff [22:17] And mobile phones use J2ME, so... [22:32] btw. I think there is a bit of a bug in the code of speedierscanner [22:34] If it finds something right after it found something, the 'j' line gets decremented too much (without being reset) [22:34] :-) [22:44] MSG: [23:34] MSG: Quit: Trillian (http://www.ceruleanstudios.com [23:54] MSG: Quit: humhum