--- Log opened Sat Apr 14 00:00:53 2007 |
00:12 | | gnolam [lenin@Nightstar-13557.8.5.253.se.wasadata.net] has quit [Quit: Whatever.] |
00:17 | < MyCatVerbs> | Argh. lint needs a few extensions. |
00:17 | < MyCatVerbs> | Like, when it tells you to explicitly cast functions' return value to void if you're ignoring them? |
00:18 | < MyCatVerbs> | It should automatically suplex you through a plate glass window if you then proceed to blindly cast everything to void instead of checking anything. |
00:18 | <@McMartin> | I don't routinely cast the return value of sprintf to void. |
00:18 | <@McMartin> | But it's rarely necessary I check the value. |
00:18 | < Doctor_Nick> | mcmartin: what |
00:19 | < Doctor_Nick> | erm |
00:19 | < MyCatVerbs> | McMartin: by "you" I mean "me" |
00:19 | <@McMartin> | Er, snprintf |
00:19 | < MyCatVerbs> | ^~ |
00:20 | <@Vornicus> | what's snprintf return anyway? |
00:20 | < MyCatVerbs> | Vornicus: number of characters that -would- have been printed if size had been infinite. |
00:21 | < MyCatVerbs> | Not including the final null. |
00:21 | | * MyCatVerbs <3: man 3 <the entire freakin' C library, plus all of POSIX> |
00:22 | <@ToxicFrog> | Yeah, sections 2 and 3 are generally awesome. |
00:22 | < MyCatVerbs> | Er, except the POSIX syscalls, of course. ^^ |
00:22 | | * Vornicus usually finds section 3 to be Too Damn Crowded To Find Anything Useful. |
00:24 | <@McMartin> | Also, totally useless for C++ |
00:26 | <@ToxicFrog> | Vornicus: man -k |
00:26 | <@ToxicFrog> | And yeah, it's useless for C++, but the only time I'm doing C++ is when working on SGOS. |
00:26 | <@ToxicFrog> | Which, er, isn't ANSI-compliant anyways. |
00:26 | <@ToxicFrog> | (although one of my jobs this summer will be fixing this!) |
00:28 | | * Vornicus is also generally working in Python or something, where the better reference is On The Internets. |
00:28 | | * ToxicFrog nods |
00:29 | <@ToxicFrog> | At some point, I need to write a program to autogenerate man pages for the Lua stdlib. |
00:29 | <@ToxicFrog> | I want to be able to go 'man string.gmatch' rather than consulting the entire Manual. |
00:42 | < MyCatVerbs> | Um, but. |
00:42 | < MyCatVerbs> | McMartin: C++ is totally useless itself. |
00:42 | < MyCatVerbs> | It'd be really bad to break the pattern. =D |
00:42 | <@McMartin> | Sometimes I have to hack C++ code to make it compile. |
00:44 | < Doctor_Nick> | hey guys |
00:44 | < Doctor_Nick> | i hear you dont like c/c++ |
00:44 | < Doctor_Nick> | confirm/deny |
00:44 | < MyCatVerbs> | Doctor_Nick: nononono |
00:44 | <@McMartin> | C is absolutely necessary for the things that it should be used for. |
00:44 | <@McMartin> | C++ can be used properly but essentially never is. |
00:44 | < MyCatVerbs> | Doctor_Nick: we think C is inappropriate for basically everything except writing operating system guts. |
00:44 | <@McMartin> | (Or game engines) |
00:44 | < Doctor_Nick> | or emulation |
00:45 | < MyCatVerbs> | Doctor_Nick: C++ just blows. |
00:45 | <@McMartin> | C++ is useful for system level GUI work. |
00:45 | <@McMartin> | So game engines will often see it. |
00:45 | <@McMartin> | Emulation may or may not require C-level work, depending on the level it's working at. |
00:45 | <@McMartin> | I've seen several VMs written in Java that nevertheless had acceptable performance. |
00:46 | < MyCatVerbs> | Heee. C++ is useful for a) videogames b) widget sets c) wasting investors' money. |
00:46 | <@McMartin> | a) is kind of a special case of b)~ |
00:46 | <@McMartin> | But, really, I mean. |
00:46 | <@McMartin> | I don't hate on Qt. |
00:46 | <@McMartin> | Which is native C++. |
00:46 | <@Vornicus> | Swing frightens me, but I can sort of see why they didn't. |
00:46 | < MyCatVerbs> | Oh and it kinda blows at widget sets, because b) forces whoever wants to use your widget set to use C++ too, causing them to perform c). |
00:46 | <@Vornicus> | er |
00:46 | <@Vornicus> | s/didn't/did it/ |
00:46 | <@McMartin> | MCV: Untrue. |
00:47 | <@McMartin> | Qt has C bindings now. |
00:47 | <@McMartin> | It's just that using them is extreme pain, much like using raw GTK+ is. |
00:47 | < MyCatVerbs> | Oh, arr. FFIs to C++? |
00:47 | <@McMartin> | Yeah, those actually exist now. |
00:48 | <@McMartin> | Once you have those, you can write the widget set in that and then rely on the wrapper language for the rest. |
00:50 | | MahalGone is now known as Mahal |
00:53 | <@ToxicFrog> | FFIs? |
00:54 | <@ToxicFrog> | And, yeah, b doesn't necessarily -> c. |
00:54 | <@McMartin> | Foreign Function INterface. |
00:54 | | * ToxicFrog points at the Lua bindings for Qt as evidence of this |
01:08 | <@ToxicFrog> | (sadly, it uses scons ;.;) |
01:08 | < MyCatVerbs> | ? |
01:08 | < MyCatVerbs> | Does scons suck? |
01:08 | <@McMartin> | What is/are scons? |
01:09 | < MyCatVerbs> | I've yet to hear of a build system that didn't, but the few scons based programs I've seen were much faster to build than autoconf-based projects. |
01:09 | <@McMartin> | Autoconf slaughters puppies as part of its traditional build process. |
01:09 | < MyCatVerbs> | McMartin: it's a build system. Meant to replace autoconf, I *think*. |
01:10 | <@McMartin> | Even its manual says the way to write config scripts is to copy a pre-existing one that works. |
01:10 | <@McMartin> | (re: scons) aha |
01:12 | <@ToxicFrog> | sconstruct is a python-based build system that's faster than make, but as far as I can tell no more readable and considerably less readily available. |
01:34 | | ReivZzz is now known as Reiver |
02:36 | < MyCatVerbs> | Hrmn. |
02:37 | < MyCatVerbs> | Might LISP code be a little less painful to read if one added {[]} to it for different purposes? |
02:39 | < MyCatVerbs> | For example, just define that one may use {} for function application only, [] for grouping only... () for anything. So that it comes out that old code is unaffected, but you can use a slightly different bracketing style in newer code to be able to confirm that the compiler is actually seeing exactly the right things in the right places, and give it a few hints as to what you had *meant* to say, when something does wrong so that you ca |
02:41 | <@Vornicus> | eh. just being able to use them freely would work fine. |
02:42 | < MyCatVerbs> | But you wouldn't get the benefit of break-early/break-cleanly. |
02:45 | | Reiver is now known as ReivOut |
03:07 | | MyCatVerbs is now known as MyCatSleeps |
05:15 | | Chalcedon [Chalceon@Nightstar-5397.dialup.ihug.co.nz] has joined #code |
05:15 | | mode/#code [+o Chalcedon] by ChanServ |
05:41 | | Chalcedon [Chalceon@Nightstar-5397.dialup.ihug.co.nz] has quit [Quit: ] |
05:43 | | * ToxicFrog rewrites large chunks of the unofficial SS1 specs |
05:51 | | * Raif sees another weekend go down the tubes before its even started. :) |
05:52 | <@ToxicFrog> | Down the tubes? On the contrary, I'm actually getting stuff done~ |
05:53 | | * ToxicFrog stops getting stuff done, as he tries to figure out how the RES API should work |
05:54 | <@Raif> | No, mine... but I think I can make yours go down the tubes too. |
05:55 | <@ToxicFrog> | Gnar. |
05:56 | <@ToxicFrog> | So, from the point of view of, say, the map API, all it needs to be able to do is ask for chunks by ID and get them. |
05:56 | <@ToxicFrog> | And eventually tell it to save all modified chunks. |
05:56 | <@ToxicFrog> | But something like, say, unres, needs to be able to operate on the resfile level rather than the resource pool level. |
05:57 | <@ToxicFrog> | What I am currently thinking is this: there is a class, Resfile. It supports loading and saving, as well as addition and removal of chunks and retrieval of chunk data. |
05:58 | <@ToxicFrog> | When it changes, it notifies the resource pool. |
05:58 | <@ToxicFrog> | The resource pool is responsible for, given a chunk ID, automatically figuring out which resfile (if any, of the ones currently loaded) can provide it, and forwarding the request. |
06:00 | <@Raif> | Reading through a file multiple times is bad. |
06:00 | <@Raif> | Efficiency counts when loading models, so make it easy to do it in one pass. |
06:01 | <@Raif> | In fact, the way I've always seen model loading done (and many other file formats), is that you scan through the file and grab the chunks you want. You never really request a specific chunk. |
06:01 | <@ToxicFrog> | ...er. |
06:02 | <@ToxicFrog> | First of all, this isn't models, it's everything. |
06:02 | <@Raif> | It's graphics data, correct? |
06:02 | <@ToxicFrog> | Some of it is. |
06:02 | <@ToxicFrog> | There's also map data, text, audio... |
06:02 | <@Raif> | I might be confusing your file format with something else. |
06:02 | <@Vornicus> | Graphics, map data, I think physics... |
06:02 | <@ToxicFrog> | Physics are handled by the gamesys, which is a seperate format. |
06:02 | <@Raif> | Oh, I'm confusing you with McM. |
06:02 | <@Raif> | He's writing a model format. |
06:02 | <@ToxicFrog> | Yeah, this is LGRES, not SVAF. |
06:02 | <@Raif> | I think I got hung up on the word "chunks". |
06:03 | <@ToxicFrog> | And I'm just talking about the API, anyways. |
06:03 | <@ToxicFrog> | Implementation-wise, I see it working something like this. |
06:03 | <@Raif> | So what do you mean by chunk? |
06:03 | <@ToxicFrog> | When a Resfile is told to load a file, it reads the header and TOC from that file, and reports to the resource pool all the chunk IDs which can be supplied by that file. |
06:04 | <@ToxicFrog> | When asked for a chunk, it returns it from cache if it has it already, otherwise it reads it from disk, caches it, and returns it. |
06:04 | <@ToxicFrog> | And it can be told to preload all chunks for efficiency reasons, if necessary. |
06:04 | <@ToxicFrog> | Er. A subfile? |
06:05 | <@ToxicFrog> | Resfiles are packed files; each one contains a set of discrete data packets. I hesistate to call them "files" because they are identified only by ID number. |
06:05 | <@ToxicFrog> | The unofficial specs call them "chunks", so that's what I use. |
06:06 | <@ToxicFrog> | Each chunk contains a texture, sprite, model, sound, log text, part of a level map, etc, and the engine asks for them by chunk ID as it needs them. |
06:07 | <@ToxicFrog> | What I am concerned with here is the API by which chunks will be accessed in my editing tools. |
06:08 | <@Raif> | So what's the hangup on the API? |
06:09 | <@ToxicFrog> | The fact that depending on which angle I look at it from, I either need "give me the chunk with this ID", or "give me all chunks pertaining to this file, then add these chunks to that set and save the lot of them" |
06:17 | <@Raif> | Implement both. :) |
06:18 | <@ToxicFrog> | Yes, that's what my proposed solution is. |
06:18 | | * ToxicFrog points up, where he said this already |
06:32 | | * Raif sees no problem. |
06:45 | | Janus [~Cerulean@Nightstar-10302.columbus.res.rr.com] has quit [Connection reset by peer] |
06:56 | | NR-Linux [~NightRain@Nightstar-763.worldnet.co.nz] has joined #code |
07:09 | | NR-Linux [~NightRain@Nightstar-763.worldnet.co.nz] has left #code [Leaving] |
07:37 | | ReivOut is now known as Reiver |
07:41 | | Doctor_Nick [~fdsaf@Nightstar-27777.rag-a.fsu.edu] has quit [Ping Timeout] |
07:44 | | Serah [~Z@87.72.36.ns-26407] has quit [Killed (NickServ (GHOST command used by ZLOK))] |
07:45 | | Serah [~Z@87.72.36.ns-26407] has joined #Code |
07:45 | | mode/#code [+o Serah] by ChanServ |
07:59 | | gnolam [lenin@Nightstar-13557.8.5.253.se.wasadata.net] has joined #Code |
07:59 | | mode/#code [+o gnolam] by ChanServ |
08:01 | | * Reiver attempts to figure out whether or not he's better off using mech marines or medium tanks. |
09:16 | <@McMartin> | 40,000 words! |
09:17 | <@Vornicus> | vwoot |
09:18 | <@jerith> | Yay 40kw! |
09:19 | | * McMartin probably will end up lowering that before he raises it again, though, due to code refactoring and such. |
09:23 | <@Raif> | More cowbell! Wooo! |
09:24 | <@Raif> | Reiver: Mech marines become useless pretty quickly. |
09:24 | <@Raif> | Unless they've just given you a brand new tech level. |
09:24 | <@Reiver> | AKA by spamming them to Hold The Line while your other factories upgrade, Raif? |
09:25 | <@Reiver> | Strictly speaking they do more damage/cost than the tanks. At the same time they also die like punks. |
09:25 | <@Raif> | I stagger my factory upgrades. |
09:25 | | * Reiver too. |
09:25 | <@Raif> | It's a rare occasion that I don't have at least 4 of each. |
09:25 | | * Reiver has taken to using a ~2:1 force of Tanks/Artillery/AA:Mech Marines. |
09:26 | <@Raif> | Plus tech 3 anything takes for fucking ever unless you've got 3 or 4 engineer bots helping. |
09:26 | <@Reiver> | They work kind of okay for tying up enemy units while your real tanks get into position, but it can't be cost efficient. >.> |
09:26 | <@Raif> | AA and Artillery don't even factor in, so what you're saying is you took a force of Tanks:Mechs 2:3 |
09:27 | <@Raif> | Also, tech 3 bombers are probably my favorite toy. |
09:27 | <@Reiver> | Nah. |
09:27 | <@Raif> | About a dozen of those can take out just about any single target, unless the other base has ridiculous levels of AA. |
09:27 | <@Reiver> | I usually only had a handful of AA. |
09:28 | <@Raif> | Though I never like to fly anything less than 20 units to a group. |
09:28 | <@Reiver> | And I sort of mix artillery with the tanks because the splash damage can be fun, and the level 1 artillery is cheap anyway. >.> |
09:28 | <@Reiver> | Oh, sure, the high tech stuff is awesome. |
09:28 | <@Raif> | I like sending in lots of cheap planes before the bomber group. The cheap planes will get blown right up, but the bombers will survive long enough to take out the anti-nuke silo(s) |
09:28 | <@Raif> | :P |
09:28 | | * Reiver is trying to work out what is effective at lower levels. |
09:29 | <@Raif> | Build a few defense towers, tanks and AA. Shell in until you get to the higher tech levels and then come out in force. |
09:29 | <@Reiver> | Afterall, if SupComm is anything at all like TA, you can't play with the big toys if you died to the level 1 swarm ten minutes in~ |
09:29 | <@Raif> | This will probably fail against a particularly good player. |
09:29 | <@Reiver> | Raif: The problem with that is that in TA, area = money |
09:29 | <@Reiver> | If you let the other guy take over 3/4 of the map - even poorly defended - he's earning 3x the income you are, generally speaking. |
09:30 | <@Raif> | You can reclaim area that others have expanded into usually. |
09:30 | <@Reiver> | Assuming you didn't get steamrolled first. :p |
09:30 | <@Raif> | I find precision strikes against specific targets deep in enemy territory tend to screw them up long enough that you can mop up whatever secondary target you want. :) |
09:30 | <@Reiver> | sure, you can use metal-makers and fusions - so could he, and he had 3x the metal playing around to get them built. >.> |
09:31 | <@Reiver> | I still find it vaugely disconcerting that your shipyards build construction engineers, though. |
09:31 | <@Reiver> | It smacks a little of 'cheap hack'. >.> |
09:31 | <@Raif> | Power is never a problem. Mass can be later in the game if you can't claim more. That shouldn't be first priority though, because you might have all the mass in the world, but they have a smattering of units that'll take out your nigh-undefended mines. :P |
09:32 | <@Raif> | Why is that cheap? |
09:32 | <@Reiver> | Eh |
09:32 | <@Raif> | All unit-producing buildings produce engineers, and engineers are amphibious. |
09:32 | <@Reiver> | TA had construction planes, vehicles, and boats |
09:32 | <@Raif> | I was never a fan of that. |
09:33 | | Serah [~Z@87.72.36.ns-26407] has quit [Ping Timeout] |
09:33 | <@Reiver> | The "Hey let's have every factory build the same thing" bit just... sounds like the designers wanted less work. >.> |
09:33 | <@Reiver> | As for the 'undefended'... This is the one aspect, I must admit, I am still looking into. |
09:33 | <@Raif> | True, but I'd rather that than some half-assed attempt at variety. |
09:33 | <@Reiver> | The trick in OTA was that you didn't have a 'base', you had 'an area you owned'. |
09:33 | <@Reiver> | Your factories would be scattered everywhere and all churning out tanks. |
09:33 | <@Raif> | Put it this way: |
09:33 | | Serah [~Z@87.72.36.ns-26407] has joined #Code |
09:33 | | mode/#code [+o Serah] by ChanServ |
09:34 | <@Reiver> | You didn't have a single base and the rest left as just metal extractors, so to speak. |
09:34 | <@Raif> | It's really, really easy to claim small chunks of new territory from an enemy that has focused on claiming lots of land. |
09:34 | <@Raif> | And it's also really easy to build good defenses around that new territory quickly. |
09:34 | <@Raif> | Because you're doing it one small chunk at a time. |
09:34 | <@Reiver> | Raif: It's equally easy for the opponent to set up a seige perimeter, because his units cost the same as yours. |
09:35 | <@Reiver> | He left himself vulnerable early-game, at the expense of vastly improved transition economy. |
09:35 | <@Raif> | Not if he's splitting all that energy between 4 different points on the map. |
09:35 | <@Raif> | Indeed, that's the trick. That'll work, but only if nobody finds you. |
09:35 | <@Reiver> | Raif: Let's say you won 1/4 the map. |
09:35 | <@Raif> | My postulate is that somebody will always find you. :) |
09:35 | <@Reiver> | He won 3/4 by expanding madly. |
09:35 | <@Reiver> | You have to defend 1/4 of the map. |
09:36 | <@Reiver> | He has to defend... 1/4 of the map. |
09:36 | <@Reiver> | (With the exception of air defense, but he actually holds the advantage there, so.) |
09:36 | <@Raif> | If he's surrounded you that quickly, then you're screwed anyway. |
09:36 | <@Reiver> | ((It's easier to whittle down a horde to nothing as it flies past than it is to put up a 'wall of AA' and pray nothing gets through.)) |
09:37 | | Serah [~Z@87.72.36.ns-26407] has quit [Ping Timeout] |
09:37 | <@Raif> | Early game is not fast. Expansion like that takes effort, and little darting strikes at his resources will improve your chances... especially if you're mobile and you're not trying to claim multiple points. |
09:37 | <@Reiver> | Yeah, well. I'm going off OTA balance here. The only thing that seems vastly different in SupCom is that engineers (The cornerstone of expansion) are even /faster/ to build. >.> |
09:37 | <@Raif> | I use both methods actually. |
09:37 | <@Raif> | I put scattered AA on outer perimeter and then wall in an inner line. |
09:38 | <@Raif> | Nothing gets into my inner base. :) |
09:38 | <@Raif> | Well, a teleport will, and then who knows what'll happen. |
09:38 | <@Raif> | I try to have two bases, but it doesn't always work out. |
09:39 | <@Raif> | Engineers are fast to build, but when they help each other they still increase your resource usage, so there's a point where more is pointless. |
09:39 | <@Raif> | Again, if you're having mass trouble, expand where you can and start building fabs. |
09:39 | <@Reiver> | Ahem. |
09:39 | <@Reiver> | The most impressive games of OTA were between folks known as the Gnugs, where entry was mostly determined by being able to beat most of their players and not being a complete asstard. |
09:40 | <@Raif> | Neat. |
09:40 | <@Reiver> | At the end of one game that lasted /four hours/, the /victor/ had a total of 250 Metal wasted. |
09:40 | <@Reiver> | In total. >.> |
09:40 | <@Raif> | Impressive. |
09:41 | | * Raif shrugs. |
09:41 | <@Raif> | I don't pretend to be the best. :) |
09:41 | <@Reiver> | When you watched the recording... he very rarely had more than 500-600 in reserve, he was eternally spending the stuff exactly as fast as he earned it. With an, uh, impressively geometric economy. >.> |
09:41 | <@Raif> | Point me to these recordings? |
09:42 | <@Reiver> | Do you have Total Annihilation lying around? |
09:42 | <@Raif> | Ah, game recordings... damn. No, I'm afraid that's been lost for a number of years. |
09:42 | <@Reiver> | You need to set up the install somewhat special to get a recording to play. |
09:42 | <@Reiver> | Ah. Bummer. |
09:42 | <@Reiver> | Yeah, this was a 3rdparty game recorder. >.> |
09:43 | <@Reiver> | You set up a 'multiplayer' game and watched as spectator. ;) |
09:44 | <@Raif> | My problem tends to be, like yours, that I've got power coming out of various orifices, but mass is rare. |
09:44 | <@Reiver> | Metal makers! ^.^ |
09:45 | <@Reiver> | (With cunning micromanagement.) |
09:45 | <@Raif> | I end up building more fabs, but it seems to be a difficult balance to keep when you're minding incoming strategic nukes and air strikes. :P |
09:45 | <@Reiver> | (...In fact I've been known to set up several on 'group 0' so I can batch turn-on/turn-off as an energy management hack. Heh.) |
09:45 | <@Raif> | I was somewhat disappointed with tac nukes. They seem to be underpowered. |
09:45 | <@Reiver> | ...Well, they'll blow a base apart, or soundly trounce an Experimental. |
09:46 | <@Raif> | No, tac nukes are the little ones. |
09:46 | <@Raif> | Strategic nukes are an awesome thing to behold. |
09:46 | <@Reiver> | You mean the nuclear cruise missile from a submarine, or a /normal/ cruise missile from a submarine? |
09:46 | <@Raif> | I've killed many incoming columns by setting a nuke to detonate just ahead of their main body. :) |
09:47 | <@Raif> | Reiv: There are tactical nuke launchers you can build silos for. Much like strategic nukes (the big ones). They kill a turret or two. |
09:47 | <@Raif> | You can also get small groups of units, but aiming is hard for the bang you get out of it. |
09:49 | <@Reiver> | Oh, right. You mean cruise missiles. |
09:49 | <@Reiver> | Yeah. I have a strong suspicion they got Nerfed(tm) in beta or something. >.> |
09:50 | <@Reiver> | Use 'em mostly as a sort of stockpiled-artillery, really. |
09:50 | <@Reiver> | Or possibly anti-ship, though I don't think they're guided. |
09:52 | <@Raif> | Nope, they're not. |
09:52 | <@Raif> | One of the bertha canons is better than a tac missile any day. |
09:53 | <@Reiver> | Alas. |
09:53 | <@Raif> | 'course a bertha cannon takes about a year to build, so... |
09:53 | <@Reiver> | Had they been guided - at least somewhat - it could have made an interesting use. |
09:53 | <@Reiver> | And left the battleships tactical missile defense with a job to do. ;) |
09:54 | <@Raif> | Yeah. |
09:54 | <@Raif> | Still, bombers are my favorite toy. |
09:54 | <@Reiver> | I mean, I know why the origional TA's missile launchers weren't guided. |
09:55 | <@Reiver> | ...Because in Beta, they were. |
09:55 | <@Raif> | Kill the anti-nukes, then nuke. |
09:55 | <@Raif> | It always surprises me how easily that works. |
09:55 | <@Reiver> | Raif: Multiplayer, or AI? |
09:55 | <@Raif> | Both. |
09:55 | <@Reiver> | Aha. |
09:55 | | * Reiver has heard most multiplayer games never make it far enough for nukes - the economy drain means you're left dead before it's finished. |
09:56 | <@Raif> | Just leave it cooking in the background. |
09:56 | <@Raif> | Maybe that's why it works. |
09:57 | <@Reiver> | You are thus building these nukes at the point in time when the economy drain is trivial? |
09:57 | <@Raif> | sorta. It would be non-trivial if I had multiple engineers on it. I think it takes around 15 mins or so with one. |
09:57 | <@Raif> | But after the silo is built I'll haul ass on the first nuke if I've got the resources to spare. |
09:58 | <@Reiver> | I more meant the economy hit is sufficient that you're sitting there, waitin' for your nuke, buildin' your troops etc OH SHIT MONKEYLORDS, PLURAL |
09:58 | <@Reiver> | *crunch* |
09:58 | <@Reiver> | *nukeneverfinished* |
09:58 | <@Raif> | Against the AI, that's common. Multi, it happens... not as often as I'd like, but it happens. :) |
09:58 | <@Reiver> | Heh. Fair nuff. |
09:58 | <@Raif> | I fucking hate monkeylords. |
09:59 | <@Raif> | I still can't beat a really good player, but meh... |
10:00 | <@Raif> | I'm not interested in being the best at strategy anymore. The problem is always that some guy with more time than I have will have figured out all the little tricks and optimal builds and whatever. |
10:00 | <@Raif> | That was more or less my problem with starcraft, actually. |
10:00 | <@Raif> | It got to the point where if you didn't search the internet for a build, you wouldn't make it to the five minute mark. |
10:00 | | * Reiver nods. |
10:01 | <@Reiver> | SupComm is sort of nice in that it's big enough that that may not be such a problem. |
10:01 | <@Raif> | That'll always be the problem with RTS, though. |
10:01 | <@Raif> | Yeah, if you're on a big map. |
10:01 | <@Reiver> | I know in TA, the game balance settled down to "Dead in ten minutes, Dead in Half an Hour, Dead Via Burnout". |
10:01 | <@Raif> | That's also why I refused to play SC on anything less than the largest map size with lots of zigzaggy corridors. |
10:01 | <@Reiver> | Oh, and Dead In Four Minutes, but that was a peewee rush on dark side. >.> |
10:02 | <@Raif> | The zerg rush took long enough to travel that people wouldn't fucking do it. |
10:03 | <@Reiver> | (Basically, it was a matter of "Did you fuck up in early game" [the one bit that was 'search for a build', even then there were half a dozen options], "Did you die in midgame" (AKA someone pulled off something clever that you hadn't counted on [Bomber raid when you'd anticipated robots or something]), or "Endgame, which lasts as long as the players can keep on their toes." |
10:04 | <@Reiver> | Even gamestart had several strategies, depending on the map and your style. |
10:04 | <@Reiver> | Jeffy First, Flash First, Construction Vehicle First, Air First, and even Samson First, though that was a big gamble. |
10:05 | <@Raif> | Not such a gamble on certain maps. |
10:05 | <@Reiver> | (Because a Samson First would beat a Jeffy First without much effort; but against any of the others but Air First, you were toast.) |
10:06 | <@Raif> | Good times. |
10:06 | <@Reiver> | They were. |
10:06 | <@Raif> | This is why I quit multiplayer not too long after the game's out. |
10:06 | <@Reiver> | People get 'too good'? |
10:06 | <@Raif> | Once people figure out The Build, it's not as much fun for me. |
10:06 | <@Raif> | Yeah. |
10:06 | | * Reiver nods. |
10:06 | <@Reiver> | Though in TA/SupCom, there was an advantage. |
10:07 | <@Reiver> | The Build mattered less than The Strategy. >.> |
10:07 | <@Raif> | The bar is raised a little too high, so you end up having this wide gulf between newbies and people who will trounce you without blinking an eye. |
10:07 | <@Reiver> | Sure, in TA the Missile Tank owned all. That's okay, it became your Generic Soldier Type. Rock-paper-scissors wasn't what the game was about anyway. >.> |
10:07 | <@Raif> | For strategy vs. humans, I'll always prefer Chess, Backgammon and Go. |
10:07 | <@Raif> | :) |
10:08 | <@Raif> | The missile tank in SC is kinda like that too. |
10:08 | <@Raif> | It makes artillery somewhat silly. |
10:11 | <@Reiver> | Missile tank being the Tech 2 artillery? |
10:11 | <@Raif> | They're seperate I think. |
10:12 | | * Raif eyes his bank account. |
10:12 | <@Raif> | ah, joy. |
10:12 | <@Raif> | this might be the most money I've ever had. |
10:12 | <@Raif> | 'course it'll be mostly gone in a month, but oh well. :P |
10:13 | <@Reiver> | http://www.supcomuniverse.com/unitdb/UEF_Land.html |
10:13 | | * Reiver raises an eyebrow. |
10:13 | <@Reiver> | I had money once. |
10:13 | <@Reiver> | Then I enrolled in university. >.> |
10:14 | <@Raif> | guess I'm mistaken.- |
10:14 | <@Raif> | Re: university: Yeah, I never had money before that either, though. |
10:14 | <@Reiver> | Heh. |
10:14 | <@Reiver> | I saved since I was 10 to go to university. |
10:14 | <@Reiver> | I went in with, uh |
10:15 | <@Reiver> | Like 4 grand in my bank account. |
10:15 | <@Reiver> | I've bled it white since. >.> |
10:15 | <@Raif> | That'd be less than a semester here. |
10:15 | | Vornicus is now known as Vornicus-Latens |
10:15 | <@Raif> | (Rent is not covered, and the college doesn't offer dorms) |
10:16 | <@Raif> | So most of one's money goes to living expenses while FAFSA will pay for the actual classes. |
10:17 | <@Reiver> | Heh. |
10:17 | <@Reiver> | I didn't spend any of it on rent and college. |
10:17 | <@Reiver> | All of /that/ went straight on my loan. >.> |
10:18 | <@Raif> | Exciting. |
10:18 | | * Reiver coughs. |
10:18 | <@Reiver> | NZ$40k and rising. |
10:18 | <@Reiver> | I'm not entirely sure how I intend to pay it back. |
10:18 | <@Raif> | US$30k, not sure what that is in NZ$. |
10:19 | <@Reiver> | About NZ$45. |
10:19 | <@Reiver> | *k |
10:19 | <@Raif> | It's pretty easy to pay back after you're in the workforce. At least in the US nobody really expects you to pay it back under 10 years (you're smart to do so, but you rarely have to) |
10:19 | <@Reiver> | >.> |
10:19 | | * Reiver nods. |
10:19 | <@Reiver> | This is a government loan. |
10:19 | <@Raif> | them NZ dollars is expensive! :P |
10:20 | <@Raif> | So are mine. I got denied for all the non-government ones. |
10:20 | <@Reiver> | It literally turns into extra taxes. |
10:20 | <@Raif> | Ah, interesting. |
10:20 | <@Raif> | I kinda like that actually. |
10:20 | <@Reiver> | Want to escape your loan payments? |
10:20 | <@Raif> | No interest then, I presume? |
10:20 | <@Reiver> | You get to go toe-to-toe with the IRD. |
10:20 | <@Reiver> | Used to be. |
10:20 | <@Raif> | There's no escape for federal student loans here. |
10:21 | <@Reiver> | Latest Labour (Socialist/left-wing) government had it as an election promise to halt all interest so long as you remained in the country. |
10:21 | <@Raif> | It's a very specific kind of debt that isn't forgiven if you default or go bankrupt. |
10:21 | <@Raif> | And the government gets mighty testy if you default. |
10:21 | <@Reiver> | Their compeditors, National, offered to wipe a loan by X% each year so it was wiped in like 10 years or something if you found employment in your feild while within the country. |
10:22 | <@Reiver> | ...Labour won the student vote. |
10:22 | <@Reiver> | Why is simple enough - NZers are cynical bastards politically. |
10:22 | <@Raif> | I don't see why either promise holds much weight. |
10:22 | <@Reiver> | And the "We'll wipe all interest and set it at 0%" thing would actually happen. ¬¬ |
10:23 | <@Raif> | We Americans (those of us with brains larger than a walnut) are also cynical. |
10:23 | <@Raif> | That happens when your leadership kicks you in the nuts for 30 years straight. |
10:23 | <@Reiver> | Well, Labour made them interest-free. They used to be pegged to the ... whatsit. Baseline reserve bank interest rate thingy. |
10:24 | <@Reiver> | Like a normal loan without the extra 'bank fee' on top. |
10:24 | <@Raif> | fun. |
10:24 | <@Reiver> | Interest-free was a big step. |
10:24 | <@Reiver> | Nationals was basically "We'll make your loan dissapear in X years without you paying a cent!". |
10:24 | <@Reiver> | No-one believed it would ever actually happen. >.> |
10:24 | <@Raif> | Yeah, but like I said, I don't see either one happening here. |
10:25 | <@Raif> | STudents in particular are taking it in the ass quite a bit lately. |
10:25 | <@Raif> | My policy on voting is "They're all crooks and the guy I wanted didn't make primaries." |
10:26 | <@Raif> | Therefore I don't vote. :) |
10:26 | | * Reiver nod. |
10:26 | <@Reiver> | NZ had a low turnout the last election. |
10:27 | <@Raif> | I can't imagine why. :P |
10:27 | | * Reiver coughs. |
10:27 | <@Reiver> | 80% of registered voters. |
10:27 | <@Reiver> | >.> |
10:27 | <@Raif> | Every election, the politicians and media complain about low turnout and what to do about it. |
10:27 | <@Raif> | The solution, they don't seem to realize, is to nominate somebody who isn't trying to fuck over 90% of the voting public. |
10:28 | <@Reiver> | (Being a restered voter involves being on the electoral roll [Legally compulsory] and eligable to vote.) |
10:28 | <@Raif> | I don't think we ever get 50% voter turnout anymore. |
10:28 | <@Reiver> | Mind you, they've made an immense effort to make it straightforward and easy. |
10:29 | <@Raif> | Hehehehe, yeah, we don't do that either. :) |
10:29 | <@Raif> | You've no doubt heard of Diebold. |
10:29 | <@Raif> | Invalidating an entire district is actually as easy as cutting a piece of tape |
10:29 | <@Reiver> | I just show up and give my name and hand over a card I got in the mail, get a sheet, take it to the booth, tick the boxes I want, stick in the box and fuck off. |
10:29 | <@Reiver> | Oh. And I get a sticker. ;) |
10:29 | <@Raif> | They're legally required to throw out data from machines that appear to be tampered with. Hee hee. |
10:30 | <@Reiver> | -.^ Genius. |
10:30 | <@Reiver> | Totally genius. |
10:30 | <@Reiver> | Yeah, ours are all-paper |
10:30 | <@Reiver> | Say what you will, but it's a bigger pain to defraud than a computer. :p |
10:30 | <@Raif> | Lots of machines here don't even print paper copies of the electronic votes. |
10:30 | <@jerith> | "So we're going to go tamper with the machines in *these* states and thus ensure that none of the opposition votes are counted." |
10:31 | <@jerith> | Seems like a winning strategy for me... |
10:31 | <@Reiver> | ...Although I do note that a lot of the bigger sites use OCR-esque tech to count the votes, IIRC. |
10:31 | <@Raif> | Meh. |
10:31 | <@Reiver> | (I may be wrong; I've only voted in the smaller ones.) |
10:32 | <@Raif> | I find the mention of politics depressing. Let's discuss the travails of emo kids instead. |
10:32 | | * jerith shoots the emo kids. |
10:32 | <@Reiver> | ...Also every vote paper has a serial number, and they track who voted in which station. The voting electorates have a phone-book-esque listinng of all eligable voters. They have to cross you off. |
10:32 | <@jerith> | What exactly is an emo kid? |
10:32 | <@Reiver> | Any suspicion of cheating, they can compare notes between different booths and find anyone who triplevoted. >.> |
10:32 | <@jerith> | Reiver: Sounds very similar to our system. |
10:33 | <@Raif> | http://www.urbandictionary.com/define.php?term=emo+kid |
10:33 | <@jerith> | Except they paint us with supposedly indelible ink stuff. |
10:33 | <@Reiver> | jerith: Old-fashioned, but at least it's moderately inconvinient to tamper with if the watchdogs are competent. >.> |
10:33 | <@Reiver> | heh |
10:33 | <@Reiver> | Not a bad idea, really. |
10:33 | <@jerith> | Some of it is gone the next day, some lasts weeks. |
10:34 | <@Raif> | Also: http://en.wikipedia.org/wiki/Emo_(slang) |
10:35 | <@jerith> | And they paint it over where your thumbnail starts. So there's bits on skin (generally comes off sooner sans tampering) and nail (can be scraped off with some effort, but otherwise has to grow out). |
10:35 | <@gnolam> | http://www.youtube.com/watch?v=1da7InQ69w4 |
10:37 | | * jerith goes to pick up his t-shirsts and bitch about 70% customs charges. |
10:37 | <@Raif> | 70%? |
10:37 | <@Raif> | Holy shit. |
10:38 | <@jerith> | Yes. |
10:38 | <@jerith> | $30 worth of clothing, R150.17 owed to customs, apparently. |
10:39 | | * AnnoDomini twitches at the spelling and capitalization (or lack thereof) in the Urban Dictionary definition. |
10:39 | <@jerith> | Why is it that so many of the people I enjoy talking to are at the more militant end of pedantry? |
10:40 | <@AnnoDomini> | Hm? |
10:40 | <@gnolam> | AnnoDomini: well, it /was/ apparently written by an emo. |
10:41 | <@AnnoDomini> | That's all well and good, but I don't really see what justifies the lacking use of language. |
10:41 | <@gnolam> | "Besides a mathematical inclination, an exceptionally good mastery of one's native tongue is the most vital asset of a competent programmer." |
10:43 | <@AnnoDomini> | Yes, yes, I think we are all familiar with that. |
10:45 | | Thaqui [~Thaqui@Nightstar-11312.jetstream.xtra.co.nz] has left #code [Leaving] |
10:47 | | Thaqui [~Thaqui@Nightstar-11312.jetstream.xtra.co.nz] has joined #code |
10:48 | | mode/#code [+o Thaqui] by ChanServ |
10:49 | <@Raif> | Anno: I just pasted the top two google links for "emo kid" |
10:50 | <@AnnoDomini> | I'm not attacking you. I'm attacking whoever wrote that definition. |
10:51 | <@AnnoDomini> | I am a case of Grammar Nazi, you know. :P |
10:54 | <@EvilDarkLord> | If someone has a good eye for fonts and feels like helping me out, would you take a look at the various images in http://www.terraquad.com/phpBB2/templates/extremedarkred/images/lang_english/ and tell me what it looks like? I am trying to replicate the look and feel for a forum, but I have no idea what the original font in that template was. |
10:56 | <@AnnoDomini> | Looks vaguely like Arial. |
10:57 | <@AnnoDomini> | Verdana. |
10:57 | <@Raif> | Sieg Heil, anno... |
10:57 | <@AnnoDomini> | :) |
10:58 | <@AnnoDomini> | EvilDarkLord: Try Verdana. |
11:06 | <@EvilDarkLord> | AnnoDomini: Cheers. I'll try. |
11:18 | | You're now known as TheWatcher |
11:43 | | Mahal is now known as MahalGone |
13:17 | | Thaqui [~Thaqui@Nightstar-11312.jetstream.xtra.co.nz] has left #code [Leaving] |
17:14 | | You're now known as TheWatcher[afk] |
17:28 | | Doctor_Nick [~fdsaf@Nightstar-27777.rag-a.fsu.edu] has joined #code |
17:42 | | * ToxicFrog works on an OO framework in which classes are themselves objects of type Class, and creating a new class is a matter of instantiating a Class |
18:16 | | You're now known as TheWatcher |
18:18 | | Reiver is now known as ReivSLEP |
18:26 | <@gnolam> | Sounds... smalltalky. |
18:27 | <@ToxicFrog> | Indeed. |
18:27 | <@McMartin> | Don't forget the Class.forName() factory. |
18:28 | <@ToxicFrog> | Class.forName()? |
18:28 | <@McMartin> | "Here is a string. Give me the Class corresponding to the class of that name." |
18:29 | <@ToxicFrog> | Aah. |
18:30 | <@ToxicFrog> | You kind of get that for free in Lua, barring environment wackiness: getfenv()[name] |
18:30 | <@ToxicFrog> | Or _G[name] if you know you're at global scope. |
18:30 | | * ToxicFrog ponders |
18:30 | <@ToxicFrog> | This could be convenient anyways, but how does it react when you have two classes with the same names in different scopes? |
18:31 | <@ToxicFrog> | Eg, I have io.File and resource.File; I ask it for "File". |
18:32 | | * ToxicFrog adds mixin support |
18:50 | <@ToxicFrog> | gnaaaaah |
18:50 | | * ToxicFrog 's head explodes |
19:14 | < MyCatSleeps> | ToxicFrog: have it punch a baby in the face. |
19:14 | <@ToxicFrog> | ... |
19:14 | < MyCatSleeps> | Reverse euphemism for, "raise an exception," of course. |
19:14 | <@McMartin> | Start in the current package, work your way out. |
19:15 | <@McMartin> | Allow imports. |
19:15 | < MyCatSleeps> | Mmmmjah. Innermost scope to outermost scope. |
19:15 | | MyCatSleeps is now known as MyCatVerbs |
19:15 | <@McMartin> | If neither is imported, if io.File and resource.File exist, and a class outside of io and resource requests "File" without importing, there is no such class. |
19:15 | < MyCatVerbs> | Perhaps you could do something fugly and Perlish in the case of ambiguity, such as having it assume the last-used namespace? |
19:17 | <@McMartin> | No, bad |
19:17 | <@McMartin> | You change the semantics of a line by inserting unrelated code before it |
19:17 | <@ToxicFrog> | ...er. Now we're down to Class keeping track of which scope each instance was created in. |
19:17 | < MyCatVerbs> | I did say fugly and Perlish. =) |
19:18 | < MyCatVerbs> | I think you ought to have it throw an exception if there's any ambiguity. Break early, break often. |
19:19 | <@McMartin> | MCV: Imports remove ambiguity. |
19:19 | <@McMartin> | And whichever package was imported last governs. If importing over a pre-existing thing in Strict mode it's a warning. |
19:19 | <@ToxicFrog> | The situation here I'm thinking of is this. |
19:20 | <@ToxicFrog> | In module io: File = Class(...) |
19:20 | <@ToxicFrog> | In module resource: File = Class(...) |
19:20 | <@ToxicFrog> | In program viewer: |
19:20 | <@ToxicFrog> | import 'io' |
19:20 | <@ToxicFrog> | import 'resource' |
19:20 | <@ToxicFrog> | foo = Class:byName("File") |
19:20 | < MyCatVerbs> | ToxicFrog: should resolve to resource. resource was the last-imported packaged. |
19:20 | <@ToxicFrog> | I do not actually plan to do anything like that, but it should have defined behaviour if someone does. |
19:20 | < MyCatVerbs> | *package |
19:21 | <@ToxicFrog> | MyCatVerbs: there's no way to check which was last imported without hacking the module subsystem, though. |
19:21 | < MyCatVerbs> | Also the compiler should scream "YARBLES!" and run a britva across your knuckles, while throwing a warning message because of the override. |
19:21 | <@ToxicFrog> | I can check which one is loaded, but if we take something like this: |
19:21 | <@ToxicFrog> | import 'io' -- io.File is defined |
19:22 | <@ToxicFrog> | import 'resource' -- resource.File is defined, and is now the default |
19:22 | <@ToxicFrog> | import 'io' -- no re-import or re-definition is done because it's already loaded, resource.File is still the default |
19:22 | < MyCatVerbs> | Oh, that is awkward. |
19:24 | < MyCatVerbs> | Can the module set some variable every time it is imported, irrelevant of whether it's been previously imported or not? |
19:24 | <@ToxicFrog> | No, because if it's already been imported no code is run. |
19:24 | <@ToxicFrog> | import() checks the imports table, sees that it's already imported and returns true. |
19:24 | < MyCatVerbs> | Eeek. Not even any effect on so much as a preprocessor? |
19:25 | <@ToxicFrog> | function import(module) |
19:25 | <@ToxicFrog> | if imports[module] then |
19:25 | <@ToxicFrog> | return imports[module] |
19:25 | <@ToxicFrog> | else |
19:25 | <@ToxicFrog> | imports[module] = assert(loadfile(module))() |
19:25 | <@ToxicFrog> | end |
19:25 | <@ToxicFrog> | return imports[module] |
19:26 | <@ToxicFrog> | end |
19:26 | <@ToxicFrog> | Simplified, but that's the gist of it. |
19:26 | <@ToxicFrog> | You can force it to reload a module by clearing the imports entry first, but this is ugly and hackish. |
19:27 | < MyCatVerbs> | .? Is this all at compile-time or run-time or...? |
19:27 | | AnnoDomini [~farkoff@Nightstar-29551.neoplus.adsl.tpnet.pl] has quit [Ping Timeout] |
19:27 | <@ToxicFrog> | ...runtime. It's an interpreted language. |
19:27 | | KBot [~karma.bot@Nightstar-29170.neoplus.adsl.tpnet.pl] has joined #Code |
19:28 | | AnnoDomini [~farkoff@Nightstar-29170.neoplus.adsl.tpnet.pl] has joined #Code |
19:28 | | mode/#code [+o AnnoDomini] by ChanServ |
19:28 | | KarmaBot [~karma.bot@Nightstar-29551.neoplus.adsl.tpnet.pl] has quit [Ping Timeout] |
19:28 | <@McMartin> | TF: I note your current behavior basically tracks python. |
19:28 | | KBot is now known as KarmaBot |
19:29 | <@McMartin> | With the possible exception that your system doesn't require imports to refer to packages by fully qualified name (maybe? unsure). |
19:29 | < MyCatVerbs> | ToxicFrog: is it possible to modify that import procedure to suit your own ends, or is that part of the 'terp and fixed for all time? |
19:29 | <@ToxicFrog> | McMartin: er. Imports are part of Lua, not part of my framework, so it's not "my system" |
19:29 | <@ToxicFrog> | MyCatVerbs: it is, but I kind want to avoid breaking every other piece of software in existence. |
19:30 | <@ToxicFrog> | McMartin: anyways. You can basically set up a path variable that it will search for imports in. |
19:30 | <@ToxicFrog> | So it will accept fully qualified names but does not require them. |
19:30 | <@ToxicFrog> | As for the stuff loaded by the import, it's allowed to put things into the global namespace. |
19:31 | <@McMartin> | Mm |
19:31 | <@McMartin> | A proper OO system shouldn't unless asked. |
19:31 | < MyCatVerbs> | ToxicFrog: but you could modify it in ways that affect your and only your own project. Like, every time a module is imported, add its name to a linked list of modules-imported-thus-far, every time it's re-imported shuffle it to the head of the list. |
19:31 | <@McMartin> | Have a purely-dynamic system for shoving things into global. |
19:31 | <@ToxicFrog> | Again, imports have nothing to do with the OO system, they're a preexisting part of the language. |
19:31 | | gnolam [lenin@Nightstar-13557.8.5.253.se.wasadata.net] has quit [Ping Timeout] |
19:31 | < MyCatVerbs> | ToxicFrog: then expose that list to the running Lua programs as something in the system namespace. |
19:32 | <@ToxicFrog> | And putting stuff in the global namespace is discouraged (and indeed SupComm implements a custom import() that prevents this) but not disallowed, because sometimes it is the right thing to do. |
19:32 | | gnolam [lenin@85.8.5.ns-20483] has joined #Code |
19:33 | | mode/#code [+o gnolam] by ChanServ |
19:33 | | * MyCatVerbs ono. |
19:34 | < MyCatVerbs> | All I can think of are adding a feature to import() which'd make this part of framework writing a little easier, throwing an exception or just writing that case up as undefined. |
19:35 | <@ToxicFrog> | Or I could just not have Class:byName() and trust the users to use Lua's built-in mechanisms for mapping strings to objects instead. |
19:38 | <@ToxicFrog> | (and/or subclass Class to implement their own variant) |
19:40 | < MyCatVerbs> | "And trust the users" <--- Apologies for quoting lwall, but the road to Hell is paved with melting snowballs. |
20:01 | | Doctor_Nick [~fdsaf@Nightstar-27777.rag-a.fsu.edu] has quit [Quit: ] |
20:11 | | gnolam [lenin@85.8.5.ns-20483] has quit [Quit: Driver borkage.] |
20:16 | | gnolam [lenin@Nightstar-13557.8.5.253.se.wasadata.net] has joined #Code |
20:16 | | mode/#code [+o gnolam] by ChanServ |
20:17 | | Derakon [~Derakon@Nightstar-12737.sea2.cablespeed.com] has joined #code |
20:18 | | mode/#code [+o Derakon] by ChanServ |
20:19 | <@Derakon> | Heh. |
20:22 | | Derakon is now known as Derakon[AFK] |
20:41 | | Derakon[AFK] is now known as Derakon |
20:46 | | X-SouL [~X-SouL@88.243.104.ns-22483] has joined #Code |
20:46 | | X-SouL [~X-SouL@88.243.104.ns-22483] has quit [Quit: ] |
20:47 | <@Derakon> | I wish table fields were automatically in-scope in Lua, so I wouldn't have to keep remembering to type "self." in front of my fields. |
20:47 | <@ToxicFrog> | setfenv() is your tiny god. |
20:47 | <@ToxicFrog> | I have an OO framework kicking around somewhere that does this, actually. |
20:48 | <@ToxicFrog> | But the short version is, given a function f that takes arguments (self, ...) and which you want to wrap so that self is in scope... |
20:49 | <@ToxicFrog> | Hmm. Actually, ok, it's not that short if you want it to interact with the object's metatable properly. |
20:50 | <@Derakon> | Heh. |
20:50 | <@ToxicFrog> | But the idea is, you create a table that overloads __index and __newindex to look in the object before looking in the current environment, then use setfenv() to apply that to the function. |
20:50 | | * Derakon nods. |
20:50 | <@Derakon> | You'd have to do that on a per-function basis? |
20:51 | <@ToxicFrog> | Yes, but you can automate the process, because yay function closures. |
20:51 | <@Derakon> | Aie closures! |
20:51 | | * Derakon runs screaming. |
20:51 | <@ToxicFrog> | for k,v in pairs(obj) if type(v) == function then obj[k] = wrap_fn(v) end |
20:55 | <@ToxicFrog> | function wrap_fn(f) |
20:55 | <@ToxicFrog> | local env = getfenv(f) |
20:55 | <@ToxicFrog> | local nenv = {} |
20:55 | <@ToxicFrog> | local mt = {} |
20:55 | <@ToxicFrog> | setmetatable(nenv, mt) |
20:55 | <@ToxicFrog> | return function(this, ...) |
20:55 | <@ToxicFrog> | local env = getfenv(2) |
20:55 | <@ToxicFrog> | local nenv = {} |
20:56 | <@ToxicFrog> | local mt = {} |
20:56 | <@ToxicFrog> | function mt:__index(key) |
20:56 | <@ToxicFrog> | local value = this[key] |
20:56 | <@ToxicFrog> | if value ~= nil then return value end |
20:56 | <@ToxicFrog> | return env[key] |
20:56 | <@ToxicFrog> | end |
20:56 | <@ToxicFrog> | function mt:__newindex(key) |
20:56 | <@ToxicFrog> | if this[key] then |
20:56 | <@ToxicFrog> | this[key] = value |
20:56 | <@ToxicFrog> | else |
20:56 | <@ToxicFrog> | env[key] = value |
20:56 | <@ToxicFrog> | end |
20:56 | <@ToxicFrog> | end |
20:56 | <@ToxicFrog> | setmetatable(nenv, mt) |
20:56 | <@ToxicFrog> | setfenv(f, env) |
20:56 | <@ToxicFrog> | return f() |
20:56 | <@ToxicFrog> | end |
20:56 | <@ToxicFrog> | end |
20:56 | <@ToxicFrog> | A quick, dirty, and entirely untested implementation, but that's the gist of it. |
20:56 | <@ToxicFrog> | If you don't need/want access to globals, you can do away with all the __index/__newindex trickery and just setfenv(f, this) |
20:56 | <@Derakon> | Yow. |
20:56 | <@ToxicFrog> | ...and that line just before the return should be "setfenv(f, nenv)" |
20:57 | <@Derakon> | What does getfenv(2) do? |
20:57 | <@ToxicFrog> | Most of that is to make sure that it behaves even if the object already has a metatable on it, and to ensure that you can still access globals. |
20:57 | <@ToxicFrog> | Returns the environment table of the function two stack levels up. |
20:58 | <@Derakon> | I'm fairly certain I understand what the __index and __newindex functions are doing. |
20:58 | <@Derakon> | O_o |
20:58 | <@ToxicFrog> | And, um. |
20:58 | <@ToxicFrog> | Those first four lines? local env through setmetatable? |
20:58 | <@ToxicFrog> | They shouldn't be there. |
20:58 | <@ToxicFrog> | I thought I deleted them. |
20:58 | <@Derakon> | Heh. |
20:58 | <@ToxicFrog> | And it should probably be getfenv(f), not getfenv(2)... |
20:58 | <@ToxicFrog> | Anyways. |
20:59 | <@Derakon> | Hah! I now have a block that the player can stand on (without constantly vibrating) and can walk off of (in which case they start falling)! |
20:59 | <@ToxicFrog> | This is all covered in more detail in the manual, but the idea is, each function has an associated environment. |
20:59 | <@ToxicFrog> | When the function asks for a global, the scope it's resolved in is the function's environment table. |
20:59 | <@Derakon> | I had to give the player a walking stick, but oh well. |
20:59 | <@Derakon> | Sounds like basically functions start with their default scope only being globals + arguments passed in. |
21:00 | <@ToxicFrog> | By default, the environment of a function is the environment of the function that declared it, and the environment of the top level is _G |
21:00 | <@Derakon> | And you're modifying their scopes. |
21:00 | <@ToxicFrog> | Yes. |
21:00 | <@ToxicFrog> | Well, default scope is locals, then arguments, then upvalues, then environment. |
21:00 | <@ToxicFrog> | And by default environment is _G, the set of globals. |
21:00 | | * Derakon nods. |
21:01 | <@ToxicFrog> | You can use getfenv() to retrieve the environment of a function, using either the function itself as the argument, or a stack level. |
21:01 | <@ToxicFrog> | And setfenv() to set a new one. |
21:01 | <@Derakon> | Man, there's a ton of stuff you can do with Lua... |
21:01 | <@ToxicFrog> | You can do these while inside a function, too. setfenv(1) sets the caller (of setfenv's) environment. |
21:01 | <@Derakon> | In some ways it reminds me of C, only with less memory-woe. |
21:01 | <@ToxicFrog> | setfenv(2) sets the environment of the caller of the caller of setfenv, and is key to my More Readable OO module. |
21:02 | <@ToxicFrog> | Which lets you do stuff like this: |
21:02 | <@ToxicFrog> | Subclass = Class(Superclass) |
21:02 | <@ToxicFrog> | member = value |
21:02 | <@ToxicFrog> | function method(self, foo, bar) ... end |
21:02 | <@ToxicFrog> | endclass() |
21:02 | <@Derakon> | Fun times. |
21:03 | <@ToxicFrog> | By twiddling function environments so that when you assign to member, you're assigning to the class definition table rather than to _G. |
21:03 | <@Derakon> | Link? |
21:03 | <@Derakon> | Er, wrong channel. |
21:03 | <@ToxicFrog> | So, yeah. Read up on it in the manual for all the fiddly details, but that's the basics. |
21:15 | <@Derakon> | Hrm...I think my walking-stick method won't actually work for the general case... |
21:15 | <@Derakon> | So, to spew onto the channel my thoughts. |
21:15 | <@Derakon> | The player is affected by gravity. Thus he falls, and when he lands on the ground, has his velocity reset and his position moved so that he is actually standing on the ground. |
21:16 | <@Derakon> | Now, we want to have the player have a "grounded" state, in which he is *not* affected by gravity, because otherwise he tends to jitter. |
21:16 | <@Derakon> | Also, it's useful to know when he's allowed to jump. |
21:16 | <@Derakon> | But when the player walks off of the ground, he needs to start falling again. |
21:16 | <@Derakon> | And what about when the player's standing on a slanted slope? |
21:17 | <@Derakon> | I had been using a walking stick - a 1-pixel dot that hovers below the player and lets him know when there's ground available, but then when the player reaches the edge of a cliff, the dot's off in space and the player starts jittering again. |
21:17 | <@Derakon> | The same would happen on a slope. |
21:21 | <@Derakon> | So what I really need here, I guess, is some way to keep the player smoothly in contact with the ground without depending on extra objects. |
21:21 | <@Derakon> | End of brain dump. |
21:31 | | AnnoDomini is now known as Yahir |
21:36 | | MahalGone is now known as Mahal |
21:39 | <@ToxicFrog> | I've done it! |
21:39 | <@Derakon> | Nandesca? |
21:39 | <@ToxicFrog> | It kind of hurts my brain, though; Class is both and object and a class at the same time. |
21:40 | <@Derakon> | If it hurts *your* brain, then it's likely to induce gibbering in *mine*. |
21:40 | | * Yahir curses his glass-related hand injuries. He was going to respond with, "Do you know what can change the nature of a man now? :P" |
21:40 | <@ToxicFrog> | OO in Lua (for the (?fifth) time), where classes are objects and new is the __call operator on them. |
21:40 | <@jerith> | Shown Them All, Especially Those Fools At The Institute? |
21:41 | | * jerith curses his lag. |
21:41 | <@ToxicFrog> | That is to say, to create a new class, you instantiate Class with certain properties; to create a new object of that type, you call the object. |
21:41 | <@ToxicFrog> | The object that was created from Class, that is. |
21:41 | | * jerith decides to stop cursing his lag and go to sleep. |
21:41 | <@ToxicFrog> | I'm not explaining this very well, I think. |
21:41 | <@ToxicFrog> | But it's Smalltalkish. |
21:42 | | gnolam [lenin@Nightstar-13557.8.5.253.se.wasadata.net] has quit [Ping Timeout] |
21:42 | <@ToxicFrog> | At first I thought that the fact that Class depends on Class.meta rather than Class.type.meta was a flaw, but then I realized that Class.type == Class, so it's all the same thing. |
21:50 | <@ToxicFrog> | Now I just need to implement instanceof, mixin, and a few other utility functions, then document and release it. |
21:59 | <@ToxicFrog> | (mixins: (a) overwrite existing behaviour, (b) skip existing behaviour, (c) throw an error when there's a conflict?) |
21:59 | | gnolam [lenin@Nightstar-13557.8.5.253.se.wasadata.net] has joined #Code |
21:59 | | mode/#code [+o gnolam] by ChanServ |
22:00 | <@McMartin> | ((d) need to die in fires) |
22:17 | | Chalcedon [Chalceon@Nightstar-1313.dialup.ihug.co.nz] has joined #code |
22:17 | | mode/#code [+o Chalcedon] by ChanServ |
22:18 | <@ToxicFrog> | McMartin: as far as I'm concerned, "copyable" and "sendable" are properties, not classes. |
22:21 | | Chalcy [Chalceon@Nightstar-5240.dialup.ihug.co.nz] has joined #code |
22:21 | | mode/#code [+o Chalcy] by ChanServ |
22:22 | | Chalcedon [Chalceon@Nightstar-1313.dialup.ihug.co.nz] has quit [Killed (NickServ (GHOST command used by Chalcy))] |
22:22 | | Chalcy is now known as Chalcedon |
22:23 | <@ToxicFrog> | McMartin: which makes it either mixins or multiple inheritance. |
22:24 | <@McMartin> | When you leave Simula semantics, these concepts get fuzzier. |
22:24 | < MyCatVerbs> | Interfaces? |
22:24 | | * jerith stabs interfaces. |
22:24 | <@ToxicFrog> | MyCatVerbs: Interfaces (1) are only signature, not implementation and (2) only make sense in a language with signatures. |
22:24 | <@McMartin> | Interfaces are a way to get multiple inheritance without the howling madness. |
22:26 | < MyCatVerbs> | ToxicFrog: oh. (1) isn't a problem in languages where the compiler won't accept a signature without an implementation, but that's not really an option for you, is it/ |
22:26 | <@ToxicFrog> | Well, it's in an issue in that that's not the behaviour I want. |
22:26 | <@ToxicFrog> | I mean, again, no signatures. Saying "this class should implement :Copy()" means dick. |
22:27 | <@ToxicFrog> | What I want to be able to do is say something like is(Copyable) and get a working Copy() method. |
22:27 | <@ToxicFrog> | Which, AIUI, is what mixins do. |
22:27 | < MyCatVerbs> | Ohhhh. |
22:28 | <@ToxicFrog> | Multiple inheritance is the other way to do this, but MI is full of spiders. |
22:28 | < MyCatVerbs> | So, like, if the class is(Copyable) but doesn't implement Copy() itself, then a default Copy() method is returned which just does memcpy()/memmove(), or if it *does* have an implementation then it returns that instead? |
22:29 | < MyCatVerbs> | 'Cuz that sounds like it'd be achievable with signatures and metaprogramming. |
22:30 | <@ToxicFrog> | Well, replace memcpy() and memmove() with stuff that's actually safe and works properly, but something along those lines. |
22:30 | <@ToxicFrog> | There. |
22:30 | <@ToxicFrog> | Are. |
22:30 | <@ToxicFrog> | No. |
22:30 | <@ToxicFrog> | Signatures!~ |
22:30 | <@ToxicFrog> | Go read the Lua manual. |
22:31 | < MyCatVerbs> | Can't be arsed. I thought you were implementing OOP on top of Lua and that Lua wasn't OO itself? |
22:31 | <@ToxicFrog> | Correct. |
22:32 | < MyCatVerbs> | And you cannot possibly do signatures in your own code, you need support for them in Lua itself? |
22:32 | <@ToxicFrog> | I can't do function signatures. I can do class signatures, but it's an assload of extra code which is of dubious utility and is trivial to circumvent. |
22:33 | <@ToxicFrog> | I'm not sure why you're so hung up on signatures. |
22:33 | <@Derakon> | It's the C/C++/Java Way. |
22:33 | < MyCatVerbs> | ToxicFrog: because it's all I know offhand. And it does solve the problem, or close enough. |
22:33 | <@ToxicFrog> | ...no, it doesn't. |
22:34 | < MyCatVerbs> | Sorry, would, if it wasn't apparently impossible in your language of choice. |
22:34 | <@ToxicFrog> | Even if it were possible it wouldn't solve the problem. |
22:34 | < MyCatVerbs> | Derakon: Haskell, too. ^^ |
22:34 | < MyCatVerbs> | Of course not. Your problems are all intractable and have never been solved and never will be. |
22:35 | <@Derakon> | Um, MCV... |
22:35 | <@McMartin> | Type signatures are completely pointless in a language with duck typing, MCV. |
22:35 | | * ToxicFrog smacks MCV |
22:35 | < MyCatVerbs> | Ehn? |
22:35 | < MyCatVerbs> | How can you have duck typing in a language without any OO? |
22:36 | <@Derakon> | I believe they're referring to the fundamental types - number, string, boolean, table, metatable. |
22:36 | <@McMartin> | TF is adding OO to Lua. |
22:36 | <@McMartin> | And his system uses duck typing, AIUI. |
22:37 | | * Derakon forgot function, and possibly some others. |
22:37 | <@ToxicFrog> | Furthermore, the signature says nothing about the implementation, and it's the implementation that's of interest here. As I said - mixins, not interfaces. |
22:37 | <@ToxicFrog> | Derakon: number, string, boolean, table, thread, function, userdata, and nil. |
22:37 | <@ToxicFrog> | Metatable is just a table used in a certain way. |
22:37 | <@Derakon> | Ahh, right. |
22:37 | <@Derakon> | I tend to ignore userdata because Lua can't really do much with it, AIUI. |
22:38 | <@ToxicFrog> | Not on its own, but userdata can be assigned metatables. |
22:38 | | Chalcedon [Chalceon@Nightstar-5240.dialup.ihug.co.nz] has quit [Quit: ] |
22:38 | <@ToxicFrog> | Give it __index and __newindex and you have something that can be interacted with like a table, but with completely user-defined semantics. |
22:38 | | * Derakon nods. |
22:38 | <@ToxicFrog> | This is the typical way to bind C structs and C++ classes to Lua. |
22:39 | <@ToxicFrog> | And in fact, one of my OO frameworks uses userdata as a proxy for the "real" object, which enables some cunning operator overload tricks not possible otherwise. |
22:40 | | * Derakon reads about mixins on Wikipedia. "Interesting..." |
22:40 | <@ToxicFrog> | McMartin: duck typing, but also provides instanceof for easy checking. |
22:41 | <@ToxicFrog> | Also, what do you have against mixins? |
22:41 | <@McMartin> | Basically, some complaints I have re: MI being full of spiders still hold even for Java interfaces. |
22:41 | <@McMartin> | Notably, if there's a name conflict, all Hell still breaks loose. |
22:42 | <@McMartin> | This objections also hold for mixins, but squared because of the default implementation provided. |
22:42 | <@ToxicFrog> | Name conflict in which sense? |
22:42 | <@ToxicFrog> | Member, method, class? |
22:42 | <@McMartin> | Method. |
22:42 | <@McMartin> | Nothing else exists in interfaces, etc. |
22:42 | <@McMartin> | It's only safe to use any of them when you have total control of the library in both directions, forever. |
22:43 | <@McMartin> | For something like Iterator, that tends to be OK. |
22:43 | <@McMartin> | But serializability is something I'd rather see in a rooted Object class if it's supposed to be that generic. |
22:44 | | * MyCatVerbs reads c2.com/wiki, blinks. |
22:45 | <@McMartin> | For adding semi-generic capabilities like widget event handlers and stuff I prefer the use of decorators and composites to mixins. |
22:45 | < MyCatVerbs> | Does CLOS have something along the lines of half of AspectJ's core features built in or something? |
22:45 | <@McMartin> | So I suppose you could say that my real beef is, in fact, with inheritance~ |
22:45 | <@ToxicFrog> | What are decorators and composites? |
22:45 | <@McMartin> | A composite is two objects with no actual direct relation other than that they are used in correlated ways. Often they are each fields of some other object, but this is not required. |
22:46 | <@McMartin> | MCV: And had them decades in advance, and they didn't come up with anything non-heinous to do with them outside of debugging then either. |
22:46 | <@McMartin> | TF: Decorators are one of several ways to do wrappers and I forget why they work better for widgets, but I seem to recall they do. |
22:47 | < MyCatVerbs> | McMartin: that'd explain Smug Lisper Syndrome, heh. |
22:47 | <@McMartin> | CLOS also has multimethods, which are full of spiders and kittens at the same time. |
22:47 | <@ToxicFrog> | Multimethods? |
22:47 | <@ToxicFrog> | (spiderkittens!) |
22:48 | | * Derakon snerks. |
22:48 | <@jerith> | They essentially allow you to declaratively wrap a function in another function. |
22:48 | <@McMartin> | Methods are selected based on the type of one of its arguments, usually called "self" or "this". |
22:48 | <@Derakon> | That sounds vaguely like function overloading. |
22:48 | <@McMartin> | A multimethod is selected based on the type of several arguments, and this is resolved at run time. |
22:48 | < MyCatVerbs> | McMartin: now you have me imagining what'd happen if Drowtales' authors all started using lysergic acid. |
22:48 | <@ToxicFrog> | Aah. Multiple dispatch. |
22:48 | <@McMartin> | Derakon: No, because overloading is resolved at compile time. This is a generalization of virtual dispatch. |
22:48 | <@jerith> | @foo\ndef(args): ... |
22:48 | <@Derakon> | Ah, okay. |
22:49 | <@McMartin> | TF: Quite so. The buzzword is "Visitors" for faking multiple dispatch with single. |
22:49 | | * McMartin has a convenient python framework for doing that with string manipulation and getattr. |
22:49 | <@jerith> | Is equivalent to a definition of the function (bar) followed by bar = foo(bar) |
22:50 | <@jerith> | Except @ can be followed by an expression that returns a function, so you can have wrapper generators as well. |
22:50 | <@jerith> | Very shiny, but should be used sparingly. |
22:51 | <@McMartin> | That pretty much sums up all of AOP. |
22:52 | <@McMartin> | Well, that and "The Principle of Maximum Surprise". |
22:52 | <@Derakon> | That sounds like an...interesting...principle. |
22:52 | < MyCatVerbs> | s/Maximum Surprise/Shiny Boobytraps/ |
22:52 | <@Vornicus-Latens> | of /maximum/ surprise? |
22:52 | | Mahal [~Mahal@Nightstar-763.worldnet.co.nz] has quit [Quit: time to get ready for work.] |
22:52 | <@McMartin> | MCV: The actual rule is minimum surprise. |
22:52 | <@Vornicus-Latens> | ...damn, I'd better read this backscroll |
22:52 | | Vornicus-Latens is now known as Vornicus |
22:52 | < MyCatVerbs> | McMartin: I know that. Maximum surprise is equivalent to shiny boobytraps, though. |
22:53 | <@McMartin> | You cannot understand an AOP program without a complete understanding of every chunk of code in the program and when it triggers |
22:53 | <@McMartin> | And the core control structure in AOP is COME FROM. |
22:53 | <@Derakon> | Ahh, INTERCAL. |
22:53 | < MyCatVerbs> | McMartin: like an overloaded function which does wildly different things based on whether the arguments are signed or unsigned integers, for great lulz? |
22:54 | <@McMartin> | The sane use of it is "Every time X happens, dump message Y to my log" |
22:54 | <@jerith> | McMartin: Decorators formalise wrappers (and some AOP principles) in a way that is actually sane. |
22:54 | <@McMartin> | And is implemented in a way that doesn't require (as decorators do) that the system have been sanely architected to begin with. |
22:54 | <@McMartin> | This is particularly important when the definition of "sanity" varies over time or by problem. |
22:54 | <@jerith> | Because you can see what decorators are applied next to the functions they're applied to. |
22:55 | <@McMartin> | OK |
22:55 | | * Derakon wanders off for gaming. Ta! |
22:55 | | Derakon is now known as Derakon[AFK] |
22:55 | | * McMartin never actually formally studied patterns, but picked up a few of the names as useful shorthands. |
22:55 | <@jerith> | Ah. We seem to be agreeing with each other very loudly. :-) |
22:55 | <@ToxicFrog> | Wait, so decorators are applied to functions, not types? |
22:55 | <@jerith> | Yes, functions. |
22:56 | <@McMartin> | ... that would be why it's handy for widgets. |
22:56 | <@jerith> | Although I believe there's a horrible, horrible hack that allows something like class decorators. |
22:56 | <@ToxicFrog> | Since my types are not functions - although one day I should write a program where they are - this is of limited utility to me. |
22:56 | <@McMartin> | You have a button class that handles button-ness, and then instead of subclassing it for 3dbutton you just decorate the renderer. |
22:56 | <@jerith> | By attaching a bunch of methods and variables at runtime. |
22:56 | <@McMartin> | Which also means you can do things like have it be 3d, bordered, and graphical without having to deal with MI. |
23:01 | | You're now known as TheWatcher[T-1] |
23:04 | | You're now known as TheWatcher[zZzZ] |
23:04 | | Yahir is now known as AnnoDomini |
23:56 | | * ToxicFrog gets instanceof working properly. |
23:56 | <@ToxicFrog> | > print(Class:instanceof(Class)) |
23:56 | <@ToxicFrog> | true |
23:57 | | * McMartin distims |
23:59 | | Raif [~corvusign@Admin.Nightstar.Net] has quit [Connection reset by peer] |
--- Log closed Sun Apr 15 00:00:53 2007 |