Not The Main Worb/ntmw.py

From Esolang
Jump to navigation Jump to search
Back to Not The Main Worb
from collections import defaultdict
import heapq
import random
import os
import sys
from time import sleep

def load_file(filename):
    with open(filename) as f:
        phase1=True
        board={}
        sites=defaultdict(list)
        transmitmap={}
        x=0
        y=0
        width=0
        height=0
        for y,line in enumerate(f):
            line=line.rstrip("\r\n")
            if line=="#": 
                phase1=not phase1
                height=y
                continue
            if phase1:
                if len(line)>width: width = len(line)
                for x in range(0,len(line)-1,2):
                    board[(x/2,y)]=[line[x],line[x+1]]
                    if line[x+1]!=" ":
                        sites[line[x+1]].append((x/2,y))
                if len(line)%2:
                    board[(len(line)/2,y)]=[line[x]," "]
            else:
                if len(line)==0: continue
                if len(line)!=2: raise ValueError("Invalid transmitter-receiver pair on line %d: %s"%(y+1,line))
                if line[1] in transmitmap.values() or line[1] in transmitmap.keys() or line[0]==line[1]:
                    raise KeyError("Receiver symbol on line %d was previously declared: %s"%(y+1,line))
                if line[0] in transmitmap.values() or line[0] in transmitmap.keys():
                    raise KeyError("Transmitter symbol on line %d was previously declared: %s"%(y,line))
                transmitmap[line[0]]=line[1]
        if phase1:
            height=y
    return NTMW(board,sites,transmitmap,width,height)

class NTMW:
   
    def __init__(self,board,sites,transmitmap,width,height):
        self.board = board
        self.sites = sites
        self.transmitmap = transmitmap
        self.width = width
        self.height = height
        
    def do_transmit(self):
        for transmitter,receiver in self.transmitmap.items():
            if (all([self.board[coord][0]=="." for coord in self.sites[transmitter]]) and
                all([self.board[coord][0]==" " for coord in self.sites[receiver]])):
                for coord in self.sites[transmitter]:
                    self.board[coord][0]=" "
                for coord in self.sites[receiver]:
                    self.board[coord][0]="."
    
    def move_bobules(self):
        priorityq = []
        newboard = {}
        for coord,contents in self.board.items():
            if contents[0]=="." and contents[1] not in self.transmitmap.keys():
                heapq.heappush(priorityq,(random.random(), coord, contents[0]))
            newboard[coord]=["." if contents[1] in self.transmitmap.keys() and contents[0]=="." else "",contents[1]]
        while priorityq:
            _ , coord, contents = heapq.heappop(priorityq)
            dx,dy = random.sample(xrange(-1,2),2)
            x,y = coord
            if (x+dx,y+dy) in newboard.keys() and not newboard[(x+dx,y+dy)][0]:
                newboard[(x+dx,y+dy)][0]=contents
                newboard[coord][0]=self.board[(x+dx,y+dy)][0]
            else:
                newboard[coord][0]=self.board[coord][0]
        for contents in newboard.values():
            if not contents[0]:
                contents[0]=" "
        self.board = newboard
    
    def print_board(self):
        os.system('cls' if os.name=="nt" else 'printf "\033c"')
        for y in range(self.height):
            print "".join(["@" if self.board[(x,y)][0]=="." else self.board[(x,y)][1] for x in range(self.width) if (x,y) in self.board.keys()])

    def run(self):
        try:
            while True:
                self.do_transmit()
                self.move_bobules()
                self.print_board()
                sleep(0.05)
        except KeyboardInterrupt:
            sys.exit(0)
        

if __name__=="__main__":
    if len(sys.argv)<2:
        print "No NTMW filename provided to execute."
        sys.exit(0)
    ntmw = load_file(sys.argv[1])
    ntmw.run()