summaryrefslogtreecommitdiff
path: root/docs/tutorial/adventure.py
blob: 0733cbe9c5db6dbd4a4c6b7c534529b4f192565e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
from __future__ import annotations

import urwid


class ActionButton(urwid.Button):
    def __init__(self, caption, callback):
        super().__init__("")
        urwid.connect_signal(self, 'click', callback)
        self._w = urwid.AttrMap(urwid.SelectableIcon(caption, 1),
            None, focus_map='reversed')

class Place(urwid.WidgetWrap):
    def __init__(self, name, choices):
        super().__init__(
            ActionButton([" > go to ", name], self.enter_place))
        self.heading = urwid.Text(["\nLocation: ", name, "\n"])
        self.choices = choices
        # create links back to ourself
        for child in choices:
            getattr(child, 'choices', []).insert(0, self)

    def enter_place(self, button):
        game.update_place(self)

class Thing(urwid.WidgetWrap):
    def __init__(self, name):
        super().__init__(
            ActionButton([" * take ", name], self.take_thing))
        self.name = name

    def take_thing(self, button):
        self._w = urwid.Text(f" - {self.name} (taken)")
        game.take_thing(self)

def exit_program(button):
    raise urwid.ExitMainLoop()

map_top = Place('porch', [
    Place('kitchen', [
        Place('refrigerator', []),
        Place('cupboard', [
            Thing('jug'),
        ]),
    ]),
    Place('garden', [
        Place('tree', [
            Thing('lemon'),
            Thing('bird'),
        ]),
    ]),
    Place('street', [
        Place('store', [
            Thing('sugar'),
        ]),
        Place('lake', [
            Place('beach', []),
        ]),
    ]),
])

class AdventureGame:
    def __init__(self):
        self.log = urwid.SimpleFocusListWalker([])
        self.top = urwid.ListBox(self.log)
        self.inventory = set()
        self.update_place(map_top)

    def update_place(self, place):
        if self.log: # disable interaction with previous place
            self.log[-1] = urwid.WidgetDisable(self.log[-1])
        self.log.append(urwid.Pile([place.heading] + place.choices))
        self.top.focus_position = len(self.log) - 1
        self.place = place

    def take_thing(self, thing):
        self.inventory.add(thing.name)
        if self.inventory >= {'sugar', 'lemon', 'jug'}:
            response = urwid.Text('You can make lemonade!\n')
            done = ActionButton(' - Joy', exit_program)
            self.log[:] = [response, done]
        else:
            self.update_place(self.place)

game = AdventureGame()
urwid.MainLoop(game.top, palette=[('reversed', 'standout', '')]).run()