This file is indexed.

/usr/lib/python2.7/dist-packages/gameclock/game.py is in gameclock 5.1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
# -*- coding: utf-8 -*-
#
# The gameclock game engines
#
# This is where the game engines reside.
#
# (C) Anarcat 2011

import re
import inspect

import gameclock.clock


def valid_game(cls):
    return inspect.isclass(cls) and not cls.__name__.startswith('Abstract')


def enumerate_games():
    classes = inspect.getmembers(gameclock.game, valid_game)
    return sorted(classes,
                  lambda x, y: cmp(_(x[1].nice_name()),
                                   _(y[1].nice_name())),
                  reverse=True)


class AbstractGame:
    """the game engine
    
    this regroups clocks and handles turn switches

    this is an abstract class, it needs to be extended to do anything.
    """

    # default settings for new games, overridable in the constructor
    # or the properties of the object after creation
    players = 2

    # either name the class after the clock (e.g. ChessClock ->
    # ChessGame) or define this to associate this game with a specific
    # clock
    clock_type = None

    def __init__(self, **settings):
        # import settings as object attributes
        for key, val in settings.iteritems():
            setattr(self, key, val)
        # export back those attributes as settings to the clock
        for key in vars(self.__class__):
            settings[key] = getattr(self, key)

        settings['start_time'] = self.time

        # this finds the class name of the clock we want, either set
        # explicitely in the game class attribute or by guessing the
        # name from the game class
        clock_type = self.__class__.clock_type or \
                     getattr(gameclock.clock,
                             self.__class__.__name__.split('Game')[0] +
                             'Clock')

        # the clock engines
        p = clock_type(**settings)  # the last clock (next_clock = None)
        # this goes backwards
        for i in range(self.players-1):
            settings['next_clock'] = p
            p = clock_type(**settings)  # the previous clock
        # the clocks in the game
        #
        # in chess there are two clocks, but there can be more. this
        # is simply a list
        self.first_clock = self.cur_clock = p

    def resize(self, players):
        clock_type = self.__class__.clock_type or \
                     getattr(gameclock.clock,
                             self.__class__.__name__.split('Game')[0]
                             + 'Clock')
        settings = {}
        for key in vars(self.__class__):
            settings[key] = getattr(self, key)
        settings['start_time'] = self.time
        settings['next'] = None

        p = self.first_clock
        p.next = None
        for i in range(players-1):
            if p.next is None:
                p.next = clock_type(**settings)
            p = p.next
        self.players = players

    def copy(self):
        """return a new game object similar to this one"""
        settings = {}
        for key in vars(self.__class__):
            settings[key] = getattr(self, key)
        return self.__class__(**settings)

    def start(self):
        """start the game
        
        this basically starts the clock
        """
        self.cur_clock.start()

    def move(self):
        """make a move, that is, end the current turn
        
        this is the handler for the main button. it will stop the
        active clock and start the other and switch the active clock
        """
        self.cur_clock.stop()
        # XXX: we might lose a few ms here
        self.next()
        self.cur_clock.start()

    def pause(self):
        """pause the game
        
        this just pauses the current clock

        returns true if the current clock is paused
        """
        self.cur_clock.pause()
        return not self.cur_clock.running()

    def next(self):
        """change the current clock to the next one"""
        self.cur_clock = self.cur_clock.next or self.first_clock

    def alive(self):
        def _check_alive(clock):
            return not clock.is_dead()
        return self.foreach(_check_alive)

    def dead(self):
        return not self.alive()

    def running(self):
        return self.cur_clock.running()

    def foreach(self, function):
        """run the given function on all clock objects

return true if all calls return true"""
        ret = True
        p = self.first_clock
        while p:
            ret = function(p) and ret
            p = p.next
        return ret

    def set_time(self, time):
        """reset the time of all clocks to the given time"""
        self.time = time

        # this is actually almost as long as the original non-foreach
        # function, but allows for testing the API
        def h(p):
            p.time = time
        self.foreach(h)

    def __str__(self):
        """make a better string representation of the objects
        
        we basically dump all variables and some functions
        """
        return "  game engine %s\n  \n  first %s\n  current %s" % \
            (object.__str__(self), self.first_clock, self.cur_clock)

    @classmethod
    def nice_name(cls):
        """this funky bit splits the class name on capital letters and gets
        rid of the last entry ('Game')
        """
        return ' '.join(filter(lambda x: x, re.split('([A-Z][a-z]*)',
                                                     cls.__name__))[:-1])


class AbstractDelayGame(AbstractGame):
    """games that have a concept of a delay"""

    delay = None  # abstract class

    def set_delay(self, delay):
        def s(clock):
            clock.delay = delay
        self.foreach(s)


class AbstractGoGame(AbstractDelayGame):
    """go games have a delay, but also a byoyomi"""

    byoyomi = None  # abstract class

    def set_byoyomi(self, byoyomi):
        def s(clock):
            clock.set_byoyomi(byoyomi)
        self.foreach(s)

    @classmethod
    def nice_name(cls):
        return _('Go: %s') % ' '.join(filter(lambda x: x,
                                             re.split('([A-Z][a-z]*)',
                                                      cls.__name__))[1:-1])


class AbstractChessGame(AbstractGame):
    clock_type = gameclock.clock.ChessClock

    @classmethod
    def nice_name(cls):
        return _('Chess: %s') % re.split('([A-Z][a-z]*)', cls.__name__)[1]


class RegularChessGame(AbstractChessGame):
    """A regular chess game of 60 minutes per player, with no increment."""
    time = 60 * 60 * 1000


class QuickChessGame(AbstractChessGame):
    """A quick 15 minutes per player chess game, no increment."""
    time = 15 * 60 * 1000


class LightningChessGame(AbstractChessGame):
    """A very fast chess game, 5 minutes per player no increment."""
    time = 5 * 60 * 1000


class FischerChessGame(AbstractDelayGame):
    """A delay timing style used for chess and designed by Bobby Fischer. Everytime the player makes a move, a delay is added to the clock. Defaults: 2 minutes per player, 10 second increment, results in a reasonably short chess game."""
    
    time = 2 * 60 * 1000
    delay = 10 * 1000

    @classmethod
    def nice_name(cls):
        return _('Chess: Fischer')


class BoardGame(AbstractGame):
    """A regular board game. A clock goes down until time runs out. The counter is reset at every move. Default is to give 2 minutes per move."""
    time = 2 * 60 * 1000


class HourglassGame(AbstractGame):
    """Behave like an hourglass: the clock goes down on one side and up on the other, 60 seconds by default."""
    time = 60 * 1000

    def start(self):
        """override the start routine to make sure clocks are properly started"""
        p = self.first_clock
        while p:
            if p == self.cur_clock:
                p.start()
            else:
                p.stop()
            p = p.next


class GoStandardByoyomiGame(AbstractGoGame):
    """A standard or "japanese" Go counter. A clock counts down until its time runs out and then enters overtime. Once in overtime the player has a specific number of overtime periods (or "Byo-yomi") to play. If the player moves within the chosen delay, the clock's time reverts to the top of the period and no periods are lost. If the player does not move within the period, the next period begins and the period count is reduced by 1. A player loses when his/her clock runs out of time and no more periods remain."""
    time = 30 * 60 * 1000  # 30 minutes
    byoyomi = 5  # 5 spare delays
    delay = 60 * 1000  # 60 seconds