#gemrb@irc.freenode.net logs for 30 May 2010 (GMT)

Archive Today Yesterday Tomorrow
GemRB homepage

[02:09:34] --> Gekz_ has joined #GemRb
[02:38:44] <-- Maighstir has left IRC (Quit: Maighstir)
[03:47:36] <tomprince> I would love to move things like that. :)
[03:53:48] <tomprince> Avenger wouldn't like that, unless we can convince him to switch to cmake to generate project files.
[03:55:06] <tomprince> I actaully had that in mind when I was thinking of moving stuff around, but didn't want to suggest it.
[05:36:08] <Gekz_> fork and run
[05:36:10] <Gekz_> lol
[05:43:13] <tomprince> fuzzie: This grew out me playing around trying to refactor the gamescript stuff.
[05:43:43] <tomprince> What I'd like to do is get it to the point where I could tie into python with it.
[05:47:11] <tomprince> The entry points I see into the GameScript code seem to be: 'new GameScript
[05:49:41] <tomprince> ', EvaluateString, ExecuteString, GenerateAction. EvaluateAllBlocks.
[05:50:20] <tomprince> , Update.
[05:52:24] <tomprince> I think if we refactor the actions, GenerateAction and ExecuteString could be handled more directly.
[05:53:20] <tomprince> Update and EvaluateAllBlocks I think are reasonable for python bindings, (renamed RunScript and RunCutscene).
[05:54:13] <tomprince> The only tricky bit seems to me to be how to handle EvaluateString which is EvaluateTriggerString, which is used in PST stores.
[08:23:38] <fuzzie> obviously EvaluateAllBlocks is wrong, but that can be fixed inside the class
[08:30:09] <fuzzie> but define 'refactor the actions'
[08:30:46] <fuzzie> if you change the Action stuff so it's unlike the original engine, I think you gain the "responsible for fixing BGScript" hat too..
[08:30:50] <fuzzie> you probably don't want that
[08:31:16] --> Maighstir has joined #GemRb
[08:31:18] <fuzzie> but i don't know what you intend on that front.
[08:37:05] <fuzzie> your previous idea of wrapping the Action queue seemed reasonable, but what you said doesn't seem to make much sense in that context - why would you need to refactor the GameScript stuff at all for that?
[08:39:08] <-- Gekz has left IRC (Quit: This computer has gone to sleep)
[08:43:43] <fuzzie> Maighstir: it looks like mingw's gcc 4.5 might just be broken in various weird and wonderful ways, although that still doesn't explain why you didn't get the DLLs when you installed the relevantgcc
[08:48:57] <Maighstir> awesome, so I should roll back to 4.4.0?
[08:55:03] <fuzzie> well, i still don't know why you'd crash so early, so that is strange :(
[08:55:36] <fuzzie> if it was that badly broken, hello world ought to crash too
[08:55:42] <fuzzie> i wonder if we have a global constructor lurking for a string or something
[08:58:22] <fuzzie> or Holders at global level.
[08:58:24] * fuzzie tips tomprince.
[08:59:48] <fuzzie> don't think that's the problem though, but who knows.:|
[09:00:58] <Maighstir> relevantgcc? perhaps I know that one under another name, but I haven't heard that term before... those dll's are not in "GemRB dependencies for mingw (dlls)" fom sourceforge, and that's all I needed to run with gcc 3.4.0.
[09:01:31] <Maighstir> s/fom/from/
[09:09:12] <fuzzie> sorry, i mean, 'relevant gcc'
[09:11:02] <fuzzie> i think somewhere in gcc 4.x they stopped linking the whole C++ library into each binary, hence why you need the seperate DLLs, but they're specific to the library version you compiled against
[09:11:20] <fuzzie> well, i should say, somewhere in mingw's version
[09:11:25] <fuzzie> i'll try looking into it further
[09:11:29] <fuzzie> but not right now
[09:12:00] <fuzzie> i am free of petri nets but need to memorise exciting things like cook-levin instead
[09:14:23] <Maighstir> "installed" is probably the wrong word, I just took a bunch of zip files and extracted them into C:\MinGW, and C:\Mingw\bin isn't normally in my path, it's only added when I run the bat file to set up the build environment... now I know I need it though
[09:15:36] --> budlust has joined #GemRb
[09:24:57] --> Gekz has joined #GemRb
[09:48:32] <-- Gekz has left IRC (Quit: This computer has gone to sleep)
[10:02:52] --> cubathy has joined #GemRb
[10:13:25] --> Gekz has joined #GemRb
[10:20:05] <-- cubathy has left IRC (Ping timeout: 240 seconds)
[10:21:37] --> cubathy has joined #GemRb
[11:39:58] <-- Gekz has left IRC (Ping timeout: 260 seconds)
[11:44:21] --> Gekz has joined #GemRb
[13:08:41] <-- budlust has left IRC (Ping timeout: 240 seconds)
[13:38:55] --> kettuz has joined #GemRb
[13:59:33] <tomprince> Maighstir: One thing you could try is dropping the dlls it complains about in the same dir as gemrb.
[13:59:50] <tomprince> There may be a better solution. I'll play around with it a bit latter.
[14:00:41] <tomprince> I think the issue might be that windows doesn't have the equivalent of LD_LIBRARY_PATH or ld.so.conf, it just uses PATH instead, as well as system32?
[14:00:44] <tomprince> Maybe?
[14:01:07] <tomprince> fuzzie:
[14:01:50] <fuzzie> the dlls aren't the problewm
[14:01:54] <fuzzie> it's crashing on startup
[14:02:00] <fuzzie> before it gets to main()
[14:02:10] <fuzzie> which is why i was wondering about global constructors or mismatched dll versions
[14:02:19] <tomprince> What I was refereing to explictitly with factoring the actions, is splitting off the relveant bits of functionallity we need, so we can call it directly, rather than constructing the string, and parsing.
[14:02:45] <fuzzie> EvaluateString is used in dialogs, no?
[14:02:50] <tomprince> I still think it might be dlls, and rember a similiar crash due to a missing libsdl.
[14:02:58] <tomprince> Maybe.
[14:03:02] <tomprince> Haven't looked yet.
[14:03:10] <tomprince> But it seems we also use it elsewhere.
[14:03:14] <fuzzie> i mean, 'EvaluateString is used in dialogs, so you still have to parse strings'
[14:03:22] <fuzzie> we just use it elsewhere because we're lazy i think
[14:04:23] <fuzzie> i mean, GenerateAction
[14:04:50] <tomprince> And more generally, I was thinking about factoring in the same way that I want to factor GUIScript. So that the actions just deal with marshalling the paramater. I think a lot of them are, anyway.
[14:04:58] <fuzzie> would be much better done with something that took a name andparameters
[14:05:18] <fuzzie> well, i mean, all the important actions do work
[14:05:30] <fuzzie> eg, the combat actions do all the combat checks/rolls/damage inside
[14:06:14] <fuzzie> if you want to change that, you are pretty much volunteering to fix the rest of the BGScript bugs
[14:06:49] <tomprince> Well, my vague thought is that it might just call some function to do that.
[14:07:07] <fuzzie> well, that is what GSUtils is intended for
[14:07:19] <tomprince> Ah.
[14:07:31] <fuzzie> there's no significant non-marshalling code in Actions.cpp/Triggers.cpp themselves, i hope?
[14:07:36] <fuzzie> i don't know what you're thinking of in particular
[14:07:55] <tomprince> I don't know, I haven't looked closely at the code yet.
[14:08:08] <tomprince> This is just me brainstorming.
[14:08:22] <fuzzie> but this is why i suggested that a better first step might be to split GSUtils.cpp
[14:08:29] <tomprince> And explaing where I'd *eventually* like to end up. Maybe.
[14:08:31] <fuzzie> i was working on that, but it doesn't look like i'll actually get it done
[14:09:01] * tomprince goes for breakfast
[14:09:46] <fuzzie> and, well, i am revising for exams, so as just brainstorming as avoidance :)
[14:09:49] <fuzzie> also just.
[14:33:37] <-- cubathy has left IRC (Quit: Leaving)
[15:27:58] <tomprince_loki> Any reason we shouldn't compile triggers and actions on load, rather than on execute?
[15:35:41] <tomprince_loki> Related question: Any reason Dialog::EvaluateDialogTrigger always evaluates all triggers in an OR block?
[15:45:22] --> cubathy has joined #GemRb
[15:47:36] <fuzzie> it isn't meant to?
[15:48:16] <fuzzie> i mean, i didn't look at the code, but i know that things rely on oddnesses of OR, i just forget what they are
[15:48:48] <tomprince_loki> I don't know. All I know is that Dialogs *do* evaluate all conditions and scripts *don't*.
[15:49:05] <fuzzie> i think scripts do in some circumstances too, we just don't handle it
[15:49:38] <tomprince_loki> My question was really whether we can use the same code to do both.
[15:50:05] <-- cubathy has left IRC (Remote host closed the connection)
[15:50:20] <fuzzie> it's another "I don't know, but please don't refactor this in a way which doesn't let us change it!" answer, I think
[15:51:20] * tomprince_loki shakes fist at crazy inconsistencies in the original engine.
[15:51:59] <fuzzie> it is always a lot less painful to just write a new engine than to reimplement an old one, for these reasons :|
[15:52:32] <wjp> especially an engine which has been used in multiple games, each iterations resulting in more hacks bolted on to it... :/
[15:52:52] <tomprince_loki> And probably time pressure on each, leading to more hacks.
[15:53:47] <fuzzie> PS:T in particular is a very obvious example of that
[15:53:59] <fuzzie> they took the bg1 engine and they just hard-coded all their new functionality
[15:54:18] <-- Gekz has left IRC (Ping timeout: 260 seconds)
[15:54:25] <fuzzie> script doesn't work properly? add a hack which reaches into the actions!
[15:55:21] <-- Gekz_ has left IRC (Quit: Leaving)
[15:55:23] <fuzzie> and the original devs have commented that it was really because it was a race to finish it before they all got fired
[15:56:10] <fuzzie> but i think bg2 has *less* hacks than bg1, plus it has a lot of things (eg, projectiles) moved out of hard-coded engine code and into files
[15:56:24] <fuzzie> i think the usual refrain is to blame Black Isle :)
[15:57:47] <fuzzie> tomprince: i don't see anything on the forums about weird OR behaviour in dialogs, which makes me suspicious
[15:58:32] --> cubathy has joined #GemRb
[15:58:45] <tomprince_loki> My hope is/was that that the difference in our code is simply a result of the code being in two places.
[15:59:43] <fuzzie> I think that is the case.
[16:01:17] <fuzzie> There was a discussion about this somewhere, but "or" is impossible to Google for.
[16:01:50] <fuzzie> But judging by svn history it's simply a bug.
[16:04:09] <fuzzie> oh, except that now i look at the code, i don't understand
[16:10:07] <-- cubathy has left IRC (Read error: Connection reset by peer)
[16:13:30] <fuzzie> i can't find anything. maybe ask devSin or Avenger
[16:13:50] <fuzzie> but i don't think it's likely that it's anything but a bug
[16:14:00] <fuzzie> and now i spent too long on that, dinnertime
[16:19:13] --> cubathy has joined #GemRb
[16:24:36] <Lightkey> you guys are so talkie-talkie lately -.-
[16:25:15] <-- cubathy has left IRC (Remote host closed the connection)
[16:25:41] <tomprince_loki> ?
[16:30:57] --> cubathy has joined #GemRb
[16:33:17] --> raevol has joined #GemRb
[16:43:30] <-- cubathy has left IRC (Remote host closed the connection)
[16:43:43] <Maighstir> tomprince: re: One thing you could try... That I did, then it said "pah, fat chance! I wuz just foolin' yoo. No gem-arr-bee for you."... or more accurately: "The application was unable to start correctly (0xc0000005).", then it quits, it opens a console window, but doesn't get the chance to start a log.
[16:46:45] --> cubathy has joined #GemRb
[16:47:19] <tomprince_loki> Are sdl and openal, and anyother dll we are compiling against there too? I am not actually familiar with windows, so that is just a shot in the dark.
[16:48:11] <tomprince_loki> It is too nice of a day for me to be indoors where my machine with my windows VM is for me to play around with. I'll try and get a chance to play around with tonight.
[16:48:54] <Maighstir> yup
[16:49:01] <Maighstir> they're there
[16:50:33] <tomprince_loki> No idea then.
[16:56:11] --> _pickle has joined #GemRb
[16:56:46] <-- raevol has left IRC (Quit: Leaving.)
[17:01:03] <Maighstir> I don't know if there's been any changes since my last build, but here's the binaries I've been trying to run last: http://ops-area.net/annat/GemRB/GemRB_Git.zip
[17:04:45] <Maighstir> CIA-24 hasn't said anything about changes since then, so I assume there hasn't been any
[17:12:13] <fuzzie> those are the gcc 4.5 versions, and those binaries start under wine here
[17:15:17] <fuzzie> you need to delete that old ZLibMgr.dll
[17:15:54] <fuzzie> and then it fails for me because that python26.dll needs stuff i don't have installed
[17:18:17] <fuzzie> (specifically, the vc++9 runtime libs)
[18:31:16] <tomprince_loki> is the cannary stuff actually usefull?
[18:34:14] <fuzzie> well, if you're manually implementing a hash table, yes..
[18:34:41] <fuzzie> or do i misunderstand?
[18:39:02] --> lynxlynxlynx has joined #GemRb
[18:39:02] --- ChanServ gives channel operator status to lynxlynxlynx
[18:41:18] <tomprince_loki> All the stuff in GameScript.h
[18:42:29] <tomprince_loki> There is no canary stuff in the manual hash tables.
[18:43:50] <fuzzie> Variables.cpp: pAssoc->Value.nValue = 0xcccccccc; //invalid value
[18:43:50] <fuzzie> Variables.cpp: pAssoc->nHashValue = 0xcccccccc; //invalid value
[18:43:54] <fuzzie> ^- this is a canary, no?
[18:44:41] <fuzzie> the canary stuff in GameScript needs to be replaced with a smart_ptr, i guess
[18:44:58] <fuzzie> i don't have your Holder in this tree, but it'll work?
[18:46:02] <tomprince_loki> Oh, is that what that is for ... yes it will.
[18:50:43] <fuzzie> (i wish it were a nice day here!)
[19:17:45] <Maighstir> VC++9 runtime, you say? You think my uninstalling VS2008 and installing 2010 may have messed that up? I'll reinstall the runtime
[19:22:52] <fuzzie> did you try removing the ZLibMgr.dll?
[19:23:00] <Maighstir> yes, no change
[19:23:28] <fuzzie> really strange
[19:49:39] <Maighstir> reinstalling the VC++ runtime didn't help either
[20:51:13] <lynxlynxlynx> for some reason, combat not visible to the party has no effect
[20:52:44] <fuzzie> but the combat happens?
[20:52:47] <lynxlynxlynx> i've narrowed it down a bit: the attack projectile gets created, but the damage effect is never hit
[20:52:53] <lynxlynxlynx> yes
[20:53:09] <fuzzie> i was about to say, the projectile updates are in Map::Draw, i think
[20:53:36] <fuzzie> i complained about this before :)
[20:54:04] <fuzzie> i suggest moving it into UpdateScripts()
[20:54:45] <lynxlynxlynx> that's where i stopped due to the big loop
[20:54:54] <lynxlynxlynx> you think that would be enough?
[20:55:06] <tomprince_loki> I seem to recall my archers killing everything in or out of sight. Unless something changed there.
[20:55:35] <lynxlynxlynx> that's the visibility bug
[20:55:42] <lynxlynxlynx> this one is just about non-pc allies
[20:56:00] <lynxlynxlynx> i've turned half the tomb to do my bidding :)
[20:56:24] <fuzzie> hmm, maybe that is not it, surely the version in Draw() should get called anyway
[20:57:47] <fuzzie> assuming this is the same area
[20:58:01] <lynxlynxlynx> yes
[20:58:02] <tomprince_loki> Is the iedsp forum on gibberlings3 where I should be asking about or()?
[20:58:15] <lynxlynxlynx> yep
[20:58:32] <fuzzie> that is where i'd do it
[21:00:18] <lynxlynxlynx> it's not getting deleted in DrawMap
[21:00:41] <fuzzie> but it is being updated?
[21:01:39] <lynxlynxlynx> nope, Map.cpp:1069 is not hit either
[21:01:52] <lynxlynxlynx> so that's a nice trail
[21:02:06] <fuzzie> but AddProjectile really gets called?
[21:02:50] <lynxlynxlynx> projectiles is empty, so no
[21:03:15] <fuzzie> where did you add the creation check?
[21:04:11] <lynxlynxlynx> i haven't, it is in useitem, but it is not added immediately due to timing
[21:04:13] <lynxlynxlynx> i guess
[21:04:40] <lynxlynxlynx> i'll check where attackProjectile is used
[21:05:05] <lynxlynxlynx> oh
[21:05:21] <fuzzie> hehe
[21:05:25] <fuzzie> i guess that was predictable :-)
[21:05:45] <lynxlynxlynx> it's Actor::Draw, not Map::DrawMap
[21:05:52] <fuzzie> that "let us assume not, for now.." is the problem
[21:06:28] <fuzzie> maybe
[21:07:30] <fuzzie> that's a difficult one :|
[21:09:49] <lynxlynxlynx> let's see
[21:13:08] <lynxlynxlynx> just adding !attackProjectile as another condition didn't help
[21:13:30] <lynxlynxlynx> but i need to recheck, maybe i forgot to rebuild
[21:13:41] <lynxlynxlynx> nope
[21:14:02] <fuzzie> the function doesn't get called, afaik, due to the checks in DrawMap
[21:14:37] <fuzzie> maybe we can get rid of a lot of that, though
[21:14:56] <fuzzie> the deactivation stuff is based on a misunderstanding about how it was meant to work
[21:17:02] <lynxlynxlynx> sounds dangerous
[21:17:49] <fuzzie> well, it has to be done sometime
[21:18:43] <tomprince_loki> Any oposition to using containers instead of arrays in GameScript.h? We actually already do when reading, and then copy to an array.
[21:19:16] <tomprince_loki> Also, moving GameScript::(Execute|Evalutate)* to *::(Execute|Evaluate)
[21:19:58] <fuzzie> for 'triggers' and 'actions'?
[21:20:12] <fuzzie> and 'responses' and 'responseBlocks', i guess
[21:20:14] <tomprince_loki> and response and response set, yes.
[21:20:18] <tomprince_loki> :)
[21:21:11] <fuzzie> i'm not really so convinced about turning those from what are basically structs into classes
[21:21:36] <fuzzie> do you have what you've done so far somewhere?
[21:21:43] <tomprince_loki> or.cz/gs2
[21:23:18] <lynxlynxlynx> fuzzie: sure, but I don't feel confident enough to tackle it
[21:23:29] <tomprince_loki> Untested.
[21:23:29] <fuzzie> well, i don't really like the deque
[21:23:46] <tomprince_loki> I can change it to vector.
[21:23:54] <tomprince_loki> But any reason you don't like the deque?
[21:24:18] <fuzzie> well, it seems a hack in a data structure to compensate for the loading code
[21:24:25] <fuzzie> that is all, though
[21:26:44] <fuzzie> it would also be nicer, as usual, if you didn't move code into a new file and change the code in the same commit :)
[21:27:18] <fuzzie> i can't check the diff for that one for that reason, but otherwise it all looks perfectly sane, although i hope you're planning to move the other stuff out to a seperate header if you're moving one thing?
[21:27:20] <tomprince_loki> Yes, well the actions commit does need to be cleaned up.
[21:27:44] <fuzzie> but it does seem like GameScript can basically go away
[21:27:57] <tomprince_loki> I wasn't planning on applying the Holder commits yet, just the other.
[21:28:16] <tomprince_loki> The action one is a bit more intrusive than I would have liked.
[21:28:53] <fuzzie> why the 'acquire()' calls in that one?
[21:29:10] <fuzzie> or acquire() call, even
[21:29:39] <tomprince_loki> That should maybe go away. I didn't look to closely at that commit.
[21:29:57] <tomprince_loki> Mostly I was using the compiler to tell me what need to change.
[21:29:58] <fuzzie> ok. sorry, just honestly curious
[21:30:01] <fuzzie> hehe :)
[21:30:34] <fuzzie> assigning pointers to smart_ptrs like that makes my internal good programmer voice shout at me, too
[21:30:53] <tomprince_loki> I think it actually can just go away.
[21:31:22] <tomprince_loki> Yes, mine too. That is why my original holder impl didn't include a Holder(T*) constructor.
[21:32:01] <tomprince_loki> But I didn't want to be to intrusive with all my smart pointer stuff ....
[21:32:34] <fuzzie> i think at this point it is probably worth the intrusiveness
[21:32:41] <-- kettuz has left IRC (Quit: Leaving)
[21:32:55] <fuzzie> it would maybe be nice if some of this could be typedeffed? the Holder<blah> everywhere is not really very easy to read, but i guess it does make it clear what's going on
[21:33:20] <tomprince_loki> I was actually wondering if I should do s/Holder/ptr/
[21:34:28] <tomprince_loki> Beyond that, I am not sure what one should typedef as what? 'typedef Holder<T> pT;' ptr<T> is probably about as concise, and clearer?
[21:35:03] <tomprince_loki> I was just planning on applying up to e46abb20e6bc8d4cee44ed592989f045000ef3b7 for now.
[21:35:04] <fuzzie> i would be worried that 'ptr' would conflict with system definitions
[21:35:52] <tomprince_loki> The reason I picked deque over vector (which is effectively what we had, since we had count+array, but without the niceities) is http://www.gotw.ca/gotw/054.htm
[21:36:08] * tomprince_loki goes to supper.
[21:36:12] <tomprince_loki> Back in a bit.
[21:36:31] <fuzzie> sure, my objection is just that the vectors in the data structures are constant
[21:37:28] <fuzzie> but it is purely the the-right-data-structures-for-the-right-task voice
[22:09:39] <-- lynxlynxlynx has left IRC (Remote host closed the connection)
[22:22:50] <tomprince_loki> I certainly agree with the right data struct for the task.
[22:23:32] <fuzzie> i would just commit it :-)
[22:26:00] <tomprince_loki> I am curious why you think it isn't the right data struct.
[22:27:48] <fuzzie> well, because a vector is pretty much the optimal data structure for a static small array
[22:28:09] <fuzzie> and a deque is optimised for large and/or oft-modified use cases :)
[22:29:20] --> Gekz has joined #GemRb
[22:47:30] <-- Gekz has left IRC (Changing host)
[22:47:30] --> Gekz has joined #GemRb
[23:03:33] --> budlust has joined #GemRb
[23:14:39] <-- Gekz has left IRC (Quit: This computer has gone to sleep)
[23:33:32] <CIA-24> GemRB: 03tom.prince * rb249ee7c9626 10gemrb/gemrb/core/ (GameScript.cpp GameScript.h):
[23:33:32] <CIA-24> GemRB: GameScript: Store triggers in a vector.
[23:33:32] <CIA-24> GemRB: Signed-off-by: Tom Prince <tom.prince@ualberta.net>
[23:33:34] <CIA-24> GemRB: 03tom.prince * r53046f83be0c 10gemrb/gemrb/core/ (GameScript.cpp GameScript.h):
[23:33:34] <CIA-24> GemRB: GameScript: Move Trigger/Condition evaluation into those classes.
[23:33:34] <CIA-24> GemRB: Signed-off-by: Tom Prince <tom.prince@ualberta.net>
[23:33:37] <CIA-24> GemRB: 03tom.prince * r4d0eb142f5f7 10gemrb/gemrb/core/ (GameScript.cpp GameScript.h):
[23:33:37] <CIA-24> GemRB: GameScript: Change Response and ResponseSet to vector/::Execute.
[23:33:37] <CIA-24> GemRB: Signed-off-by: Tom Prince <tom.prince@ualberta.net>
[23:33:39] <CIA-24> GemRB: 03tom.prince * r9c6ba6a2dd35 10gemrb/gemrb/core/ (GameScript.cpp GameScript.h): GameScript: Add another deque.
[23:41:15] <fuzzie> tomprince_loki: you know i really *am* just braindumping in here? you've proven yourself to be more than capable of refactoring the code, i really apologise if you feel you have to change things like the deque, i truly don't intend it that way
[23:43:00] <CIA-24> GemRB: 03tom.prince * r7f9e947132bb 10gemrb/gemrb/core/GameScript.h: Fix stupid typo.
[23:43:55] <tomprince_loki> No, i went and looked a the code with gcc-4.5.0, and convinced myself that vector was better here.
[23:44:56] <tomprince_loki> If we switched to holding objects, rather than pointers, which might make sense for some of them, I would revisit that decision.
[23:45:39] <tomprince_loki> The minimum size of a deque of pointers on 64bit is 64...
[23:46:24] <tomprince_loki> I suspect that most of those won't approach that size.
[23:48:12] <tomprince_loki> I may have proven that I am capable of refactoring code, but you have proven to have valuable insights on cod design.
[23:48:35] <tomprince_loki> s/cod/code/
[23:49:18] <tomprince_loki> I really don't know anything about the design of fish. :)