3 # a utility to extract information from Creatures 1/2 SFC (world save)/EXP (creature export) files
4 # reverse-engineered by fuzzie and nornagon
6 # TODO: a lot of reads probably need to be changed to signed reads
8 # TODO: lots of unknown values :)
12 for i
in open("identifiers.txt").readlines():
13 x
= i
.strip().split("\t")
14 identifiers
[x
[0]] = x
[1]
18 def getidentifier(family
, genus
, species
):
19 x
= "%d%02d%03d" % (family
, genus
, species
)
25 # utility functions to read values from a stream
30 return struct
.unpack("<i", x
)[0]
34 return struct
.unpack("<I", x
)[0]
38 return struct
.unpack("<H", x
)[0]
42 return struct
.unpack("<B", x
)[0]
52 # read an MFC class from file object f
53 # if you pass reqclass, the code will assert it got an object of that class
56 def slurpMFC(f
, reqclass
= None):
57 global existingobjects
58 # read the pid (this only works up to 0x7ffe, but we'll cope)
64 # completely new class
68 newclass
= sys
.modules
['__main__'].__dict
__[name
]
69 existingobjects
.append(newclass
)
70 elif x
& 0x8000 != 0x8000:
71 # return an existing object which we already read
72 assert x
- 1 < len(existingobjects
)
73 o
= existingobjects
[x
- 1]
75 # assert o.__class__ == reqclass
76 #print "* Returning a " + newclass.__name__ + " (id #" + str(x) + ")"
80 # create an instance of an already-existing class
82 newclass
= existingobjects
[x
- 1]
85 assert newclass
== reqclass
, "slurpMFC wanted " + reqclass
.__name
__ + " but got " + newclass
.__name
__
86 #print "* creating: " + newclass.__name__
88 existingobjects
.append(n
)
93 # this is where all the real logic is - read() slurps up the contents
97 self
.openness
= read8(f
)
98 self
.otherroom
= read16(f
)
100 assert x
== 0, "CDoor zero wasn't zero"
103 # we don't know where 'visited flag' is...
109 self
.roomid
= read32(f
)
111 # check rooms are in order, as they should be, maybe?
113 assert nextroom
== self
.roomid
114 nextroom
= self
.roomid
+ 1
116 # read magic constant
118 assert x
== 2, "magic constant for CRoom wasn't 2"
120 # read room bounding box
121 self
.left
= read32(f
)
123 self
.right
= read32(f
)
124 self
.bottom
= read32(f
)
126 # read doors from four directions
127 self
.doordirections
= []
130 self
.doordirections
.append([])
131 for j
in range(nodoors
):
132 x
= slurpMFC(f
, CDoor
)
134 self
.doordirections
[i
].append(x
)
136 # read roomtype, 0-3 in C2
137 self
.roomtype
= read32(f
)
138 assert self
.roomtype
< 4, "CRoom found weird roomtype: " + str(self
.roomtype
)
141 self
.floorvalue
= read8(f
)
142 self
.inorganicnutrients
= read8(f
)
143 self
.organicnutrients
= read8(f
)
144 self
.temperature
= read8(f
)
145 self
.heatsource
= reads32(f
)
146 self
.pressure
= read8(f
)
147 self
.pressuresource
= reads32(f
)
150 self
.windx
= reads32(f
)
151 self
.windy
= reads32(f
)
153 # slurp up some more data
154 self
.lightlevel
= read8(f
)
155 self
.lightsource
= reads32(f
)
157 # slurp up some more data
158 self
.radiation
= read8(f
)
159 self
.radiationsource
= reads32(f
)
161 # TODO: slurp up 800 unknown bytes! disease data?
162 self
.randombytes
= f
.read(800)
166 assert nopoints
< 100, "sanity check on nopoints"
167 self
.floorpoints
= []
168 for i
in range(nopoints
):
171 self
.floorpoints
.append((pointx
, pointy
))
173 # TODO: slurp up unknown value
175 assert x
== 0, "first footer of CRoom was " + str(x
)
177 self
.music
= readstring(f
)
178 self
.dropstatus
= read32(f
)
179 assert self
.dropstatus
< 3, "dropstatus was " + str(self
.dropstatus
)
184 self
.noframes
= read32(f
)
185 # four chars of filename
186 self
.filename
= f
.read(4)
187 self
.firstsprite
= read32(f
)
188 # TODO: number of references?
189 self
.refs
= read32(f
)
191 # read each piece of framedata in
193 for i
in range(self
.noframes
):
196 # i suspect this may be 'no of references' - fuzzie
197 #assert x == 1 or x == 4, "CGallery framedata 1st byte was " + str(x)
200 # apparently this is '6' in the first eden SimpleObject o.O
201 #assert x == 0, "CGallery framedata 2nd byte was " + str(x)
204 # apparently this is 4 inside eden obj #370, a blackboard
205 # apparently this is 5 inside eden obj #552, a blackboard
206 assert x
== 0 or x
== 1 or x
== 4 or x
== 5, "CGallery framedata 3rd byte was " + str(x
)
208 data
['width'] = read32(f
)
209 data
['height'] = read32(f
)
210 data
['offset'] = read32(f
)
212 print "gallery read file '" + self
.filename
+ "' with " + str(self
.noframes
) + " frame(s) starting at " + str(self
.firstsprite
)
219 print "this is a Creatures 1 SFC file"
221 print "this is a Creatures 2 SFC file"
223 assert False, "didn't understand version " + str(version
)
224 self
.savecount
= read16(f
) # TODO: prbly not actually savecount
225 x
= read16(f
) # <- this is prbly uint32 bit
226 assert x
== 0, "third bytes of MapData were not zero but " + str(x
)
228 x
= read32(f
) # TODO who knows? 0 (common) or 4, so far
229 assert x
== 0 or x
== 4, "fourth bytes of MapData were not zero but " + str(x
)
231 assert x
== 0, "fifth bytes of MapData were not zero but " + str(x
)
233 # sprite for background tiles
234 self
.gallery
= slurpMFC(f
, CGallery
)
237 self
.roomcount
= read32(f
)
238 print "trying to read " + str(self
.roomcount
) + " rooms"
240 for i
in xrange(self
.roomcount
):
248 roomtypes
= ["Indoors", "Surface", "Undersea"]
249 print "room at (" + str(left
) + ", " + str(top
) + "), (" + str(right
) + ", " + str(bottom
) + ") - type " + roomtypes
[roomtype
]
251 self
.rooms
.append(None)
254 self
.rooms
.append(slurpMFC(f
, CRoom
))
258 self
.groundlevel
= []
259 for x
in xrange(261):
260 self
.groundlevel
.append(read32(f
))
262 # mysterious random bytes! like the in-room ones of C2
264 self
.randombytes
= f
.read(800)
266 readingcompound
= False
267 readingscenery
= False
269 class Entity
: # like a compound part?
271 print "--- start part ---"
274 self
.sprite
= slurpMFC(f
)
275 print "sprite file: " + self
.sprite
.filename
277 # currently displayed sprite details
278 self
.currsprite
= read8(f
)
279 self
.imageoffset
= read8(f
)
280 print "curr sprite#: " + str(self
.currsprite
) + ", img offset: " + str(self
.imageoffset
)
283 # TODO: not sure if this should be signed, it makes pointer weird
284 self
.zorder
= reads32(f
)
285 print "zorder: " + str(self
.zorder
)
290 print "loc: " + str(self
.x
) + ", " + str(self
.y
)
292 self
.haveanim
= read8(f
)
293 assert self
.haveanim
== 0 or self
.haveanim
== 1
294 if self
.haveanim
== 1:
295 self
.animframe
= read8(f
)
297 self
.animstring
= f
.read(32)
299 self
.animstring
= f
.read(99)
300 x
= self
.animstring
.find("\0")
302 self
.animstring
= self
.animstring
[:x
]
303 print "on frame " + str(self
.animframe
) + " of animation '" + self
.animstring
+ "'"
309 self
.relx
= read32(f
)
310 self
.rely
= read32(f
)
311 print "part offset: " + str(self
.relx
) + ", " + str(self
.rely
)
314 self
.zorder2
= reads32(f
)
315 if self
.zorder
!= self
.zorder2
:
316 # kaelis's Eden.sfc has this differing for obj#816!
317 # TODO: work out what the heck
318 print "strange zorder: " + str(self
.zorder2
)
320 # TODO: finish decoding this
321 self
.clickbhvr
= f
.read(3)
322 self
.touchbhvr
= read8(f
)
323 print "* touch bhvr: " + str(self
.touchbhvr
) + ", click bhvr:",
324 for z
in self
.clickbhvr
: print "%02X" % ord(z
),
327 if version
== 0: return
329 num_pickup_handles
= read16(f
)
330 self
.pickup_handles
= []
331 for i
in xrange(num_pickup_handles
):
332 self
.pickup_handles
.append((read32(f
), read32(f
)))
334 num_pickup_points
= read16(f
)
335 self
.pickup_points
= []
336 for i
in xrange(num_pickup_points
):
337 self
.pickup_points
.append((read32(f
), read32(f
)))
339 print "read " + str(len(self
.pickup_handles
)) + " pickup handles and " + str(len(self
.pickup_points
)) + " pickup points"
342 def partialread(self
, f
):
345 # we should make sure this value doesn't actually matter.
346 # for now fuzzie is assuming it doesn't, it's presumably the unused portion
347 # of CLAS - it's not always zero, some Terra Nornia scenery has it as 0xff
349 #assert x == 0, "Object lacking nulls at start, instead has " + str(x)
350 # genus/family/species
352 self
.species
= read8(f
)
353 self
.genus
= read8(f
)
354 self
.family
= read8(f
)
356 self
.genus
= read8(f
)
357 self
.family
= read8(f
)
359 assert x
== 0, "Object lacking nulls at start, instead has " + str(x
)
360 self
.species
= read16(f
)
363 identifier
= getidentifier(self
.family
, self
.genus
, self
.species
)
367 identifier
= " - '" + identifier
+ "'"
368 print "agent " + self
.__class
__.__name
__ + ": (" + str(self
.family
) + ", " + str(self
.genus
) + ", " + str(self
.species
) + ")" + identifier
+ ","
372 # TODO: should make sure this is really only set for pointer?
373 # might be mysteriousness byte from c2..
374 if x
: print "pointer-only byte was" + str(x
)
377 self
.unid
= read32(f
)
378 print "unid: " + str(self
.unid
)
382 # TODO: 0 or 1 normally, but 'Hook', unid: 56314, at least, has it at 4
383 assert x
== 0 or x
== 1 or x
== 4
384 print "* mysteriousness (0/1/4): " + str(x
)
388 # TODO: verify this sometime :)
391 self
.attr
= read16(f
)
392 print "attr: " + str(self
.attr
)
405 assert zarros
== 0, "zarros: " + str(zarros
)
407 # drat, PointerTool in eden has this as 1803
409 print "zarros: " + str(zarros
)
412 print "coords? " + str(one
) + ", " + str(two
) + ", " + str(three
) + ", " + str(four
) + ", actv: " + str(self
.actv
)
415 self
.sprite
= slurpMFC(f
, CGallery
)
418 self
.tickreset
= read32(f
)
419 self
.tickstate
= read32(f
)
420 assert self
.tickreset
>= self
.tickstate
421 print "* tick time: " + str(self
.tickreset
) + ", state: " + str(self
.tickstate
)
423 self
.objp
= slurpMFC(f
)
425 self
.currentsound
= f
.read(4)
426 if self
.currentsound
[0] != chr(0):
427 print "current sound: " + self
.currentsound
429 if version
== 0: numvariables
= 3
430 else: numvariables
= 100
434 for i
in xrange(numvariables
):
435 self
.variables
.append(read32(f
))
438 # misc physics-ish data
440 self
.range = read32(f
)
443 print "* mysterious physicsish value (probably GRAV related): " + str(x
)
444 self
.accg
= read32(f
)
445 self
.velx
= reads32(f
)
446 self
.vely
= reads32(f
)
447 print "velx: " + str(self
.velx
) + ", vely: " + str(self
.vely
)
448 self
.rest
= read32(f
)
449 self
.aero
= read32(f
)
450 x
= f
.read(6) # TODO: unknown [for pointer: 0000 0400 0000]
451 # [for eden #1: d101 0400 0000]
452 print "* post-physics bytes:",
453 for z
in x
: print "%02X" % ord(z
),
456 self
.threat
= read8(f
)
458 print "accg: " + str(self
.accg
) + ", rest: " + str(self
.rest
) + ", aero: " + str(self
.aero
) + ", size: " + str(self
.size
) + ", range: " + str(self
.range) + ", threat: " + str(self
.threat
)
460 # TODO: 01 normally, 03 when frozen, 00 for scenery?
461 self
.flags
= read8(f
)
462 assert self
.flags
== 0 or self
.flags
== 1 or self
.flags
== 3, str(self
.flags
)
464 # TODO: sane scriptness
466 numscripts
= read32(f
)
467 for i
in range(numscripts
):
478 script
= readstring(f
)
479 print "event #" + str(eventno
) + " for " + str(family
) + ", " + str(genus
) + ", " + str(species
) + ": " + script
480 self
.scripts
[eventno
] = script
482 class SimpleObject(Object
):
484 Object
.partialread(self
, f
)
486 self
.entity
= slurpMFC(f
, Entity
)
489 class PointerTool(SimpleObject
):
491 SimpleObject
.read(self
, f
)
493 # TODO: data from C2 eden is shown below
494 # 02 00 00 00 02 00 00 00
501 # 00 00 00 00 00 00 00 00 00
502 # CD CD CD CD CD CD CD CD CD CD CD CD
503 # bear in mind CD CD CD CD is prbly unallocated memory from microsoft's CRT
505 print "pointer bytes: ",
506 for z
in x
: print "%02X" % ord(z
),
509 self
.bubble
= slurpMFC(f
, Bubble
)
513 print "pointer bytes: ",
514 for z
in x
: print "%02X" % ord(z
),
517 x
= f
.read(4 + 16 + 9 + 12)
518 print "pointer bytes: ",
519 for z
in x
: print "%02X" % ord(z
),
522 class Bubble(SimpleObject
):
524 SimpleObject
.read(self
, f
)
530 print "bubble bytes: ",
531 for z
in x
: print "%02X" % ord(z
),
537 self
.bubblestring
= f
.read(bubblelen
)
539 self
.bubblestring
= f
.read(36)
540 x
= self
.bubblestring
.find("\0")
542 self
.bubblestring
= self
.bubblestring
[:x
]
543 print "bubble string: " + self
.bubblestring
546 x
= f
.read(11 + 8) # this is probably terribly wrong
549 print "more bubble bytes: ",
550 for z
in x
: print "%02X" % ord(z
),
553 class CompoundObject(Object
):
555 Object
.partialread(self
, f
)
557 global readingcompound
558 readingcompound
= True
560 num_parts
= read32(f
)
562 print "reading " + str(num_parts
) + " parts.."
563 for i
in xrange(num_parts
):
564 print "reading part #" + str(i
)
565 e
= slurpMFC(f
, Entity
)
570 for z
in x
: print "%02X" % ord(z
),
573 assert e
, "part 0 was null"
574 assert e
.relx
== 0 and e
.rely
== 0
576 readingcompound
= False
581 hotspotinfo
['left'] = reads32(f
)
582 hotspotinfo
['top'] = reads32(f
)
583 hotspotinfo
['right'] = reads32(f
)
584 hotspotinfo
['bottom'] = reads32(f
)
585 self
.hotspots
.append(hotspotinfo
)
590 functioninfo
['hotspot'] = reads32(f
)
591 self
.functions
.append(functioninfo
)
595 self
.functions
[i
]['message'] = read16(f
)
596 assert read16(f
) == 0
598 self
.functions
[i
]['mask'] = read8(f
)
603 class Vehicle(CompoundObject
):
605 CompoundObject
.read(self
, f
)
608 self
.xvec
= reads32(f
)
609 self
.yvec
= reads32(f
)
611 print "xvec: " + str(self
.xvec
) + ", yvec: " + str(self
.yvec
) + ", bump flags: " + str(self
.bump
)
613 self
.coordx
= read16(f
)
616 print "vehicl bytes:",
617 for z
in x
: print "%02X" % ord(z
),
622 self
.coordy
= read16(f
)
625 print "vehicle coords: " + str(self
.coordx
) + ", " + str(self
.coordy
)
627 # TODO: this could all be nonsense, really
628 self
.cabinleft
= read32(f
)
629 self
.cabintop
= read32(f
)
630 self
.cabinright
= read32(f
)
631 self
.cabinbottom
= read32(f
)
633 print "cabin coords: " + str(self
.cabinleft
) + ", " + str(self
.cabintop
) + ", " + str(self
.cabinright
) + ", " + str(self
.cabinbottom
)
638 # TODO: is it Vehicle subclass?
641 Vehicle
.read(self
, f
)
644 # x = f.read() # TODO
645 self
.numcallbuttons
= read32(f
)
646 self
.curcallbutton
= read32(f
)
647 self
.mysterybytes
= f
.read(5)
648 assert self
.mysterybytes
== "\xff\xff\xff\xff\x00"
649 self
.callbuttonys
= []
651 self
.callbuttonys
.append(read32(f
))
652 assert read16(f
) == 0
653 print "call buttons defined: " + str(self
.numcallbuttons
)
654 print "current floor: " + str(self
.curcallbutton
)
655 print "call button y-vals: " + str(self
.callbuttonys
)
658 print "lift bytes: ",
659 for z
in x
: print "%02X" % ord(z
),
662 class CallButton(SimpleObject
):
664 SimpleObject
.read(self
, f
)
666 self
.lift
= slurpMFC(f
, Lift
)
668 self
.buttonid
= read8(f
)
669 print "button #" + str(self
.buttonid
) + " for lift " + str(self
.lift
)
671 class Blackboard(CompoundObject
):
673 CompoundObject
.read(self
, f
)
675 # TODO: none of this is verified
677 self
.backgroundcolour
= read8(f
)
678 self
.chalkcolour
= read8(f
)
679 self
.aliascolour
= read8(f
)
680 self
.textx
= read8(f
)
681 self
.texty
= read8(f
)
683 self
.backgroundcolour
= read32(f
)
684 self
.chalkcolour
= read32(f
)
685 self
.aliascolour
= read32(f
)
686 self
.textx
= read8(f
)
687 self
.texty
= read8(f
)
688 print "text at (" + str(self
.textx
) + ", " + str(self
.texty
) + ")"
689 print "colours: " + str(self
.backgroundcolour
) + ", " + str(self
.chalkcolour
) + ", " + str(self
.aliascolour
)
696 for i
in xrange(totalwords
):
703 print "blackboard string #" + str(num
) + ": " + x
705 class Scenery(SimpleObject
):
707 global readingscenery
708 readingscenery
= True
709 SimpleObject
.read(self
, f
)
710 readingscenery
= False
717 print "probably a C1 creature?"
719 elif x
== 1 or x
== 2:
720 print "probably a C2 creature?"
723 assert False, "didn't understand Creature first byte " + str(x
)
729 print "creature bytes:",
730 for z
in x
: print "%02X" % ord(z
),
733 self
.gallery
= slurpMFC(f
, CGallery
)
738 x
= f
.read(455) # 255 + 200?
739 print "creature bytes:",
740 for z
in x
: print "%02X" % ord(z
),
743 self
.moniker
= f
.read(4)
744 self
.mommoniker
= f
.read(4)
745 self
.dadmoniker
= f
.read(4)
747 print "reading creature with moniker " + self
.moniker
750 self
.text1
= readstring(f
)
751 self
.text2
= readstring(f
)
753 self
.body
= slurpMFC(f
, Body
)
757 print "creature bytes:",
758 for z
in x
: print "%02X" % ord(z
),
766 for i
in range(vocabsize
):
767 print readstring(f
) + " " + readstring(f
),
775 print "creature bytes:",
776 for z
in x
: print "%02X" % ord(z
),
779 self
.brain
= slurpMFC(f
, CBrain
)
783 print "creature (brain?) bytes:",
784 for z
in x
: print "%02X" % ord(z
),
787 self
.biochem
= slurpMFC(f
, CBiochemistry
)
789 # TODO: read instincts (CInstinct) here
790 # TODO: read random data [voice files, birth data, history?] here
791 # TODO: read genome (CGenome) here
797 for z
in x
: print "%02X" % ord(z
),
800 # fuzzie has little idea what's going on here, so this is probably wrong
801 # (but limb #18 is present in some C2 files, and there's no null there in some C1 files)
807 for i
in range(nolimbs
):
808 print "trying to read limb.."
809 limb
= slurpMFC(f
, Limb
)
810 self
.limbs
.append(limb
)
817 for z
in x
: print "%02X" % ord(z
),
820 somepose
= readstring(f
)
821 print "maaaaybe current pose: " + somepose
828 for z
in x
: print "%02X" % ord(z
),
836 for i
in range(noposestrings
):
845 for i
in range(noanims
):
853 for z
in x
: print "%02X" % ord(z
),
858 print "reading biochem"
861 # thanks to Chris Double for working out some of this structure, years ago
862 # http://www.double.co.nz/creatures/creatures2/expbrain.htm
867 print "brain bytes:",
868 for z
in x
: print "%02X" % ord(z
),
872 print str(nolobes
) + " lobes:"
875 for i
in range(nolobes
):
888 self
.output
= read8(f
)
889 self
.state
= read8(f
)
895 #print "neuron bytes:",
896 #for z in x: print "%02X" % ord(z),
900 nodendrites
= read8(f
)
901 dendritetype
= read8(f
)
903 #print "neuron bytes:",
904 #for z in x: print "%02X" % ord(z),
907 for j
in range(nodendrites
):
921 self
.width
= read32(f
)
922 self
.height
= read32(f
)
923 print "reading lobe at (" + str(self
.x
) + ", " + str(self
.y
) + "), size " + str(self
.width
) + "x" + str(self
.height
)
927 for z
in x
: print "%02X" % ord(z
),
930 self
.nominalthreshold
= read8(f
)
932 self
.leakagerate
= read8(f
)
933 self
.reststate
= read8(f
)
934 self
.inputgain
= read8(f
)
936 print "lobe has nominal threshold " + str(self
.nominalthreshold
) + ", leakage rate " + str(self
.leakagerate
) + ", rest state " + str(self
.reststate
) + " and input gain " + str(self
.inputgain
)
943 for z
in x
: print "%02X" % ord(z
),
946 self
.dendrite0details
= DendriteDetails()
947 self
.dendrite0details
.read(f
)
948 self
.dendrite1details
= DendriteDetails()
949 self
.dendrite1details
.read(f
)
951 self
.nocells
= read32(f
)
952 assert self
.nocells
== self
.width
* self
.height
953 self
.nodendrites
= read32(f
)
955 def readNeurons(self
, f
):
957 for i
in range(self
.nocells
):
960 self
.neurons
.append(f
)
963 class DendriteDetails
:
965 self
.sourcelobe
= read32(f
)
966 self
.minimum
= read8(f
)
967 self
.maximum
= read8(f
)
968 self
.spread
= read8(f
)
969 self
.fanout
= read8(f
)
970 self
.minltw
= read8(f
)
971 self
.maxltw
= read8(f
)
972 self
.minstr
= read8(f
)
973 self
.maxstr
= read8(f
)
975 print "src lobe %d, min %d, max %d, spread %d, fanout %d, minltw %d, maxltw %d, minstr %d, maxstr %d" % (self
.sourcelobe
, self
.minimum
, self
.maximum
, self
.spread
, self
.fanout
, self
.minltw
, self
.maxltw
, self
.minstr
, self
.maxstr
)
977 self
.migrationrule
= read8(f
)
978 self
.relaxsuscept
= read8(f
)
979 self
.relaxstw
= read8(f
)
980 self
.ltwgainrate
= read8(f
)
982 print "migration rule %d, relax suscept %d, relax STW %d, LTW gain rate %d" % (self
.migrationrule
, self
.relaxsuscept
, self
.relaxstw
, self
.ltwgainrate
)
984 # the first bit of this, at least, seems to still be meaningful (ie: not all zeros)
989 print "dendrite bytes:",
990 for z
in x
: print "%02X" % ord(z
),
993 # -------------------------------------------------------------------
997 assert len(sys
.argv
) == 2
998 f
= open(sys
.argv
[1], "r")
1002 # first thing in an EXP file is Creature
1003 if isinstance(data
, Creature
):
1006 # first thing in an SFC file is MapData
1007 assert isinstance(data
, MapData
)
1009 print "successfully read " + str(len(data
.rooms
)) + " rooms"
1011 # seek through nulls to find the number of objects
1017 # read number of objects
1019 numobjects
= read32(f
)
1020 print "reading " + str(numobjects
) + " objects.."
1023 # read all the objects
1024 for i
in range(numobjects
):
1025 print "object #" + str(i
+ 1) + ":"
1028 print "made a mistake somewhere :("
1034 numscenery
= read32(f
)
1035 print "reading " + str(numscenery
) + " scenery objects.."
1038 # read all the scenery objects
1039 for i
in range(numscenery
):
1040 print "scenery object #" + str(i
+ 1) + ":"
1041 x
= slurpMFC(f
, Scenery
)
1043 print "made a mistake somewhere :("
1048 # TODO: sane scriptness
1050 numscripts
= read32(f
)
1051 print "reading " + str(numscripts
) + " scripts.."
1052 for i
in range(numscripts
):
1063 script
= readstring(f
)
1064 print "event #" + str(eventno
) + " for " + str(family
) + ", " + str(genus
) + ", " + str(species
) + " (global): " + script
1065 scripts
[eventno
] = script
1069 # TODO: not sure about these, but they change when i scroll :)
1072 print "scrolled to " + str(scrollx
) + ", " + str(scrolly
)
1073 # TODO: definitely not sure about these!
1076 favplacename
= readstring(f
)
1077 print "aaaand, to finish off, our favourite place is: " + favplacename
1083 print "and now, for " + str(len(data
.rooms
)) + " rooms.."
1086 roomtypes
= ["In-Doors", "Surface", "Underwater", "Atmosphere"]
1087 dropstatuses
= ["Never", "Above-floor", "Always"]
1088 doordirs
= ["Left", "Right", "Up", "Down"]
1090 for i
in data
.rooms
:
1091 print "room # " + str(i
.roomid
) + " at (" + str(i
.left
) + ", " + str(i
.top
) + "), to (" + str(i
.right
) + ", " + str(i
.bottom
) + ")"
1093 print "doors in direction " + doordirs
[j
] + ":",
1094 if len(i
.doordirections
[j
]) == 0:
1096 for k
in i
.doordirections
[j
]:
1097 if k
!= i
.doordirections
[j
][0]: print ",",
1098 print "openness " + str(k
.openness
) + " to room #" + str(k
.otherroom
),
1100 print "wind: (" + str(i
.windx
) + ", " + str(i
.windy
) + ")"
1101 print "room type: " + roomtypes
[i
.roomtype
] + " (" + str(i
.roomtype
) + ")"
1102 print "floor value: " + str(i
.floorvalue
)
1103 print "inorganic nutrients: " + str(i
.inorganicnutrients
) + ", organic nutrients: " + str(i
.organicnutrients
)
1104 print "temperature: " + str(i
.temperature
) + ", heat source: " + str(i
.heatsource
)
1105 print "pressure: " + str(i
.pressure
) + ", pressure source: " + str(i
.pressuresource
)
1106 print "radiation: " + str(i
.radiation
) + ", radiation source: " + str(i
.radiationsource
)
1107 if len(i
.music
) > 0:
1108 print "music: " + str(i
.music
)
1109 if len(i
.floorpoints
) > 0:
1110 print "Surface points:",
1111 for x
in i
.floorpoints
:
1112 print "(" + str(x
[0]) + ", " + str(x
[1]) + ")",
1114 print "drop status: " + dropstatuses
[i
.dropstatus
] + " (" + str(i
.dropstatus
) + ")"