Beispiel #1
0
def debit(player, cost):
    if player.points < cost:
        malt.serve("You do not have enough points!")
        return False
    else:
        player.score(-cost)
        return True
Beispiel #2
0
def progress_game(party):
    """Advance the party forward one turn."""

    hot = party.hotseat()
    if hot.pending_protection:
        hot.protected = True
        hot.pending_protection = False

    party.rotate()
    party.turn_number += 1

    if party.turn_number >= party.turns_per_player*len(party.players):
        malt.serve("game over!")

    if party.turn_number in party.alert_turns:
        malt.line("#")
        malt.serve("Alert! Turn {} has been reached.".format(party.turn_number))
        malt.line("#")
        party.alert_turns.remove(party.turn_number)

    if party.to_shuffle:
        random.shuffle(party.players)
        party.to_shuffle = False

#    if party.points_win_condition:
#        if any([p.points >= party.points_win_condition for p in party.players]):
#            print("[ERROR]: the game should end now!")

#    elif party.turns_win_condition:
#        if party.turn_number >= party.turns_win_condition:
#            print("[ERROR]: the game should end now!")

    if party.autosave and party.save_location:
        disk.yaml_dump(party.save_location, party)
Beispiel #3
0
def yaml_load(path):
    """Directly load a python object from a yaml file."""

    try:
        target = open(path, 'r')
    except IOError as e:
        malt.serve("Unable to open {} for reading.".format(path))
    else:
        malt.serve("Reading from '{}'...".format(path))
        result = yaml.load(target)
        target.close()
        return result
Beispiel #4
0
def yaml_dump(path, obj):
    """Dump a python object as a yaml file."""

    try:
        target = open(path, 'w')
    except IOError as e:
        malt.serve("Unable to open {} for writing.".format(path))
        return False
    else:
        malt.serve("Writing to '{}'...".format(path))
        target.write(yaml.dump(obj))
        target.close()
        return True
Beispiel #5
0
def select_index(items):
    while True:
        malt.serve("Enter 'use [int n]' to select from the list.")
        max_index = len(list(items))
        for (i, (text, value)) in enumerate(items):
            v_string = ('.'*(5-len(str(value)))) + str(value)
            malt.serve("{:2}: ({}) {}".format(i+1, v_string, text))
        response = malt.fill(["use n:int"])
        if response != "use":
            continue

        n = response.n
        if n < 1 or n > max_index:
            continue
        else:
            return n-1
Beispiel #6
0
def deck_builder_menu(deck=None):
    options = [
        "add pack_file",
        "remove pack_file",
        "check",
        "export"
    ]
    pack_files = []
    while True:
        response = malt.fill(options)
        if response == 'add':
            pack_files.append(response.pack_file)

        elif response == 'remove':
            if response.pack_file in pack_files:
                pack_files.remove(response.pack_file)

        elif response == 'check':
            malt.serve(pack_files)

        elif response == 'export':
            return
Beispiel #7
0
def timer(timestring):
    """Display an interactive timer.

    Accepts one string formatted as a number with either 's', 'm', or 'h'
    attached to signify seconds, minutes, or hours. Waits for that amount of
    time, printing dots every second, minute, or hour. Can be cancelled while
    running with ^C.
    """
    suffix = timestring[-1]
    number = int(timestring[0:-1])
    if suffix == 's':
        unit = 'seconds'
        multiplier = 1
    elif suffix == 'm':
        unit = 'minutes'
        multiplier = 60
    elif suffix == 'h':
        unit = 'hours'
        multiplier = 3600
    else:
        raise ValueError("Invalid time signature (must be 's', 'm', or 'h')")

    malt.serve("You set a timer for {} {}. ".format(number, unit), nl=False)
    try:
        for i in range(number*multiplier):
            if i%20 == 0:
                malt.serve("")
                sys.stdout.flush()
            # using malt.show to maintain indentation
            malt.serve(".", nl=False)
            sys.stdout.flush()
            time.sleep(1)
    except KeyboardInterrupt:
        # use ^C to cancel mid-timer
        pass
    finally:
        malt.serve()
        malt.serve("### RING RING ###")
Beispiel #8
0
def perk_menu(party):
    # NOTE: may change in the future
    base_cost = util.points_value(2)
    hot = party.hotseat()
    options = [
        'curse',
        'shuffle',
        'protection',
        'skip',
        'immunity',
    ]
    while True:
        response = malt.fill(options)

        if response == 'curse':
            malt.serve("Make an opponent's next turn extra hard.")
            cost = base_cost*5

            if malt.confirm("Purchase for {} points? ".format(cost)):
                name = malt.freefill("Which player would you like to affect? ")
                if not party.verify(name):
                    malt.serve("{} is not a registered player.".format(name))
                    malt.serve("Your cost has been refunded.")
                    continue
                elif name == hot:
                    malt.serve("You may not curse yourself.")
                    malt.serve("Your cost has been refunded.")
                    continue
                else:
                    p = party.lookup(name)
                    if not p.cursed:
                        if debit(hot, cost):
                            p.cursed = True
                            malt.serve("{}'s next task will be extra spicy.".format(p))
                            return
                    else:
                        malt.serve("{} has already been cursed.")
                        malt.serve("Your cost has been refunded.")
                        continue

        elif response == 'shuffle':
            malt.serve("Shuffle the turn order for everyone in the party.")
            # for 2p games, as 50% chance to give double turn
            cost = base_cost*20

            if malt.confirm("Purchase for {} points? ".format(cost)):
                if debit(hot, cost):
                    party.to_shuffle = True
                    malt.serve("Shuffled turn orders.")
                    return

        elif response == 'protection':
            malt.serve("Automatically skip your next turn.")
            cost = base_cost*20

            if malt.confirm("Purchase for {} points? ".format(cost)):
                if debit(hot, cost):
                    hot.pending_protection = True
                    malt.serve("Your next turn will be skipped.")
                    return

        elif response == 'skip':
            malt.serve("Skip this turn.")
            cost = base_cost*100

            if malt.confirm("Purchase for {} points? ".format(cost)):
                if debit(hot, cost):
                    hot.protected = True
                    return
            
        elif response == 'immunity':
            malt.serve("Reject any one task at no cost.")
            malt.serve("More than one can be purchased at a time.")
            cost = base_cost*50

            if malt.confirm("Purchase for {} points? ".format(cost)):
                if debit(hot, cost):
                    hot.immunities += 1
                    malt.serve("You have {} immunity tokens.".format(hot.immunities))
                    return

        elif response == 'back':
            break
Beispiel #9
0
def game_menu(deck, party):
    options = [
        "task",
        "set difficulty",
        #"manual",
        "perks",
        "scores",
        "tools",
        #"tip name amount:int",
        "challenge name",
    ]
    while True:
        hotseat = party.hotseat()
        if hotseat.protected:
            hotseat.protected = False
            malt.serve("{} skips their turn.".format(hotseat))
            progress_game(party)
            continue

        malt.serve()
        update_string = "It is {}'s turn.".format(hotseat)
        malt.serve(update_string)
        malt.serve("="*len(update_string))
        response = malt.fill(options)

        if response == "task":
            if hotseat.stored_task:
                (task, points) = hotseat.stored_task
                hotseat.stored_task = None
            else:
                (task, points) = new_task(hotseat, deck, party)

            with malt.indent():
                task_menu(party, hotseat, (task, points))

        elif response == "set":
            try:
                hotseat.mod = util.rating_value(response.difficulty)
            except ValueError:
                malt.serve("Task difficulty must be easy, normal, hard, or brutal.")
            else:
                malt.serve("Set difficulty to {}.".format(response.difficulty))
            continue

        elif response == "manual":
            malt.serve("Manually creating new task.")
            with malt.indent():
                manual_task_creation_menu(deck)

        elif response == "perks":
            malt.serve("Entering perk shop.")
            with malt.indent():
                shop.perk_menu(party)

        elif response == "scores":
            for p in party.players:
                malt.serve("{}: {} Points".format(p.name, p.points))

        elif response == 'tools':
            malt.serve("Entering gameplay utilities.")
            with malt.indent():
                sugar.game_tools_menu(party)

        elif response == 'until':
            n = response.winning_points
            if n < 0:
                party.points_win_condition = 0
                malt.serve("Disabled win condition.")
            else:
                party.points_win_condition = n
                malt.serve("First person to {} points wins.".format(n))

        elif response == 'back':
            break
Beispiel #10
0
def task_menu(party, hotseat, card):
    (task, points) = card

    options = [
        'yes',
        'no',
        'mercy',
        'transfer name',  # TODO: touch up
    ]
    while True:
        #malt.serve()
        #malt.serve("### TASK ###")
        #malt.line("#")
        malt.serve("{}: {}.".format(hotseat, task))
        response = malt.fill(options)

        if response == 'yes':
            malt.serve("You accept the task and have earned {} points.".format(points))
            party.score(hotseat, points)
            break

        elif response == 'no':
            if hotseat.immunities > 0:
                if malt.confirm("Would you like to consume an immunity token? "):
                    hotseat.immunities -= 1
                    malt.serve("You do not lose any points.")
                    break
            malt.serve("You reject the task, losing {} points.".format(points))
            party.score(hotseat, -points)
            break

        elif response == 'mercy':
            malt.serve("You will not lose points, but will be presented another task.")
            return # don't rotate so the same player gets another

        elif response == 'transfer':
            recipient = response.name
            if hotseat == recipient:
                malt.serve("Naughty, naughty. You can't transfer a task to yourself.")
                continue
            try:
                party.score(recipient, points*2)
            except ValueError:
                malt.serve("{} is not a registered player.".format(recipient))
            else:
                malt.serve("You send the task to {}, who earns {} points.".format(
                    recipient, points*2))
                break

        elif response == 'back':
            malt.serve("You postpone the choice for later.")
            hotseat.stored_task = (task, points)
            return

    progress_game(party)
Beispiel #11
0
def game_tools_menu(party):
    """Run the interface for non-essential gameplay tools."""
    options = [
        'timer seconds:str',
        'countdown turns:int',
        'flip',
        'modify name amount:int',
        'reject name',
        'show name',
        'intensity x:int',
    ]

    while True:
        response = malt.fill(options)
        if response == 'timer':
            with malt.indent():
                timer(response.seconds)

        elif response == 'countdown':
            with malt.indent():
                if response.turns < 1:
                    malt.serve("Can only countdown one or more turns in advance.")
                    continue
                malt.serve("Scheduling an alert in {} turns.".format(response.turns))
            party.alert_turns.append(party.turn_number + response.turns)
                

        elif response == 'flip':
            with malt.indent():
                flip_coin()

        elif response == 'back':
            break

        elif response == 'modify':
            name = response.name
            points = response.amount
            if party.score(name, points):
                malt.serve("Adding {} to {}'s score.".format(points, name))
            del name

        elif response == 'reject':
            name = response.name
            player = party.lookup(name)
            if player:
                player.reject()
                malt.serve("Rejected {}'s last attempt.".format(name))
                points = player.points
                malt.serve("{} has been reverted to {} points.".format(name, points))
            else:
                malt.serve("{} is not a registered player.".format(name))
            del name, player

        elif response == "show":
            name = response.name
            p = party.lookup(name)
            if p:
                malt.serve("{}: {} Points".format(p.name, p.points))
            else:
                malt.serve("{} is not a registered player.".format(name))
            del name, p

        elif response == "intensity":
            x = response.x
            malt.serve("Setting intensity level to [{}].".format('X'*x))
            party.intensity = x
            del x

        elif response == 'back':
            break
Beispiel #12
0
def flip_coin():
    malt.serve("You flip and coin and catch it...")
    malt.pause()
    malt.serve("It was {}.".format(random.choice(['heads', 'tails'])))
Beispiel #13
0
def main_menu(args):
    """Run the main interactive menu.

    In this menu, party can be added to or removed from the game, and both
    the normal gameplay loop and the special debug loop can be accessed.
    """
    try:
        deck = setup_deck(args)
        party = setup_party(args)
    except SystemExit:
        print("Aborting startup.")
        return

    # Immediately enter debug mode if --debug is given.
    if args.debug:
        malt.serve("entering debug mode...")
        with malt.indent():
            debug.debug_menu(deck, party, args)

    options = [
        'start',
        'mercy',
        'daily',
        'debug',
        'add name',
        'remove name',
        'save game_file',
        'resume game_file',
        'export deck_file',
        'autosave toggle',
    ]
    while True:
        response = malt.fill(options)

        if response == 'start':
            if len(party.players) < 2:
                malt.serve("Please register at least two players to begin the game.")
                continue
            # check if the users want to set a losing punishment
            with malt.indent():
                play.game_menu(deck, party)

        elif response == 'debug':
            malt.serve("Entering debug mode.")
            with malt.indent():
                debug.debug_menu(deck, party, args)

        elif response == 'add':
            name = response.name
            if name in party.names():
                malt.serve("{} is already registered!".format(name))
            else:
                malt.serve("Registering {} as a new player.".format(name))
                party.add(name)

        elif response == 'remove':
            name = response.name
            if name in party.names():
                malt.serve("Removing {} from the game.".format(name))
                party.kick(name)
            else:
                malt.serve("{} is not a registered player!".format(name))

        elif response == 'save':
            path = response.game_file
            disk.yaml_dump(path, party)

        elif response == 'resume':
            path = response.game_file
            new_party = disk.yaml_load(path)
            if new_party is not None:
                party = new_party

        elif response == 'export':
            path = response.deck_file
            disk.yaml_dump(path, deck)

        elif response == 'autosave':
            toggle = response.toggle
            if toggle == 'on':
                filename = malt.freefill("filename: ")
                if disk.yaml_dump(filename, party):
                    party.autosave = True
                    party.save_location = filename
                    malt.serve("Enabled autosave.")
                else:
                    malt.serve("Cancelled autosave.")

            elif toggle == 'off':
                party.autosave = False
                malt.serve("Disabled autosave.")
            elif toggle == 'check':
                malt.serve("Autosave is currently {}.".format(
                    'on' if party.autosave else 'off'))
            else:
                malt.serve("The only options for autosave are on, off, and check.")

        elif response == 'back':
            break
Beispiel #14
0
def debug_menu(deck, party, args):
    """Offer options for viewing and tweaking internal variables."""

    options = [
        'batch n:int',
        #'level n:int',
        'progress difficulty',
        'np difficulty',
        'dump level',
        'intensity level:int',
        'args',
    ]
    while 1:
        response = malt.fill(options)

        if response == 'batch':
            for i in range(response.n):
                (text, value) = taskgen.random_task(deck)
                print('[{}] '.format(i), end='')
                display((text, value))

        # Print out all tasks at a certain level.
        elif response == 'level':
            level = response.n
            nested = taskgen.all_combinations(deck.base, deck.subs)
            # remove all out-of-level tasks
            nested = [[(t, v) for (t, v) in base if v==level] for base in nested]
            # clean up empty lists
            nested = [base for base in nested if len(base) > 0]
            # sort tasks alphabetically
            nested = sorted(nested, key=lambda x: x[0][0:5])
            for base in nested:
                # sort variations by point value
                base = sorted(base, key=lambda x: x[1])
                print("========================================")
                for variation in base:
                    display(variation)
                print("")

        elif response == 'progress':
            try:
                mod = util.rating_value(response.difficulty)
            except ValueError:
                malt.serve("Invalid difficulty.")
                continue

            points = 0
            turn_num = 0
            while turn_num < 20:
                turn_num += 1
                target = util.target_rating(points, mod)
                (text, rating) = taskgen.random_task(deck, target)
                print("({}) {}".format(rating, text))
                points += util.points_value(mod)

        elif response == 'np':
            # Take arguments.
            try:
                mod = util.rating_value(response.difficulty)
            except ValueError:
                malt.serve("Invalid difficulty.")
                continue
            #end = response.turns

            points = 0
            turn_num = 0
            while turn_num < 20:
                turn_num += 1
                target = util.target_rating(points, mod)
                print("[{}] (Level {})".format(util.format_number(points), target))
                points += util.points_value(mod)

        # Dump every possible complete task.
        elif response == 'dump':
            nested = taskgen.all_combinations(deck.base, deck.subs)
            if response.level == 'all':
                pass
            else:
                try:
                    rating = util.rating_value(response.level)
                    # remove all out-of-level tasks
                    nested = [
                        [(t, v) for (t, v) in base if v==rating] for base in nested]
                    # clean up empty lists
                    nested = [base for base in nested if len(base) > 0]
                except ValueError:
                    malt.serve("Invalid difficulty.")
                    continue
            # sort tasks alphabetically by the first five characters
            nested = sorted(nested, key=lambda x: x[0][0:5])
            for base in nested:
                # sort variations by point value
                base = sorted(base, key=lambda x: x[1])
                print("========================================")
                for variation in base:
                    display(variation)
                #print("")

        # Set the intensity level.
        elif response == 'intensity':
            malt.serve("setting flag -{}".format('x'*response.level))
            party.intensity = response.level

        elif response == 'args':
            malt.serve(args)

        elif response == 'back': break