314 lines
10 KiB
Python
Executable File
314 lines
10 KiB
Python
Executable File
#!/usr/bin/python3
|
|
|
|
# Import some necessary libraries.
|
|
import random
|
|
import re
|
|
import inflect
|
|
import util.puzzle
|
|
|
|
p = inflect.engine()
|
|
challenges = {}
|
|
SCORE_FILE = "/home/krowbar/Code/irc/data/tildescores.txt"
|
|
JACKPOT_FILE = "/home/krowbar/Code/irc/data/tildejackpot.txt"
|
|
JACKPOT_MIN = 3
|
|
DEBUG = False
|
|
GOOD_CHAN = "#bots" # The name of the "good" channel that the bot is allowed to run in
|
|
|
|
def too_recent(time1, time2):
|
|
return int(float(time1)) - int(float(time2)) < 60 * 60
|
|
|
|
|
|
def get_positive():
|
|
return random.choice(
|
|
[
|
|
"Yes",
|
|
"Yep",
|
|
"Yeppers",
|
|
"Correct",
|
|
"You got it",
|
|
"Yeah",
|
|
"Right on",
|
|
"Uh-huh",
|
|
"Positive",
|
|
"Totally right",
|
|
"Close enough",
|
|
"That's it",
|
|
"Winner, winner",
|
|
"Bingo",
|
|
"Affirmative",
|
|
]
|
|
)
|
|
|
|
|
|
def get_negative():
|
|
return random.choice(
|
|
[
|
|
"No",
|
|
"Nope",
|
|
"Sorry",
|
|
"Wrong",
|
|
"Nuh-uh",
|
|
"Negatory",
|
|
"Incorrect",
|
|
"Not today",
|
|
"Try again",
|
|
"Maybe later",
|
|
"Maybe next time",
|
|
"Probably not",
|
|
"Answer hazy",
|
|
"Not quite",
|
|
"Not even close",
|
|
"Not for you",
|
|
"I think not",
|
|
"Wait... uh maybe?",
|
|
"It could have been",
|
|
"It should have been",
|
|
"Whoops",
|
|
"SegFault: Insufficient Tildes",
|
|
"Wait, what did you guess?"
|
|
]
|
|
)
|
|
|
|
|
|
def get_superlative(score):
|
|
if score > 4:
|
|
return random.choice(
|
|
[
|
|
"super cool",
|
|
"totally rad",
|
|
"extraordinary",
|
|
"dynomite",
|
|
"#topdrawer",
|
|
"a #TopLad",
|
|
"the cat's meow",
|
|
"a tilde town hero",
|
|
"my favorite person",
|
|
"incredibly lucky",
|
|
"unbelievable",
|
|
"a tilde town hunk",
|
|
"could bring all the boys to the yard",
|
|
"worth twice their weight in gold",
|
|
"the hero we need",
|
|
"no ordinary townie",
|
|
"the bot whisperer",
|
|
"probably predicting rng",
|
|
]
|
|
)
|
|
elif score > 2:
|
|
return random.choice(
|
|
[
|
|
"really cool",
|
|
"pretty neat",
|
|
"rather nice",
|
|
"a dynamic doggo",
|
|
"radical",
|
|
"intense",
|
|
"pretty lucky",
|
|
#"knows the territory",
|
|
#"has what it takes",
|
|
#"has mad skillz",
|
|
"going the distance",
|
|
"a hard worker",
|
|
"my sunshine",
|
|
"ready to rumble",
|
|
"better than sliced bread",
|
|
"main protagonist material",
|
|
"right as rain",
|
|
"a puzzle prophet",
|
|
"a counter-captcha expert",
|
|
]
|
|
)
|
|
else:
|
|
return random.choice(
|
|
[
|
|
"cool",
|
|
"nice",
|
|
"acceptible",
|
|
"good enough",
|
|
"a promising pupper",
|
|
"better than a horse",
|
|
"swell",
|
|
"a little lucky",
|
|
"just credible",
|
|
"my friend",
|
|
"probably not a robot",
|
|
"valuable to the team",
|
|
"now trending",
|
|
"on your way up",
|
|
"credit to team",
|
|
"a net positive",
|
|
"groovy",
|
|
"competent",
|
|
"not wrong",
|
|
"on the right track",
|
|
]
|
|
)
|
|
|
|
|
|
def get_bad_thing():
|
|
return random.choice(
|
|
[
|
|
"is a meanie",
|
|
"mugs me right off",
|
|
"miffed me off",
|
|
"is worse than a horse",
|
|
"smells like a ghost",
|
|
"probably didn't bathe today",
|
|
"probably shakes babies",
|
|
"didn't guess hard enough",
|
|
"isn't lucky",
|
|
"smells of elderberries",
|
|
"should reconsider their life choices",
|
|
"did't believe in the heart of the tilde",
|
|
"came to the wrong side of town",
|
|
"should have stopped while they were ahead",
|
|
"requires annotations from an authoratative source",
|
|
"could have been a contender",
|
|
"spreads vicious rumors",
|
|
"drank my milkshake",
|
|
"is probably cheating",
|
|
"is trying too hard",
|
|
"didn't really try",
|
|
"should try harder",
|
|
"caught me in a bad mood",
|
|
"should have gone with their first choice",
|
|
"did not receive IFR clearance from tower",
|
|
"was tardy for class",
|
|
"is on double secret probation",
|
|
"forgot their keys",
|
|
"forgot to bribe me",
|
|
"forgot to close the door",
|
|
"waited too long",
|
|
"doesn't call me on my cellphone",
|
|
"isn't wearing a seatbelt",
|
|
"didn't courtesy flush",
|
|
"asked a bot for answers",
|
|
"was right but I didn't feel like it",
|
|
"is right on opposite day",
|
|
"actually answered the last question",
|
|
"has their pants on backwards",
|
|
"forgot their own name",
|
|
"got me really confused",
|
|
"is a gambler"
|
|
]
|
|
)
|
|
|
|
|
|
def get_prize(user, isHuman, bonus=0):
|
|
prizes = [1] * 8 + [2] * 4 + [3] * 2 + [5] * isHuman # no 5pt prize for non-humans
|
|
prize = random.choice(prizes) + bonus
|
|
if (
|
|
random.randint(1, 10) > 6 - 4 * isHuman
|
|
): # 80% of the time it's a normal prize (40% for not humans)
|
|
return [
|
|
prize,
|
|
"{}: {}! You are {} and get {} tildes!".format(
|
|
user,
|
|
(get_positive() if isHuman else get_negative()),
|
|
get_superlative(prize),
|
|
p.number_to_words(prize),
|
|
),
|
|
]
|
|
else: # 20% of the time its a jackpot situation
|
|
with open(JACKPOT_FILE, "r+") as jackpotfile:
|
|
jackpot = int(jackpotfile.readline().strip("\n"))
|
|
jackpotfile.seek(0)
|
|
jackpotfile.truncate()
|
|
if (
|
|
random.randint(1, 10) > 1 or not isHuman
|
|
): # 90% of the time it's a non-prize. non-humans never win jackpot
|
|
new_jackpot = jackpot + max(1, prize)
|
|
jackpotfile.write(
|
|
str(new_jackpot)
|
|
) # increase the jackpot by the prize size
|
|
return [
|
|
0,
|
|
"{} {} and gets no tildes! (Jackpot is now {} tildes)".format(
|
|
user, get_bad_thing(), new_jackpot
|
|
),
|
|
]
|
|
else: # hit jackpot!
|
|
jackpotfile.write(str(JACKPOT_MIN))
|
|
return [
|
|
jackpot,
|
|
"{} hit the jackpot and won **{}** tildes!".format(
|
|
user, p.number_to_words(jackpot)
|
|
),
|
|
]
|
|
|
|
|
|
def show_jackpot():
|
|
with open(JACKPOT_FILE, "r") as jackpotfile:
|
|
jackpot = int(jackpotfile.readline().strip("\n"))
|
|
return "The jackpot is currently {} tildes!".format(p.number_to_words(jackpot))
|
|
|
|
|
|
def give_tilde(user, time, human, bonus=0):
|
|
found = False
|
|
with open(SCORE_FILE, "r+") as scorefile:
|
|
scores = scorefile.readlines()
|
|
scorefile.seek(0)
|
|
scorefile.truncate()
|
|
message = ""
|
|
for score in scores:
|
|
name, score_on_file, timestamp = score.strip("\n").split("&^%")
|
|
if name == user:
|
|
found = True
|
|
if too_recent(time, timestamp) and not DEBUG:
|
|
message = "{} asked for a tilde too recently and {}. Try again later.".format(user, get_bad_thing())
|
|
else:
|
|
prizevalue, prizetext = get_prize(user, human, bonus)
|
|
score = "{}&^%{}&^%{}\n".format(
|
|
user, str(int(score_on_file) + prizevalue), time
|
|
)
|
|
message = prizetext
|
|
scorefile.write(score)
|
|
if not found:
|
|
prizevalue, prizetext = get_prize(user, True, bonus)
|
|
scorefile.write("{}&^%{}&^%{}\n".format(user, str(prizevalue + 1), time))
|
|
message = "Welcome to the tilde game, {}! Here's {} free tildes to start you off.".format(user, p.number_to_words(prizevalue + 1))
|
|
|
|
return message
|
|
|
|
|
|
def show_tildescore(user):
|
|
with open(SCORE_FILE, "r") as scorefile:
|
|
for _idx, score in enumerate(scorefile):
|
|
record = score.strip("\n").split("&^%")
|
|
if record[0] == user:
|
|
return "{} has {} tildes!".format(user, p.number_to_words(record[1]))
|
|
# person has not played yet
|
|
return "{} has no tildes yet!".format(user)
|
|
|
|
|
|
def challenge(channel, user, time):
|
|
global challenges
|
|
challenge = util.puzzle.make_puzzle()
|
|
challenges[user] = challenge[1:]
|
|
return "{}: {}".format(user, challenge[0])
|
|
|
|
def valid_answer(answer, guess):
|
|
guess = guess.lower();
|
|
if callable(answer):
|
|
return answer(guess)
|
|
else:
|
|
# convert the guess and answer to just alphanumeric values. some
|
|
# "answers" acidentally have punctuation or other things in them
|
|
guess = re.sub(r'\W+', '', guess)
|
|
answer = re.sub(r'\W+', '', str(answer).lower())
|
|
return (guess == answer or guess == p.number_to_words(answer))
|
|
|
|
def challenge_response(user, time, msg):
|
|
global challenges
|
|
# print(msg)
|
|
response = ""
|
|
if user in challenges:
|
|
answer, bonus = challenges[user]
|
|
if valid_answer(answer, msg):
|
|
response = give_tilde(user, time, True, bonus)
|
|
else:
|
|
response = give_tilde(user, time, False, 0)
|
|
del challenges[user]
|
|
# delete the user from challenges either way
|
|
return response
|