--- Log opened Fri Jan 16 00:00:38 2009 |
00:03 | | Vornicus [~vorn@Admin.Nightstar.Net] has quit [Ping Timeout] |
00:03 | | Vornicus [~vorn@Admin.Nightstar.Net] has joined #code |
00:03 | | mode/#code [+o Vornicus] by ChanServ |
00:08 | | You're now known as TheWatcher[T-2] |
00:09 | <@ToxicFrog> | gnolam: holy shit, where? |
00:11 | <@gnolam> | http://www.gigabyte.com.tw/Products/VGA/Products_Overview.aspx?ProductID=2900 <- enjoy the Engrish ;) |
00:12 | <@gnolam> | (But the model number is all that matters anyway) |
00:13 | <@gnolam> | One one hand, I've vowed not to buy ATI again. On the other hand, I'm a noise freak. :-/ |
00:13 | <@gnolam> | s/One/On |
00:14 | | You're now known as TheWatcher[zZzZ] |
00:14 | <@ToxicFrog> | Using "multi-core" to refer to their cooling system is kind of aggravating given that there now exist multicore video cards. |
00:14 | | crem_ [~moo@Nightstar-28703.adsl.mgts.by] has joined #code |
00:15 | | crem [~moo@Nightstar-28703.adsl.mgts.by] has quit [Connection reset by peer] |
00:47 | | C_tiger_remote is now known as C_tiger |
00:55 | | Derakon [~Derakon@Nightstar-4920.hsd1.ca.comcast.net] has joined #code |
00:55 | | mode/#code [+o Derakon] by ChanServ |
01:01 | | Attilla [~The.Attil@Nightstar-9469.cdif.cable.ntl.com] has quit [Quit: <Insert Humorous and/or serious exit message here>] |
01:10 | <@Derakon> | Okay, I'm working on splitting up bulletml.py into multiple files, since it's just too damned big. |
01:11 | <@Derakon> | Right now I have bulletml.py, bml.py (for objects actually related to parsing and handling BulletML files), and util.py (logging, display, text, etc.). |
01:11 | <@Derakon> | I have a global singleton GameManager instance that I need to be able to reference from bml.py even though it's instantiated in bulletml.py. |
01:11 | <@Derakon> | How do I do this? |
01:45 | | C_tiger [~cheng@Nightstar-5625.hsd1.ca.comcast.net] has quit [Operation timed out] |
01:52 | | gnolam [lenin@Nightstar-1382.A163.priv.bahnhof.se] has quit [Quit: Z?] |
01:59 | | C_tiger_remote [~cheng@Nightstar-5625.hsd1.ca.comcast.net] has joined #code |
01:59 | | mode/#code [+o C_tiger_remote] by ChanServ |
01:59 | | C_tiger_remote is now known as C_tiger |
02:28 | <@Derakon> | So for example, I have bulletml.py, which initializes the gameManager variable. And I have bml.py, which needs access to that variable. |
02:28 | <@Derakon> | Having the two files import each other causes problems. |
02:28 | <@ToxicFrog> | Take note: Opera Dragonfly is awesome. |
02:30 | <@Derakon> | It seems like I have an explicit circular dependency here. How do I solve this? |
02:31 | <@ToxicFrog> | Ummmm |
02:31 | <@ToxicFrog> | Initialize it in bulletml.py before importing bml.py? |
02:31 | <@ToxicFrog> | Alternately, if bml.py doesn't need to access it in initialization, make sure bulletml.py defines it before anything provided by bml.py is used? |
02:33 | <@Derakon> | gameManager is initialized/defined right after I've finished initializing pygame and setting some constants. |
02:33 | <@Derakon> | But it's an instance of a class that is defined in bulletml.py. Hrm. |
02:33 | <@Derakon> | I find myself wanting headers. Or at least multipass interpreters. |
02:35 | <@Derakon> | I can't initialize GameManager before importing bml.py because GameManager has a dependency on bml.py |
02:36 | <@Derakon> | I can't import bml.py before initializing the GameManager because bml.py needs to be able to refer to the instance variable gameManager. |
02:36 | <@Derakon> | Doesn't Python have a "Just trust me on this, it'll be ready by the time this code runs" mode or something? |
02:37 | <@MyCatVerbs> | Derakon: if you have a circular dependency, it's often a sign that two things you thought were seperate are actually one and the same. |
02:37 | <@Vornicus> | This seems very smelly to me. |
02:37 | <@Vornicus> | In much the same direction that MCV thinks it seems smelly. |
02:38 | <@Vornicus> | That, and you seem to be misusing global variables. |
02:38 | <@Derakon> | This would be trivial in C/C++ with headers. |
02:38 | <@MyCatVerbs> | Derakon: also, Python is pretty laissez-faire. If you don't run any of the methods in bml.py that make use of GameManager until after GameManager has been created, then it'll be fine. |
02:38 | <@Derakon> | Okay, look. GameManager, when instantiated, itself instantiates an Emitter. The Emitter needs to be able to instantiate ActionFuncs, BulletFuncs, etc. There's my dependency on bml.py |
02:39 | <@MyCatVerbs> | Derakon: and also you appear to be a) using a global variable and b) unaware of just how many levels that is unnecessary and also a bad idea upon. |
02:39 | <@Derakon> | WTF, globals are not universally bad. |
02:39 | <@MyCatVerbs> | Yes they are. ^_^ |
02:39 | <@Derakon> | You don't want me to dismiss you out of hand as a cargo cult programmer, do you? |
02:39 | <@Vornicus> | No, they're not. But you seem to be misusing them in this case. |
02:40 | <@Derakon> | The alternative to making gameManager global is to pass it down through every single damn update function just in case I want to be able to create bullets. |
02:40 | <@Derakon> | Misusing how? |
02:40 | <@MyCatVerbs> | Feel free to. But the set of problems for which global variables are actually a good idea is rather smaller than you seem to think it is. |
02:41 | <@Derakon> | See http://en.wikipedia.org/wiki/Singleton_pattern, MCV. You appear to be one of the people who think it is an anti-pattern. |
02:41 | <@MyCatVerbs> | Derakon: possibly. Or attach those methods to an object which has a reference to the current game manager, which seems a bit more like natural OO style to my way of stinking. |
02:42 | <@Derakon> | ...how is "an object that has a reference to the current game manager" different from "an object that is the current game manager"? |
02:42 | <@Vornicus> | You seem to be setting up the global variable in a way that requires initialization, without explicitly initializing it first. This is bad, and one of the reasons global variables are bad: you have to explicitly initialize them, and if there isn't an easy way to do it, you're screwing yourself over. |
02:42 | <@MyCatVerbs> | Derakon: it isn't. Why would you even ask that question? |
02:42 | <@Derakon> | Because the latter is what I'm doing. |
02:42 | <@Derakon> | Or trying to, at any rate. |
02:43 | <@Vornicus> | However, you also appear to have way too much coupling - why does bulletml need to know about the gamemanager? |
02:43 | <@Derakon> | bulletml is the main script, including the main loop. |
02:43 | <@Derakon> | It needs to know about the game manager so it can call the main update and draw functions. |
02:44 | <@Vornicus> | Why is bulletml calling update and draw? |
02:44 | <@Derakon> | Because they're part of the main loop. |
02:44 | <@Vornicus> | or, rather, why does the emitter need to know about them? |
02:44 | <@Derakon> | bml is the set of classes for dealing with bulletML files (my script names could be better, I admit). It needs to know about the game manager so it can instantiate new bullets, and about the player so it can use the "aim" direction type. |
02:44 | <@MyCatVerbs> | Derakon: okay, let's straighten this out. You've decided that it's problematic for gameManager to not be a global, because otherwise all of the functions that want to create bullets have to have a reference to it passed to them. I asked you, is there any reason those functions shouldn't be methods of either gameManager or another object which has a reference to gameManager? |
02:45 | <@Vornicus> | Can't you pass in an target point and return lists of bullet objects? |
02:45 | <@Derakon> | Y'know what? This isn't going anywhere fast. Give me a moment to make a paste. |
02:45 | <@MyCatVerbs> | Derakon: make bml parse the bulletML files and then make callbacks for creating bullets. |
02:49 | <@MyCatVerbs> | That way, bml doesn't have to know anything about gameManager at all. gameManager, or whoever instantiates it, instantiates bml and hands it a bunch of callbacks that it calls when it needs to interact with game state. |
02:49 | <@MyCatVerbs> | Your dependency graph becomes acyclic and a small, fuzzy kitten curls up on your lap and goes to sleep. Also, rainbows. |
02:50 | <@Derakon> | Okay, have a crude sketch of my current setup: http://paste.ubuntu.com/105399/ |
02:52 | <@MyCatVerbs> | What do ActionFunc, FireFunc, AccelFunc's methods look like? |
02:52 | <@Derakon> | __init__ parses a node in the document tree. |
02:53 | <@Derakon> | __call__ performs the action required by that node (e.g. creating a bullet, accelerating an object, calling other Funcs). |
02:53 | <@Derakon> | reset() returns the state of the Func to what it was immediately after __init__. |
02:53 | <@Derakon> | __call__ will also do lazy evaluation of parameters as needed. |
02:58 | <@MyCatVerbs> | Why have all of those exposed? How about writing one class that parses a BulletML file, takes callsbacks for getting the player's position, creating and destroying bullets and for setting bullets' appearance+position, and then exposes a single method, call it frame(), that when called interprets the program in the BulletML file for one frame? |
02:59 | <@Derakon> | You've just described the purpose of the GameManager and Emitter classes. |
03:00 | <@Derakon> | The problem being: how do you implement the callbacks so that they're available to the Funcs without having to pass them every which way? |
03:00 | <@MyCatVerbs> | Put Emitter in bml.py, pass it those callbacks on construction. |
03:01 | <@MyCatVerbs> | When you construct *Func objects, pass any callback funs you might be interested in to the *Func's constructor and hang it off the Func object. |
03:01 | <@Derakon> | That would be all of the callback functions for basically every Func. |
03:02 | <@Derakon> | Since most of them can contain ActionFuncs which in turn can contain everything. |
03:02 | <@Derakon> | This is basically the same as passing the game manager down every update cycle. |
03:02 | <@MyCatVerbs> | Oh well. Then give them all a reference to the Emitter that created them and hang the callbacks off that. |
03:03 | <@Derakon> | Again, same basic effect. |
03:03 | <@Derakon> | I'm looking for a solution where I have global state. |
03:03 | <@Derakon> | Because the state is fundamentally global. |
03:03 | <@MyCatVerbs> | Yes, but without any circular dependencies. Also, no globals necessary. |
03:03 | <@Derakon> | There's no point passing it down to objects when it's going to be the same for all of them anyway. |
03:03 | <@MyCatVerbs> | Hang on, do you have a problem with passing the game manager everywhere other than just the extreme verbosity of it? |
03:04 | <@Derakon> | Not really, no. |
03:05 | <@MyCatVerbs> | Thank heck. |
03:05 | <@Derakon> | Fundamentally speaking, there is one game manager and one player at any given moment. |
03:05 | <@Derakon> | They are global. |
03:05 | <@Derakon> | So they should be accessible everywhere. |
03:05 | <@Derakon> | (note that Emitters are not global because I still may want to allow for more than one to exist at a time) |
03:06 | <@MyCatVerbs> | Okay, remember which one of us had a circular dependency issue a couple dozen minutes back? |
03:06 | <@Derakon> | That would be me, yes. |
03:08 | | ToxicFrog [~ToxicFrog@Admin.Nightstar.Net] has quit [Operation timed out] |
03:11 | <@Derakon> | Did you have a followup for that? |
03:12 | | ToxicFrog [~ToxicFrog@67.212.7.ns-3924] has joined #code |
03:12 | | mode/#code [+o ToxicFrog] by ChanServ |
03:13 | <@MyCatVerbs> | Derakon: no, I thought I might as well stop talking there. I thought it was pretty likely that you'd stop paying attention if I carried on, and I don't have anything interesting to add anyway. |
03:13 | <@MyCatVerbs> | The latter two data points might even be related, somehow. |
03:13 | <@Derakon> | Heh. |
03:15 | <@MyCatVerbs> | I mean, if you switch to using callbacks, you get rid of the circular dependency. And if you put Emitter into bml and make it the only class in bml that anyone can see externally, then bml gets simpler to use. And if you hang those callbacks off the Emitter object, then you don't need to use any globals at all. That's it, really. |
03:16 | <@Vornicus> | mmm, tasty callbacks. |
03:16 | <@Derakon> | Except that the game manager should be tracking bullets, not the emitter (since there may be multiple emitters). And using callbacks is fundamentally equivalent to passing the manager down through the update stack, which I philosophically object to. |
03:16 | <@MyCatVerbs> | Hell, you could just ignore the last point, and have gameManager stuff callback functions into global variables somewhere where Emitter can see them. |
03:16 | <@MyCatVerbs> | Philosophically object to on what grounds? |
03:17 | <@Derakon> | On the grounds that there is no point adding a parameter to a function (or a field to a class) when the value for that parameter/field will always be the same. |
03:17 | <@MyCatVerbs> | Weaksauce excuse. |
03:17 | <@Derakon> | Got an argument that isn't a logical fallacy? |
03:18 | <@MyCatVerbs> | No. Coming up next, I insult your mother. |
03:18 | | * Derakon snerks. |
03:18 | <@MyCatVerbs> | But seriously, couldn't you find something important to worry about instead? |
03:18 | <@Derakon> | I'm sticking on this because Python really, really should be able to handle it, and I'm baffled that it seems so hard to do. |
03:18 | <@Derakon> | This would be trivial in C++, granted that I'd be using header files for it (and, y'know, I'd be using C++). |
03:19 | <@MyCatVerbs> | Perhaps it's related to the fact that Python's designer would probably yell at you for using global variables anywhere where it wasn't strictly necessary. |
03:19 | <@MyCatVerbs> | Well, not actually yell. He's merely Dutch, after all. |
03:20 | <@Derakon> | Okay, I have a question for you. |
03:20 | <@Derakon> | Is there any situation in which you would consider it acceptable to allow globals? |
03:20 | <@MyCatVerbs> | Yes. Logging verbosity. |
03:21 | <@Derakon> | You could just instantiate a logger with the desired verbosity level and then pass it along to everything instead. Why not do that and avoid the evil, evil global? |
03:22 | <@MyCatVerbs> | Because I'm not a total fucking zealot. Merely *usually*. |
03:22 | <@Derakon> | I'm really not seeing the difference between your use case and mine. |
03:23 | <@MyCatVerbs> | Also, objects which are required to be singletons for externally-imposed reasons. Plus things which're most efficient as singletons, and for which being made a singleton will never break the semantics (e.g. caches). |
03:23 | <@Derakon> | Or, say, an object that maintains global game state? |
03:24 | <@MyCatVerbs> | Difference number one is that I'm far more certain that I don't want to set the verbosity level in more than one place than I am that I don't want to ever have more than one game state. |
03:25 | <@Derakon> | Assume, for the sake of argument, that there will only ever be one game state. |
03:26 | <@MyCatVerbs> | No. How about if you want to write an interactive BulletML editor which runs several BulletML programs side-by-side so that you can compare related versions? |
03:28 | <@Derakon> | I'm going to ignore that argument, reason being that you can always come up with a use case that invalidates any not totally generic design. |
03:28 | <@Derakon> | I tried the totally generic thing once. I spent four years on it and produced precisely zilch. |
03:28 | <@Vornicus> | "two players" |
03:28 | <@Derakon> | I'm designing towards my desired use case now. If I want to extend it later, I'll redesign. |
03:28 | <@Derakon> | The gameplay is fundamentally singleplayer, Vorn. Competition exists only in your score. |
03:29 | <@Vornicus> | There's "enough coupling to get things done" and there's "waay too much coupling" - you seem to be deep into the latter. Why does the emitter need /every function/ in the game manager? Can't you just set up callbacks for the things it needs? |
03:29 | <@MyCatVerbs> | Bull poo. I'm not saying make everything completely generic, I'm saying that it'll be easier to very slightly alter the design to avoid globals than it will to hack around the fact that Python's designs discourage you from using global variables. |
03:30 | <@Derakon> | Vorn, could you please describe what you're thinking of when you say "callback"? Because I'm not coming up with anything that doesn't involve having access to the game manager instance anyway. |
03:31 | <@Derakon> | And MCV: I'm still struggling with the concept that Python can't do something and that therefore that something is wrong. |
03:31 | <@MyCatVerbs> | Derakon: can! Doesn't want to! Learn the difference! |
03:31 | <@MyCatVerbs> | If you force gameManager to be global, then you also force your BulletML interpreter to be a singleton too because there's no way to have two of them sending messages to different places (and if they both send messages to a single place, you won't be able to tell which one sent which messages). |
03:32 | <@Derakon> | Yes, and? |
03:32 | <@MyCatVerbs> | So with one fell stroke, you're eliminating a whole load of possible interesting things you could do with a BulletML interpreter, in return for negligible gain. |
03:32 | <@Vornicus> | Callback: when setting up the emitter, pass in functions for the the things you need it to do. The emitter will then /use/ the functions passed in to it when you need to do certain actions. |
03:32 | <@Derakon> | (Let's be perfectly clear here: at this point the argument is pretty much entirely philosophical) |
03:32 | <@ToxicFrog> | While in principle I agree that the ability to create and run multiple interpreters concurrently is a Good Thing - |
03:33 | <@ToxicFrog> | - MCV, I think you're getting way too worked up about this at the cost of not coming anywhere near answering the question that was actually asked. |
03:33 | <@Derakon> | (Because we've determined a way I could solve my problem. It's just not the way I want.) |
03:33 | <@MyCatVerbs> | ToxicFrog: I'm not that worked up, and I answered the question that was actually asked ("how do I fix this cyclic dependency?") like half an hour ago. |
03:33 | <@Vornicus> | So for instance if you need the emitter to know where the player is, you tell it "here's a function that will always tell you where the player is" |
03:33 | <@Derakon> | Vorn: the issue being, when I'm twelve-deep into the document tree and need to create a bullet, where's the emitter? |
03:33 | <@ToxicFrog> | That said. |
03:34 | <@ToxicFrog> | Derakon: isn't python lazy about these things by default? |
03:34 | <@Derakon> | I don't know. I guess? I'm not that familiar with Python. |
03:34 | <@MyCatVerbs> | ToxicFrog: ssh, didn't want to let him know that. ;P |
03:34 | <@ToxicFrog> | That is to say, if bml.py has references to the gameManager, won't it only blow up if it tries to use those before it's instantiated? |
03:34 | <@MyCatVerbs> | The answer is, yes it is. |
03:34 | <@Derakon> | bml.py only defines classes. |
03:34 | <@ToxicFrog> | ...problem solved, then? |
03:34 | <@Derakon> | bulletml.py, when run, starts the game going. |
03:35 | <@ToxicFrog> | As long as you don't actually use any of those classes before creating the gamemanager, you're good to go. |
03:35 | <@Derakon> | GameManager sits on top of all call stacks that access them. |
03:35 | <@ToxicFrog> | So where's the problem? |
03:36 | <@Derakon> | When bml.py tries to import gameManager from bulletml.py, bulletml.py starts running, instantiates a GameManager instance (to assign to gameManager), and starts trying to parse the bulletML file...which requires functions in bml.py, which isn't done loading yet because we're still trying to import gameManager. |
03:37 | <@MyCatVerbs> | Derakon: when you say "requires" do you mean "actually calls" or "will call"? |
03:37 | <@Derakon> | Here: http://paste.ubuntu.com/105417/ |
03:37 | <@ToxicFrog> | UM |
03:37 | <@Derakon> | Part of instantiating GameManager is parsing a BulletML file. |
03:37 | <@ToxicFrog> | This implies to me that gameManager should not be in the same place as main |
03:37 | <@MyCatVerbs> | Derakon: as in, "actually calls while parsing the bulletML file" or "will call when Emitter starts calling methods on them"? |
03:37 | <@ToxicFrog> | But rather a seperate file that both bml and bulletml can import |
03:37 | <@Derakon> | Actually calls when parsing the file. |
03:38 | <@MyCatVerbs> | Derakon: ...what? Why? oO |
03:38 | <@Derakon> | Because every single node in a bulletML file needs to get instantiated as a class, that has state (the subnodes within that node, any labels it has, its inner text, etc.). |
03:39 | <@ToxicFrog> | So, wait |
03:39 | <@MyCatVerbs> | What methods does gameManager define that bml's classes call while the file is being parsed? |
03:39 | <@ToxicFrog> | bml requires the gameManager |
03:39 | <@ToxicFrog> | the gameManager requires parsing the bulletML file |
03:39 | <@ToxicFrog> | And that parsing requires functions defined in bml? |
03:40 | <@Derakon> | No. |
03:40 | <@Derakon> | Parsing the bulletML file does not require access to the gameManager instance. |
03:40 | <@Derakon> | Here's the process, AIUI: |
03:40 | <@Derakon> | I run bulletml.py. |
03:41 | <@Derakon> | bulletml.py says "Oh, I need to import bml.py". |
03:41 | <@Derakon> | Loading bml.py, I hit "import from bulletml gameManager, player". |
03:41 | <@Derakon> | So now I'm back to loading bulletml.py. |
03:41 | <@Derakon> | bulletml.py hits "gameManager = GameManager()" and starts running the __init__ function. |
03:41 | <@McMartin> | Incidentally, your game needs an actual title. |
03:41 | <@Derakon> | The __init__ function starts parsing the bulletML file. |
03:41 | <@McMartin> | I suggest "Firewheel" or "Fusillade". |
03:42 | <@Derakon> | It tries to get the type of a node in the file, says "Wait, I don't know how to get node types! That's in bml.py!" and crashes. |
03:42 | <@Derakon> | McM: chopping bulletml.py up into little chunks was supposed to take, like, a half-hour, after which point I was going to work on a title screen~ |
03:43 | <@McMartin> | Actually, I have a bunch of end-user level suggestions for things that are nonglorious but which would make it a ship-whenever kind of affair. |
03:43 | <@McMartin> | But, dinner. |
03:43 | <@McMartin> | Then, more coordination with people in India. ;_; |
03:43 | <@Derakon> | Well, I hope your dinner is tasty. |
03:43 | <@Derakon> | And I'm always open to suggestions. |
03:45 | <@McMartin> | My big one is that I don't like how rank works. |
03:45 | | * Derakon moves GameManager, Player, Bullet, and Bomb into gameobjects.py, gets a lovely little stack: bulletml -> gameobjects -> bml -> bulletml -> crash because Player is not defined. Argh! |
03:45 | <@McMartin> | I think you need some quality time with a sketchpad here. |
03:46 | <@Derakon> | I'd be fine if I could declare dependencies without having to load the file at the same time. |
03:46 | <@McMartin> | Loading should be lazy unless you're Doing It Wrong, which you may be. |
03:46 | <@McMartin> | More later |
03:47 | <@Derakon> | gameobjects needs bml because bml has the functions needed to finish creating an Emitter. bml needs bulletml because bulletml holds the gameManager and player variables. bulletml needs gameobjects because gameobjects defines the GameManager and Player classes. |
03:48 | <@McMartin> | Right, but loading it should never run *anything* but def() commands unless you're the main program. |
03:48 | <@Derakon> | I'm just doing "from bml import *". |
03:48 | <@Derakon> | So...something screwy's going on here. |
03:48 | <@McMartin> | Yes, and if bml is executing expressions... |
03:49 | <@McMartin> | You're running code somewhere in here, not just defining bindings. |
03:49 | <@Derakon> | The only lines that have text in the first character (not whitespace) are shebangs, imports, "from foo import bar", def, and class. |
03:49 | <@Vornicus> | Stuff inside classes get executed on load, except for stuff that is also inside defs. |
03:50 | <@Derakon> | Classes only contain defs. |
03:50 | <@Derakon> | But besides, it's not even getting that far AFAICT. It's hitting the "from bulletml import gameManager, player" line and going back off to bulletml.py. |
03:51 | <@Derakon> | bulletml.py does have a lot of code that isn't part of a class or def. Constants, for example. |
03:51 | <@Derakon> | And initialization, loading of assets, etc. |
03:55 | <@Derakon> | I appear to literally not get past any import lines until I'm trying to load bulletml.py for the second time. |
04:03 | | * Derakon hacks things up a bit, manages to get the program past the import phase. Now it's complaining that ActionFunc is not defined in gameobjects.py, despite the "from bml import *" at the top of the file. |
04:03 | <@Derakon> | Wait, no, my bad. gameobjects was only importing getType because I'm stupid. |
04:04 | <@MyCatVerbs> | We could've told you th-just joking =D |
04:05 | <@Derakon> | Okay, so bulletml.py now consists solely of the following: a bunch of imports; initializations of player and gameManager to None; the run() function; logic that says "If I'm the main module, run()". |
04:05 | <@Derakon> | The first thing that run() does is set player and gameManager. |
04:05 | <@Derakon> | But when bml.py tries to access gameManager.spawnBullet(), I get the error "'NoneType' object has no attribute 'spawnBullet'" |
04:07 | <@Derakon> | It's like bml.py is getting a copy of gameManager instead of a reference to it. >.< |
04:08 | <@MyCatVerbs> | Derakon: where's bml.py get ahold of gameManager? |
04:09 | <@Derakon> | from bulletml import gameManager, player |
04:10 | <@Derakon> | I just tried creating functions in bulletml.py to return player and gameManager instead, and those give the same result. |
04:10 | <@MyCatVerbs> | You do remember to set gameManager to something other that None later on, right? |
04:10 | <@Derakon> | Yes. |
04:11 | <@Derakon> | Though I may be misusing the 'global' keyword. Is this right? http://paste.ubuntu.com/105421/ |
04:11 | <@MyCatVerbs> | Cheap shot, just put a print "I scream, you scream, we all scream for ice-cream!" next to that statement to make sure it's being run. |
04:11 | <@Derakon> | It is, trust me, bml.py code wouldn't be run otherwise, but I may have scoping problems. |
04:14 | <@McMartin> | More generally, I would actually object to the use of "from x import y", much less * |
04:14 | <@MyCatVerbs> | Have it refer to the module specifically, please? Scratch from bulletml import gameManager, player; make with import bulletml, and then use bulletml.gameManager and bulletml.player, and see whether that works? |
04:15 | <@Derakon> | Still None. |
04:15 | <@Derakon> | Which implies to me that the gameManager I'm setting in run() is not the same as the one I'm declaring a few lines earlier. |
04:16 | <@MyCatVerbs> | When you set gameManager in run, do you remember to use the global gameManager? |
04:17 | <@Derakon> | I said "global gameManager" right beforehand. Is there some other distinction I should be making? |
04:17 | <@Derakon> | Remember this is my first serious Python project. |
04:17 | <@MyCatVerbs> | Because if you're not using the global keyword then you'll just end up creating a local variable called gameManager inside the namespace of the run() method, which wouldn't at all be what you want. |
04:17 | <@McMartin> | The code you listed ought to work. |
04:17 | <@McMartin> | Or at least, have them not be none. |
04:18 | <@MyCatVerbs> | No? Then presumably that's not it. Care to hand over any more code, please? Can't think of anything else offhand. |
04:18 | <@McMartin> | My suspicion is Module Init code going berserk |
04:19 | <@Derakon> | http://derakon.dyndns.org/~chriswei/temp2/foo.tgz |
04:19 | <@Derakon> | That's the entire codebase... |
04:19 | <@Derakon> | Though it occurs to me that it won't run as-is because it's missing all the assets. A moment. |
04:20 | <@Derakon> | http://derakon.dyndns.org/~chriswei/temp2/images.tgz |
04:21 | <@MyCatVerbs> | Oh, hatred. What's up with people assuming that "copy" doesn't include "copy to the selection buffer, too" anymore? |
04:22 | <@Derakon> | Dammit, this was supposed to be simple and straightforward. |
04:22 | <@Derakon> | And I've been working on it for two and a half hours now and have a headache. >.< |
04:22 | <@Derakon> | I hate it when fun projects aren't fun. :\ |
04:23 | <@McMartin> | Some parts are always work. |
04:23 | <@Derakon> | Well, it's all work. Just some parts are more fun than others. |
04:24 | <@Derakon> | I love how all the comments I see about circular imports in Python on the net are saying "If your code's that tightly-coupled, it should all be in one module anyway", completely disregarding the problems inherent in having a 1000-line Python file. |
04:25 | <@McMartin> | That's because it's not supposed to evaluate that hard. |
04:25 | <@Derakon> | Parse error. |
04:25 | <@McMartin> | sec, doing 3 things at once |
04:25 | <@Derakon> | NP. |
04:28 | | crem [~moo@Nightstar-28703.adsl.mgts.by] has joined #code |
04:29 | | crem_ [~moo@Nightstar-28703.adsl.mgts.by] has quit [Connection reset by peer] |
04:30 | <@MyCatVerbs> | Derakon: playing with the interactively in the REPL is fun. |
04:31 | <@MyCatVerbs> | Derakon: every time I import *anything*, I end up with a huge black window being constructed on screen. |
04:31 | <@MyCatVerbs> | Derakon: is it really deliberate that importing the module called "constants" should be enough to cause the graphics to be initialized? |
04:32 | <@Derakon> | That could be done better, I'll grant. |
04:32 | <@Derakon> | I want to get it working first, clean second. |
04:32 | <@Derakon> | At the time my main goal was to simplify bulletml.py itself as much as possible. |
04:32 | <@McMartin> | OK, so |
04:33 | <@McMartin> | Stuff isn't supposed to be evaluated until the last minute. |
04:33 | <@McMartin> | If you have f() that calls g() and g() that calls f(), as long are both are deffed before you run either, you're golden. |
04:33 | <@McMartin> | So I'm having trouble seeing why you're getting actual circular dependencies. |
04:33 | <@Derakon> | I got to implement that myself for the BulletML parser, BTW. |
04:33 | <@McMartin> | As opposed to mere forward references, which should be fine |
04:34 | <@Derakon> | Well at the moment, I'm not getting any complaints about circular references. |
04:34 | <@Derakon> | Just an object being None when it shouldn't be. |
04:34 | <@McMartin> | Is the initialization happening? Does the log function in startGame() happen? |
04:34 | <@Derakon> | Yes. |
04:35 | <@Derakon> | And I just put a log message at the end of startGame(), and it too shows up. |
04:35 | <@Derakon> | Which means that GameManager::__init__ is completing successfully, which means that the gameManager in run() is being assigned to. |
04:36 | <@Derakon> | In any event, the crash happens in gameManager::update(), which I manifestly could not call if it were still None. |
04:36 | <@McMartin> | I'm failing in from constants import *, actaully |
04:36 | <@Derakon> | Okay... |
04:36 | <@McMartin> | Oh, images |
04:36 | <@McMartin> | Where do I unzip that? |
04:37 | <@Derakon> | Same directory as the scripts. |
04:37 | <@Derakon> | Hey look, util.py has constants in it. *facepalms* |
04:38 | <@McMartin> | I'm a little concerned about constants being imported multiple times. |
04:38 | <@Derakon> | Doesn't Python only import once? |
04:38 | <@Derakon> | "I already imported this file, so no need to do so again" kinda thing. |
04:38 | <@McMartin> | IOError: [Errno 2] No such file or directory: 'bmls/weave.bml' |
04:38 | <@Derakon> | D'oh. |
04:39 | <@McMartin> | Inside self.startGame() |
04:39 | <@Derakon> | http://derakon.dyndns.org/~chriswei/temp2/weave.bml |
04:39 | <@Derakon> | Make a directory "bmls" and put that there. Sorry. |
04:41 | <@McMartin> | I betAttributeError: 'NoneType' object has no attribute 'spawnBullet' |
04:41 | <@McMartin> | This? |
04:41 | <@Derakon> | Yep. |
04:41 | <@Derakon> | Line 204 of bml.py. |
04:42 | <@MyCatVerbs> | Here we go. |
04:42 | <@MyCatVerbs> | At the head of run(), cut the global lines, they don't do what you want at all. |
04:43 | <@MyCatVerbs> | I think you want to write, player = Player(), gameManager = GameManager(), bulletml.player = player, bulletml.gameManager = gameManager, and go from there. |
04:44 | <@MyCatVerbs> | There we go. Doesn't fail with the attempt to reference a member of Nonetype, but instead fails later on with an undefined something or other. Says "player" is not defined. |
04:44 | <@Derakon> | Yeah, working on that. |
04:44 | <@Derakon> | That's really weird, though. |
04:44 | <@Derakon> | I feel like assigning to the current module name shouldn't be necessary. |
04:45 | <@MyCatVerbs> | I think that in Python, "global" just means "global within this module". |
04:46 | <@MyCatVerbs> | Modules, however, are first-class objects. You can add whatever members to them that you feel like (exercise for the reader: abuse this for memoization ;D). |
04:47 | <@Derakon> | Aaaand it's running. |
04:47 | <@Derakon> | Thanks, MCV. |
04:47 | <@Derakon> | Good gravy that took a long time. >.< |
04:48 | <@MyCatVerbs> | No worries. ^^ |
04:48 | <@MyCatVerbs> | BTW, modules are first-class objects, y'know. Check out the "imp" module sometime for laughs. =D |
04:49 | <@Derakon> | ...I'll read about that in more detail when my brain isn't fried. |
04:49 | <@Derakon> | I've spent the last three and a half hours chasing Python around. |
04:49 | <@MyCatVerbs> | It's just a module that gives you access to the machinery that the import statement uses. |
04:50 | <@Derakon> | Yeah, I see that. |
04:51 | <@MyCatVerbs> | So you can do deranged stuff, like write a directory full of Python modules that each define their own foo(), bar() and baz() functions, and then have a program that loads all the modules in that directory and does... something arbitrarily stupid with them. |
04:52 | <@MyCatVerbs> | Not all that different to what you can do with current Java's runtime access to the class loader, but you get to do it without having to type out half of War and Peace first. |
04:55 | | * Derakon verifies that py2app still handles everything directly. |
04:59 | <@MyCatVerbs> | Any joy? |
05:05 | <@Derakon> | Hm? It works fine. I'm playing D2 now to give my brain some rest, though. |
05:07 | | Alek [~omegaboot@Nightstar-23762.dsl.emhril.sbcglobal.net] has joined #code |
05:08 | <@MyCatVerbs> | Spiffy. |
05:57 | | crem [~moo@Nightstar-28703.adsl.mgts.by] has quit [Ping Timeout] |
06:33 | | Derakon is now known as Derakon[AFK] |
06:50 | | KarmaBot [AnnoDomini@Nightstar-29324.neoplus.adsl.tpnet.pl] has quit [Connection reset by peer] |
06:50 | | KBot [AnnoDomini@Nightstar-29324.neoplus.adsl.tpnet.pl] has joined #Code |
06:51 | | crem [~moo@Nightstar-28703.adsl.mgts.by] has joined #code |
06:53 | | KBot is now known as KarmaBot |
07:14 | | Alek is now known as Alek|gone |
08:46 | | AnnoDomini [~farkoff@Nightstar-29324.neoplus.adsl.tpnet.pl] has joined #Code |
08:46 | | mode/#code [+o AnnoDomini] by ChanServ |
08:56 | | KBot [AnnoDomini@Nightstar-29055.neoplus.adsl.tpnet.pl] has joined #Code |
08:57 | | AnnoDomini [~farkoff@Nightstar-29324.neoplus.adsl.tpnet.pl] has quit [Ping Timeout] |
08:57 | | KarmaBot [AnnoDomini@Nightstar-29324.neoplus.adsl.tpnet.pl] has quit [Ping Timeout] |
08:59 | | KBot is now known as KarmaBot |
09:03 | | AnnoDomini [~farkoff@Nightstar-29055.neoplus.adsl.tpnet.pl] has joined #Code |
09:03 | | mode/#code [+o AnnoDomini] by ChanServ |
09:09 | | You're now known as TheWatcher |
10:10 | | ToxicFrog [~ToxicFrog@67.212.7.ns-3924] has quit [Operation timed out] |
10:12 | | ToxicFrog [~ToxicFrog@Admin.Nightstar.Net] has joined #code |
10:12 | | mode/#code [+o ToxicFrog] by ChanServ |
10:13 | | Attilla [~The.Attil@Nightstar-9469.cdif.cable.ntl.com] has joined #code |
10:13 | | mode/#code [+o Attilla] by ChanServ |
13:38 | | gnolam [lenin@Nightstar-1382.A163.priv.bahnhof.se] has joined #Code |
13:38 | | mode/#code [+o gnolam] by ChanServ |
13:46 | | Vornicus [~vorn@Admin.Nightstar.Net] has quit [Ping Timeout] |
13:46 | | Vornicus [~vorn@Admin.Nightstar.Net] has joined #code |
13:46 | | mode/#code [+o Vornicus] by ChanServ |
14:02 | | Reiv [ReivTop@Nightstar-22042.ipnet.xnet.co.nz] has joined #Code |
15:52 | | Reiv [ReivTop@Nightstar-22042.ipnet.xnet.co.nz] has quit [Quit: Laptop fall down go boom...] |
17:09 | | You're now known as TheWatcher[afk] |
18:32 | | You're now known as TheWatcher |
18:58 | | You're now known as TheWatcher[afk] |
19:45 | | You're now known as TheWatcher |
19:55 | | Serah [~Z@87.72.35.ns-26506] has quit [Quit: Be right back, got some smiting and righteous justice to attend to.] |
20:24 | | Vornicus [~vorn@Admin.Nightstar.Net] has quit [Quit: ] |
21:33 | | Attilla [~The.Attil@Nightstar-9469.cdif.cable.ntl.com] has quit [Connection reset by peer] |
21:36 | | Attilla [~The.Attil@Nightstar-9469.cdif.cable.ntl.com] has joined #code |
21:36 | | mode/#code [+o Attilla] by ChanServ |
21:41 | | Attilla [~The.Attil@Nightstar-9469.cdif.cable.ntl.com] has quit [Connection reset by peer] |
21:48 | | Attilla [~The.Attil@Nightstar-9469.cdif.cable.ntl.com] has joined #code |
21:48 | | mode/#code [+o Attilla] by ChanServ |
22:15 | | Serah [~Z@Nightstar-5401.atm2-0-1041217.0xc329e232.boanxx12.customer.tele.dk] has joined #Code |
22:15 | | mode/#code [+o Serah] by ChanServ |
22:42 | <@MyCatVerbs> | Jesus H Fucking Christ, Boatmurdered. >_< |
22:44 | <@Serah> | You murdered Jebus? |
22:45 | <@ToxicFrog> | I HOPE YOU LIKE MIASMA |
22:45 | <@MyCatVerbs> | That sounds like a pretty good idea, but no. |
22:45 | <@MyCatVerbs> | http://lparchive.org/LetsPlay/Boatmurdered/ <- by far the worst Let's Play performance I've read yet. |
22:46 | <@MyCatVerbs> | Goddamn funny, though. |
22:46 | <@MyCatVerbs> | ToxicFrog: figures that you'd've read it. :) |
22:46 | <@ToxicFrog> | Of course. |
22:47 | <@Serah> | TF has too much spare time? |
22:47 | <@AnnoDomini> | MyCatVerbs: Boatmurdered is epic. |
22:47 | <@MyCatVerbs> | Seconded. |
22:47 | <@AnnoDomini> | I'm playing DF right now. |
22:48 | <@AnnoDomini> | This game is just wonderfully detailed. |
22:48 | <@MyCatVerbs> | Serah: we're on IRC. By definition, we either have far too much time, or we're so brazenly incapable of time management that it's a wonder we meet our deadlines on breathing in order to avoid asphyxiation. |
22:49 | <@McMartin> | MCV: Note that Boatmurdered produced a large list of bug reports for Dwarves doing insane, counterproductive things and such. |
22:49 | <@McMartin> | Not to mention being buzzsawed to death by carp |
22:49 | <@Serah> | Actually, I get paid to be on IRC. |
22:50 | <@AnnoDomini> | McMartin: Carp are still very, very capable of killing a normal dwarf. |
22:50 | <@Serah> | Besides, I would suggest that if he had too much time, he could box some of it up and send it to me. |
22:52 | <@McMartin> | I think the carp were retained. |
22:53 | <@McMartin> | But the "hurl yourself into the lava then go around beating people to death while on fire" thing? Not so much |
22:53 | <@AnnoDomini> | They don't gain Swimmer skill anymore, but they keep their 1d6 bite. |
22:53 | <@McMartin> | Also not trying to loot corpses in the middle of battle |
22:53 | <@McMartin> | Thus causing them to line up to be trampled to death by elephants |
22:54 | <@ToxicFrog> | Actually, carp were a non-threat in boatmurdered. |
22:54 | <@ToxicFrog> | Mandrills and elephants were. |
22:54 | <@AnnoDomini> | You can prevent immediate lootings in the options now. I think. |
22:54 | <@ToxicFrog> | The death carp didn't show up until the 3d version. |
22:55 | <@ToxicFrog> | And yeah, the options are actually for auto-forbidding of items dropped by the dead. |
22:55 | <@McMartin> | I recall some stuff on the official changelog being "This should reduce Boatmurdered-style yadda yadda yadda" |
22:56 | <@AnnoDomini> | I lost a fourth of a fortress' population because booze ran out, and there was a mass exodus towards the river. |
22:57 | <@ToxicFrog> | Oh holy shit, there's an official linux native version now |
22:57 | <@ToxicFrog> | AnnoDomini: this is why you set up an internal pool and mark that as a water source. |
22:58 | <@AnnoDomini> | I had problems with zones... it says on the wiki, that it doesn't matter how far below the well the water is. |
22:58 | <@AnnoDomini> | But I dug like to level -7 to an underground river, and found wells didn't work. |
22:59 | <@ToxicFrog> | I'm not 100% sure that wells work with flowing water |
22:59 | <@ToxicFrog> | That said |
22:59 | <@AnnoDomini> | They do with a brook, anyway. |
22:59 | <@ToxicFrog> | You're sure you had no hatches/floors/etc in the way? |
22:59 | <@AnnoDomini> | Nope. Straight down. |
23:00 | <@AnnoDomini> | Thanks for the tip, though. |
23:00 | <@AnnoDomini> | I'll try that now, since I'm on a carpy map. |
23:04 | <@Serah> | The VLC inyourface is bugged. |
23:04 | | * Serah is bothered. |
23:05 | <@MyCatVerbs> | Serah: you get paid to be on IRC? oO |
23:05 | <@MyCatVerbs> | McMartin: huh, I had wondered about whether some of the crazier happenings might result in bug reports. |
23:06 | <@ToxicFrog> | You can also just dig a pit, mark it as a pond/water source, and have them fill it with buckets |
23:06 | <@Serah> | No, actually I just get paid, what I do with the time doesn't matter as long as I serve whatever guests happen to require me. (Which tends to be little to none) |
23:06 | <@ToxicFrog> | Or channel it to the river and install a grating so carp don't get in |
23:07 | <@MyCatVerbs> | Serah: ah, genius. Out of curiosity, what're you on the clock for? |
23:07 | <@MyCatVerbs> | Serah: I mean, job title? |
23:07 | <@Serah> | Night clerk at a hotel. |
23:07 | <@Serah> | Rather small hotel. 84 rooms. |
23:07 | <@MyCatVerbs> | Sounds big enough to me. |
23:08 | <@Serah> | Currently 54 guests. |
23:08 | <@Serah> | And they're all in bed. |
23:09 | <@Serah> | I meet at 11 PM, get off at 7 AM. |
23:09 | <@Serah> | From three to four I set up the buffet, from six to seven I make coffee. |
23:09 | <@Serah> | Rest of the time is... IRC time! ^_^ |
23:09 | <@GeekSoldier> | Wells should work with flowing water. |
23:09 | <@Serah> | Also watching NCIS, I tend to watch movies I will watch Next after this episode. |
23:12 | <@Consul> | Serah: You have the perfect musician's job. :-) |
23:13 | <@Serah> | Thanks |
23:13 | <@Serah> | I think. |
23:13 | <@Serah> | I only work every other weekend too. |
23:13 | <@Serah> | And I don't have economical problems. |
23:13 | <@Serah> | So... *shrugs* |
23:13 | <@Consul> | No, I mean in terms of free time. Write lyrics, work out some chord changes, etc. |
23:13 | <@MyCatVerbs> | Consul: s/musician's/NetHack player's/ |
23:13 | <@Consul> | Heh |
23:14 | <@MyCatVerbs> | Shit, you could farm puddings. =D |
23:14 | <@Consul> | s/musician's/part-time OSS coder's/ :-) |
23:14 | <@Serah> | OSS? |
23:14 | <@Consul> | open-source software |
23:19 | <@Consul> | How does one get into the pudding farm business? |
23:33 | <@MyCatVerbs> | Consul: Black Puddings are a type of amorphous acid blob monster in Nethack. |
23:33 | <@MyCatVerbs> | If you hit one with something ferrous, the thing you hit it with will corrode, and it might split in two if it survives. |
23:35 | <@Consul> | Oh, okay... |
23:35 | <@MyCatVerbs> | "Pudding farming" is the practice of using a rusty tin opener to deliberately split black puddings tens or hundreds or even thousands of times in order to harvest the crap they randomly drop on death, and sacrifice their corpses to your deity for favours from your god: artifact weapons, spellbooks, crowning, luck bonuses and filling your stomach if you're hungry when you pray to them and they're happy with you. |
23:36 | <@MyCatVerbs> | The Dev Team have known about the "exploit" of pudding farming for a long time now, and have deliberately refrained from fixing it. |
23:36 | <@MyCatVerbs> | It is felt that the ideal punishment for people pudding farming is... pudding farming. It's the most tedious thing ever. :) |
23:38 | <@Serah> | DF? |
23:38 | <@GeekSoldier> | Dwarf Fortress |
23:38 | <@Serah> | Yes, but is Pudding farming a DF thing? |
23:38 | <@AnnoDomini> | Nethack, rather. |
23:38 | <@GeekSoldier> | no. It's Nethack. |
23:39 | <@Serah> | Oh, okay. |
23:39 | <@Serah> | Then the world makes sense once more. |
--- Log closed Sat Jan 17 00:00:50 2009 |