Skip to content

Instantly share code, notes, and snippets.

@rharkanson
Created October 7, 2020 20:29
Show Gist options
  • Save rharkanson/1ece8376f310718c859189cad1f8684f to your computer and use it in GitHub Desktop.
Save rharkanson/1ece8376f310718c859189cad1f8684f to your computer and use it in GitHub Desktop.
who dunnit??
#!/usr/bin/env python3
from os import getenv
from random import choices, shuffle, randint
from argparse import ArgumentParser
import curses
CHAR_FRAMES=['ඞ','ඬ','ඩ','ඕ']
STARS={
' ': 90000,
'.': 800,
'`': 400,
'*': 200,
'+': 200,
'x': 200,
'X': 200,
'o': 100,
'O': 40,
'/': 40,
'\\': 40,
'෴': 10,
'⫸': 1
}
def main(stdscr, name, color, remain, impostor):
# Fix args
name = name if len(name) > 0 else "`sudo rm -rf /`"
color = color if 0 <= color < 256 else 2
remain = remain if 0 <= remain else 1
# Start screen
curses.start_color()
curses.use_default_colors()
# Set colors
curses.init_pair(1, 248, -1)
curses.init_pair(2, color, -1)
# Frame rate in millis
stdscr.timeout(1000//24)
# Screen width and height
cols = (curses.COLS - 1) - 4
lines = min(curses.LINES - 1, (9*cols)//32) - 4
# Generate sky
star_index = choices(list(STARS.keys()), list(STARS.values()), k=lines*cols*2)
stars = [''.join(star_index[l*cols*2:l*cols*2+cols*2]) for l in range(lines)]
# Messages
final_msg = "{} was{}An Impostor.".format(name, " " if impostor else " not ")
rem = "1 Impostor remains." if remain == 1 else "{} Impostors remain.".format(remain)
# Initial speeds and displacements
speeds = [s+2 for s in choices(range(5), k=6)]
d = [0 for _ in speeds]
# Set initial time and begin loop
t = 0
bye = True
msg = ""
while stdscr.getch()==-1:
# Draw top frame
stdscr.clear()
stdscr.addstr(0, 0, " +" + ("-"*cols) + "+ ", curses.color_pair(0))
# Draw current sky
for i in range(lines):
o = d[i%len(d)]
if o+cols < 2*cols:
ln = stars[i][o:o+cols]
else:
ln = (stars[i][o:2*cols]) + (stars[i][0:(o+cols) - 2*cols])
# ln="".join(star[so:so+cols])
stdscr.addstr(i+1, 0, " |", curses.color_pair(0))
stdscr.addstr(ln[::-1], curses.color_pair(1))
stdscr.addstr("| ", curses.color_pair(0))
# Draw bottom frame
stdscr.addstr(lines+1, 0, " +" + ("-"*cols) + "+ ", curses.color_pair(0))
if bye:
# Draw the gentleman
if 20 < t < cols*3+20:
stdscr.addstr((lines//2)-1, ((t-20)//3)+2, CHAR_FRAMES[(t//4)%4], curses.color_pair(2))
# Build the message
if (3*cols//2)+21 < t and t % 2 == 0 and msg != final_msg:
msg = final_msg[0:len(msg)+1]
# If the gentleman has left the building and msg is done
if t >= cols*3 + 20 and msg == final_msg:
bye = False
else:
# Print remaining message
stdscr.addstr((lines//2)+1, ((cols-len(rem))//2)+2, rem, curses.color_pair(0))
# Print current typed message
stdscr.addstr((lines//2)-1, ((cols-len(msg))//2)+2, msg, curses.color_pair(0))
# Move cursor out of the damn way
stdscr.addstr(lines+2, 0, "", curses.color_pair(0))
stdscr.refresh()
# Update time
t += 1
# Update displacement as function of speed per line
d = [((s*t)//3) % (cols*2) for s in speeds]
# If key animation is done, allow t to reset when all displacements are 0
if sum(d)==0 and not bye:
t = 0
shuffle(speeds)
# Parse command line args
parser = ArgumentParser(description="who dunnit??")
parser.add_argument("-n", "--name", type=str, help="name of ejected", default=getenv('USER',"it"))
parser.add_argument("-c", "--color", type=int, help="color of ඞ", default=randint(9,14))
parser.add_argument("-r", "--remain", type=int, help="impostors remaining", default=1)
parser.add_argument("-i", "--impostor", action="store_true", help="is impostor")
args = parser.parse_args()
# Begin the curses wrapper with parsed args
exit(curses.wrapper(main, args.name, args.color, args.remain, args.impostor))
@rharkanson
Copy link
Author

sus

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment