code logs -> 2013 -> Thu, 23 May 2013< code.20130522.log - code.20130524.log >
--- Log opened Thu May 23 00:00:32 2013
00:19
<@Reiv>
I don't mind Python.
00:20
<@Reiv>
I do mind the spaces-instead-of-tabs. If they're so critical to the proper operation of your program, why the cheese did you not enact dynamic tabbing :/
00:33 himi [fow035@Nightstar-5d05bada.internode.on.net] has quit [Ping timeout: 121 seconds]
00:43
<@celticminstrel>
At some point I might ask for more ideas for special moves, but I kinda want to finish implementing the ideas I have first. >_>
01:07 You're now known as TheWatcher[T-2]
01:10 Derakon[AFK] is now known as Derakon
01:10 You're now known as TheWatcher[zZzZ]
01:19
< RichyB>
Lambdacats. http://spl.smugmug.com/Humor/Lambdacats/13227630_j2MHcg#!i=960526314&k=sFRhzX6&l b=1&s=L
01:21 * McMartin applies a Yarn Combinator.
01:29
< [R]>
<froztbyte> I'm more interested in why people pick an initial thing, and then just fiercely defend it for reason of "I've already invested effort in this, why must I do it again?" <-- imprinting (psychology) most likely. Affects OS choice too.
01:50
<@gnolam>
Cognitive Dissonance, more like.
01:54
< [R]>
IMO that's a symptom
01:55
< [R]>
Unrelated: what's the difference between Scheme and Lisp (I'm thinking about learning one)
01:57
<&McMartin>
Scheme is a Lisp dialect.
01:57
<&McMartin>
Are you asking the differences that make Scheme Scheme compared to other Lisps, or are you asking for a comparison between Scheme and Common Lisp?
01:58
< [R]>
I'm asking because I'm kind of interested in learning one. I know shit all about them other than they use parens like mad.
01:58
<&McMartin>
Ah, OK
01:58
<&McMartin>
So, the only two I'd suggest actually learning are Scheme and Clojure, and it's probably best to learn Scheme first.
01:58
<&McMartin>
Both Scheme and Clojure have a stronger functional/immutability focus
01:59
<&McMartin>
Common LISP is honestly closer to BASIC in terms of how it's used
01:59
< [R]>
Ah, alright.
01:59 * [R] will see if there's a Scheme Hard Way.
02:00
<&Derakon>
...right, applying a decorator to a function in a base class does not apply the decorator to overrides of that function in child classes. ?.?
02:00
<&McMartin>
The best book for messing about with Scheme is "The Structure and Interpretation of Computer Programs".
02:01
<&Derakon>
So I guess either I can modify the child classes to also use the decorator, or I can use a different approach that's a bit more local.
02:01
<&Derakon>
(I need to threadsafe a datastructure, so I can either decorate the functions in which it is modified, or explicitly use a lock when it's read/written)
02:01
<&Derakon>
(The former is easy, the latter slightly messier...)
02:02
<&McMartin>
I do not consider Stock Scheme to actually be appropriate for writing true applications in, due to a rather lacking standard library
02:02
<&McMartin>
Gambit is a very good Scheme-to-C-to-machine-code compiler, though, so for practice it's fine
02:03
<&Derakon>
I guess the latter approach is the right one, though, which is a shame because I rather like this: http://pastebin.com/y9FJ5rMa
02:03
<&McMartin>
Clojure is Lisp-like, but has some properties that makes its status as a Lisp slightly questionable IMO - however, it also interoperates seamlessly with Java.
02:04
< [R]>
I might pick that up later
02:04
< [R]>
Because I've got this Java IRC bot...
02:04 * [R] really doesn't like Java that much
02:04
<&McMartin>
Yeah
02:04
<&McMartin>
Clojure is The Best Way To JVM, imo.
02:04
<&McMartin>
But Clojure also doesn't have, for instance, tail recursion elimination.
02:05
<&McMartin>
It also has native data types that are not "list", and Clojure Lists and Cons cells do not work the way they do in any other Lisp dialect.
02:05
<&McMartin>
Clojure has in effect borrowed a great deal from ML and Java while staying *mostly* Lisp-y.
02:06
< [R]>
Since I'm going with scheme, is a dumb IRC bot a decent test project? (For grasping the language, not for actual use)
02:07
<&McMartin>
Tricky
02:07
<&McMartin>
I'd go with something that talks stdin/stdout instead of trying to do network interfaces.
02:07
< [R]>
k
02:07
<&McMartin>
One of the things Lisps are not very good at is string processing.
02:07
<&McMartin>
This is why SICP is great
02:07
<&McMartin>
It does all kinds of crazy things
02:07
< [R]>
SICP?
02:07
<&McMartin>
Structure and Interpretation of Computer Programs.
02:08
<&McMartin>
One learns Lisp mainly because one wishes to discern the eldritch secrets of the Outer Gods, not because one wants to learn superior forms of architecture, nor again new ways of doing old things.
02:09
< [R]>
Since I'm an SA by profession, can you think of something that'd be semi-useful that I could use Scheme for? Or am I just going to be stuck doing hello world shit?
02:09
<&McMartin>
That's a difficult question to answer.
02:09
<&McMartin>
Also, can you expand SA
02:09
< [R]>
Systems Administrator
02:10
<&McMartin>
It will not be directly applicable.
02:10
< [R]>
:/
02:10
< [R]>
Alright, will try anyways
02:10 himi [fow035@D741F1.243F35.CADC30.81D435] has joined #code
02:10 mode/#code [+o himi] by ChanServ
02:10
<&McMartin>
But in learning its secrets, things that are treated as ad-hoc special case techniques instead fall away and are recreations of a purer thing.
02:10
<&McMartin>
It will level you up as an architect.
02:11
<&McMartin>
About half of the patterns in Design Patterns are "here are how you can stumblingly re-implement the functionality to get effects that you'd get in a Lisp by Just Writing It Down"
02:12
<@Reiv>
You learn Scheme for the New Way Of Looking At Problems, not to actually, uh, use it for much~
02:12
<&McMartin>
It'll give you the core background for things like map/reduce based problems.
02:12
<@Reiv>
Which you then solve with more traditional techniques.
02:12
<@Reiv>
But they no longer hurt your head~
02:13
<&McMartin>
Or, you know, you don't - now that things like Hadoop and well, mapreduce exist, you might actually then unleash an entire cluster on it
02:13
<&McMartin>
But yeah, not kidding about the eldritch part
02:13
<&McMartin>
In both Clojure and Scheme, one of the things you generally don't do is "assign values to variables"
02:14
<&Derakon>
Functional programs tend to be short on visible state in general.
02:14
<&McMartin>
In Clojure, almost everything is immutable; in Scheme, one tends to pretend this is the case.
02:14
<&McMartin>
Well, yes
02:14
<&McMartin>
I guess that's actually the point
02:14
<&McMartin>
You shouldn't be doing this "to learn Scheme"
02:14
<&McMartin>
You should be doing this "to learn the functional programming paradigm"
02:15 VirusJTG_ [VirusJTG@2B12AA.572255.206A2A.901581] has joined #code
02:16
<&McMartin>
Because, seriousyl
02:16
<&McMartin>
I read this book, from 1995, and even by then, so much had been lost.
02:16
<&McMartin>
Some of it has managed to come back.
02:16
<&McMartin>
List comprehensions in Python come from the functional languages.
02:16
<@Reiv>
... so much had been lost?
02:16
<&McMartin>
Reiv: One of the "Design Patterns" is essentially a restatement of the notion of modules.
02:17
<&McMartin>
But even then, they want to instantiate an object to represent the module as an intermediary
02:17
<&McMartin>
("Facade")
02:17
<&McMartin>
There are also about five different things that are various forms of "you write a lambda here"
02:18
<@Reiv>
OK
02:18 VirusJTG [VirusJTG@Nightstar-09c31e7a.sta.comporium.net] has quit [Ping timeout: 121 seconds]
02:20
<&McMartin>
(Strategy, Template Method, and Command, and arguably also Mediator and Chain of Responsibility, for the record)
02:21
<&McMartin>
Hmm.
02:21
<&McMartin>
One thing Scheme doesn't put in explicitly (because you can make it happen with lambdas~) is lazy evaluation
02:21
<&Derakon>
As a general rule I find that I have no idea what most design patterns are by name, but I routinely reinvent them as needed~
02:22
<&McMartin>
This is because Python, being both multiparadigm and Actually Good, has most of the things you'd need them to work around as language primitives~
02:22
<&Derakon>
Well, I've done them in C++ too.
02:23
<&McMartin>
Ah yes, the Prototype pattern
02:23
<&McMartin>
aka "So, um, if you wanted JavaScript inheritance, why aren't you using JavaScript?"
02:23
<&Derakon>
I don't recall how Javascript inheritance works. Manually?
02:23
<&McMartin>
Via prototypes~
02:24
<&McMartin>
JS doesn't have classes per se. Instead, all objects are objects, and if you try to access a field it doesn't have, it checks its prototype object to see if it does, and then *its* prototype and so on up the chain.
02:25
<&Derakon>
Ah.
02:25
< [R]>
Aye, which can be slow. Especially when adding stuff to native objects.
02:25
< [R]>
It's also confusing as hell for anyone who has done OOP elsewhere.
02:25
< [R]>
There's a few billion libs that try and "fix" it though.
02:26
<&McMartin>
Which is precisely the wrong thing to do.
02:26
<&McMartin>
It needs to embrace it. =P
02:26
<&McMartin>
Trying to put classes into JS is like trying to take duck typing out of Python.
02:27
<@Reiv>
... duck typing
02:27
<&McMartin>
Duck typing.
02:27
<@Reiv>
Quack quack?
02:27
<&McMartin>
It's a specific kind of dynamic typing as applied to OO-like languages.
02:28
< [R]>
One thing I learned pretty quick was: Thing.prototype.x = 5; // all things have an x, they /share/ this x.
02:28
<&McMartin>
Instead of checking some kind of type hierarchy to see if function A can operate on data type B, one checks to see if data type B supports the operations that function A uses.
02:28
<&McMartin>
That is, if data type B walks and quacks like a duck, then it is a duck.
02:28
<&McMartin>
Even if B does not inherit from Duck or, indeed, anything at all.
02:29
<&McMartin>
In C++, or Java, or C#, or, indeed, any language descended from Simula, you must explicitly declare your class to derive from Duck or it may not be passed to a function that expects Duck.
02:30
<&McMartin>
In Python or Perl or Ruby or Objective-C or, more or less, any language ultimately inspired by Smalltalk, all that is necessary is that you support walk() and quack().
02:30
<&McMartin>
There are ways to rigidify the duck-typed languages, and there are ways to make the stricter ones more flexible, but when you do these things it is obvious that you are working around the language, not just using it
02:31
<&McMartin>
[R]: Yeah, my favored technique is to only have one constructor call like that anywhere, and it is in a function that takes an object and gives you a fresh object with your argument as its prototype
02:31
<&McMartin>
Then I don't mess around with .prototype anywhere.
02:32 * McMartin ponders
02:32
<&McMartin>
... I bet you could make Python have prototypal inheritance for a set of objects by inheriting them all from a single class defined in one place
02:33
<&McMartin>
By overriding __getattr__ and having a prototype field.
02:33
<&Derakon>
Why would you ever do this?
02:33
<&McMartin>
If you were in a situation where prototypal inheritance was better
02:34
<&McMartin>
Which tends to come up in gaming contexts, I think.
02:34
<&McMartin>
But if you're doing it in the Simula-style, you'd do it by making seriously heavy use of the copy constructor and default values.
02:34
<&Derakon>
FWIW Pyrel does manual inheritance for all of its creatures.
02:35
<&McMartin>
It can be done
02:35
<&McMartin>
If, however, you have a situation like, say, most IF
02:35
<&Derakon>
Because the templates et al are all defined in datafiles, and it's easier to just modify the dict that defines the creator than it is to try to shoehorn into Python's inheritance system.
02:35
<&McMartin>
Where you have large numbers of *almost* identical objects but no two are quite the same
02:35
<&McMartin>
It's really nice to be able to say "this instance is that instance but with these values changed"
02:36
<&Derakon>
Yeah, that's what the templating system does.
02:36
< [R]>
McMartin: you lose out on being able to use 'instanceof' and comparing the Properties that are Functions.
02:36
<&McMartin>
I'm pretty firmly of the opinion that if you're using instanceof you're doing it wrong~
02:36
< [R]>
*shrugs*
02:37 * [R] rarely uses it
02:37
<&McMartin>
You're replacing a single computed GOSUB with an if-else chain, more or less.
02:37
<&McMartin>
... Except in ML and related languages, or when you do that by hand in C, which is A Thing
02:37 * [R] sticks to variables and closures in the constructor, everything else in the prototype.
02:37
<&McMartin>
<-- was a compilers guy, so tends to keep the under-the-hood stuff readily to hand
02:39 * [R] is an SA with ~8 languages under his belt. Mostly Linux/Sec admin.
02:39
<&McMartin>
GML (Game Maker's scripting language) is also prototypal-inheritance
02:39
< [R]>
Since we're posturing...
02:39
< [R]>
GML is EMCAScript now AIUI
02:39
<&Derakon>
I have to admit it's been years since I did anything besides Python/C/C++.
02:40
<@Reiv>
I write a lot of SQL and know two dialects, including vaguely eldritch machinations in Oracle?~
02:40
<&McMartin>
R: Well, so, this is again why you want to look a Lisp.
02:40
< [R]>
Yeah
02:40
<&McMartin>
It gives you a new set of techniques you don't *generally* see elsewhere and makes them primary
02:40 * [R] will also be picking up Ruby soon.
02:41
<&McMartin>
Those things tend to have parallels in the modern scripting languages but aren't usually hit as hard.
02:41
<&McMartin>
Which means instead of sorting out some mess of fors and ifs, you may just rip through a one-line list comprehension that ends up being easier to read in the end *anyway*
02:42
<&McMartin>
Hilariously, JS actually takes a lot of its function and closure semantics *from Scheme*, so those parts will actually be familiar, and many of the tricks therein deployed are directly transplantable back.
02:42
<&ToxicFrog>
Re duck typing: shoutout here to "structural typing", which is basically statically typed duck typing.
02:42
< Xon>
<RichyB> The grognards still using Git will not ever stop saying "but I can achieve that in Git too with nothing more than a sequence of rebase commands!"
02:42
< Xon>
as bad as Git is, svn or cvs branche merges make me want to hurt someone so bad
02:42
< RichyB>
Xon: I have miscommunicated.
02:42
< Xon>
svn branche merges used to be utterly /fucking evil/
02:43
< Xon>
now they are just evil
02:43
<&McMartin>
1.6, IIRC, is when that became actually even theoretically usable
02:43
<&McMartin>
TF: I'm generally pro-static-typing, yeah~
02:43
< RichyB>
Xon: what I meant there is that, if/when something new comes along that is technically superior to git-style DVCSs (and to the line of svn, cvs, rcs too, obviously)
02:44
< RichyB>
Xon: we will then have git diehards instead of svn diehards.
02:44
< Xon>
McMartin, still evil in 1.6
02:45
<&McMartin>
There is some revision before which the svn:mergeinfo property would not actually do the right thing.
02:45
<&ToxicFrog>
McMartin: I was firmly anti-static-typing until I used languages that do it well~
02:45
<&McMartin>
What's left for that, actually~
02:45
<&McMartin>
I count OCaml and maybe Haskell
02:45
<&ToxicFrog>
Haskell and Scala.
02:46
<&McMartin>
Ah, OK
02:46
<&McMartin>
I should try Scala on Osmium at some point to see if it works better there
02:46
<&McMartin>
OCaml has structural typing but discourages its use
02:46
<&ToxicFrog>
Until using those, years of comparing C, C++, and Java to Lua and Python had me convinced that static typing was The Devil.
02:46
< Xon>
ToxicFrog, I prefer static typing tbh
02:47
<&ToxicFrog>
I am now very much in favour of it.
02:47
< RichyB>
There's other languages that have progressed ahead of Haskell or Scala in the "the static type system is actually useful" front, mostly at the cost of extra complexity or compromises in automatic inference.
02:47
<@Reiv>
Haskell static typing is batshit /insane/
02:48
< RichyB>
No, it really isn't. Haskell98's type system is, bar the monomorphism restriction, very simple.
02:48
<@Reiv>
In the wonderful, labcoat and lightning rod MUAHAHAHAHAHA EEEEETS ALIIIIIIVE insane.
02:49
< RichyB>
If you switch on things like GADTs and FunDeps then it gets more fun, but really it's very straightforward unless you try doing very-silly things with typeclasses.
02:49
< RichyB>
Yes, getting away from "Foo bar = new Foo();" is a significant blessing. Java in particular can go to heck for that.
02:51
<&McMartin>
Still not a patch on "for (std::map<std::string, std::vector<std::string> >::iterator i = m.begin(); i != m.end); ++i)"
02:51
<&McMartin>
C++11 finally fixed that
02:52
< [R]>
Anyways, morbid curiousity strikes me now.
02:52
< [R]>
McMartin: got a sample of your "favored technique" with JS?
02:52
<&McMartin>
Not offhand, though I think I have an implementation of The One Place Where New Lives around here somewhere.
02:52
<&McMartin>
... but not in ~/devel
02:53
<&McMartin>
So I'll have to dig it out of the book when I get home tonight
02:53
< [R]>
Can you whip one up quick?
02:53
< [R]>
<NightStar:#code:McMartin> [R]: Yeah, my favored technique is to only have one constructor call like that anywhere, and it is in a function that takes an object and gives you a fresh object with your argument as its prototype <-- this thing
02:53
<&McMartin>
I honestly don't use inheritance of any kind for much
02:53
<&McMartin>
Yeah, that
02:53
<&McMartin>
No, I can't whip up an implementation of that quick
02:54
< [R]>
More interested in an example.
02:54
<&McMartin>
But as for a place to use it; if I were doing something like a Game Maker-y game, I'd build an enemy class and then prototypes of enemy type
02:54
<&McMartin>
Then I'd cast copies of the prototypes to place them within the level
02:54
<&Derakon>
I think I've heard that referred to as the Flywheel.
02:54
< [R]>
Oh gods
02:56
<&McMartin>
But the code would be something like x = createFroj(Jet) or y = createFrom(tank)
02:56
< [R]>
I think I've seen that before, took me an hour of research to figgure out WTF was going on. Then again ExtJS might have botched that, so... YMMV
02:56
<&McMartin>
Er, *createFrom
02:56
<&McMartin>
I mean, in GML this happens semi-automatically by selecting your prototype object and then repeatedly clicking on the map.
02:57
<&McMartin>
(Which in turn makes it a good candidate for automatic generation from data files)
02:58
<&McMartin>
It looks like https://hkn.eecs.berkeley.edu/~mcmartin/CCA.html is the only remotely interesting JS I have online right now
02:58
<&McMartin>
But it also doesn't use inheritance of any kind, or any objects not made from literals.
02:59
< [R]>
http://en.wikipedia.org/wiki/Flyweight_pattern <-- this?
02:59
<@Reiv>
So, there's a type of programming that, uh
03:00
<&McMartin>
Flyweight is basically "how you make immutable data actually be efficient"
03:00
<@Reiv>
It's like object oriented, with inherentance, but... not
03:00
<&McMartin>
Most of the languages we've been discussing end up doing that incidentally internally.
03:01
< [R]>
is createFrom basically cloning it and then applying mixin?
03:01
< [R]>
Or are you useing Object.createFrom()?
03:01
<@Reiv>
In that instead of "A Car inherets from Wheeled Vehicle", you instead say "A Car is Moves As Wheeled Vehicle, Carries Passengers, and People Use It." or something?
03:02
<@Reiv>
And rather than a tree of objects, the diagrams can end up more like venn diagrams >_>
03:03
<@Reiv>
But I cannot think of the name.
03:03
< [R]>
Mixins
03:03
<&McMartin>
R: It's basically Object.createFrom(), but the code predates that actually being part of ECMAScript
03:04
<&McMartin>
And it doesn't incur the cloning cost; it's a prototype
03:04
<&McMartin>
If you createFrom(x) and then change x.y, then the return value's .y will change
03:04
< [R]>
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Obj ect/create
03:04
<&McMartin>
Reiv: You may be thinking of logic-programming
03:05
< [R]>
^ there isn't actually a createFrom apparently. Don't know where I got that name. I'm assuming you meant Object.create (or assumed a functionality of it)
03:05
<&McMartin>
It was actually a reimplementation of it, because it predated widespread support for ECMAScript 5th
03:05
<@Reiv>
Can you give a cliff notes on logic-programming so I can pattern-match my memory?
03:05
<&McMartin>
But yeah, this
03:05
<&McMartin>
Reiv: It's a lot like SQL but with insanity I don't have in an easy-to-summarize form to give loops and if/then
03:06
<&McMartin>
[R]: So, the use case for the 2D game would be that I've have an object that represented the enemy type and I'd use Object.create(enemy, {x: ??, y: ??}); where the ??s are where I wanted it to be, and I could tune health or firing rate or attack strategy or w/e there too.
03:07
<&McMartin>
It's technically imperative but you can still format it so it works out to basically be A Table Of Dudes that you can just read off the screen.
03:07
<&Derakon>
The alternate case which Pyrel uses is to have a CreatureFactory class which creates creatures and fills in their attributes as desired.
03:07 Turaiel is now known as TurShower
03:07
< [R]>
Alright, interesting
03:07 * [R] will experiement with it
03:08
<&McMartin>
Sadly, my actual 2D Game Project is in C++~
03:09
<&McMartin>
And I haven't gotten far enough in to know whether or not it's going to be worth it to do something like this, or to have a Full Table Of Attributes For Everything at which point there's nothing gained by it (since I can just construct each object from scratch at that point with a regular constructor)
03:09
<&McMartin>
GML has some things where prototypes are extra useful but they rely on the ability to morph what kind of object you are, and that is an idiomatic way in Game Maker to represent state machines
03:09
<&McMartin>
That is *complete batshittery* pretty much anywhere else, I think including JS.
03:09
<@Reiv>
hrn, that may not be it then
03:10
<@Reiv>
Unless it actually is. Mumble.
03:10
<&ToxicFrog>
Reiv: what you describe actually sounds more like Entity-Component Programming, which was used in the Dark Engine to great effect and is basically Mixin All Of The Things.
03:10
<&McMartin>
Reiv: Try searching for Prolog. If that isn't what you expect, it's what TF says.
03:10
<&McMartin>
Entity-Component Programming is something you can do in any paradigm, really, it's just a question of how you make it happen.
03:10
<@Reiv>
Is that where you can program a set of traits and then assign them to a Thing?
03:10
<&McMartin>
Mixins as a language construct tend to Fall Down Very Hard.
03:11
<&McMartin>
Prolog is a language
03:11
<@Reiv>
(Which is, I note, what I had /always hoped/ OOC would be, and then was bitterly dissapointed)
03:11
<&Derakon>
OOC?
03:11
<&Derakon>
Object-oriented code?
03:11
<&McMartin>
Mixins are a form of multiple inheritance that promises to totally be not full of recursively nested spiders, honest and then totally is.
03:11
<@Reiv>
Ya
03:11
<@Reiv>
... oh. Really? Hrn.
03:12
<&McMartin>
Because multiple inheritance is always spiderful
03:12
<&ToxicFrog>
Reiv: well, it's where Things and Traits are decoupled. So you have, say, a Robot entity type, which has the Components Collideable(bounding_box), Damageable(hp, attacktypes), AI, etc, etc
03:12
<@Reiv>
I had thought entity-component programming was sort of The Fix to the spiders.
03:13
<&McMartin>
You still have to solve the question of "what happens when two traits conflict over what happens under a certain circumstance?"
03:13
<&McMartin>
You need some kind of combinator.
03:13
<&ToxicFrog>
Done right, this lets you define all of the Entity/Component mappings outside the code, which means once you add Hackable it's thirty seconds in the gamesys editor to add that characteristic to all Robots.
03:13
<&McMartin>
That combinator is where the spiders live.
03:13
<&McMartin>
(The patterns "Decorator" and "Chain of Responsibility" are two ways of setting this up by hand so that you can have your own combinators and not use Whatever Your Language Does Because Whatever It Is It Will Be Wrong)
03:14 * Reiv stares blankly at McM
03:14
<&McMartin>
I hold that then they are *still* spiders, but as they are *your* spiders that *you put there* you are in much better shape.
03:14
<&ToxicFrog>
(I have been told that CEP is a natural fit for database-backed MMOs, but the only place I've actually encountered it is in the Dark engine, where it rocks a million faces)
03:15
<&McMartin>
Reiv: Suppose you have components that let you fly, and components that let you swim.
03:15
<&McMartin>
And both of those are going to want to modify the part of the AI that says "Find me a path I can take from A to B"
03:16
<&ToxicFrog>
...I should open up the SS2 gamesys and see how they did AI.
03:16
<&McMartin>
It is a nontrivial problem to set things up in a way where "can fly" and "can swim" can coexist.
03:17
<&McMartin>
And it's even harder to do it in a way where not only can they both exist on the same object, but any future mobility power can plug in as well.
03:18
<&McMartin>
The fully general case of this problem maps to roughly the same problem as "how can I have an object inherit from more than one parent class", and it is demonstrably the case that any single answer to this question is wrong.
03:18
<&McMartin>
(Which is why C++ offers two different kinds)
03:18
<&McMartin>
So you find yourself in a position where you need to say "I need to restrict some part of this problem"
03:19
<&ToxicFrog>
The first thing that comes to mind is to have the AI query each component that implements pathTo() and then takes the shortest path, but then e.g. the swimming component needs to understand how to path across land to get to the water's edge, too.
03:19
<&ToxicFrog>
Hrm.
03:19
<&McMartin>
Yeah, I mean, the key thing here is that you now have to treat mobility powers as some kind of set of modifiers to a generic pathfinder.
03:19
<&Derakon>
The way I'd handle that would be to allow flight, walking, etc. to enable traversal over different kinds of terrain.
03:19
<&Derakon>
So the same pathing logic would be used, but it would reflect upon itself to see what it can move through.
03:20
<&McMartin>
Right
03:20
<&McMartin>
That will also work
03:20
<&McMartin>
It is also an ad-hoc solution that you cannot build into the inheritance mechanism extensibly.
03:20
<&Derakon>
But that only works well if you move the same way in all cases (i.e. the generated paths are the same)
03:20
<&McMartin>
That's why I'm sort of saying that this model of design is independent of language - because no matter what language you use, you'll have to build the mechanism to do What This Problem Needs.
03:21
<&ToxicFrog>
(it kind of helps here that components are Totally Allowed to implement the same methods and have the same properties, which is not generally the case for MI or mixins)
03:21
<@Reiv>
Interesting. I think I get it.
03:21
<&McMartin>
TF: Is this because the components operate within their own namespaces, or are there defined ways that they interact in the case of identical names?
03:22
<&ToxicFrog>
Reiv: if you want a practical demonstration, open up the Object Heirarchy in ShockEd or DromEd.
03:22
<&ToxicFrog>
McMartin: the former. Components are distinct things; an Entity has a set of components each with their own property, rather than being made up of the sum of a set of components as would be the case with "normal" MI.
03:22
<&ToxicFrog>
*own properties.
03:23
<&Derakon>
So Entities contain Components, which mutate the Entities as needed.
03:23
<&McMartin>
That raises the question for me of "how does the engine as a whole know when to activate some component?"
03:23
<&ToxicFrog>
(it is also generally assumed that components can query other components on the same object; is totally reasonable for a lot of components to depend on their host entity having a Position component)
03:23
<&McMartin>
also "will order matter?"
03:23
<&ToxicFrog>
That's the hard part~
03:24
<&McMartin>
Hm
03:24
<@Reiv>
So is this something you could do in, like, Python?
03:24
<&McMartin>
Since it's ducktyped it seems like you could realize this directly in Python
03:24
<&McMartin>
As a discipline
03:24
<&McMartin>
The language wouldn't enforce it
03:25 * Reiv scratches his chin, wonders how you'd do it then.
03:25
<&McMartin>
As a first pass
03:25
<&McMartin>
An Entity is just a dictionary
03:25
<&ToxicFrog>
(What I would like to do here is consult the literature, because this isn't actually something I know well, but there isn't a lot of open source work in this domain that I'm aware of)
03:25
<&McMartin>
The keys of this dictionary are Component names.
03:26
<&ToxicFrog>
(Dark Engine leaks notwithstanding)
03:26
<&McMartin>
The value would be an object of that type, which have methods that take the dict itself as an argument.
03:26
<&McMartin>
So when you need to query other components, you'd just refer to entity['position'] from inside yourself.
03:26
<&McMartin>
And then you could read entity['position'].x out because that's how objects work.
03:27
<@Reiv>
... hunh. I think that almost makes sense.
03:27
<&McMartin>
And you don't even need that, because you could have entity be an empty object instead of a dictionary and it's semantically almost identical; you'd just assign components with entity.position = Position(x, y) at first, and then other components could refer to agent.position.
03:27
<@Reiv>
It would take some serious Learnin', though.
03:28
< [R]>
... damnit people. If you're going to talk about frameworks or patterns /show some code/.
03:28
<&McMartin>
Python *already* doesn't have an implicit "this" in field dereferences, so there would be very little difference between code that does this compared to code that does it the other way.
03:28
<&Derakon>
McM: checking if an object has an attribute is a bit messier than checking if a dict has a key, though, since you have to use hasattr.
03:28
<&McMartin>
If we get to *assume* it though we can just rely on the exception being thrown on ugly cases.
03:28
<&Derakon>
Well, yes.
03:29
<&McMartin>
R: Showing code involves executing a design
03:29
<&McMartin>
Executing a design involves *having* a design.
03:29 * Reiv starts to get the slightly fuzzy feeling in the head of an idea trying to gel on insufficient foundations. Suspects he needs to go try learning Python. Again.
03:29
<&Derakon>
Heh.
03:29
<&Derakon>
It's a good language! >.>
03:29
<&ToxicFrog>
Aha! Here's one of the blogs I was thinking of, the T=Machine series on entity system programming in gaming: http://t-machine.org/index.php/2007/09/03/entity-systems-are-the-future-of-mmog- development-part-1/
03:29
<@Reiv>
It shouldn't be hard
03:30
<@Reiv>
But it's so formless I tend to just flail about a lot and then get annoyed when I hit one of its Odd Limits.
03:30
<&McMartin>
One of the weirder bits of Python is indeed that modules, classes, objects, and dictionaries are all semantically almost identical, which is not the case for most languages.
03:30
<&ToxicFrog>
Formless?
03:30
<&McMartin>
But using any of those instead of some other is almost purely a matter of convention.
03:30
<&McMartin>
(Outside of corners like membership testing)
03:30
< [R]>
McMartin: even psuedo code is fine
03:31 * [R] needs code to grok patterns
03:31
<&McMartin>
That was pseudocode.
03:31
<&McMartin>
It was just lacking in linebreaks~
03:31
<&ToxicFrog>
Objects and dictionaries and almost semantically identical and yet you have to use . for one and [] for the other >.<
03:31
< [R]>
Oh
03:31
< [R]>
My comment was because I was reading E/C posts
03:31
<&McMartin>
ToxicFrog: And "in" only works on one of them, yeah
03:31
< [R]>
The ones that had code, didn't really have any for their examples
03:31
<&Derakon>
And isinstance is different, and probably a bunch of other things.
03:32
<&McMartin>
My instinct for the entity system in Python would be to use dictionaries to emphasize "the things we're using as keys here are dynamic and mutable"
03:33
<&McMartin>
While within a component I would not, because every position has exactly one .x, .y, .z
03:33 * ToxicFrog nods
03:34
<@Reiv>
I cannot remember the issue I had last time
03:34
<@Reiv>
But it was a Simple Question That Wasn't Simple Afterall, 'Cuz Python Does Y instead of X.
03:35
<@Reiv>
I actually vaugely remember that the closest we could get was a dictionary. And then that got rapidly messy, or something.
03:35
<&McMartin>
TF: I note in passing that this also plays to a personal bias, viz, Composition Is Better Than Inheritance
03:35
<&ToxicFrog>
Ideally - and this is a large part of what makes entity systems attractive - you store that dictionary (and the constructor arguments for each component) in something externally editable, so you can make potentially drastic changes to the game mechanics without changing the code.
03:35
<&McMartin>
Yup
03:36
<&ToxicFrog>
In MMOs this is a database somewhere accessed via editing tools; in Dark it's the gamesys. In SS1 it's OBJPROP.DAT, if SS1 uses entity systems, which I'm not entirely convinced it doesn't.
03:36
<&McMartin>
(It'll be interesting to see how Project Monocle sorts that out)
03:36
<&McMartin>
(Because I think an unnerving amount of the intelligence is going to live in the map)
03:36
<&Derakon>
In Pyrel, entity definitions include references to Procs, which are small self-contained bits of code.
03:36
<@Reiv>
Were entity systems around in the era of SS1 to be implemented?
03:37
<&McMartin>
I would not be surprised if something like Entity Systems existed by the mid-1970s/
03:37
<&Derakon>
So e.g. the base Creature record template says that its AI is handled by "standard creature AI" which refers to the BasicAIProc function.
03:37
<&Derakon>
Yeah, a lot of basic CS design is Ancient.
03:37
<&ToxicFrog>
Reiv: I don't know but I wouldn't be at all surprised.
03:37
<&Derakon>
"I see you are reimplementing something that Lisp has had for decades" is/was a common refrain.
03:38
<&McMartin>
"Oh boy, we can do mapcar in C++" was an actual (deeply sarcastic) summary of Design Patterns~
03:38 Kindamoody[zZz] is now known as Kindamoody
03:39
<&ToxicFrog>
And it's a reasonable guess; LGS were technically very advanced in general, we know Dark uses entity systems, and Dark originated as a combination of the Centauri and Shock engines that could handle indoor and outdoor terrain.
03:40
<&Derakon>
Incidentally, Yahtzee did SS2 for this week's review~
03:40
<&ToxicFrog>
There may have been a bit of feature creep~
03:40
<&ToxicFrog>
I noticed. I'm way behind on ZP but will get around to it eventually.
03:40
<@Reiv>
Why then would entity programming not be much more standard, especially in computer games where, eg, Planet, Star, Spaceship, and Satellite are all likely to share features with each other...
03:41
<&ToxicFrog>
Because getting it right is hard and requires more up-front effort, whereas if standard OOP is The Wrong Answer the spiders won't show up until it's too late a lot of the time.
03:41
<&ToxicFrog>
Also, everyone and their dog learns OOP in school.
03:42
<&Derakon>
One common issue you will run into with developers is that they would much rather puzzle things out themselves than look at how other people have solved the same problem.
03:42
<&Derakon>
Hell, I do that all the time. ?.?
03:42
<@Reiv>
Fair.
03:42
<&Derakon>
It tends to mean that non-obvious but superior answers are not repeatedly stumbled upon.
03:43
<@Reiv>
It's one of these things that Entity Programming seems it would be perfect for my Obligatory Game Projects basic function, given it involves Lots Of Things that all overlap but in different ways.
03:43
<@Reiv>
But now I'm worried if I'd just be biting off more than I can chew with the thing~
03:44
<&Derakon>
Heh.
03:44
<&Derakon>
If it's a game project, you are pretty much by definition biting off more than you can chew~
03:44
<&Derakon>
This is why you don't try to complete a game in a single meal, to stretch a metaphor rather painfully.
03:45
<@Reiv>
Indeed.
03:45
<@Reiv>
This was "Can I assemble a working-ish model of the games key components"
03:48
<@Reiv>
I've /no idea/ how to do the Game Proper... but being able to prod thoughtfully at its fundamental principles seems like a good place to start in the meantime.
03:54 TurShower is now known as Turaiel
04:13 VirusJTG_ [VirusJTG@2B12AA.572255.206A2A.901581] has quit [[NS] Quit: Program Shutting down]
04:29
<&McMartin>
One danger of that is that it is very easy to discover that you have designed a pile of bricks instead of a building.
04:30
<@Reiv>
I am okay with that.
04:30
<@Reiv>
This is partly a self-teaching excersize, and wondering what the bricks would even look like.
04:34 Vornicus [vorn@ServerAdministrator.Nightstar.Net] has joined #code
04:34 mode/#code [+qo Vornicus Vornicus] by ChanServ
04:45
< Syka>
why is everyone else absolutely useless :(
04:46
< Turaiel>
Because they're not meeeeee :P
04:46
< Syka>
I need to get into an email account because a company's IT support is being handed over to me
04:46
< [R]>
Because you have failed to notice your divine ascention.
04:46
< Syka>
the clown who's handing it over was like yeah i'll send you the password
04:46
< Syka>
week later, I poke him
04:46
< Syka>
he's like oh yeah
04:46
< Syka>
2 days later he 'changes' it
04:46
< Syka>
password doesn't work
04:47
< Syka>
two days after immediately telling him, he's not yet fixed it
04:47
< Syka>
how do these people not choke on their own breakfast???
04:47
< Syka>
the reason he was sending me the password was because he also set it up with a personal password, so he had to change it first
04:48
< [R]>
http://xiennith.com/annoy.txt <-- reminds me of dealing with one CTO (note: CCP is the name I'm using as anomynization of the company, and beyond the CTO, CEO and I there was a programer. End of employee list.)
04:48
< [R]>
Geez
04:49
< Syka>
oh man I have a great set of emails
04:49
< Syka>
from someone I call 'the FNG'
04:49
< [R]>
Fucking Number God?
04:49
< Syka>
fucking new guy
04:49
< Syka>
he was supposed to be my new manager
04:49
< Syka>
he was clueless
04:49
< Syka>
eventually quit
04:50
< Syka>
but, before I went on holidays, I was publishing some patches to an (3-person IT department only!) application
04:50
< Syka>
I accidently did a typo in the 'last allowed update'
04:50
< Syka>
and broke the login
04:50
< Syka>
no problem, I was just like uhhh I need to patch this
04:51
< Syka>
so I did, then I went on holiday, the app was perfectly stable while I was gone
04:51
< Syka>
I then got a big-ass email complaining about how I'd patched the application 'without permission'
04:51
< Syka>
and that having two development tracks ('beta' and 'stable') was 'cheeky'
04:52
< Syka>
then he wanted me to do a literal 4 page document for every feature I wanted to implement
04:52
< Syka>
yeah, he had literally no idea
04:54
< [R]>
When I was at IBM we got a new team lead. 2 days in he starts bitching me out because I didn't follow procedure in doc Y. In my comments of the ticket (I was Helldesk) I mentioned Doc Z did not provide useful information, submitting ticket as a best effort basis, and that documentation (which they provide) should be updated. Doc Y did not come up with any keywords for the issue. My response to his initial bitch out: "Doc Y doesn't come up with a search.
04:54
< [R]>
Documentation needs updating, please read my comments in the ticket for why I did it that way." His response to that: "You should've read Doc Y, not Doc Z."
04:54 * [R] only had like 10 days left at that point, so I basically just ignored him from then on.
04:55
< [R]>
I mean, if you're not going to /read/ what /I/ write, why should I give you what you deny me?
04:56
< [R]>
But if he wants a document for an update that's got more pages than he has minions something is fucked up.
04:57
< Syka>
hehe
04:57
< Syka>
my favourite argument with this guy
04:57
< Syka>
we needed to buy a new switch
04:57
< Syka>
no big deal, HP still made the switch
04:58
< Syka>
it was a HP ProCurve 2810al-48G, or something
04:58
< Turaiel>
> Provides exact model number > "or something"
04:58
< Turaiel>
Nice.
04:58
< Syka>
haha it might actually be the exact switch
04:59
< Syka>
wait no, it isn't
04:59
< Syka>
this was a PoE+ switch
04:59
< Syka>
we had 2810al-24Gs, with some 48 port poe+s
04:59
< Syka>
anyway, it came back from the supplier as "HP Networking 2810al" (just using that product code)
04:59
< Syka>
I was like 'hm' and looked it up
05:00
< Syka>
turns out that HP EOL'd the Procurve brand, rolled everything in with "HP Networking" when they bought Juniper
05:00
< Syka>
same switch, different branding, essentially
05:00
< Syka>
the FNG *would not accept that*
05:01
< Syka>
he was adamant that it wasn't the right switch, even though I pointed him to the wiki page about HP Procurve not existing
05:01
< Syka>
so he was scouring the net, attempting to buy a HP Procurve 2810al, which, as this was a few months after the rebranding, *literally nobody did*
05:02
< Syka>
I have no idea how he got through university
05:02
< Turaiel>
I have a switch that's got 3 different brands xD Mine's the original, Marconi ES-1200
05:03
< Turaiel>
D-Link was the last one to make it, I think
05:03
< Turaiel>
It's horrid. Nice managed switch, except it has a couple dead ports and it crashes all the time
05:04
< Syka>
oh yay, mouse wheel zoom is broken in KSP now
05:05
< Turaiel>
Whee.
05:05
< Turaiel>
I forgot what that game's supposed to be about
05:05
< Syka>
SPESS
05:05
< Turaiel>
I knew that much :P
05:06
<&McMartin>
Attaching lawn chairs to booster rocketes and hurling dudes to awesome fiery deaths
05:06
< Turaiel>
Oh, the D-Link model is DES-3624
05:06
< Turaiel>
Fun
05:07
< Syka>
now i'm spinning uncontrollably through the atmosphere
05:07
< Syka>
progress!
05:09
< Syka>
because the arrow keys always seem to be in reverse
05:25 AverageJoe [evil1@Nightstar-4b668a07.ph.cox.net] has joined #code
05:39 Reiv [NSwebIRC@Nightstar-95746c1f.kinect.net.nz] has quit [Ping timeout: 121 seconds]
05:41 RichyB [richardb@Nightstar-86656b6c.cable.virginmedia.com] has quit [Connection closed]
05:49 Vornicus [vorn@ServerAdministrator.Nightstar.Net] has quit [Operation timed out]
06:28 Derakon is now known as Derakon[AFK]
06:42 Kindamoody is now known as Kindamoody|afk
07:01 Kindamoody|afk is now known as Kindamoody
07:06 You're now known as TheWatcher
07:09 [R] [rstamer@genoce.org] has quit [Ping timeout: 121 seconds]
07:12 PinkFreud [WhyNot@NetworkAdministrator.Nightstar.Net] has quit [Ping timeout: 121 seconds]
07:13 PinkFreud [WhyNot@NetworkAdministrator.Nightstar.Net] has joined #code
07:13 mode/#code [+o PinkFreud] by ChanServ
07:19 Vornicus [vorn@ServerAdministrator.Nightstar.Net] has joined #code
07:19 mode/#code [+qo Vornicus Vornicus] by ChanServ
07:27 Turaiel is now known as Turaiel[Offline]
07:57 celticminstrel [celticminst@Nightstar-e83b3651.cable.rogers.com] has quit [[NS] Quit: And lo! The computer falls into a deep sleep, to awake again some other day!]
08:14 You're now known as TheWatcher[afk]
09:03 Vornicus [vorn@ServerAdministrator.Nightstar.Net] has quit [[NS] Quit: Leaving]
09:03 Kindamoody is now known as Kindamoody|afk
09:38 himi [fow035@D741F1.243F35.CADC30.81D435] has quit [Ping timeout: 121 seconds]
09:42 You're now known as TheWatcher
09:49 [R] [rstamer@Nightstar-e681a855.org] has joined #code
09:53 AverageJoe [evil1@Nightstar-4b668a07.ph.cox.net] has quit [Connection closed]
10:30 RichyB [richardb@Nightstar-86656b6c.cable.virginmedia.com] has joined #code
10:53 You're now known as TheWatcher[d00m]
11:33
<@froztbyte>
https://twitter.com/paulanthonywils/status/337473792144179200
11:33 himi [fow035@Nightstar-5d05bada.internode.on.net] has joined #code
11:33 mode/#code [+o himi] by ChanServ
12:03 Kindamoody|afk is now known as Kindamoody
12:34 Kindamoody is now known as Kindamoody|afk
13:47 You're now known as TheWatcher
13:50 * TheWatcher stabs SQL
13:50
<@TheWatcher>
why is this saying that a column doesn't exist when I'm looking right at it!?
13:52
< Syka>
column of +2 stealth
13:55
<@Azash>
A bug in the matrix
14:46 You're now known as TheWatcher[afk]
15:00 celticminstrel [celticminst@Nightstar-e83b3651.cable.rogers.com] has joined #code
15:00 mode/#code [+o celticminstrel] by ChanServ
15:15 ToxicFrog is now known as ToxicFrog|W`rkn
16:37
<@froztbyte>
TheWatcher[afk]: something breaking on column name length? different charset in a name?
17:37
<&ToxicFrog|W`rkn>
Is there a python equivalent to ->>?
17:38
<&ToxicFrog|W`rkn>
Specifically, I want an equivalent to (->> errors sort (map str) (.join ', '))
17:39
< [R]>
What's that do?
17:40
<&ToxicFrog|W`rkn>
It's eqv to (.join ', ' (map str (sort (errors))))
17:40
<&ToxicFrog|W`rkn>
Or, in python, ', '.join(map(str, sorted(errors)))
17:40
<&ToxicFrog|W`rkn>
I.e. it sorts 'errors', stringifies the contents, and then joins the contents on ', '
17:43
< [R]>
[].sort().map(str).join(', '); //?
17:44
< [R]>
Ugh
17:44
< [R]>
Python .sort() is in-place
17:47
< [R]>
Python2 doesn't have .join()... WTF
17:48
< [R]>
>>> map(str, sort([1,4,7,2,3]))
17:48
< [R]>
['1', '2', '3', '4', '7']
17:48
< [R]>
Close as I got. sort(a) is just: `a.sort(); return a`
17:49
< [R]>
Ah
17:49
< [R]>
>>> ', '.join(map(str, sort([1,4,7,2,3])))
17:49
< [R]>
'1, 2, 3, 4, 7'
17:49 Vornicus [vorn@ServerAdministrator.Nightstar.Net] has joined #code
17:49 mode/#code [+qo Vornicus Vornicus] by ChanServ
17:50
<@celticminstrel>
Python2 does have join...
17:50
<@celticminstrel>
It's just in the wrong class. <_<
17:51
< [R]>
DAMNIT PYTHON
17:52
< [R]>
OH
17:52
< [R]>
k
17:52
< [R]>
I have it all on one line now
17:52
< [R]>
>>> a = [1,5,3,2,4,8,6,7,9]; ', '.join(map(str, (a.sort(), a)[1]))
17:52
< [R]>
'1, 2, 3, 4, 5, 6, 7, 8, 9'
17:52
< [R]>
Without a second function
17:53
< [R]>
That what you wanted?
17:55
<~Vornicus>
sorted(a), not that ridiculous tuple thing
17:56
< [R]>
Wouldn't need that if Python didn't hi-jack the comma operator.
17:56
<~Vornicus>
a = [1,5,3,2,4,8,6,7,9]; ', '.join(map(str, sorted(a)))
18:01
<~Vornicus>
Which also works on things that aren't lists. Like, say, tuples or sets.
18:14
<&ToxicFrog|W`rkn>
[R]: yeah, .sort() is in-place has bitten me before and is completely inexcusable
18:15
<&ToxicFrog|W`rkn>
If lists were actually sensible, then yes, [].sort().map(str).join(', ') is exactly what I would want.
18:16 * [R] is so glad he didn't get into Python that heavy now
18:24
<~Vornicus>
(but lists are the only thing of several container types that even /can/ be sorted in place. Of course it would have an in place sort method.)
18:25
< [R]>
.inlineSort()
18:25
<~Vornicus>
(but then if you move sorted to container.sort then custom containers have to implement it themselves.
18:26
< [R]>
Or just name sorted sort
18:26
<~Vornicus>
but
18:26
< [R]>
Because no-one else uses past-tense verbs as function names.
18:26
<&ToxicFrog|W`rkn>
In-place sort should be sort!()
18:27
<&ToxicFrog|W`rkn>
More seriously, the crazy part isn't that lists have an in-place sort method, it's that they don't have an out-of-place sort method
18:27
< [R]>
Or at least do what JS does (which is return this)
18:27
<&ToxicFrog|W`rkn>
Yeah.
18:28
<~Vornicus>
Python specifically removed returns on the in-place sort method because they found actually returning surprising
18:28
<&ToxicFrog|W`rkn>
whaaaaaaaaaaaaaaaaaaaaaaaaaaaaaat
18:29
< [R]>
TBF, JS doesn't have an out-of-place sort either. But you can mimic one with: a.slice(0).sort()
18:29
<~Vornicus>
Because people kept expecting it (because it returned something) to be out of place
18:33
<&ToxicFrog|W`rkn>
Python has a lot of really weird corners.
18:34
<~Vornicus>
actually I do kind of wonder why ! and ? aren't allowed in identifiers; they're not used anywhere else in the language.
18:43
<&ToxicFrog|W`rkn>
A great many languages disallow punctuation in identifiers for no good reason and it pisses me off.
18:44
<&ToxicFrog|W`rkn>
-, !, and ? are the ones I miss most, although - is at least semi-excusable (it's usually also the subtraction operator)
18:44
< Syka>
...usually?
18:44
<~Vornicus>
Syka: in postscript, the subtraction operator is "sub"
18:45 Turaiel[Offline] is now known as Turaiel
18:45
< Syka>
ahh
18:45
<@celticminstrel>
[R]: TBF, JS doesn't have an out-of-place sort either. But you can mimic one with: a.slice(0).sort()
18:45
<@celticminstrel>
You can do that in Python too. :P
18:45
<@celticminstrel>
a[:].sort(), I think it would be?
18:46
< [R]>
Aye, but you don't have a .sort() that returns this :p
18:46
<~Vornicus>
Or you could just use sorted, which works on things that aren't already lists, so long as you can iterate it
18:46
<@celticminstrel>
...right.
18:46
<@celticminstrel>
Forgot that detail!
18:46
<&ToxicFrog|W`rkn>
And on the flip side, in lisp, - is a valid character in identifiers and the subtraction operator is a function named "-"
18:46
<@celticminstrel>
<_<
18:46
<~Vornicus>
Why are you people so damn insistent on creating hacks for functionality that already exists, jesus
18:46
<@celticminstrel>
XD
18:46
<@Azash>
Vornicus: Because ^C0,5FUN^O
18:46
<@froztbyte>
rofl
18:47
< [R]>
Vornicus: because we're talking about a language that insists on being different even when the difference is massively disruptive to people who know more than it.
18:49
< [R]>
s/it/just said language/
18:50
<&ToxicFrog|W`rkn>
Vornicus: because the functionality that already exists is organized stupidly~
18:50
<~Vornicus>
oh no, a function that works on iterables and a method that doesn't pretend it makes something new
18:51 * [R] doesn't disagree with needing a sort() outside of List's members
18:51 * [R] disagrees with naming it in a past-tense.
18:52
< [R]>
Unless /every/ function was named in such a way.
18:52
< [R]>
Then that'd be fine.
18:52
< [R]>
Stupid, but at least intuitable from prior behavior.
18:55
<&ToxicFrog|W`rkn>
Yeah, if there were a language-wide policy that 'verb' is in-place and 'verbed' is out-of-place it would bother me less, but AFAICT this is not the case.
18:56
< [R]>
Or do that.
18:56
<&ToxicFrog|W`rkn>
(I'm not actually convinced that's stupid, either; "sort" sorts the list in place, "sorted" is the sorted version of the list. It makes sense if you're willing to let go of the position that in-place sorting should never be the default.)
18:57
<&ToxicFrog|W`rkn>
(Which I'm not, but)
18:58
<&ToxicFrog|W`rkn>
So, yeah, to me there are three unpleasant surprises here:
18:58
<&ToxicFrog|W`rkn>
- list.sort() is not in place
18:58
<&ToxicFrog|W`rkn>
- list.sort() does not return a sorted list (or, indeed, anything)
18:58
<&ToxicFrog|W`rkn>
- there is no method on lists that returns a sorted list, only an external function
18:58
<&ToxicFrog|W`rkn>
And of those I find the last the most offensive.
18:58
< [R]>
list.sort() returns None
18:58
<&ToxicFrog|W`rkn>
It's object oriented, except when that would actually be useful, and then suddenly it's not!
18:59
< [R]>
I think it's more that it assumes that chainable interfaces either don't exist or are evil.
18:59
<&ToxicFrog|W`rkn>
Whereas to me chainable interfaces are arguably the big win of having verbs inside nouns.
19:00
<&ToxicFrog|W`rkn>
a.foo().bar().baz() is way more readable than baz(bar(foo(a)))
19:00
< [R]>
Aye
19:00
< [R]>
Though splitting the latter up can make it readable
19:00
< [R]>
But that leads to line-bloat which has its own issues.
19:01
<&ToxicFrog|W`rkn>
This is also why I prefer | to $() in bash, and like -> and ->> in clojure.
19:01
< [R]>
Uhh
19:01
< [R]>
| and $() do different things.
19:01
<&ToxicFrog|W`rkn>
Yes.
19:01
<~Vornicus>
list.osrt is in place
19:02 * [R] actually uses echo $(...) | sed/awk often enough.
19:02
<&ToxicFrog|W`rkn>
But in general I prefer designs that let me do foo a | bar | baz over baz $(bar $(foo a))
19:02
< [R]>
Ah, yeah
19:02 * [R] would like an inline echo $()
19:02
< [R]>
Actually... I could write one
19:02
< [R]>
Just no idea what to name it
19:04
<@celticminstrel>
Returning None is exactly the same as returning nothing.
19:04
<&ToxicFrog|W`rkn>
Vornicus: where is that documented? Because it's not on the website.
19:04
<~Vornicus>
um
19:05
<@celticminstrel>
...
19:05
< [R]>
Help on built-in function sort:
19:05
< [R]>
sort(...)
19:05
< [R]>
L.sort(cmp=None, key=None, reverse=False) -- stable sort *IN PLACE*;
19:05
< [R]>
cmp(x, y) -> -1, 0, 1
19:05
< [R]>
Emphasis theirs.
19:05
< [R]>
From help([].sort)
19:05
<&ToxicFrog|W`rkn>
Er
19:05
<&ToxicFrog|W`rkn>
I mean, where is the list.osrt function documented
19:05
< [R]>
Typo man
19:05 * ToxicFrog|W`rkn headdesks
19:06
<@celticminstrel>
Incidentally, I'm pretty sure the documentation from help() is exactly the same as the documentation on the website.
19:06
<&ToxicFrog|W`rkn>
(also, what do you mean by "an inline echo $(...)")
19:06
<@celticminstrel>
Both being generated from the docstrings.
19:06
<~Vornicus>
why did you say that "list.sort() is not in place"
19:06
<&ToxicFrog|W`rkn>
Er
19:06
< [R]>
I mean instead of doing echo `xsel` | sed ... | bc
19:06
<&ToxicFrog|W`rkn>
I meant to type "is in place"
19:06
<&ToxicFrog|W`rkn>
[R]: ummmm
19:06
<&ToxicFrog|W`rkn>
xsel | sed .... | bc
19:06
< [R]>
I do: xsel | inline-echo | sed | bc
19:07
<&ToxicFrog|W`rkn>
echo `foo` is eqv to foo
19:07
<&ToxicFrog|W`rkn>
Except I guess that it adds a newline on the end
19:07
< [R]>
ToxicFrog|W`rkn: how to make sed remove linebreaks?
19:07
< [R]>
Because bc chokes on line breaks
19:07
<&ToxicFrog|W`rkn>
It's probably really easy, but I just use tr -d \\n
19:07
< [R]>
echo `...` makes the linebreaks go away (also compresses all whitespace into a single space)
19:09
<&ToxicFrog|W`rkn>
xsel | tr -d \\n | bc
19:10
< [R]>
... and now bc complains about the complete lack of linebreaks
19:10 * [R] might just be better off using something instead of bc
19:10
<&ToxicFrog|W`rkn>
Wow, bc is way more finicky than I realized
19:10
< [R]>
Yeah
19:10
<~Vornicus>
Give us a sample of the text you're trying to convince bc to use?
19:11
< [R]>
$ awk '{print $1}' pirates.xp.txt | tr \\n '+' | sed s/.$//
19:11
< [R]>
8+8+8+8+8+8+8+8+8+8+12+8+8+8+12+8+8+8+8+8+8+12+8+8+4+8+8+8+8+8+8+8+8+4+8+8
19:11
< [R]>
$ awk '{print $1}' pirates.xp.txt | tr \\n '+' | sed s/.$// | bc
19:11
< [R]>
(standard_in) 1: syntax error
19:11
< [R]>
$ awk '{print $1}' pirates.xp.txt | tr \\n '+' | sed s/.$/\\n/ | bc
19:11
< [R]>
292
19:11
< [R]>
Woo!
19:12
< [R]>
<3 TF
19:13 Turaiel is now known as Turaiel[Offline]
19:13
<&ToxicFrog|W`rkn>
You might also be able to replace the awk with 'cut -f 1'
19:14
< [R]>
Nope
19:14
< [R]>
It's not a CSV or similar
19:14
< [R]>
It's uhh, fixed-length with readable padding?
19:14
< [R]>
http://xiennith.com/pirates.xp.txt
19:15
<&ToxicFrog|W`rkn>
The default delimiter for cut is TAB; if it's fixed width you can use cut -c
19:15
<&ToxicFrog|W`rkn>
e.g. cut -c-8 selects the first eight characters of each line
19:15
<&ToxicFrog|W`rkn>
It is less flexible than awk, though
19:16 You're now known as TheWatcher
19:16
< [R]>
Yeah
19:17
<@celticminstrel>
What should I call a special move where you take a hit in order to guarantee landing your own strike?
19:17
< [R]>
Ugh that actually has a name.
19:17
< [R]>
Like actually.
19:17
<@celticminstrel>
Heh.
19:18
<@celticminstrel>
I don't know what the name is, though...
19:18
<@celticminstrel>
.
19:20
< [R]>
http://tvtropes.org/pmwiki/pmwiki.php/Main/DeliberateInjuryGambit
19:21
< [R]>
(Similar names in link)
19:22
<@celticminstrel>
Hm...
19:26
<&ToxicFrog|W`rkn>
Does it have an actual real-world name as opposed to a TVT name?
19:26
<&ToxicFrog|W`rkn>
I'd be surprised if it didn't.
19:27
<&ToxicFrog|W`rkn>
(if you're looking for a name for a specific in-game move, rather than a general class of moves, you can always go with something generic like "Reckless Strike")
19:27
<@celticminstrel>
Hm... that might imply a higher chance of missing though. >_>
19:28
<@sshine>
let's say I perform k-means clustering a number of times. what's a good way to compare two runs? I currently do a sum-of-squares for distances of each point to its cluster centroid. but I can come up with examples of data where the SSE is really high, but the clustering is still good, e.g. if there's one cluster with a high internal variance, k-means'es SSE score will improve if it regards that as several clusters.
19:29
<@sshine>
I can't come up with any easy ways to overcome this example except "shape-based clustering" which I know nothing about.
19:30
<@celticminstrel>
Still, it's the best I have right now, so I guess I'll go with it.
19:30
<@sshine>
so... the good thing is: I actually have the true labels to compare with. but even here, I'm a little stumped: what if my k-means run divides the data completely different so that clusters don't map directly. then I can't even say how many it "got right", can I?
19:30
<@EvilDarkLord>
You could add cluster distance from each other as a heuristic, maybe.
19:31
<@sshine>
EvilDarkLord, yeah, that's a good idea.
19:31
<@sshine>
EvilDarkLord, I looked at a k-means initialization method called k-means++ that attempts to initialize centroids so they're far apart. so this is certainly a valued property.
19:33
<@sshine>
(it's super simple and really cool: pick one centroid at random, measure distance to all other points, pick another centroid at a weighted random proportional to their distance from the former. continue until k initial centroids are found, but recalculate distance to new initial centroids. it's O(k*n), sadly, but the authors say it beats running k-means a lot of times.)
19:35
<@froztbyte>
https://thoughtstreams.io/glyph/they-lives/
19:35
<@EvilDarkLord>
SOM would probably solve th
19:35
<@EvilDarkLord>
Err, stupid enter key
19:35
<@sshine>
SOM?
19:36
<@sshine>
so the bigger distance between clusters, the better.
19:36
<@sshine>
hmm...
19:37
<@EvilDarkLord>
I just had vague thoughts about self-organizing maps and how large-variance clusters would look in them. Pay me no mind, it was a half-formed thought. :P
19:37
<~Vornicus>
celmin: "attack when its tail is up" :P
19:38
<@celticminstrel>
...
19:38
<@sshine>
okay so this would be cool: having large distance between cluster centers and low internal variance.
19:39
<&ToxicFrog|W`rkn>
celticminstrel: personally, I don't think it has that implication, but even if it does the ability description should clear up any confusion - "an attack that always hits, at the cost of leaving yourself completely defenseless during it" or similar.
19:39
<&ToxicFrog|W`rkn>
(you do have inline ability descriptions, right? Right?)
19:39
<@sshine>
the risk may be that you detect a cluster within a cluster, but you really can't know if that's true or not.
19:39
<@EvilDarkLord>
That should at least help weed out some of your cluster variance issues.
19:39
<@celticminstrel>
Not at this time.
19:39
<@celticminstrel>
>_>
19:40
<@EvilDarkLord>
Of course if the cluster is really huge in terms of variance you could still end up with many centers being a good match, but.
19:40
<@sshine>
yes
19:41
<@EvilDarkLord>
And now you get the additional fun challenge of choosing good weights for the heuristics!
19:42
<@sshine>
I imagine two overlapping spheres of points with different point densities. my method won't deal well with that, but then again, the characteristics that define the spheres must derived in another way.
19:42
<@sshine>
so this is a harder problem than what I'm dealing with now.
19:43
<@celticminstrel>
I do have ability descriptions, just not inline. >_>
19:45
<&ToxicFrog|W`rkn>
If the user does not have a way to get the ability description at the point where they are invoking it, you have failed as a UI designer
19:46
<@celticminstrel>
Probably. >_>
19:47
<@sshine>
EvilDarkLord, currently I'm only minimizing SSE for distance between points and cluster centers. if I should also maximize external distance between cluster centers, I'm not sure how to compare both of those.
19:49
<@EvilDarkLord>
sshine: Make sure your measures scale similarly if you multiply all coordinates by a constant, then apply weights to both.
19:50
<@EvilDarkLord>
Hmm, I found a neat-looking algorithm in a research paper for shape-based clustering. Basically it clusters things with k-means and then gloms the clusters together if they meet certain similarity measures.
19:53
<@sshine>
EvilDarkLord, I've looked a little into "manifold clustering", but when I ask my TA, she just says "that is very hard. you should take a course in geometry." and I wonder if I should. :P
19:54 Turaiel[Offline] is now known as Turaiel
19:57
<@EvilDarkLord>
You should, then I can bug you about it in case you learn any fascinating new geometries.
19:58
<@sshine>
learning about geometry so far has been both good and bad. for example, whenever I read Lovecraft fan-fic and they say "non-Euclidean geometry", it used to sound spooky, and now I think "geez, he's sitting on a ball?"
19:59
<@EvilDarkLord>
We must make sacrifices in our quest for mental power.
20:01
<@sshine>
yeah, besides, Hello Cthulhu [ http://www.hello-cthulhu.com/?date=2003-11-30 ] kind of wrecked him being evil anyway.
20:01
<@EvilDarkLord>
This is kind of like how tvtropes ruins things, except useful in engineering.
20:14 Derakon [chriswei@Nightstar-a3b183ae.ca.comcast.net] has joined #code
20:14 mode/#code [+ao Derakon Derakon] by ChanServ
20:17 Kindamoody|afk is now known as Kindamoody
20:49 Turaiel is now known as Turaiel[Offline]
20:54 himi [fow035@Nightstar-5d05bada.internode.on.net] has quit [Ping timeout: 121 seconds]
20:59 Kindamoody is now known as Kindamoody[zZz]
21:04 * Derakon amuseds at USAA, which just increased his credit limit by ~25% when his USAA card's absolute limit is still about a fifth that of his other card.
21:04
<&Derakon>
Oh, well. Thanks, guys.
21:04
< [R]>
gg
21:04
< [R]>
Mine are 4500 and 2000
21:05
< [R]>
First went: 500 -> 1000 -> 1500 -> 3000 -> 4500
21:05
< [R]>
Second went: 1000 -> 2000
21:05
< [R]>
Second needed me to phone in to do so.
21:06
<&Derakon>
Whoops, meant to post this in #fleet, oh well.
21:07
< [R]>
Interesting that that one alternates with 100%/50% increments
21:07
< [R]>
(4500 is the legal max here AIUI)
21:07 himi [fow035@Nightstar-5d05bada.internode.on.net] has joined #code
21:07 mode/#code [+o himi] by ChanServ
21:08
<&ToxicFrog|W`rkn>
Does python have a mapcat equivalent?
21:08
<&Derakon>
What does mapcat do?
21:09
<&ToxicFrog|W`rkn>
maps over a collection and concatenates the results, which must themselves be collections.
21:09
<&Derakon>
Concatenates as in strings, or extending lists?
21:11
< [R]>
Derakon: I think he means .map() on the first level of a 2-level array (IE a 2D array), then flattens the array.
21:11
<&Derakon>
I mean, generally there's the list comprehension.
21:11
<&McMartin>
List comprehensions don't flatten
21:12
<&Derakon>
Ah.
21:12
<&ToxicFrog|W`rkn>
Is there a difference? mapcat(lambda x: [x, x+10], [1,2,3]) -> [1, 11, 2, 12, 3, 13]
21:12
<&McMartin>
I forget if there *is* an easy flatten operation, but I suspect the Pythonic way of doing this is to flatten your comprehension.
21:12
<&ToxicFrog|W`rkn>
(specifically, I have an iterator over a bunch of objects which contain objects which contain methods which return iterators over the objects I actually care about)
21:14
<&ToxicFrog|W`rkn>
Is the idiomatic way to do this just a really long list comprehension?
21:14
<&Derakon>
To make sure I have the relationships accurately...
21:14
<&Derakon>
for obj in iterator: thingsICareAbout = obj.subObj.method()
21:14
<&Derakon>
Where method() also is an iterator.
21:15
<&Derakon>
And you want just a list that's the concatenation of all the thingsICareAbouts.
21:15
<&ToxicFrog|W`rkn>
for container in iterator: for obj in container.contents(): do stuff with obj
21:15
<&ToxicFrog|W`rkn>
This can be trivially replaced with a single filter -> map if I can get all of the objs into a single iterable.
21:16
<&Derakon>
[doStuff(obj) for obj in container.contents() for container in iterator]
21:17
< RichyB>
McMartin: import operator; flatten = lambda sequences: reduce(operator.concat, sequences)
21:17
<&ToxicFrog|W`rkn>
See, that's what I tried first, but it gets me a "local variable 'container' referenced before assignment" error.
21:17
<&Derakon>
Hm.
21:17
< RichyB>
^ has certain downsides, like I expect that it's probably O(n**2).
21:17
<&ToxicFrog|W`rkn>
(well, without the enclosing doStuff(), because the filter needs to come before the map, and is a sufficiently complicated expression that I'm not inlining it into the comprehension)
21:20
<&ToxicFrog|W`rkn>
Aha. The answer seems to be that the associativity of list comprehensions is not what I expect.
21:20
<~Vornicus>
itertools has chain
21:20
<&ToxicFrog|W`rkn>
[(obj for obj in container.contents()) for container in iterator]
21:20
<&ToxicFrog|W`rkn>
...ooooor not.
21:21
< RichyB>
McMartin: flatten = lambda sequences: itertools.chain(*sequences) # is probably actually linear-time rather than made of fail.
21:21
<&ToxicFrog|W`rkn>
That gets me the container.contents() generator (I assume; it's a <generator object <genexpr> at <address>>), rather than the values it generates.
21:21
<&ToxicFrog|W`rkn>
Wtf.
21:22
<&Derakon>
(i for i in generator()) is itself a generator expression.
21:22
<&Derakon>
Use [] instead of ().
21:23
<&Derakon>
...except that will not flatten for you.
21:23
<@celticminstrel>
list(...)
21:23
<~Vornicus>
just [obj for obj in container.contents() for container in iterator]
21:23
<&ToxicFrog|W`rkn>
Vornicus: <&ToxicFrog|W`rkn> See, that's what I tried first, but it gets me a "local variable 'container' referenced before assignment" error.
21:23
<@celticminstrel>
Doesn't list(iterable) construct the list with the items from the iterable?
21:23
<&Derakon>
CM: has the same problem as using [] -- you get a list of lists.
21:24
<~Vornicus>
that surprises me
21:24
<@celticminstrel>
...oh right. Duh.
21:24
< RichyB>
lambda sequences: list(itertools.chain(*sequences)) # :: [[a]] -> [a]
21:24
<&Derakon>
>>> [i for i in xrange(10) for j in xrange(2)]
21:24
<&Derakon>
[0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9]
21:24
<&Derakon>
I can replace the 10 with j without causing a name error.
21:24
< RichyB>
Derakon: Interesting, wonder when that was added.
21:24
<&Derakon>
Seems like the same structure that Vorn/I suggested.
21:24
<@celticminstrel>
[obj for container in iterator for obj in container.contents()]?
21:25
<&ToxicFrog|W`rkn>
>>> [i for i in xrange(j) for j in xrange(2)]
21:25
<&ToxicFrog|W`rkn>
Traceback (most recent call last): File "<stdin>", line 1, in <module>
21:25
<&ToxicFrog|W`rkn>
NameError: name 'j' is not defined
21:25
<&ToxicFrog|W`rkn>
What python version are you using?
21:25
<&ToxicFrog|W`rkn>
I'm on 2.7 here.
21:26
<&Derakon>
WTF.
21:26
<&Derakon>
2.7.2.
21:26
<&ToxicFrog|W`rkn>
Oh man check this out
21:26
<&ToxicFrog|W`rkn>
It's awesome
21:26
<&Derakon>
I just C&P'd your code and it works for me.
21:26
<&ToxicFrog|W`rkn>
And by awesome I mean horrible
21:26
<&Derakon>
Uh oh.
21:26
<&ToxicFrog|W`rkn>
After a cold restart of the terp:
21:26
<&ToxicFrog|W`rkn>
>>> [i for i in xrange(j) for j in xrange(2)]
21:26
<&ToxicFrog|W`rkn>
Traceback (most recent call last): File "<stdin>", line 1, in <module>
21:26
<&ToxicFrog|W`rkn>
NameError: name 'j' is not defined
21:26
<&ToxicFrog|W`rkn>
>>> [i for i in xrange(10) for j in xrange(2)]
21:26
<&ToxicFrog|W`rkn>
[0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9]
21:27
<&ToxicFrog|W`rkn>
>>> [i for i in xrange(j) for j in xrange(2)]
21:27
<&ToxicFrog|W`rkn>
[0, 0]
21:27
<&Derakon>
Oh right, retained scope.
21:27
<&Derakon>
Python never deletes variables when you want it to.
21:27
<&Derakon>
One of my few peeves with the language.
21:28
<&ToxicFrog|W`rkn>
Wait, this is intended behaviour?
21:28
<&ToxicFrog|W`rkn>
I thought I'd just found a bug in 2.7.5.
21:28
< [R]>
Yay Python!
21:28
<~Vornicus>
no, that makes no sense to me
21:28
< RichyB>
Yeah. Evaluating [x for y in z] leaves the binding to y lying around.
21:28
<&Derakon>
Declared variables will not go out of scope except a) at the end of a function, b) at the end of a module, or c) if removed manually with the "del" statement.
21:28
<&Derakon>
There is no such thing as block scope in Python.
21:28
<&McMartin>
I'm very confused by the fact that triangular interation does not work
21:28
<&McMartin>
*iteration
21:28 * ToxicFrog|W`rkn pokes itertools.chain with a stick. Why are you returning a list of lists?
21:29
<&Derakon>
(I really wish there was, but by now it's probably too late. :( )
21:30
<&ToxicFrog|W`rkn>
Oh, because I need to call it.chain.from_iterable(list) rather than it.chain(list)
21:39
<&ToxicFrog|W`rkn>
Ok, this is what I've come up with:
21:39
<&ToxicFrog|W`rkn>
http://pastebin.starforge.co.uk/566
21:41
<&Derakon>
I note that you can rewrite that as a for loop and an if statement at the cost of a single line.
21:42
<&Derakon>
Like so: http://pastebin.starforge.co.uk/567
21:42
<&Derakon>
Not to belittle list comprehensions, but sometimes I find them harder to read than the more...imperative? approach.
21:43
<&ToxicFrog|W`rkn>
.append makes me feel dirty :(
21:43
<&Derakon>
Heh.
21:43
<&McMartin>
Given that x[-1] is constant time I *strongly* suspect that a chained extend will be linear time not quadratic.
21:47 * ToxicFrog|W`rkn starts work on the tests for the tests
21:49
< RichyB>
McMartin: the thing that I claimed would be quadratic was "reduce(operator.concat, ...)"
21:49
< RichyB>
list(itertools.chain(...)) should be linear, yes.
21:50
< RichyB>
reduce(operator.concat, ...) will keep allocating new lists or tuples with the (+) operator from left to right.
21:54 Derakon_ [chriswei@Nightstar-a3b183ae.ca.comcast.net] has joined #code
21:56 Derakon [chriswei@Nightstar-a3b183ae.ca.comcast.net] has quit [Ping timeout: 121 seconds]
21:56 Derakon [Derakon@Nightstar-a3b183ae.ca.comcast.net] has joined #code
21:56 mode/#code [+ao Derakon Derakon] by ChanServ
21:57 Derakon[AFK] [Derakon@31356A.8FA1FE.CF2CE9.D6CF77] has quit [Ping timeout: 121 seconds]
22:04 Derakon__ [chriswei@Nightstar-a3b183ae.ca.comcast.net] has joined #code
22:06 gnolam_ [lenin@B19C04.C4B928.3477B4.1341ED] has joined #code
22:06 gnolam is now known as NSGuest3204
22:06 gnolam_ is now known as gnolam
22:06 mode/#code [+o gnolam] by ChanServ
22:06 Derakon_ [chriswei@Nightstar-a3b183ae.ca.comcast.net] has quit [Ping timeout: 121 seconds]
22:07 NSGuest3204 [lenin@Nightstar-b2aa51c5.cust.bredbandsbolaget.se] has quit [Ping timeout: 121 seconds]
22:07 Derakon [Derakon@Nightstar-a3b183ae.ca.comcast.net] has quit [Ping timeout: 121 seconds]
22:08 Derakon [Derakon@31356A.8FA1FE.CF2CE9.D6CF77] has joined #code
22:08 mode/#code [+ao Derakon Derakon] by ChanServ
22:19 himi [fow035@Nightstar-5d05bada.internode.on.net] has quit [Ping timeout: 121 seconds]
22:24 Derakon_ [chriswei@Nightstar-a3b183ae.ca.comcast.net] has joined #code
22:27 Derakon__ [chriswei@Nightstar-a3b183ae.ca.comcast.net] has quit [Ping timeout: 121 seconds]
22:28 Derakon [Derakon@31356A.8FA1FE.CF2CE9.D6CF77] has quit [Ping timeout: 121 seconds]
22:29 Derakon [Derakon@31356A.8FA1FE.CF2CE9.D6CF77] has joined #code
22:29 mode/#code [+ao Derakon Derakon] by ChanServ
22:32 himi [fow035@Nightstar-5d05bada.internode.on.net] has joined #code
22:32 mode/#code [+o himi] by ChanServ
22:50 d4de [olorin@687AAB.418D22.566E2F.BC5950] has joined #code
22:58 Reiv [NSwebIRC@Nightstar-95746c1f.kinect.net.nz] has joined #code
22:58 mode/#code [+o Reiv] by ChanServ
23:00 VirusJTG [VirusJTG@Nightstar-09c31e7a.sta.comporium.net] has joined #code
23:08 himi [fow035@Nightstar-5d05bada.internode.on.net] has quit [Ping timeout: 121 seconds]
23:12 Turaiel[Offline] is now known as Turaiel
23:21 himi [fow035@Nightstar-5d05bada.internode.on.net] has joined #code
23:21 mode/#code [+o himi] by ChanServ
23:43 himi [fow035@Nightstar-5d05bada.internode.on.net] has quit [Ping timeout: 121 seconds]
23:53 Turaiel is now known as Turaiel[Offline]
23:53 Turaiel[Offline] is now known as Turaiel
23:56 himi [fow035@0C0840.B22E58.E3471A.E028A1] has joined #code
23:56 mode/#code [+o himi] by ChanServ
--- Log closed Fri May 24 00:00:20 2013
code logs -> 2013 -> Thu, 23 May 2013< code.20130522.log - code.20130524.log >

[ Latest log file ]