forked from zgrep/happybot
zgrep
8b6c9697e0
The Earth revolves around the God. The God gives you a world full of viral diseases. You curse God. You revolve around God. God revolves around a door. The door opens. This is going nowhere, you can stop reading now. I said you could stop. Okay, that's it, I'm really ending it now.
313 lines
9.3 KiB
Python
313 lines
9.3 KiB
Python
#!/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 'l<w←':
|
|
yield left()
|
|
elif c in 'r>e↓':
|
|
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:])
|