Re: #define (from C) in Python
> Python IS slower than perl, especially since you are dealing with > objects. However, I'd suggest go the cPickle route - have a Z80Cpu > module, and its C equivalent, cZ80, and use that one if available. This > way, the emulator will be actually usable everywhere. Thanks for the advice but ... my (currently working) emulator is already written in C, I don't see the point of calling it from a python module. I had 2 options: port the emulator from C+Allegro to C +SDL or port it to Python+Pygame+SDL... And the fun is trying to write it in pure python with pygame, without external C :-) I'll do a quick test, if I see that I can't achieve 100% speed in my other computer (DualCore2 1.82Ghz, the basic-standard-minimum computer nowadays), then I'll give up, but at least I want to try it X-D Today or tomorrow I'm finishing the pyinliner.py preprocessor X-D. I'll paste the results here :-) Thanks for your answer :-) -- http://mail.python.org/mailman/listinfo/python-list
Re: #define (from C) in Python
> Hey, I got 100% with ASM ZX Spectrum emulator on a low end 386 :-) (I do > not remember the CPU freqeuncy anymore, maybe 25MHz). Yes, in ASM a simple 25 or 33Mhz 386 computer was able to emulate the Spectrum. At least, under MSDOS, like did Warajevo, Z80, x128 and "Spectrum" from Pedro Gimeno. > First emulator in C that appeared on the emu-scene (I guess it > was x128) needed 486 (~80MHz?) to run at realtime. Pentium and > Pentium II was A LOT of power :-) x128 was not pure C. The first emulator written in pure C was Aspectrum, although Philip Kendall "finished" FUSE (Free UNIX Spectrum Emulator) before my emulator was able to emulate 128K models. But currently only FUSE and ASpectrum can be compiled in lost of platforms (Wii, Dreamcast, PocketPC, NDS...) just by translating the O.S. dependent functions or if the destination platform supports the Allegro library... And at least a P1-P2 is needed for that :-) > http://perl-spectrum.sourceforge.net/ > > It is quite fast IMHO. It does not run 100% in my 1.8Ghz centrino computer :-(, but almost. At least, is a good start to see that is possible, at least no current DualCore computers :-) Thanks! -- http://mail.python.org/mailman/listinfo/python-list
Re: #define (from C) in Python
> > #define STORE_nn_rr(dreg) \ > > r_opl = Z80ReadMem(r_PC); r_PC++;\ > > r_oph = Z80ReadMem(r_PC); r_PC++; \ > > r_tmp = dreg; \ > > Z80WriteMem((r_op),r_tmpl, regs); \ > > Z80WriteMem((r_op+1),r_tmph, regs) > > Someone writing such code and calling it C should be taken > behind the barn and shot. That code is mine and maybe you should look the context before doing such kind of affirmations. In the Intel Pentium and P-II ages, I started to wrote the very first Spectrum emulator in C. With that "cpu power", emulators had to be written in ASM to be capable to emulate the destination machines at 100% full speed in multitasking systems. In the emulation world, every CPU cycle you can save is gold, and writing the above code as inline code saved lots of CALLS, PUSHs/POPs (parameters to stack), and RETs. That allowed ASpectrum to run 100% speed on old computers and even to be ported to the Sega Dreamcast's 200Mhz CPU. Think that Z80ReadMem() can be called up to 6 times in each emulated CPU-cycle. Saving 6 CALLs, 6 PUSHes, 6 POPs, and 6 RETs in each cycle of the 3.500.000 of Hz **did** make the difference that allow Aspectrum to run at 100% speed in ancient machines. Obviously, I prefer to write well structured code but I had to sacrifize SIZE by SPEED (size as inline code is included in the binary executable file). Each coding technique has their application environment and using inline macros, like loop unrolling or using "register" variables fall bellow all the techniques needed to write a fast emulator. Now I'm porting the emulator to a scripted language, so I need even more previous design ideas before starting to code, so that I can achieve (I hope I'll be able to do it with this group's help) 100% cpu speed in an standard desktop PC. > > But it seems that is not possible :-( > > Thank getenv("DEITY") not! Well, I don't agree with that, "constants" and "macros" wouldn't hurt python, when using them in the right situations. Thanks a lot anyway for all your help :-) -- http://mail.python.org/mailman/listinfo/python-list
Re: Writing an emulator in python - implementation questions (for performance)
I'm going to quote all the answers in a single post, if you all don't mind: > [greg] > But keep in mind that named "constants" at the module level > are really global variables, and therefore incur a dictionary > lookup every time they're used. > > For maximum speed, nothing beats writing the numeric literals > directly into the code, unfortunately. So, finally, there are not constants available in python? (Like:) #define R1 1 > Generally, I think you're going to have quite a battle on > your hands to get a pure Python implementation to run as > fast as a real Z80, if it's even possible at all. Well... I'm trying to emulate the basic Z80, clocked at 3.5Mhz.. I hope python in a 2Ghz computer can emulate a 3.5Mhz machine ... Finally, if it's not possible... well, then I would just have some fun... :-) > [Steven D'Aprano] > The shift and mask are a little faster on my machine, but that's > certainly what I would call a micro-optimization. Unless the divmod call > is the bottleneck in your code -- and it almost certainly won't be -- It can be a real bottleneck. An emulator executes continously machine code instructions. Those machine code instructions are read from memory, and operands are read from memory too. The minimum opcode (00h -> NOP) requires 1 memory read, and the CPU task is read from mem & decode & execute. My problem is that I would need to "encapsulate" Memory reads and Memory Writes in functions. In C I use #define so that: - No function call is done (¿code unrolling?) - I can "call" my function so I don't have to manually repeat my code - I can optimize my "#define" macro just once and all the "calls" are optimized too. This way (in C) I can write readable code and the compiler replaces my "readable macros" with the final code. > I don't think it's worth the obfuscation to use shift/mask. An idea. I think I'm going to write a layer previous to my python program, to allow to use macros in my emulator, and generate the final .py program with a script. VERY SIMPLE EXAMPLE: My program: File emulator.pym: == #!/usr/bin/python import blah import sys MACRO BEGIN Z80WriteMem( address, value ) blablablah inc blah p = p + x MACRO END MACRO BEGIN Z80ReadMem( address ) ( memory[address>>4][blah] ) MACRO END (more code) pepe = @@@Z80ReadMem( reg_A ) (more code) @@@Z80WriteMem( 0x121212, value ) == And then, use a script to replace macro calls @@@ by the final code. This way I could write my emulator with "macros" and my "preprocessor" would rewrite the final .py files for the "binary" releases. While I can keep the .pym files as the "real" source (because .py files would be generated from .pym macro-files). Can the above be easily done with another already-existing application? (example: can m4 do this job)? -- http://mail.python.org/mailman/listinfo/python-list
Re: Writing an emulator in python - implementation questions (for performance)
> How about > page, index = divmod(address, 16384) Surely, much better and faster :-) Thanks a lot. -- http://mail.python.org/mailman/listinfo/python-list
Re: Writing an emulator in python - implementation questions (for performance)
Oops, numpy arrays start with index=0 :-) -- http://mail.python.org/mailman/listinfo/python-list
Re: Writing an emulator in python - implementation questions (for performance)
> You can do clever memory slicing like this with numpy. For instance: > > breg = numpy.zeros((16,),numpy.uint8) > wreg = numpy.ndarray((8,),numpy.uint16,breg) > > This causes breg and wreg to share the same 16 bytes of memory. You > can define constants to access specific registers: What I'm doing wrong? [srom...@compiler:~]$ cat test.py #!/usr/bin/python import numpy # Register array breg = numpy.zeros((16,),numpy.uint8) wreg = numpy.ndarray((8,), numpy.uint16, breg ) reg_A = 1 reg_F = 2 reg_AF = 1 reg_B = 3 reg_C = 4 reg_BC = 3 breg[reg_B] = 5 breg[reg_C] = 10 print breg[reg_B] print breg[reg_C] print wreg[reg_BC] [srom...@compiler:~]$ python test.py 5 10 0 ? -- http://mail.python.org/mailman/listinfo/python-list
Re: #define (from C) in Python
On 12 nov, 18:16, Stefan Behnel wrote: > Santiago Romero, 12.11.2009 17:43: > > > Is there a Python version of C's language #define statements? > > > Example: > > > #define ReadMem( (x) ) memory[ (x) ] > > Yes: > > ReadMem = memory.__getitem__ > > Stefan Well, In the above concrete example, that would work, but I was talking for multiple code lines, like: #define LD_r_n(reg) (reg) = Z80ReadMem(r_PC++) #define LD_rr_nn(reg) r_opl = Z80ReadMem(r_PC); r_PC++; \ r_oph = Z80ReadMem(r_PC); r_PC++; \ reg = r_op #define LOAD_r(dreg, saddreg) (dreg)=Z80ReadMem((saddreg)) #define LOAD_rr_nn(dreg) r_opl = Z80ReadMem(r_PC); r_PC++; \ r_oph = Z80ReadMem(r_PC); r_PC++; \ r_tmpl = Z80ReadMem(r_op); \ r_tmph = Z80ReadMem((r_op)+1); \ dreg=r_tmp #define STORE_nn_rr(dreg) \ r_opl = Z80ReadMem(r_PC); r_PC++;\ r_oph = Z80ReadMem(r_PC); r_PC++; \ r_tmp = dreg; \ Z80WriteMem((r_op),r_tmpl, regs); \ Z80WriteMem((r_op+1),r_tmph, regs) But it seems that is not possible :-( -- http://mail.python.org/mailman/listinfo/python-list
#define (from C) in Python
Is there a Python version of C's language #define statements? Example: #define ReadMem( (x) )memory[ (x) ] Instead of using a function, when you call to ReadMem(), the code is INCLUDED, (no function is called, the "compiler" just substitues the ReadMem( expression ) with memory[ (expression) ] . I want to avoid function calls to speed up a program by sacrifizing the resulting size ... Is that possible? -- http://mail.python.org/mailman/listinfo/python-list
Re: Writing an emulator in python - implementation questions (for performance)
> > I'm trying to port (just for fun), my old Sinclair Spectrum emulator, > > ASpectrum, from C to Python + pygame. > > The answer to your question is, "Use numpy". More details below. Let's see :-) > > How can I implement this in Python, I mean, define a 16 byte variable > > so that high and low bytes can be accessed separately and changing W, > > H or L affects the entire variable? I would like to avoid doing BIT > > masks to get or change HIGH or LOW parts of a variable and let the > > compiled code to do it by itself. > > You can do clever memory slicing like this with numpy. For instance: > > breg = numpy.zeros((16,),numpy.uint8) > wreg = numpy.ndarray((8,),numpy.uint16,breg) > > This causes breg and wreg to share the same 16 bytes of memory. You > can define constants to access specific registers: > > R1L = 1 > R1H = 2 > R1 = 1 > > breg[R1H] = 2 > print wreg[R1] And how about speed? Assuming a 16 bit register named BC which contains 2 8 bit regiters (B and C)... Will the above be faster than shifts and bit operations (<<, and, >> ) with new B and C values to "recalculate" BC when reading or changing either B, C or BC? > > Is python's array module the best (and fastest) implementation to > > "emulate" the memory? > > I'd use numpy for this as well. (I doubt the Z80 had a 16-bit bus, > but if it did you could use the same memory sharing trick I showed you > with the registers to simulate word reads and writes.) Z80 has a 16 bit ADDRESS bus, 8 bit DATA bus. This means you can address from 0 to 65535 memory cells of 8 bytes. Z80 has 16 bit bus operations, but currently in C I write 16 bit values as two 8 bit consecutive values without using (unsigned short *) pointers. But it seems that numpy would allow me to do it better than C in this case... > Note that, when performing operations on single values, neither numpy > nor array module are necessarily a lot faster than Python lists, might > even be slower. But they use a LOT less memory, which is important > for largish arrays. Well, we're talking about a 128KB 1-byte array, that's the maximum memory size a Sinclair Spectrum can have, and always by using page swapping of 16KB blocks in a 64KB addressable space... If you really think that python lists can be faster that numpy or array modules, let me know. Maybe I'll make a "benchmark test", by making some millions of read / write operations and timing the results. I wan't to write the emulator as "pythonic" as possible... > > I don't know how to emulate paging in python... > > numpy again. This would mean you'd have to fiddle with addresses a > bit, but that shouldn't be too big a deal. Create the physical > memory: > > mem = numpy.zeros((128*1024,),numpy.uint8) A 128K array of zeroes... > Then create the pages. (This is a regular Python list containing > numpy slices. numpy slices share memory so there is no copying of > underlying data.) > > page = [mem[0:16*1024], > mem[16*1024:32*1024], > mem[32*1024:48*1024], > mem[48*1024:64*1024]] Those are just like pointers to the "mem" numpy array, pointing to concrete start indexes, aren't they? > To access the byte at address 42432, you'd have use bit operations to > get a page number and index (2 and 9664 in this case), then you can > access the memory like this: Do you mean: page = address / 16384 index = address MOD 16384 ? Or, better, with: page = address >> 14 index = address & 16383 ? > page[2][9664] = 33 > p = page[3][99] > > To swap a page, reassign the slice of main memory, > > page[2] = mem[96*1024:112*1024] > > Now, accessing address 42432 will access a byte from a different page. But the above calculations (page, index) wouldn't be slower than a simple play 64KB numpy array (and make no paging mechanism when reading or writing) and copy memory slices when page swappings are requested? > If you don't want to fiddle with indirect pages and would just rather > copy memory around when a page swap occurs, you can do that, too. > (Assigning to a slice copies the data rather than shares.) I don't > know if it's as fast as memset but it should be pretty quick. That's what I was talking about. With "page and index" I'm slowing down EACH memory read and write, and that includes opcode and data fetching... With "memory copying in page swaps", memory is always read and write quickly, and if "slice copies" are fast enough, the emulation will be >100% of speed (I hope) for a 3.5Mhz system ... > Hope these brief suggestions help. If you don't want third party > libraries, then numpy will be of no use. But I guess if you're using > pygame third party modules are ok. So get numpy, it'll make things a > lot easier. It can be a bit daunting to learn, though. Yes, you've been very helpful! How about numpy portability? Is array more portable? And finally, do you think I'm doing right by using global variables for registers, memory, and so, or should I put ALL into
Writing an emulator in python - implementation questions (for performance)
Hi. I'm trying to port (just for fun), my old Sinclair Spectrum emulator, ASpectrum, from C to Python + pygame. Although the Sinclair Spectrum has a simple Z80 8 bit 3.5Mhz microprocessor, and no aditional hardware (excluding the +2/+3 model's AYsound chip), I'm not sure if my loved scripted language, python, will be fast enought to emulate the Sinclair Spectrum at 100% speed. There are Java Spectrum emulators available, so it should be possible. Anyway, this message is directed to prepare the DESIGN so that the code can run as fast as possible. I mean, I want to know the best way to do some emulation tasks before starting to write a single line of code. My questions: GLOBAL VARIABLES VS OBJECTS: == I need the emulation to be as fastest as possible. In my C program I have an struct called "Z80_Processor" that contains all the registers, memory structures, and so on. I pass that struct to the Z80Decode(), Z80Execute() or Z80Dissassemble() functions, i.e.. This allows me (in my C emulator) to emulate multiple z80 processors If I want. As Python is scripted and I imagine that emulation will be slower than the emulator written in C, I've thought of not creating a Z80_Processor *object* and declare global variables such as reg_A, reg_B, reg_PC, array main_memory[] and so on, and let the z80 functions to directly access that global variables. I'm doing this to avoid OOP's extra processing... but this makes the program less modular. Do you think using processor "objects" would make the execution slower, or I'm doing right using global variables and avoiding objects in this type of program? Should I start writing all the code with a Z80CPU object and if performance is low, just remove the "object" layer and declare it as globals, or I should go directly for globals? HIGH AND LOW PART OF REGISTERS: = - In C, I have the following structs and code for emulating registers: typedef union { struct { unsigned char l, h; } B; unsigned short W; } eword; eword reg_A; This means that reg_A is a 16 bit "variable" that I can directly access with reg_A.w=value, and I can access also the LOW BYTE and HIGH BYTES with reg_A.B.h and reg_A.B.l. And more importante, changing W modifies l and h, and changing l or h modifies W. How can I implement this in Python, I mean, define a 16 byte variable so that high and low bytes can be accessed separately and changing W, H or L affects the entire variable? I would like to avoid doing BIT masks to get or change HIGH or LOW parts of a variable and let the compiled code to do it by itself. I know I can write an "object" with set and get methods that implement that (that could be done in C too), but for emulation, I need the FASTEST implementation possible (something like the C's Union trick). MEMORY (ARRAYS): === To emulate Spectrum's memory in C, I have a 64KB array like: unsigned char memory_array[65535]. Then I can access memory_array[reg_PC] to fetch the next opcode (or data for an opcode) and just increment reg_PC. Is python's array module the best (and fastest) implementation to "emulate" the memory? MEMORY (PAGES): = The Sinclair Spectrum 8 bit computer can address 64KB of memory and that memory is based on 16KB pages (so it can see 4 pages simultaneously, where page 0 is always ROM). Programs can change "pages" to point to aditional 16KB pages in 128KB memory models. I don't know how to emulate paging in python... My first approach would be to have eight 16KB arrays, and "memcpy()" memory to the main 64KB array when the user calls page swapping. I mean (C + pseudocode): main_memory[65536]; memory_blocks[8][16384]; // Initial settings current_pages[4] = [0, 1, 2, 3] // User swaps last memory page (3) to block 7, so I: page_to_swap_from = 3 page_to_map = 7 // Save the contents of current page (page being unmapped): memcpy( main_memory, // Source 16384*page_to_swap_from, // Starting at memory_blocks[current_pages[page_to_swap_from], // To 16384 ); // 16K // Now map page 7 to memory block 3: memcpy( memory_blocks[page_to_map], // Source 0, // Starting at main_memory[page_to_swap_from*16384],// To 16384 ); // 16K current_pages[page_to_swap_from] = page_to_map; Memcpy is very fast in C, but I don't know if doing the same in python with arrays would be fast enough, or if there is a better approach to simulate paging of 16KB blocks in a 64KB memory windows (4 mappable memory blocks). Maybe another approach based in pointers or something like that? -- http://mail.python.org/mailman/listinfo/python-list
Re: Read binary file and dump data in
> If you are reading arbitrary bytes then it will likely not always "look" > like integers. What you probably meant is: > > for i in data: > print "%d, " % ord(i) That's it! :-) Thanks a lot. -- http://mail.python.org/mailman/listinfo/python-list
Read binary file and dump data in
Hi. Until now, all my python programs worked with text files. But now I'm porting an small old C program I wrote lot of years ago to python and I'm having problems with datatypes (I think). some C code: fp = fopen( file, "rb"); while !feof(fp) { value = fgetc(fp); printf("%d", value ); } I started writing: fp = open(file, "rb") data = fp.read() for i in data: print "%d, " % (int(i)) But it complains about i not being an integer... . len(data) shows exactly the file size, so maybe is a "type cast" problem... :-? What's the right way to work with the binary data (read 1 byte values and work with them, dumping them as an integer in this case)? Thanks. -- http://mail.python.org/mailman/listinfo/python-list
Re: How to ignore the first line of the text read from a file
> I want to read text line-by-line from a text file, but want to ignore > only the first line. I know how to do it in Java (Java has been my > primary language for the last couple of years) and following is what I > have in Python, but I don't like it and want to learn the better way > of doing it. Why don't you read and discard the first line before processing the rest of the file? file = open(filename, 'r') file.readline() for line in file: print line, (It works). -- http://mail.python.org/mailman/listinfo/python-list
Re: What Python looks like
> I'm curious, what did Python code look like to those of you who have > seen a bunch of Python code for the first time before k Clean and readable. -- http://mail.python.org/mailman/listinfo/python-list
Re: How to access object attributes given a string
> >> You are using a scripting language.. why not use python directly? > > > I just want to execute an small set of commands (PLAYSOUND, PLAYMUSIC, > > WALKTO, PLAYERSAY, SLEEP and a couple more) ... do you think I can > > write python code inside my object.exec (list attribute) loaded from a > > file? > > Something like that. > > Build a dictionary -that will be used as the script global namespace- > (...) > > Warning: this is unsafe!!!. Malicious users could execute arbitrary code; > although this may not be an issue if the game runs on the user's own > system. > > The advantage is that you let them use all the power of Python as a > scripting language. That's why I was trying to write my own "small" scripting language :-). It works, but I would like to know how to write it better or safer. That's why I posted the source code. Thanks. -- http://mail.python.org/mailman/listinfo/python-list
Re: How to access object attributes given a string
This is faster: http://www.sromero.org/python/zx_parseexec.py http://www.sromero.org/python/test.par XD -- http://mail.python.org/mailman/listinfo/python-list
Re: How to access object attributes given a string
And the rest of the code: # def ExecParser_Exec( exec_type, code, game, debug=0 ): """ Execute the previously "compiled" code: """ code_level = 0 #player = game.player #world = game.world # Take only opcodes for EXEC or EXEC2, deppending on exec_type exec_code = filter( lambda x : x[0] == exec_type, code ) i = -1 while 1: i += 1 cmd_level, cmd, params = exec_code[i][1:4] spaces = " "*((code_level+1)*3) # End of script (appended by the compiler) if code_level == cmd_level: if cmd.startswith("IF ") or cmd.startswith("ELIF "): # Get boolean funtion and evaluate it # IF true: #remove all ELIF/ELSE blocks until next ENDIF at the same code level #increase codelevel # IF false: #remove all code until next ELIF/ELSE/ENDIF at the same code level booleanf = cmd.split(" ")[1] if debug: print "Checking ", spaces, cmd, params, " (returned", if ExecParser_CheckBoolean(booleanf, params): if debug: print "TRUE)" # Ignore lines until we find an ENDIF at the same code level: done = 0 j = i # Ignore all lines until we found the same code level (next ELIF/ELSE/ENDIF): while not done: j += 1 next_cmd_level, next_cmd = exec_code[j][1:3] if next_cmd_level==cmd_level or next_cmd.startswith("END"): done = 1 nextcond_line = j # Next branch is an endif, do nothing: if exec_code[nextcond_line][2].startswith("ENDIF") or \ exec_code[nextcond_line][2] == "END": pass # Next branch is ELIF or ELSE: delete all until ENDIF +cmd_level found else: done = 0 while not done: if exec_code[nextcond_line] [2].startswith("ENDIF") or \ exec_code[nextcond_line][2] == "END": done = 1 else: del exec_code[nextcond_line] # - Endif -> stop here code_level += 1 i -= 1 else: if debug: print "FALSE)" done = 0 # Ignore all lines in the current while not done: i += 1 next_cmd_level, next_cmd = exec_code[i][1:3] if (next_cmd.startswith("ELIF ") or next_cmd.startswith("ELSE")): i -= 1 done = 1 elif next_cmd.startswith("ENDIF") and (next_cmd_level == code_level): done = 1 continue if cmd.startswith("ELSE") and cmd_level != -1: if debug: print "Entering ", spaces, "ELSE" code_level += 1 elif cmd.startswith("ENDIF") and cmd_level != -1: if code_level > 0: code_level -= 1 else: if code_level == cmd_level: if cmd == "END": if debug: print "Executing", spaces, cmd return 1 else: if debug: print "Executing", " "*((code_level+1)*3), cmd, params ExecParser_ExecOpcode( cmd, params, game, debug ) return 1 # def ExecParser_PrintCode( code, formatted=0 ): """ Print code compiled/parsed by ExecParser_Parse(). Prints opcodes (formatted=0) or indented source code (formatted=1) from a previously compiled/parsed opcode list. """ if not formatted: # Print opcodes: print "\n> Compiled opcodes: <" print "\nExecType CodeLevel Opcode" print "--" for c in code: print "%-8s %-8s" % (c[0],c[1]), for f in c[2:]: if f != []: print f, print else: # Display source code indented print "\n> Formatted code (parsing opcodes): <" print "\nMain:" for i in code: spaces = " " * 3*(1+i[1]) func = i[2] params = [ str(x) for x in i[3] ] if func == "REM": print "%s%s %s" % (spaces, func, i[3][0]) else: if params != []: print "%s%s(" % (spaces, func), for i,p in enumerate(params): if i == len(params)-1: print "%s )" % (p) else: print "%s," % (p), else : print "%s%s" % (spaces, func) That's all. I can put the .py and test.par files online if anyone wants to test it and point me to the right direction on "how to code your own small scripting language written in python scriptin
Re: How to access object attributes given a string
And the big functions: I imagine that the following is HORRIBLE in the pythonic-vision and surely can be rewriten with a single map+reduce+filter + 200 lambdas functions X-D, but I come from C and any advice on how to implement my "simple scripting language" without using lex or yacc is welcome :) # def ExecParser_Parse( key, value, line, file ): """ Parses an exec or exec2 line, generating a list of "opcodes". This function takes an exec= line from a OBJ file and parses it generating a list of "executable opcodes" in a format executable by ExecParser_Exec(). The rules for this "small" language are: - Spaces and tabs are stripped. - Comments (starting by REM) are ignored. - A simple set of commands is available. Those commands modify some game variables or objects. As an example: PLAYSOUND(snd), plays the sound identified by the sound_tag "snd". - Commands must be separated by ";" characters. - Commands can receive parameters enclosed between ( and ) of types INT or STR. - Programmer can use "self" to refer to the current object in functions that accept an object or enemy text id. - Simple control flow is present with IF, ELIF, ELSE and ENDIF statements. - IF and ELIF statemens are followed by a BOOLEAN command, which will return 0 or 1. Example ('\' character wraps lines in the OBJ file): KILLOBJECT(coin);\ REM Wait 5 seconds;\ IF FLAG(5);\ SLEEP(5);\ PLAYERSAY(test,5);\ SETMAP(10,10,top,5);\ IF FLAG(6);\ NOP();\ SLEEP(7);\ ELIF FLAG(7);\ NOP();\ SLEEP(9);\ ELSE;\ SLEEP(999);\ ENDIF;\ IF FLAG_VALUE(7,1);\ CHANGESCREEN(start,10,100);\ PLAYERFACING(0);\ ENDIF;\ ENDIF;\ SLEEP(12);\ SLEEP(11); This function will parse the exec line and produce as output opcodes in this format: [ type_of_exec, if_level, opcode, parameters ] type_of_exec = 1 for exec= lines, and 2 for exec2= lines. if_level is the current code "level" or scope. IF statements increase if_level and ENDIF statements decrease it. opcode and parameters are the function_name and the params for this command. Example: ExecType CodeLevel Opcode and params -- 10KILLOBJECT ['coin'] 00REM ['Wait 5 seconds'] 10IF FLAG [5] 11SLEEP [5] 11PLAYERSAY ['test', 5] 11SETMAP [10, 10, 'top', 5] 11IF FLAG [6] 12NOP 12SLEEP [7] 11ENDIF 10ENDIF 10END The function makes some small checkings, like: count(IF)==count(ENDIFs), check number of arguments, argument type checking, validate command functions, and some others, but it does not cover all possible syntax errors or typing mistakes. """ reserved_words = { "SETMAP" : ( 4, "int", "int", "str", "int" ), "KILLOBJECT" : ( 1, "str" ), "ENABLEOBJECT" : ( 1, "str" ), "DISABLEOBJECT" : ( 1, "str" ), "PLAYSOUND" : ( 1, "str" ), "PLAYMUSIC" : ( 1, "str" ), "SLEEPCYCLES" : ( 1, "int" ), "SLEEP" : ( 1, "int" ), "SHOWTEXT" : ( 1, "str" ), "SHOWTEXTTIMED" : ( 2, "str", "int" ), "SHOWSCREEN" : ( 2, "str", "int" ), "CHANGESCREEN" : ( 3, "str", "int", "int" ), "ADDINVENTORY" : ( 1, "str" ), "REMOVEINVENTORY" : ( 1, "str" ), "OBJECTFACING" : ( 2, "str", "int" ), "PLAYERFACING" : ( 1, "int" ), "PLAYERSAY" : ( 2, "str", "int" ), "OBJECTSAY" : ( 3, "str", "str", "int" ), "SETFLAG" : (2, "int", "int" ), "INCFLAG" : (1, "int" ), "DECFLAG" : (1, "int" ), "DELEXEC" : (1, "int" ), "REM" : ( 0, ), "NOP" : ( 0, ), "END" : ( 0, ), "TRUE" : ( 0, ), "FALSE" : ( 0, ), "IF" : ( 0, ), "ELIF" : ( 0, ), "ELSE" : ( 0, ), "ENDIF" : ( 0, ), "FLAG" : ( 1, "int" ), "NOT_FLAG" : ( 1, "int" ), "FLAG_VALUE" : ( 2, "int", "int" ), "PLAYER_HAS" : ( 1, "str" ), "PLAYER_HAS_NOT" : ( 1, "str" ), "SCREEN_IS" : ( 1, "str" ), "SCREEN_IS_NOT" : ( 1, "str" ) } #input is something like: "exec=COMMAND;COMMAND;COMMAND..." if key.upper() == "EXEC": exec_type = 1 code = [] # Resulting code if ";" in value: commands = value.split(";") else: commands = list( value ) # Filter empty lines commands = filter( lambda x: len(x) > 1, commands ) code_level = level_inc = 0 # Current scope level found_if = found_elif = 0 # Parse all commands in the input script for cmd_counter, cmd in enumerate(commands): if cmd == '': continue
Re: How to access object attributes given a string
Before I reinvent the wheel, I'm going to post the code. Feel free to give any advice, and think that I'm new to python, it's only 1 month since I began programming in python "seriously" (up to that moment, I wrote just a few log-text parsing system administration scripts to speed up some old bash scripts). First of all, my currently test file: KILLOBJECT(coin);\ REM Wait 5 seconds;\ IF FLAG(5);\ SLEEP(5);\ PLAYERSAY(test,5);\ SETMAP(10,10,top,5);\ IF FLAG(6);\ NOP();\ SLEEP(7);\ ELIF FLAG(7);\ NOP();\ SLEEP(9);\ ELSE;\ SLEEP(999);\ ENDIF;\ IF FLAG_VALUE(7,1);\ CHANGESCREEN(start,10,100);\ PLAYERFACING(0);\ ELSE;\ PLAYERFACING(1);\ ENDIF;\ ENDIF;\ SLEEP(12);\ SLEEP(11) And the parse code: if __name__ == "__main__": """ To test: create an example file test.par with language commands. """ numline = 0 try: fp = open("test.par") except: print "Error, cant open test.par" import sys sys.exit(0) while 1: # Read line, ignore comments and stop with EOF numline += 1 line = fp.readline() if line == '': break line = line.strip() startline = numline # Join lines splitted with \ in the text file while line.endswith("\\"): next_line = fp.readline() if next_line == '': break if next_line.strip() == '': continue numline += 1 next_line = next_line.strip() line = line[:-1] + next_line code = ExecParser_Parse( "exec", line, startline, "test.par" ) for i in 0, 1: ExecParser_PrintCode( code, i ) print ExecParser_Exec( 1, code, 0, debug=1 ) And this is the output: > Compiled opcodes: < ExecType CodeLevel Opcode -- 10KILLOBJECT ['coin'] 00REM ['Wait 5 seconds'] 10IF FLAG [5] 11SLEEP [5] 11PLAYERSAY ['test', 5] 11SETMAP [10, 10, 'top', 5] 11IF FLAG [6] 12NOP 12SLEEP [7] 11ELIF FLAG [7] 12NOP 12SLEEP [9] 11ELSE 12SLEEP [999] 11ENDIF 11IF FLAG_VALUE [7, 1] 12CHANGESCREEN ['start', 10, 100] 12PLAYERFACING [0] 11ELSE 12PLAYERFACING [1] 11ENDIF 10ENDIF 10SLEEP [12] 10SLEEP [11] 10END > Formatted code (parsing opcodes): < Main: KILLOBJECT( coin ) REM Wait 5 seconds IF FLAG( 5 ) SLEEP( 5 ) PLAYERSAY( test, 5 ) SETMAP( 10, 10, top, 5 ) IF FLAG( 6 ) NOP SLEEP( 7 ) ELIF FLAG( 7 ) NOP SLEEP( 9 ) ELSE SLEEP( 999 ) ENDIF IF FLAG_VALUE( 7, 1 ) CHANGESCREEN( start, 10, 100 ) PLAYERFACING( 0 ) ELSE PLAYERFACING( 1 ) ENDIF ENDIF SLEEP( 12 ) SLEEP( 11 ) END Executing KILLOBJECT ['coin'] Checking IF FLAG [5] (returned TRUE) ExecutingSLEEP [5] ExecutingPLAYERSAY ['test', 5] ExecutingSETMAP [10, 10, 'top', 5] Checking IF FLAG [6] (returned FALSE) Checking ELIF FLAG [7] (returned FALSE) Entering ELSE Executing SLEEP [999] Checking IF FLAG_VALUE [7, 1] (returned FALSE) Entering ELSE Executing PLAYERFACING [1] Executing SLEEP [12] Executing SLEEP [11] Executing END -- http://mail.python.org/mailman/listinfo/python-list
Re: How to access object attributes given a string
> > def ChangeAttribute( object, attribute, value ): >help(setattr) > > Help on built-in function setattr in module __builtin__: > > setattr(...) setattr(object, name, value) > > Set a named attribute on an object; setattr(x, 'y', v) is > equivalent to`x.y = v''. and > Gary Herron write: > You want getattr and setattr: Thanks a lot, that's what I was looking for. > Dennis Kempin wrote: > You are using a scripting language.. why not use python directly? Well, I have a .OBJ with something like: # exec is the code executed when the player gets the object ADDOBJECT:coin:x=10:y=10:screen=200:exec=\ SETMAP(10,10,1);\ SLEEP(1);\ PLAYSOUND(get_coin);\ IF FLAG(10);\ SETLOOKING(left);\ PLAYERSAY(blah);\ SLEEP(2);\ ELSE;\ PLAYERSAY(blahblah);\ SLEEP(3);\ ENDIF;\ That's a simple example of the language I've wrote for my game. Now it's being "compiled" nicely and it works. I just want to execute an small set of commands (PLAYSOUND, PLAYMUSIC, WALKTO, PLAYERSAY, SLEEP and a couple more) ... do you think I can write python code inside my object.exec (list attribute) loaded from a file? Currently I'm compiling the above in a ( scope_level, function, parameters ) list: object.exec = [ [ 0, "SETMAP", [10, 10, 1] ], [ 0, "SLEEP", [1] ], [ 0, "PLAYSOUND", ["get_coin"] ], [ 0, "IF FLAG", [10] ], [ 1, "SETLOOKING", ["left"] ], (...) ] I make some checks (as many resulting opcodes as input commands, check of IF/ELIF/ELSE/ENDIF statements to see if all are correct, right parameter types (currently only integer or strings), right parameter number, and so on. Do you mean that I can replace my "language" by just python (defining SETMAP, SLEEP and all those functions somewhere in my main source code). -- http://mail.python.org/mailman/listinfo/python-list
How to access object attributes given a string
Hi... I'm trying to guess how to access attributes of an existing object given the attribute name in a string. I mean: class Object: self.x = 12 self.y = 20 self.name = "blah" def ChangeAttribute( object, attribute, value ): # Insert here the code for object.attribute = value X Allowing this kind of calls: ChangeAttribute( object, "x", 200 ) ChangeAttribute( object, "name", "my name" ) Thanks. PS: I need it for a concrete case in a game scripting language I'm writing, so that I can call functions like "CHANGE_PLAYER_VALUES( "x", 100 )". -- http://mail.python.org/mailman/listinfo/python-list
Why not a Python compiler?
( Surely if this question has been asked for a zillion of times... ) ( and sorry for my english! ) I'm impressed with python. I'm very happy with the language and I find Python+Pygame a very powerful and productive way of writing 2D games. I'm not, at this moment, worried about execution speed of the small game I'm working on (it runs at full 60 fps even in an old AMD- K6 450 Laptop computer), but I continue asking me the same question: Why not a Python COMPILER? It would be very nice to be able to output Linux, MAC or Windows binaries of compiled (not bytecompiled) code. It would run faster, it will be smaller in size (I think) and it will be easy to distribute to people not having python installed. Yes, I know about py2exe, but I'm not sure if that's the right aproach. So, what's wrong with compiling python? Maybe is not possible due to nature of the language? Is just a decision? What do you think about this? -- http://mail.python.org/mailman/listinfo/python-list
Re: Removal of element from list while traversing causes the next element to be skipped
On 30 ene, 08:09, Paul Rubin <http://[EMAIL PROTECTED]> wrote: > Santiago Romero <[EMAIL PROTECTED]> writes: > > > > >>> li = [1,2,3,4,5] > > > >>> filter(lambda x: x != 3, li) > > > [1, 2, 4, 5] > > > I haven't measured it, but this should be the fast solution in all > > the thread ... > > li.remove(3) is probably faster. But that only removes the first ocurrence of item==3. In a = [1, 2, 3, 3, 3, 4, 3, 3, 2, 3], the filter solution will efectively remove all items with value == 3 while li.remove(3) will only remove the first ocurrence. Bye! -- http://mail.python.org/mailman/listinfo/python-list
Re: Removal of element from list while traversing causes the next element to be skipped
> how about > > >>> li = [1,2,3,4,5] > >>> filter(lambda x: x != 3, li) > [1, 2, 4, 5] I haven't measured it, but this should be the fast solution in all the thread ... -- http://mail.python.org/mailman/listinfo/python-list
Re: Removal of element from list while traversing causes the next element to be skipped
> Look at this -- from Python 2.5.1: > > >>> a = [1, 2, 3, 4, 5] > >>> for x in a: > ... if x == 3: > ... a.remove(x) > ... print x Well ... you could use: >>> for i in range(len(a)-1, -1, -1): ...print a[i] ...if a[i] == 3: del a[i] ... 5 4 3 2 1 >>> print a [1, 2, 4, 5] Bye. -- http://mail.python.org/mailman/listinfo/python-list
Re: Sorting a list depending of the indexes of another sorted list
Thanks all for the answers ... I'll use a tuple as you said :) Anyway, is interesting to know how to sort 2 lists when you dont want to use tuples, so thanks also to Peter :) > Then one have to split the list twice.Given the list is large,it's maybe > not good for performance.Is it a more effective split way? Well, I just use: rows = i.split(' ') a = rows[3] b = rows[5] X-D -- http://mail.python.org/mailman/listinfo/python-list
How to use py2exe ...
Hi... I'm a Linux user, and I would like some windows-friends to test a game I'm writing with python+pygame without they needing to install python, pygame, and so on. I've heard about py2exe and pygame2exe, but I'm not sure on how to use them to create: a.- standalone exe files with a single .py program. Example: myprogram.py or b.- exe files containing all my source code + data directories (png files, data files, and so). Example: main.py, doc/README, src/*.py and data/* The problem is I'm not sure on how to use py2exe and pygame2exe to build the executables... And finally, a question: if I want to provide source code separately ... can I include .pyc files instead of .py files? -- http://mail.python.org/mailman/listinfo/python-list
Sorting a list depending of the indexes of another sorted list
Hi ... I have the following DNS MX records info: domain.com preference 10 host mx1.domain.com preference 30 host anotherhost.domain.com preference 20 host mx2.domain.com I'm storing this info in 2 lists: preferences = [10, 30, 20] hosts = [ "mx1.domain.com", "anotherhost.domain.com", "mx2.domain.com"] (I was about to use a dict of preferences : domain, but it's possible to find 2 mx records with the same preference, so keys wouldnt be unique). I'm trying to sort both lists so that they end like this: preferences = [10, 20, 30] hosts = [ "mx1.domain.com", "mx2.domain.com", "anotherhost.domain.com" ] I want to sort hosts list depending on the numeric order of "preferences". And finally ... do you think there is a better python structure to store this data and sort it in a more easy way? Thanks. -- http://mail.python.org/mailman/listinfo/python-list
Re: Converting a bidimensional list in a bidimensional array
> > - Speed Performance: Do you think that changing from list to Array() > > would improve speed? I'm going to do lots of tilemap[y][x] checks (I > > mean, player jumping around the screen, checking if it's falling over > > a non-zero tile, and so). > First of all: if you have enough memory to use a python list, then I > suggest you to use a list. > > Often python lists are faster than array.array (maybe because python > lists actually contain pyobjects). My problem is that, in my game, each screen is 30x20, and I have about 100 screens, so my tilemap contains 32*20*100 = 6 python objects (integers). If each integer-python-object takes 16 bytes, this makes 6 * 16 = almost 1MB of memory just for the tilemaps... Using array of type H (16 bits per item = 2 bytes), my maps take just 6*2 = 120KB of memory. After that, I just will access tilemap data for reading (i.e. value = tilemap.GetTile(x,y)) ... Do you think I should still go with lists instead of an H-type array? -- http://mail.python.org/mailman/listinfo/python-list
Re: How to get memory size/usage of python object
> Would you care to precisely define "REAL size" first? Consider: > > >>> atuple = (1, 2) > >>> mylist = [(0, 0), atuple] > > Should sizeof(mylist) include sizeof(atuple) ? No, I'm talking about "simple" lists, without REFERENCES to another objects into it. I mean: lists = [ 0, 1, 2, 3, 4, (1,2), 3] or array = [ [0,0,0,0,0,0,0], [1,1,1,1,2,1,2], ... ] Maybe I can "pickle" the object to disk and see the filesize ... :-? -- http://mail.python.org/mailman/listinfo/python-list
Re: Converting a bidimensional list in a bidimensional array
> C:\> \python25\python -m -s :-) Thanks a lot :-) -- http://mail.python.org/mailman/listinfo/python-list
Re: printing dots in simple program while waiting
On 9 ene, 17:48, John <[EMAIL PROTECTED]> wrote: > i want to print something like: > > (1sec) working... > (2sec) working > (3sec) working. > > where the 'working' line isn't being printed each second, but the dots > are being added with time. > > something like: > > import time > s = '.' > print 'working' > while True: > print s > time.sleep(1) > > however, this doesn't work since it prints: > > working > . > . Change > print s to > print s, (With the ending ",", which sends NO linefeed to stdout) Bye :) -- http://mail.python.org/mailman/listinfo/python-list
How to get memory size/usage of python object
Is there a way to check the REAL size in memory of a python object? Something like > print sizeof(mylist) or > print sizeof(myclass_object) or something like that ... Thanks. -- http://mail.python.org/mailman/listinfo/python-list
Re: Converting a bidimensional list in a bidimensional array
> > This is how I create the tilemap (and the clipboard, a copy of my > > tilemap): > > > def __init__( self, bw, bh, tiles ): > > self.tilemap = [] > > (...) > > for i in range(bh): > > self.tilemap.append([0] * bw) >def __init__( self, bw, bh, tiles ): > self.width, self.height = bw, bh > self.tilemap = array.array('b', [0]) * bw * bh > > Gives a pure linearization (you do the math for lines). Do you mean : tilemap[(width*y)+x] ? >def __init__( self, bw, bh, tiles ): > self.width, self.height = bw, bh > self.tilemap = [array.array('b', [0]) * bw for row in range(bh)] > > Gives a list of arrays. I punted on the type arg here; you should make > a definite decision based on your data. What do you think about: - Memory Performance: Of course, my maps will take ( 16 bytes / 2-4 bytes ) = 8 or 4 times less memory (32 / 64 bit processores) ... right? - Speed Performance: Do you think that changing from list to Array() would improve speed? I'm going to do lots of tilemap[y][x] checks (I mean, player jumping around the screen, checking if it's falling over a non-zero tile, and so). And thanks a lot for your answer :-) -- http://mail.python.org/mailman/listinfo/python-list
Converting a bidimensional list in a bidimensional array
Hi :) First of all, I must apologize for my poor english :) I'm starting with python and pygame and for testing (and learning) purposes I wrote an small "Map Editor" for a small game project I'm going to start next month. The tilemap editor is working fine, but reading Guido's Van Rossum PYTHON TUTORIAL I found that my game map is "wasting" memory by using about 16 bytes for each item in it, because every item in a python list takes 16 bytes in memory. In the same tutorial, I found references to the "array()" function of the "array" module. I'm trying to change my current working source code so that it works with an array instead of using a list, but I'm not managing to do it. My tilemap is something like (think on 0=empty, 1=floor, 2=rock, and so...): [ [0 ,0, 0, 0, 0, 0, 0, 0 ,0], [0 ,0, 0, 0, 0, 0, 0, 0 ,0], [2 ,0, 0, 0, 0, 2, 2, 0 ,0], (...) [2 ,2, 0, 0, 2, 2, 2, 0 ,0], [1 ,1, 1, 1, 1, 1, 1, 1 ,1], ] This is how I create the tilemap (and the clipboard, a copy of my tilemap): def __init__( self, bw, bh, tiles ): self.width, self.height = bw, bh self.tilemap = [] self.clipboard = [] (...) for i in range(bh): self.tilemap.append([0] * bw) self.clipboard.append([0] * bw) And that's how I'm using it (the functions I'm having trouble to convert to use the array): #- def CopyToClipboard( self ): for j in range( self.height ): self.clipboard[j][:] = self.tilemap[j][:] #- def Draw( self, clear=1 ): screen = pygame.display.get_surface() if clear: self.Clear() for j in range(self.GetHeight()): for i in range(self.GetWidth()): self.DrawBlock( i, j ) #- def DrawBlock( self, x, y ): screen = pygame.display.get_surface() xd = (x * self.TileWidth()) + self.originx; yd = (y * self.TileHeight()) + self.originy; b = self.tilemap[y][x] self.tileset.tiles[b].Draw( screen, xd, yd ) #- def ResizeWidth( self, new ): bw, bh = self.GetWidth(), self.GetHeight() if new > bw: for j in range(bh): for i in range(new-bw): self.tilemap[j].append( 0 ) self.clipboard[j].append( 0 ) self.SetWidth( new ) elif new < bw: for j in range(bh): for i in range(bw-new): del self.tilemap[j][-1] del self.clipboard[j][-1] self.SetWidth( new ) #- def ResizeHeight( self, new ): bw, bh = self.GetWidth(), self.GetHeight() if new > bh: for i in range(new-bh): self.tilemap.append([0] * bw) self.clipboard.append([0] * bw) self.SetHeight( new ) elif new < bh: for i in range(1,bh-new): del self.tilemap[-1] self.SetHeight( new ) In fact, I'm even unable to create the array correctly: I've tried: self.tilemap = array('H', []) for i in range(bh): self.tilemap.append([0] * bw) and: for i in range(bh): for j in range(bw): self.tilemap[i].append(0) But I receive errors like (either defining or using the array): b = self.tilemap[y][x] TypeError: 'int' object is unsubscriptable or: self.tilemap.append( [0] * bw ) TypeError: an integer is required So ... please ... any idea on how to convert my "python object" array of lists to a bidimensional array and how to use it to index [y][x] elements, or even resize it with the ResizeWidth() and Height() functions? Thanks everybody. PS: Please, think that I come from C/C++ so I still have some "C ways of doing things" while there are better/faster ways to do the same in Python. Feel free also to correct any "C-Style" programming way that you can find in my source code above... :-) -- http://mail.python.org/mailman/listinfo/python-list