First Implementation Considerations
Hi!
This entry is just my rant about what considerations I have made about the game to be created. In accordance to the rules, I haven't done any coding, but I have considered some general aspects about the code.
I am now determined to make a small RPG. It does seem like the simplest thing for me to do.
So, I have been brainstorming abstractly what I may need.
Initially, I considered hard-coded events, but the more I think about it, it seems like a really stupid idea. I would only create a completely obscure monstrous source code that even I won't understand the next morning (^_^;;
Implementing a really proper and nice-looking event system is clearly not possible in such a short time (My calculations are - because I have internet only until Thursday afternoon - that Python programming must be finished by Tuesday morning at the latest, so I have one day to do content expansion). Besides obviously implementing only the minimum functions, I guess that using separate files to store text (like in message boxes) would be the best way to handle things since I don't need to work with dynamic length arguments in the file loader for the event proper.
After having determined that, I also figured that handling saves may be easiest using a similar method, splitting the data that needs to be saved into several files put into a common directory. So, I have to check what functions (preferably in the default library or wxPython (^_^;; ) can be used to handle directories (I remember seeing a function that can check whether a directory exists or not, and I think the FAQ over at python.org mentioned something about how to delete files).
It will be interesting to work with dictionaries and arrays (ah, I just checked the documentation, you call them lists here (^_^;; ) simultaneously. The way I see it, dictionaries are most efficient when dealing with index data provided as a string, which would be the default for anything read from a file, whilst arrays work best if I had numeric index data. So, during implementation, I am going to examine which kind of index data is more likely for each candidate and try to choose the type accordingly.
Originally, I considered allowing only exactly screen-sized maps, but I reconsidered, figuring that the benefit in terms of game fun of having things you find only by going to the edge of the map clearly outweight the potential trouble the few lines of extra-code that would require (I would need variable sized maps and would need to handle centering and being close to the map border; all of these should be easily implemented, but since they increase the amount of code, I consider them basically a liability).
I also spent a little thought on speed vs. memory concerning events, figuring that memory is more important.
The thing is, event files need to crunch the event data quite tightly, while interpretation is likely to benefit from cutting it into smaller pieces for easy handling and reference. The question I asked myself was whether I would want to have that cutting up into smaller pieces take place for all events when they are loaded (in effect when a new map is entered), or only for one event when it is accessed.
Converting all events upon entering a map would be time-efficient since conversion happens only once, but it would probably waste a lot of memory because each event would be cut into dozens if not hundreds of tiny strings (which are bound to have a bit of ID and processing stuff added by the system).
Converting only the current event clearly saves memory since only one converted event is kept in memory, but it means that conversion has to be done again and again, every time the event is triggered.
I figured that conversion is probably not so slow a task as to hinder gameplay, so I figured that preserving memory should have a higher priority.
Concerning the completely unintuitive handling of globals and locals in Python (yes, I do believe that giving spontaneous overriding priority over access is not an intuitive system), I guess the safest way is to access globals always using the __main__. terminology, even if they are on the right hand side. I find it simply odd that, when working within a given code block, I can address a global by (name) if it is on the right hand side, but need to write __main__.(name) if it is on the left hand side. Two different notations for the same variable seem to be unnecessarily confusing. Thus, I will always use the ugliest, but unfortunately only universal terming.
During the brain storming, I figured that I may want to do an HTML manual. This should be relatively portable (although I will not do any IE/Netscape/Whatever compatibility code or any Javascript at all (^_^;; ) and allow for giving detailed instructions in an easy-to-read fashion. If you are now raising concerns about the time, that is already considered: The last phase of the development (Wednesday to Thursday afternoon) is playtesting/debugging. This means that I am basically on standby, only modifying the program or its data in response to bug reports. More likely than not, that means that I have some periods of interactivity where I can't do anything. That time would be ideal for working on the instructions since they would have no impact on the bugs in the game and it needs to be written last anyway, since it should describe the features the program has, and not those I wanted it to have at the start of the programming.
Finally, I think it is a good idea to add a lots of comments. I figure that during programming and debugging, time is a luxury. And with the amount of programming/coding I will have to do on the first day, it is quite likely that I will forget many of the details I came up with during the process. So, by Tuesday, large parts of the code may be completely obscure even to myself if I don't comment them properly.
Besides, this competition is meant to help build a code base for Python. While I don't think that my code will be briliant or something, I do believe that people will be able to learn from it - but only if they understand what I am doing or trying to do.
In addition, library/engine images are a pet peeve of mine. It is frustrating me to no end that Kirikiri, which is basically C++ without the portability (to be implemented in the next release) and without the 300+ error messages if you don't tell the compiler your computer sucks at chess and you like the color green beforehand, is generally considered a dedicated digital novel engine. Kirikiri's standard functions offer all you need for many types of game and other applications, but its distribution includes KAG (Kirikiri Adventure Game system) which is a dedicated digital novel engine written in Kirikiri.
Similarly, I see people talking about PyGame all the time for game programming, but I think that wxPython may actually be easier for certain game genres to use (RPG being top because of the default joystick/pad availability, but also strategy (not RTS, though) and simulations). And as I mentioned elsewhere, wxPython also comes with really good and helpful installation instructions (not to mention a seemingly comprehensive and helpful demo, which needs to be downloaded separately, but which is really worth it.).
Mind you, I am not saying that PyGame is no good. It is simply that I believe that it is more suited for action and RTS types of games while things like wxPython may have advantages when trying to do other genres (actually, I find it really odd that Ren'py is based on PyGame (^_^;; ).
I think I will implement a few simple spells, so that levelling the character results in new options (and so that combat becomes less monotonous). But I will quite obviously not implement event spells (spells triggering special event code), instead sticking to simple healing and damaging spells and their kin.
At the moment, I think animation is most probably not to be implemented since it would increase the amount of artwork required too much. I realize that this is a painful decision because animated characters are something players expect of an RPG, but with these time constraints, it is just illusory (^_^;;.
I may use sound effects (not sure about that), but no music since I would be limited to WAV if I wanted things to be fully portable (wxPython has a command for playing general media, but that is not supported yet by Linux, I think). Besides, musics is not really my field, I am more with graphics :) :) :).
Well, these are all the considerations I have made thus far.
Deathworks(log in to comment)
Comments
def myfunction(): __main__.someotherfunction() instance = __main__.SomeClass()By the way, using the 'global' keyword you can make globals work on the left hand side:
foo = "Something" def myfunction(): global foo foo = "else"
Another way to solve it is to use classes. I come from Java so that would be the natural thing for me.
Hi!
Neppord: Be careful if you are using modules. IIRC, __main__ will not work properly during the initialization of a module (I haven't tested whether functions defined in modules work). The way I see it, what namespace is actually used by modules integrated via "import" is really quite a mess (initialization differing from functions, and some things are even irregular with that, it seems).
Faasen: Well, please allow me to be a bit inconsistent by limiting __main__ to variables. The issue is that unlike classes and functions, variables can be defined without any special command word.
My main problem with the current implementation is the following:
x = f(x)
f() can be a function or could be any expression including the argument. So, if you don't like 'x = f(x)', just make it 'x = 2 * x + 8'. The same goes for all my examples.
This single line by itself is currently highly ambiguous. You do not know whether 'x' on the left hand side and 'x' on the right hand side are actually the same object. 'x' on the left hand side definitely refers to a local variable 'x' which will be created if it doesn't exist. So, the meaning of the left hand side 'x' is relatively clear. But the 'x' on the right hand side refers to a local variable 'x' only if that local variable has been defined before. if it hasn't, it refers to a global variable 'x', so, depending on the circumstances, the two instances of 'x' in that line could refer to different objects altogether.
To make matters worse, the creation of the local variable could take place at any point within that function level, even within 'if' statements.
And then we have the following line:
__main__.x = f(x)
The funny thing is, if there is no local variable 'x' declared, then '__main__.x' and 'x' refer to exactly the same object. But add a 'x = 1' into the execution before that, and that is no longer the case. Personally, I think it would make more sense if you either required explicit overriding of global variables, or required marking of global variables in all cases.
Also try explaining the following:
x = f(x)
when no local 'x' is defined before is the same as
x = f(__main__.x)
Right? But you can't simply add the same line again without breaking the symmetry:
x = f(x)
x = f(x)
is not the same as
x = f(__main__.x)
x = f(__main__.x)
Just consider a little routine like this
def stupid(gumpy):
___ alfred = 2
___ john = 0
___ while (john < 10):
_______ john = john + 1
_______ alfred = 2 * alfred + x
_______ if (alfred > 20):
___________ x = x - 1
('_' used to enforce indentation under html)
Try to explain what object 'x' refers to in the line 'alfred = 2 * alfred + x'.
As far as I know, functions and classes are never on the left hand side since they exclusively defined by being the argument of a build-in statement like 'def'. So they don't have that hard to explain ambiguity.
About the global statement: It is kind of an inverted declaration. Like instead of declaring the newly created local variable, you have to declare the global variable - in every routine over and over again (^_^;;
And in order to avoid errors, I would need to declare all my globals in every routine for fear of during revision of the routine unexpectedly adding usage of a global variable that had not been used before. So, relying on global seems like a liability to me.
Neppord: Well, I have nearly no experience in programming in Python, but that was the solution I came up with when searching through the manuals to find a way to have global variables that can be reached from any nesting level.
Therefore, please make sure that things actually work properly that way. But if they do, I am glad to have been able to provide some new information.
Tigga: Just as I mentioned before, I haven't done any programming in Python thus far. I had only started on my big project by making a few variable declarations, loading one variable from a file using open() and read(), and creating an empty application window by creating one instance of application and frame each from the wxPython library. So, basically, I still need to look up each and every Python command as I try to use it (even while writing the above examples, I had to check on the syntax for while (^_^;; ). In addition, I only have time till Thursday to finish my project, so spending some thought on what facilities I need is necessary since I need to look up specific functions and statements I will need. I have had programmed with the wxWindows library under C++ before, but that was years ago with an obsolete version of that library at that time. Today, I don't really remember any details about it, except that it was easy to handle and that there was something odd about putting images onto the screen (I don't remember what it was, but I hope that it has been fixed or that I can at least circumvent it if I come around it (^_^;; ).
However, during the last years, I have tried to get a start at programming an RPG in various script languages similar to C++, but I usually made the projects too big and got bogged down by the graphics (Kirikiri was actually a very good candidate, although I disliked the limitations on file access). So, even if I don't know Python, I already know basically what kind of elements an RPG would require.
Anyhow, I hope we all will have fun at this and that everyone is able to get their games up and running.
DeathworksHi!
Faassen: My apologies for misspelling your name. That was really not on purpose. Even if I seem to have a different view on globals and locals in Python, I found your comment quite interesting. After all, you gave some information I didn't have at that time (I found the global command only after writing my initial post in this diary entry (^_^;; ).
Tee: Sorry about not referring to you directly. This was just because the post got so long, I kind of lost track of things. I am not that great a planner, but as the circumstances are, I had to make these considerations.
In addition, I am really, really excited about this challenge, seeing it as a genuine chance to finally get a game finished and - now that I have chosen to do an RPG - actually get a lot of code I can harvest for the big project I want to programm eventually. I am kind of nearly exploding with excitement (^_^;;
Deathworksclass A(object): pass B = AYou may also get potential confusion of the sort you describe like this:
class x(object): pass def foo(): x = f(x)Of course typically the convention is to lowercase local variables and uppercase class names, so this rarely occurs in practice. There is in fact a way to create a new function from scratch without using def (though still using a special keyword, lambda):
square = lambda x: x ** 2Similarly it's possible to create a class using the type() function:
B = type('B', (), {'foo', 'bar'})Of course the last bit is something that I'd only tolerate somewhere deep in framework code, and even then I'd try to avoid it.
This is not uncommon, BTW. You see it a lot if you read comp.lang.python :)
Hi!
Well, seeing that withing a block elements can subtly shift from global to local without a special identification simply doesn't seem very clear to me ( x = 3 does not really catch the eye (^_^;; )
Anyhow, I mainly return to this thread to point out that addressing __main__. does not seem to work (I thought I had used it in my first advances but that must have been a mistake). I hope I haven't confused anyone with that.
(sarcasm)Ah, and global has the nice feature that you can't use exec, execfile or any other pseudo-macro on it.(/sarcasm)
DeathworksI'm a little confused by your last statement too. How do you use the "exec" statement, or the execfile() function on a "global" statement? exec and execfile() both take an optional argument which is the dictionary to use for global variables, so you could pass the globals() dictionary... But perhaps that's not what you mean?
Hi!
My problem is with accidentally creating a local variable by having a global on the left hand-side. It would be nicer if you got an error if you do that without explicitly saying you are overriding the global.
And actually, I am not planning on overriding globals since they are usually referring to objects/concept that exist only once for the entire program (for instance the current map data as a nested list). So, I am mainly concerned with bug prevention.
Basically, with execfile, I can create an external macro. So I hoped I could create single py file, maybe globallist.py consisting only of a series of global statements, nothing else. Then, any method that has anything to do with globals at all (or at least all the complex ones) could simply have the single statement execfile("code/globallist.py") at its very beginning and then presto, all globals would be there. But reading the manual entry of "global", it explicitly states that it can effectively not be used in any of the exec functions.
Oh well, anyhow, I have come to terms with this and will try to get along with things the way they are. Sorry for causing the commotion, but that is one aspect that seemed rather daunting to me. Sorry if I sounded aggressive, it was just the excitement and that this kind of worried me. I hope you can accept that apology.
Deathworks
Tee on 2007/09/01 11:38:
Wow. That's a lot of considerations. It looks like you're a good planner, which is a skill I need to practice a bit more. :)