2011-04-01 71 views
2

我目前正在开发一款游戏机器人,希望能够更多地了解编程。不幸的是,当我进入二进制数组主题时,我刚刚添加的一个新命令变得非常困难。基本上,我采取了一项已经制定的命令,在其中将物品放置在两个地方,以便定义您将要恢复的区域。我对该命令的编辑将会允许整个地图的完整还原,而无需放置任何项目来定义地图。挣扎着用二进制数组:python

在执行还原命令之前,会执行一个备份命令,在该备份命令中,二进制数组由整个映射组成,然后存储在文件中。为了恢复整个地图,新的命令仍然需要处理两点的坐标。一个将位于地图的底角(0,0,0),然后另一个位于地图顶部对角的角落,这个角度总是随着你想要的服务器而变化。我解决这个问题的理由是仅仅为每个坐标检索二进制数组的长度。不幸的是,我一直在试图做到这一点,我真的不知道如何找到二进制数组的维度。显示数组的包和解包以及我无法解决的部分代码。

奇怪的是,如果我手动输入数字,如if语句与一个服务器IP地址,机器人完美工作。只是为了制作适用于任何地图的代码而不仅仅是一张地图的任何努力都毫无结果。

enter code here 
def onBackup(self,user,filename): 
    fn = bakFolder+filename+".backup" 
    try: 
     f = open(fn,"r") 
     self.bot.sendMessage("A backup by that name already exists.") 
     f.close() 
     return 
    except IOError: 
     try: 
     f = open(fn,"wb") 
     f.write(struct.pack("!3i",self.bot.level_x,self.bot.level_y,self.bot.level_z)) 
     self.bot.block_array.tofile(f) 
     self.bot.sendMessage("Backup saved to file %s.backup"%filename) 
     print "Backup save to %s.backup"%filename 
     return 
     except IOError: 
     self.bot.sendMessage("Error opening %s.backup"%filename, false) 
     print "Backup: Error opening file" 
     return 
def restoremap(self): 
    fn = bakFolder+self.restore_filename+".backup" 
    try: 
     f = open(fn,"rb") 
     header_x, header_y, header_z = struct.unpack('!3i',f.read(12)) 
     backup_array = array.array('B') 
     backup_array.fromfile(f,header_x*header_y*header_z) 
     x1,y1,z1 = (0,0,0) 
     if server == "204.232.197.228": 
      x2,y2,z2 = (64,1020,64) #special server that already has coordinates 
     else: 
      x2,y2,z2 = ??? rest of servers, coordinates derived from the binary array 
     if x1 > x2 : x1, x2 = x2, x1 
     if y1 > y2 : y1, y2 = y2, y1 
     if z1 > z2 : z1, z2 = z2, z1 
     tiles_to_deglass = [] 
     tiles_to_build = [] 
     while x1 <= x2: 
      y = y1 
      while y <= y2: 
       z = z1 
       while z <= z2: 
        offset = self.bot.calculateOffset(x1,y,z) 
        current_tile = int(self.bot.block_array[offset]) 
        backup_tile = int(backup_array[offset]) 
        if not (current_tile == backup_tile): 
         if (current_tile == 0) and (backup_tile in self.valid_blocks): 
          tiles_to_build.append((backup_tile,x1,y,z)) 
         elif (current_tile >= 8) and (current_tile <= 11) and (backup_tile == 0): 
          ## This deals with water & lava in what used to be empty spaces 
          ## first we'll glass it all, and then deglass later! 
          self.blocks.append((20,x1,y,z)) 
          tiles_to_deglass.append((0,x1,y,z)) 
         elif backup_tile == 7:##use stone 
          tiles_to_build.append((0,x1,y,z)) 
          tiles_to_build.append((1,x1,y,z)) 
         elif backup_tile in self.valid_blocks: 
          ## This is the fall through... We'll try to erase 
          ## the current tile and then restore it to the other state 
          tiles_to_build.append((0,x1,y,z)) 
          tiles_to_build.append((backup_tile,x1,y,z)) 
         elif (backup_tile == 0) and not (current_tile == 0): 
          tiles_to_build.append((0,x1,y,z)) 

        z+=1 
       y += 1 
      x1 +=1 
     self.DrawBlocks() 
     self.blocks += tiles_to_build 
     self.DrawBlocks() 
     self.blocks += tiles_to_deglass 
     self.DrawBlocks() 
     self.bot.sendMessage("Restoring...",ignorable=True) 
     ##self.bot.action_queue.append(SayAction(self.bot,"Done restoring.")) 
     self.onReset(silent=True) 

    except IOError: 
     self.bot.sendMessage("Error while restoring (couldn't read file).") 
+0

不应该x2,y2,z2是否与header_x,header_y,header_z相同? – interjay 2011-04-01 10:41:44

+0

实际上,它可能是header_x,y,z的len,那就是答案 – joseph 2011-04-02 05:06:48

回答

0

考虑长度1024;这也可以变成(X,Y,Z):

2 2 256 
2 4 128 
2 8 64 
2 16 32 
2 32 16 
... 
128 4 2 
256 2 2 

即使数组的长度为1001,你不会得到非常友好的答案:

7 11 13 
11 7 13 
7 13 11 
11 13 7 
13 11 7 
13 7 11 

所以,你救文件必须包括每个特定映射的(x,y,z)坐标。

它看起来像onBackup()例程保存前三个整数位置(每个四个字节)中的bot的坐标。您可以通过将机器人漫游到最远的地图来扩展此程序,然后然后保存坐标。或者你可以看到服务器是否可以以某种方式报告地图的范围,并捕获信息。

但我不认为你可以猜测给定输入数组的维数。

1

看来你使用X2,Y2的唯一场所,Z2是设置X1,y和z限制在这些循环:

while x1 <= x2: 
     y = y1 
     while y <= y2: 
      z = z1 
      while z <= z2: 
       offset = self.bot.calculateOffset(x1,y,z) 
       current_tile = int(self.bot.block_array[offset]) 
       ... 
       z+=1 
      y += 1 
     x1 +=1 

,如果你设置,比方说会发生什么,X2是否过大?你有例外吗?如果是这样, 也许你可以简单地捕捉异常,找出多大的x2可以。 例如:

x2=y2=z2=None 
    while x2 is None or x1<=x2: 
     y = y1 
     while y2 is None or y<=y2: 
      z = z1 
      while z2 is None or z<=z2: 
       try: 
        offset = self.bot.calculateOffset(x1,y,z) 
        current_tile = int(self.bot.block_array[offset]) 
       except Exception: #<-- Change to most specific exception possible 
        if z2 is None: 
         z2=z-1 
        elif y2 is None: 
         y2=y-1 
        elif x2 is None: 
         x2=x1-1 
        break 
       ... 
       z+=1 
      y += 1 
     x1 +=1 

俗话说,it's easier to ask for forgiveness than permission


PS。要找出要捕获的特定异常,请删除上面的tryexcept并运行该脚本,使其失败。回溯错误消息的最后一行告诉您所引发的异常的类型。例如,它可能会说

IndexError: x,y,z out of bounds 

在这种情况下,加回tryexcept改变ExceptionIndexError