def setTile(self, glyph, color): self.monster = None if glyph in Tile.dngFeatures: self.glyph = glyph self.color = color self.explored = self.explored or (glyph != ' ') if self.items: Kernel.instance.log( "Removing items on %s because I only see a dngFeature-tile" % str(self.coords())) self.items = [] if glyph not in Tile.walkables.keys() and not self.isDoor(): Kernel.instance.log("Setting %s to unwalkable." % self) self.walkable = False if glyph in Tile.walkables.keys() and glyph not in [' ']: self.walkable = True #Kernel.instance.log("Found feature: %s, Color: %s, at (%d,%d). Tile is now: %s" % (glyph, str(color), self.y, self.x, str(self))) elif glyph in Tile.dngItems: it = Item(None, glyph, color) if not self.items: Kernel.instance.log("Added item(%s) to tile(%s)" % (str(it), str(self))) self.items.append(it) else: self.items[0] = it if glyph == '0': self.walkable = False else: self.walkable = True #Kernel.instance.log("Found item: %s, Color: %s, at (%d,%d). Tile is now: %s" % (str(it), str(color), self.y, self.x, str(self))) elif self.coords() == Kernel.instance.Hero.coords(): self.explored = True self.walkable = True # Might cause some trouble # TODO: Write comments that actually explains problems (No idea why I said the above, and no idea what the below does.. :) if not self.isWalkable(): self.walkable = True self.glyph = None elif glyph in Tile.dngMonsters: self.monster = Monster(glyph, color) self.walkable = True if self.glyph == ']': if Kernel.instance.Dungeon.tile(self.y - 1, self.x).glyph == '|': self.glyph = '-' else: self.glyph = '|' self.color = TermColor(33, 0, False, False) #Kernel.instance.log("Found monster:%s, Color: %s, at (%d,%d). Tile is now: %s" % (str(self.monster), str(color), self.y, self.x, str(self))) else: Kernel.instance.die("Couldn't parse tile: " + glyph)
def __init__(self): EeekObject.__init__(self) SignalReceiver.__init__(self) SocketObserver.__init__(self) self.gameStarted = False self.screen = [] self.state = "" self.y = 0 self.x = 0 self.color = TermColor() self._file = open("logs/frames.txt", "wa") self.firstParse = True self.last = "" for x in range(0, WIDTH*HEIGHT): self.screen.append(FBTile()) self.ansi =\ { "\xf0" : "ignore", "\x1b[m" : "reset color", "\x1b[0m" : "reset color", "\x1b[1m" : "bold", "\x1b[7m" : "reverse", "\x1b[?47l": "ignore", "\x1b[?47h": "ignore", "\x1b[?1l" : "ignore", "\x1b8" : "ignore", "\x1b7" : "ignore", "\xff\xfcc": "ignore", "\xfa" : "ignore", "\x00" : "ignore", "\x08" : "backspace", "\x0a" : "LF", "\x0a" : "LF", "\x0d" : "CR", "\x1b(B" : "ignore", "\x1b)0" : "ignore", "\x1b>" : "ignore", "\x1b[?1l" : "ignore", "\x1b[H" : "home", "\x1b[J" : "clear to end of screen", "\x1b[0J" : "clear to end of screen", "\x1b[1J" : "clear to beginning", "\x1b[2J" : "clear screen", "\x1b[K" : "clear to end of line", "\x1b[A" : "up", "\x1b[B" : "down", "\x1b[C" : "right", "\x1b[D" : "left", "\x1by" : "ignore", } for x in range(ord(' '), ord('~')+1): self.ansi[chr(x)] = "print"
def setTile(self, glyph, color): self.monster = None if glyph in Tile.dngFeatures: self.glyph = glyph self.color = color self.explored = self.explored or (glyph != ' ') if self.items: Kernel.instance.log("Removing items on %s because I only see a dngFeature-tile" % str(self.coords())) self.items = [] if glyph not in Tile.walkables.keys() and not self.isDoor(): Kernel.instance.log("Setting %s to unwalkable." % self) self.walkable = False if glyph in Tile.walkables.keys() and glyph not in [' ']: self.walkable = True #Kernel.instance.log("Found feature: %s, Color: %s, at (%d,%d). Tile is now: %s" % (glyph, str(color), self.y, self.x, str(self))) elif glyph in Tile.dngItems: it = Item(None, glyph, color) if not self.items: Kernel.instance.log("Added item(%s) to tile(%s)" % (str(it), str(self))) self.items.append(it) else: self.items[0] = it if glyph == '0': self.walkable = False else: self.walkable = True #Kernel.instance.log("Found item: %s, Color: %s, at (%d,%d). Tile is now: %s" % (str(it), str(color), self.y, self.x, str(self))) elif self.coords() == Kernel.instance.Hero.coords(): self.explored = True self.walkable = True # Might cause some trouble # TODO: Write comments that actually explains problems (No idea why I said the above, and no idea what the below does.. :) if not self.isWalkable(): self.walkable = True self.glyph = None elif glyph in Tile.dngMonsters: self.monster = Monster(glyph, color) self.walkable = True if self.glyph == ']': if Kernel.instance.Dungeon.tile(self.y-1, self.x).glyph == '|': self.glyph = '-' else: self.glyph = '|' self.color = TermColor(33, 0, False, False) #Kernel.instance.log("Found monster:%s, Color: %s, at (%d,%d). Tile is now: %s" % (str(self.monster), str(color), self.y, self.x, str(self))) else: Kernel.instance.die("Couldn't parse tile: " + glyph)
def __init__(self, y, x, level): Findable.__init__(self) self.y = y self.x = x self.level = level self.glyph = None self.color = TermColor() self.explored = False self.items = [] self.monster = None self.walkable = True self.searches = 0 self.searched = False self.inShop = False self.locked = False self.shopkeepDoor = False
class Tile(Findable): dngFeatures = ['.', '}', '{', '#', '<', '>', ']', '^', '|', '-', '~', ' '] dngItems = [ '`', '0', '*', '$', '_', '[', '%', ')', '(', '/', '?', '!', '"', '=', '+', '\\' ] dngMonsters = map( chr, range(ord('a'), ord('z') + 1) + range(ord('A'), ord('Z') + 1) + range(ord('1'), ord('5') + 1)) + ['@', "'", '&', ';', ':'] walkables = { '.': 1, '}': 1, '{': 1, '#': 1, '<': 1, '>': 1, '^': 100, ' ': 1 } #glyph: weight def __init__(self, y, x, level): Findable.__init__(self) self.y = y self.x = x self.level = level self.glyph = None self.color = TermColor() self.explored = False self.items = [] self.monster = None self.walkable = True self.searches = 0 self.searched = False self.inShop = False self.locked = False self.shopkeepDoor = False def coords(self): return (self.y, self.x) def setTile(self, glyph, color): self.monster = None if glyph in Tile.dngFeatures: self.glyph = glyph self.color = color self.explored = self.explored or (glyph != ' ') if self.items: Kernel.instance.log( "Removing items on %s because I only see a dngFeature-tile" % str(self.coords())) self.items = [] if glyph not in Tile.walkables.keys() and not self.isDoor(): Kernel.instance.log("Setting %s to unwalkable." % self) self.walkable = False if glyph in Tile.walkables.keys() and glyph not in [' ']: self.walkable = True #Kernel.instance.log("Found feature: %s, Color: %s, at (%d,%d). Tile is now: %s" % (glyph, str(color), self.y, self.x, str(self))) elif glyph in Tile.dngItems: it = Item(None, glyph, color) if not self.items: Kernel.instance.log("Added item(%s) to tile(%s)" % (str(it), str(self))) self.items.append(it) else: self.items[0] = it if glyph == '0': self.walkable = False else: self.walkable = True #Kernel.instance.log("Found item: %s, Color: %s, at (%d,%d). Tile is now: %s" % (str(it), str(color), self.y, self.x, str(self))) elif self.coords() == Kernel.instance.Hero.coords(): self.explored = True self.walkable = True # Might cause some trouble # TODO: Write comments that actually explains problems (No idea why I said the above, and no idea what the below does.. :) if not self.isWalkable(): self.walkable = True self.glyph = None elif glyph in Tile.dngMonsters: self.monster = Monster(glyph, color) self.walkable = True if self.glyph == ']': if Kernel.instance.Dungeon.tile(self.y - 1, self.x).glyph == '|': self.glyph = '-' else: self.glyph = '|' self.color = TermColor(33, 0, False, False) #Kernel.instance.log("Found monster:%s, Color: %s, at (%d,%d). Tile is now: %s" % (str(self.monster), str(color), self.y, self.x, str(self))) else: Kernel.instance.die("Couldn't parse tile: " + glyph) def appearance(self): if self.monster: return self.monster.glyph elif self.items: return self.items[-1].glyph else: return self.glyph def isDoor(self): return (self.glyph == '-' or self.glyph == '|') and self.color.getId() == COLOR_BROWN def isWalkable(self): #TODO: Shops might be good to visit sometime ..:) # if not self.adjacent({'explored': True}): # return False if not self.glyph: return not self.monster and self.walkable else: if self.isDoor(): return not self.monster and True return not self.monster and self.glyph in Tile.walkables.keys( ) and self.walkable def walkableNeighbours(self): ret = [] for neighbour in self.neighbours(): if neighbour.isWalkable() and not (neighbour.isDoor() or self.isDoor()): ret.append(neighbour) continue if (self.isDoor() or neighbour.isDoor()) and ( self.x == neighbour.x or self.y == neighbour.y) and neighbour.isWalkable(): ret.append(neighbour) continue return ret def isAdjacent(self, other): for neighbour in self.neighbours(): if neighbour == other: return True return False def straight(self, find): ret = [] for x in range(-1, 2): for y in range(-1, 2): if x * y == 0 and x != y: tile = self.level.tiles[(x + self.x) + (y + self.y) * WIDTH] if tile.find(find): ret.append(tile) return ret def adjacent(self, find): return [tile for tile in self.neighbours() if tile.find(find)] def neighbours(self): ret = [] for x in range(-1, 2): for y in range(-1, 2): if x + self.x < 0 or x + self.x > WIDTH - 1 or y + self.y < 0 or y + self.y > HEIGHT - 4 or ( x == 0 and y == 0): continue tile = self.level.tiles[x + self.x + (y + self.y) * WIDTH] ret.append(tile) return ret def isHero(self): return self.coords() == Kernel.instance.Hero.coords() def tilesFromCurrent(self): return (abs(Kernel.instance.Hero.x - self.x) + abs(Kernel.instance.Hero.y - self.y)) def __str__(self): return "(%s,%s)->g:%s, c:(%s), e:%s, @:%s, m:(%s), i:(%s) w:%s(is:%s) sea:%s" % tuple( map(str, (self.y, self.x, self.glyph, self.color, self.explored, self.isHero(), self.monster, map(str, self.items), self.walkable, self.isWalkable(), self.searches))) def __eq__(self, other): return self.coords() == other.coords() def __ne__(self, other): return self.coords() != other.coords()
class FramebufferParser(SignalReceiver, SocketObserver, EeekObject): def __init__(self): EeekObject.__init__(self) SignalReceiver.__init__(self) SocketObserver.__init__(self) self.gameStarted = False self.screen = [] self.state = "" self.y = 0 self.x = 0 self.color = TermColor() self._file = open("logs/frames.txt", "wa") self.firstParse = True self.last = "" for x in range(0, WIDTH*HEIGHT): self.screen.append(FBTile()) self.ansi =\ { "\xf0" : "ignore", "\x1b[m" : "reset color", "\x1b[0m" : "reset color", "\x1b[1m" : "bold", "\x1b[7m" : "reverse", "\x1b[?47l": "ignore", "\x1b[?47h": "ignore", "\x1b[?1l" : "ignore", "\x1b8" : "ignore", "\x1b7" : "ignore", "\xff\xfcc": "ignore", "\xfa" : "ignore", "\x00" : "ignore", "\x08" : "backspace", "\x0a" : "LF", "\x0a" : "LF", "\x0d" : "CR", "\x1b(B" : "ignore", "\x1b)0" : "ignore", "\x1b>" : "ignore", "\x1b[?1l" : "ignore", "\x1b[H" : "home", "\x1b[J" : "clear to end of screen", "\x1b[0J" : "clear to end of screen", "\x1b[1J" : "clear to beginning", "\x1b[2J" : "clear screen", "\x1b[K" : "clear to end of line", "\x1b[A" : "up", "\x1b[B" : "down", "\x1b[C" : "right", "\x1b[D" : "left", "\x1by" : "ignore", } for x in range(ord(' '), ord('~')+1): self.ansi[chr(x)] = "print" def mapTiles(self): return self.screen[WIDTH:-WIDTH*2] def getChars(self): return "".join(x.char for x in self.screen) def mapLines(self): return "".join(x.char for x in self.screen[WIDTH:-2*WIDTH]) def topLine(self): return "".join(x.char for x in self.screen[:WIDTH]) def botLines(self): return "".join(x.char for x in self.screen[22*WIDTH:]) def getRowLine(self, row): if row < 1 or row > 24: return "" return "".join(x.char for x in self.screen[(row-1)*WIDTH:row*WIDTH]) def printChar(self, char): cur = self.screen[self.x + self.y*WIDTH] cur.set(char, self.color.copy()) self.x = self.x+1 def log(self, line): self._file.write(line+"\n") self._file.flush() def parse(self, line): self.last = line self.state = "" if not self.gameStarted: sys.stdout.write(line) sys.stdout.flush() return for char in line: self.state = self.state + char if self.state in self.ansi: action = self.ansi[self.state] if action == "print": self.printChar(char) elif action == "reset color": self.color = TermColor() elif action == 'CR': self.x = 0 elif action == 'backspace': self.x = self.x - 1 elif action in ('LF', "down"): self.y = self.y + 1 elif action == "up": self.y = self.y - 1 elif action == "left": self.x = self.x - 1 elif action == "right": self.x = self.x + 1 elif action == 'ignore': pass elif action == "home": self.x = 0 self.y = 0 elif action == "clear to end of screen": for i in range(self.x + self.y * WIDTH, WIDTH * HEIGHT): self.screen[i].set(' ', TermColor()) elif action == "clear to end of line": for i in range(self.x + self.y * WIDTH, WIDTH * (self.y + 1)): self.screen[i].set(' ', TermColor()) elif action == "clear to beginning": for i in range(self.x + self.y * WIDTH, 0, -1): self.screen[i].set(' ', TermColor()) elif action == "clear screen": for i in range(0, HEIGHT*WIDTH): self.screen[i].set(' ', TermColor()) elif action == "bold": self.color.bold = True elif action == "reverse": self.color.reverse = True self.state = "" if self.x >= WIDTH: self.x = 0 self.y = self.y + 1 if self.y >= HEIGHT: self.y = HEIGHT - 1 continue match = re.match("\x1b\[(\d+);(\d+)H", self.state) if match: self.y = int(match.group(1)) - 1 self.x = int(match.group(2)) - 1 self.state = "" continue if len(self.state)>10: Kernel.instance.log("Couldn't parse ANSI: %s\nBuffer was: %s" % (line, self.state)) Kernel.instance.die("Couldn't parse ANSI") return match = re.match("\x1b\[(\d+)m", self.state) if match: col = int(match.group(1)) if col>=30 and col<=37: self.color.fg = col elif col>=40 and col<=47: self.color.bg = col else: Kernel.instance.die("Invalid color: %d" % col) self.state = "" continue if True: for y in range(0, HEIGHT): for x in range(0, WIDTH): cur = self.screen[x+y*WIDTH] sys.stdout.write("\x1b[%dm\x1b[%d;%dH%s" % (cur.color.fg, y+1, x+1, cur.char)) sys.stdout.flush() else: sys.stdout.write(line) sys.stdout.flush() self.logScreen() Kernel.instance.screenParsed() def logScreen(self): for y in range(0, HEIGHT): self._file.write("\n") for x in range(0, WIDTH): if y == HEIGHT-1 and x > WIDTH-5: break self._file.write(self.screen[x+y*WIDTH].char) if Kernel.instance.Dungeon.curBranch: self._file.write(str(Kernel.instance.curTile().coords())) self._file.write("\n"+str(self.y)+","+str(self.x)) self._file.flush() def game_start(self): Kernel.instance.log("Got game_start signal in FrameBufferParser") Kernel.instance.NethackSock.s.recv(99999) Kernel.instance.NethackSock.s.send("\x12") self.gameStarted = True
def __init__(self): self.char = ' ' self.color = TermColor() self.marked = None
def parse(self, line): self.last = line self.state = "" if not self.gameStarted: sys.stdout.write(line) sys.stdout.flush() return for char in line: self.state = self.state + char if self.state in self.ansi: action = self.ansi[self.state] if action == "print": self.printChar(char) elif action == "reset color": self.color = TermColor() elif action == 'CR': self.x = 0 elif action == 'backspace': self.x = self.x - 1 elif action in ('LF', "down"): self.y = self.y + 1 elif action == "up": self.y = self.y - 1 elif action == "left": self.x = self.x - 1 elif action == "right": self.x = self.x + 1 elif action == 'ignore': pass elif action == "home": self.x = 0 self.y = 0 elif action == "clear to end of screen": for i in range(self.x + self.y * WIDTH, WIDTH * HEIGHT): self.screen[i].set(' ', TermColor()) elif action == "clear to end of line": for i in range(self.x + self.y * WIDTH, WIDTH * (self.y + 1)): self.screen[i].set(' ', TermColor()) elif action == "clear to beginning": for i in range(self.x + self.y * WIDTH, 0, -1): self.screen[i].set(' ', TermColor()) elif action == "clear screen": for i in range(0, HEIGHT*WIDTH): self.screen[i].set(' ', TermColor()) elif action == "bold": self.color.bold = True elif action == "reverse": self.color.reverse = True self.state = "" if self.x >= WIDTH: self.x = 0 self.y = self.y + 1 if self.y >= HEIGHT: self.y = HEIGHT - 1 continue match = re.match("\x1b\[(\d+);(\d+)H", self.state) if match: self.y = int(match.group(1)) - 1 self.x = int(match.group(2)) - 1 self.state = "" continue if len(self.state)>10: Kernel.instance.log("Couldn't parse ANSI: %s\nBuffer was: %s" % (line, self.state)) Kernel.instance.die("Couldn't parse ANSI") return match = re.match("\x1b\[(\d+)m", self.state) if match: col = int(match.group(1)) if col>=30 and col<=37: self.color.fg = col elif col>=40 and col<=47: self.color.bg = col else: Kernel.instance.die("Invalid color: %d" % col) self.state = "" continue if True: for y in range(0, HEIGHT): for x in range(0, WIDTH): cur = self.screen[x+y*WIDTH] sys.stdout.write("\x1b[%dm\x1b[%d;%dH%s" % (cur.color.fg, y+1, x+1, cur.char)) sys.stdout.flush() else: sys.stdout.write(line) sys.stdout.flush() self.logScreen() Kernel.instance.screenParsed()
class Tile(Findable): dngFeatures = ['.', '}', '{', '#', '<', '>', ']', '^', '|', '-', '~', ' '] dngItems = ['`', '0', '*', '$', '_', '[', '%', ')', '(', '/', '?', '!', '"', '=', '+', '\\'] dngMonsters = map(chr, range(ord('a'), ord('z')+1) + range(ord('A'), ord('Z')+1) + range(ord('1'), ord('5')+1)) + ['@', "'", '&', ';', ':'] walkables = {'.': 1, '}': 1, '{': 1, '#': 1, '<': 1, '>': 1, '^': 100, ' ': 1} #glyph: weight def __init__(self, y, x, level): Findable.__init__(self) self.y = y self.x = x self.level = level self.glyph = None self.color = TermColor() self.explored = False self.items = [] self.monster = None self.walkable = True self.searches = 0 self.searched = False self.inShop = False self.locked = False self.shopkeepDoor = False def coords(self): return (self.y, self.x) def setTile(self, glyph, color): self.monster = None if glyph in Tile.dngFeatures: self.glyph = glyph self.color = color self.explored = self.explored or (glyph != ' ') if self.items: Kernel.instance.log("Removing items on %s because I only see a dngFeature-tile" % str(self.coords())) self.items = [] if glyph not in Tile.walkables.keys() and not self.isDoor(): Kernel.instance.log("Setting %s to unwalkable." % self) self.walkable = False if glyph in Tile.walkables.keys() and glyph not in [' ']: self.walkable = True #Kernel.instance.log("Found feature: %s, Color: %s, at (%d,%d). Tile is now: %s" % (glyph, str(color), self.y, self.x, str(self))) elif glyph in Tile.dngItems: it = Item(None, glyph, color) if not self.items: Kernel.instance.log("Added item(%s) to tile(%s)" % (str(it), str(self))) self.items.append(it) else: self.items[0] = it if glyph == '0': self.walkable = False else: self.walkable = True #Kernel.instance.log("Found item: %s, Color: %s, at (%d,%d). Tile is now: %s" % (str(it), str(color), self.y, self.x, str(self))) elif self.coords() == Kernel.instance.Hero.coords(): self.explored = True self.walkable = True # Might cause some trouble # TODO: Write comments that actually explains problems (No idea why I said the above, and no idea what the below does.. :) if not self.isWalkable(): self.walkable = True self.glyph = None elif glyph in Tile.dngMonsters: self.monster = Monster(glyph, color) self.walkable = True if self.glyph == ']': if Kernel.instance.Dungeon.tile(self.y-1, self.x).glyph == '|': self.glyph = '-' else: self.glyph = '|' self.color = TermColor(33, 0, False, False) #Kernel.instance.log("Found monster:%s, Color: %s, at (%d,%d). Tile is now: %s" % (str(self.monster), str(color), self.y, self.x, str(self))) else: Kernel.instance.die("Couldn't parse tile: " + glyph) def appearance(self): if self.monster: return self.monster.glyph elif self.items: return self.items[-1].glyph else: return self.glyph def isDoor(self): return (self.glyph == '-' or self.glyph == '|') and self.color.getId() == COLOR_BROWN def isWalkable(self): #TODO: Shops might be good to visit sometime ..:) # if not self.adjacent({'explored': True}): # return False if not self.glyph: return not self.monster and self.walkable else: if self.isDoor(): return not self.monster and True return not self.monster and self.glyph in Tile.walkables.keys() and self.walkable def walkableNeighbours(self): ret = [] for neighbour in self.neighbours(): if neighbour.isWalkable() and not (neighbour.isDoor() or self.isDoor()): ret.append(neighbour) continue if (self.isDoor() or neighbour.isDoor()) and (self.x==neighbour.x or self.y==neighbour.y) and neighbour.isWalkable(): ret.append(neighbour) continue return ret def isAdjacent(self, other): for neighbour in self.neighbours(): if neighbour == other: return True return False def straight(self, find): ret = [] for x in range(-1,2): for y in range(-1,2): if x*y == 0 and x!=y: tile = self.level.tiles[(x+self.x) + (y+self.y)*WIDTH] if tile.find(find): ret.append(tile) return ret def adjacent(self, find): return [tile for tile in self.neighbours() if tile.find(find)] def neighbours(self): ret = [] for x in range(-1,2): for y in range(-1,2): if x+self.x<0 or x+self.x>WIDTH-1 or y+self.y<0 or y+self.y>HEIGHT-4 or (x==0 and y==0): continue tile = self.level.tiles[x+self.x + (y+self.y)*WIDTH] ret.append(tile) return ret def isHero(self): return self.coords() == Kernel.instance.Hero.coords() def tilesFromCurrent(self): return (abs(Kernel.instance.Hero.x-self.x) + abs(Kernel.instance.Hero.y-self.y)) def __str__(self): return "(%s,%s)->g:%s, c:(%s), e:%s, @:%s, m:(%s), i:(%s) w:%s(is:%s) sea:%s" % tuple(map(str, (self.y, self.x, self.glyph, self.color, self.explored, self.isHero(), self.monster, map(str, self.items), self.walkable, self.isWalkable(), self.searches))) def __eq__(self, other): return self.coords() == other.coords() def __ne__(self, other): return self.coords() != other.coords()