#!/usr/bin/env python3 from subprocess import Popen, PIPE from random import choice, random from time import sleep from os import chdir map_url = 'https://zgrep.org/taxreturns/rfk.txt' # Log. def logging(msg): with open('log.txt', 'a') as fh: fh.write(msg.strip() + '\n') # Items. def get_items(): with open('rfk.txt') as fh: return [l.strip() for l in fh] def add_item(item): items = set(get_items() + [item]) with open('rfk.txt', 'w') as fh: fh.write('\n'.join(items) + '\n') logging('add item: ' + item) return 'Added item: ' + item def del_item(item): items = set(get_items()) if item in items: items.remove(item) with open('rfk.txt', 'w') as fh: fh.write('\n'.join(items) + '\n') logging('del item: ' + item) return 'Removed item: ' + item else: removal = None for maybe in items: if maybe.lower().startswith(item.lower()): if removal: break else: removal = maybe else: if removal: items.remove(removal) with open('rfk.txt', 'w') as fh: fh.write('\n'.join(items) + '\n') logging('del item: ' + removal) return 'Removed item: ' + removal else: return 'No items matched: ' + item return 'More than one item matched: ' + item # Robot finds kitten bits below. grid = {} width, height = 30, 15 rx, ry = width // 2, height // 2 percent = 0.1 blind = False found = False def string(): # prints the grid as a string global grid, rx, ry, width, height, found result = '' for y in range(height): for x in range(width): if (x, y) in grid: item = grid[(x, y)] if found and item[2]: result += 'K' else: result += item[0] elif x == rx and y == ry: result += '#' else: result += ' ' result += '\n' return result def move(x, y): # teleports to location global rx, ry, width, height, grid, found if x < 0 or y < 0 or x >= width or y >= height: return 'There is a wall in the way.' elif (x, y) in grid: result = grid[(x, y)] if result[2]: found = True return result[1] else: rx, ry = x, y return None up = lambda: move(rx, ry - 1) down = lambda: move(rx, ry + 1) left = lambda: move(rx - 1, ry) right = lambda: move(rx + 1, ry) symbols = '~!@$%^&*()`[]{}=+\\/?|-_;:\'"<>,.abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' def reset(): # Set up a new game. global width, height, rx, ry, grid, percent, found grid = {} found = False items = get_items() rx, ry = width // 2, height // 2 for y in range(height): for x in range(width): if random() <= percent and x != rx and y != ry: grid[(x, y)] = (choice(symbols), choice(items), False) if not grid: kitten = (rx - 2, ry - 2) else: kitten = choice(list(grid)) with open('found.txt') as fh: messages = [f.strip('\n') for f in fh.read().strip('\n').split('\n%\n')] grid[kitten] = (choice(symbols), choice(messages), True) if len(grid) == 1: objects = 'there is 1 object' else: objects = 'there are {} objects'.format(len(grid)) if not blind: append = 'Map: ' + map_url else: append = 'No map is being made, blind is set to true.' return 'New game! The grid is {} by {}, and {}. You are in the center. {}'\ .format(width, height, objects, append) # Parsing input. def tofile(): global blind if not blind: with open('/home/zgrep/tax/rfk.txt', 'w') as fh: fh.write(string()) def dedup(gen): prev = None for item in gen: if item == prev: continue else: prev = item yield item def parse(cmd, normalcase): global width, height, percent, blind if all(c in 'udlrnsew^v<>←↑→↓' for c in cmd): for c in cmd: if c in 'u^n↑': yield up() elif c in 'dvs→': yield down() elif c in 'le↓': yield right() tofile() elif cmd in ('up', 'north'): yield up() tofile() elif cmd in ('down', 'south'): yield down() tofile() elif cmd in ('left', 'west'): yield left() tofile() elif cmd in ('right', 'east'): yield right() tofile() elif cmd.startswith('size '): cmd = cmd.replace('size ', '', 1) try: w, h = map(int, cmd.split('x')) w = min(max(w, 5), 1000) h = min(max(h, 5), 1000) width, height = w, h yield reset() tofile() yield topic() except: yield 'The correct format for size is 10x10.' elif cmd.startswith('blind '): cmd = cmd.replace('blind ', '', 1) if ' ' not in cmd: if cmd in ('true', 'yes', 'on', '1'): blind = True with open('/home/zgrep/tax/rfk.txt', 'w') as fh: fh.write('Blind is turned on, no map is being generated.\n') yield topic() yield 'Blind has been set to true, no new maps with be generated.' elif cmd in ('false', 'no', 'off', '0'): blind = False tofile() yield topic() yield 'Blind has been turned off, a map has been generated: ' + map_url else: yield 'Expected either true or false.' elif cmd.startswith('prob '): cmd = cmd.replace('prob ', '', 1) try: m = 1 if cmd[-1] == '%': cmd = cmd[:-1] m = 0.01 p = min(max(m*float(cmd), 0), 1) percent = p yield reset() tofile() yield topic() except: yield 'The correct format for prob is 0.1 or 10%.' elif cmd.startswith('add item '): yield add_item(normalcase[9:]) elif cmd.startswith('del item '): yield del_item(normalcase[9:]) elif cmd in ('reset', 'new game', 'restart'): yield reset() tofile() yield topic() elif cmd == 'help': yield 'Commands: size, prob, add item, del item, up (north), down (south), left (west), right (east), new game, blind, map, help.' yield '^<>vudlrnsew becomes up left right down up down left right north south east west. Only the one-character short commands can be chained together in one IRC message.' if not blind: yield 'A map of the grid can be found at: {}'.format(map_url) else: yield 'Currently blind is set to true, and therefore no map of the grid is generated. But normally, it would be found here: {}'.format(map_url) elif cmd in ('map', 'grid'): yield map_url elif cmd == 'size': yield '{} by {}'.format(width, height) elif cmd == 'prob': s = 's' if len(grid) == 1: s = '' yield '{}%, with {} object{} on the current grid.'\ .format(percent*100, len(grid), s) elif cmd == 'blind': yield ('blind is set to false, a map is being generated.', 'blind is set to true, no map is being generated.')[blind] # IRC-specific bits below. def topic(): global found, width, height, grid s = 's' if len(grid) == 1: s = '' append = 'No map.' if not blind: append = 'Map: ' + map_url finding = '' if found is True: finding = ' Kitten has been found!' elif found: finding = ' Kitten has been found by {}!'.format(found) return '/t Robot finds kitten. To play, type "help". | The grid is {} by {}, and has {} object{}.{} {}'\ .format(width, height, len(grid), s, finding, append) def cmd(args): proc = Popen(args, stdout=PIPE) while True: line = proc.stdout.readline() if line: try: yield str(line[:-1], 'utf-8', 'ignore') except: pass else: break def begin(fin, fout): global found fin = '/home/zgrep/offtopiabday/' + fin fout = '/home/zgrep/offtopiabday/' + fout def send(msg): if msg: with open(fin, 'w') as fh: fh.write(msg.strip() + '\n') send(reset()) tofile() send(topic()) for line in cmd(['tail', '-n', '0', '-f', fout]): _, _, nick, line = line.split(' ', 3) nick = nick[1:-1] if nick in ('happybot', 'hatebot'): continue output = list(dedup(parse(line.lower(), line))) if found is True: found = nick with open('finders.txt', 'a') as fh: fh.write(found + '\n') send(topic()) time = 0 if len(output) > 3: time = 0.5 for line in output: send(line) sleep(time) from sys import argv if len(argv) != 3: print('Usage: in out') exit(1) chdir('/home/zgrep/offtopiabday/rfk') begin(*argv[1:])