This file is indexed.

/usr/share/games/bouncy/rabbit.py is in bouncy 0.6.20071104-5.

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
import math, os
import euclid, objloader, collide, objects
from OpenGL.GL import *
from OpenGL.GLUT import *

class Rabbit:
    def load(cls):
        cls.models = {}
        for name in ['rabbit-sitting', 'rabbit-hopping', 'rabbit-landing',
                'bump', 'rabbit-dig1', 'rabbit-dig2']:
            obj = objloader.OBJ(os.path.join('data', '%s.obj'%name),
                outline=objects.toon_program is not None)
            cls.models[name] = obj
    load = classmethod(load)

    ST_SITTING = 'State: SITTING'
    ST_HOPPING = 'State: HOPPING'
    ST_DIGGING = 'State: DIGGING'
    ST_EATING = 'State: EATING'
    ST_UNDERGROUND = 'State: UNDERGROUND'
    ST_SURFACING = 'State: SURFACING'

    hit_offset = euclid.Vector3(0, 1.5, 0)
    def __init__(self, position, rotation):
        self.position = euclid.Point3(*position)
        self.velocity = euclid.Vector3(0, 0, 0)
        self.direction = rotation
        self.model = self.models['rabbit-sitting']
        self.state = self.ST_SITTING
        self.hitbox = collide.AABox(self.position + self.hit_offset,
            2, 3., 2)
        self.hunger = {}
        self.eating = None

    def is_underground(self):
        return (self.state is self.ST_UNDERGROUND or
            self.state is self.ST_SURFACING)

    def move(self, move):
        if self.state is self.ST_HOPPING:
            mag = abs(euclid.Vector2(self.velocity.x, self.velocity.z))
            desired = euclid.Vector2(move.x, move.z).normalize()
            result = desired * mag
            self.velocity.x = result.x
            self.velocity.z = result.y
            if abs(result):
                self.direction = math.atan2(result.x, result.y) * 180 / math.pi
            return

        if not abs(move):
            return

        impulse = move * .15
        self.direction = math.atan2(move.x, move.z) * 180 / math.pi
        if self.state is self.ST_SITTING:
            self.model = self.models['rabbit-hopping']
            self.state = self.ST_HOPPING
            self.velocity += impulse + euclid.Vector3(0, .3, 0)
            self.position += self.velocity
            self.hitbox.c = self.position + self.hit_offset
        elif self.state is self.ST_UNDERGROUND:
            self.position += impulse
            self.hitbox.c = self.position + self.hit_offset

    def dig(self):
        if self.state is self.ST_UNDERGROUND:
            self.state = self.ST_SURFACING
            self.surface_time = 0

        elif self.state is self.ST_SITTING:
            self.state = self.ST_DIGGING
            self.model = self.models['rabbit-dig1']
            self.dig_time = 0

    def stop_dig(self):
        if self.state is self.ST_DIGGING:
            self.model = self.models['rabbit-sitting']
            self.state = self.ST_SITTING
        if self.state is self.ST_SURFACING:
            self.state = self.ST_UNDERGROUND

    def eat(self):
        if self.state is self.ST_SITTING:
            self.state = self.ST_EATING
            self.eat_time = 0

    def stop_eat(self):
        if self.state is self.ST_EATING:
            self.state = self.ST_SITTING

    class RabbitFed:
        pass

    GRAVITY = 1.5/1000.
    def animate(self, ts, level):
        # gravity is a constant
        self.velocity.y -= self.GRAVITY * ts

        if self.state is self.ST_HOPPING:
            if self.velocity.y <= 0:
                self.model = self.models['rabbit-landing']

        elif self.state is self.ST_EATING:
            food = level.find_food(self.eat_sphere)
            if food is not None and food.name.split('-')[0] in self.hunger:
                food_name = food.name.split('-')[0]
                if self.eating is not food:
                    self.eating = food
                    self.eat_time = 0
                else:
                    self.eat_time += 1
                if self.eat_time > 10:
                    self.eat_time = 0
                    level.eat_food(food)
                    self.hunger[food_name] = max(0,
                        self.hunger[food_name] - food.food_value)
                    for value in self.hunger.values():
                        if value > 0: break
                    else:
                        raise self.RabbitFed

        elif self.state is self.ST_DIGGING:
            self.dig_time += ts
            if self.dig_time%300 > 100:
                self.model = self.models['rabbit-dig2']
            else:
                self.model = self.models['rabbit-dig1']

            if self.dig_time > 300:
                self.dig_time += ts
                r = euclid.Matrix4.new_rotatey(self.direction * math.pi / 180)
                hole = r * euclid.Vector3(0., 0., 1.)
                level.add_hole(self.position + hole)

            if self.dig_time > 1200:
                self.state = self.ST_UNDERGROUND
                self.model = self.models['bump']
                r = euclid.Matrix4.new_rotatey(self.direction * math.pi / 180)
                bump = r * euclid.Vector3(0., 0., 1.)
                self.position += bump

        elif self.state is self.ST_UNDERGROUND:
            # no collision detection
            # TODO: collide with streams
            return

        elif self.state is self.ST_SURFACING:
            self.surface_time += ts
            if self.surface_time > 500:
                r = euclid.Matrix4.new_rotatey(self.direction *
                    math.pi / 180)
                hole = r * euclid.Vector3(0., 0., 1.)
                level.add_hole(self.position + hole)
                self.state = self.ST_SITTING
                self.model = self.models['rabbit-sitting']

        # move
        old_pos = self.position.copy()
        self.position = self.position + self.velocity
        self.hitbox.c = self.position + self.hit_offset

        # no level - simple animation
        if level is None:
            if self.position.y < 0:
                self.state = self.ST_SITTING
                self.position.y = 0
                self.velocity = euclid.Vector3(0., 0., 0.)
            return

        # handle collision with the level
        l = level.is_intersecting(self.hitbox)
        vy = self.velocity.y
        resting = False
        if l:
            # back-track
            self.position = old_pos
            self.hitbox.c = self.position + self.hit_offset

            # now resolve
            for hitbox in l:
                self.hitbox.c, vmod = hitbox.resolve_collision(self.hitbox)
                self.velocity = self.velocity * vmod
                if vy < 0 and vmod.y == 0: resting = True

            # now use velocity
            self.hitbox.c = self.hitbox.c + self.velocity

            # set rabbit center using hitbox offset
            p = self.hitbox.c - self.hit_offset
            self.position = euclid.Point3(p.x, p.y, p.z)

        # if we're hopping but we've not moved then revert to sitting
        if resting and self.state is self.ST_HOPPING:
            self.velocity = euclid.Vector3(0., 0., 0.)
            self.state = self.ST_SITTING
            self.model = self.models['rabbit-sitting']

        # place the eating sphere
        r = euclid.Matrix4.new_rotatey(self.direction * math.pi / 180)
        eat_vec = r * euclid.Vector3(0., 1., 2.)
        self.eat_sphere = euclid.Sphere(self.position + eat_vec, 2.)

    def render(self, show_collide=False):
        if show_collide:
            self.hitbox.render()
            glPushMatrix()
            glTranslate(self.eat_sphere.c.x, self.eat_sphere.c.y,
                self.eat_sphere.c.z)
            glColor(.5, .5, 1)
            glutWireSphere(self.eat_sphere.r, 8, 8)
            glPopMatrix()
        else:
            glPushMatrix()
            glTranslate(self.position.x, self.position.y, self.position.z)
            glRotate(self.direction, 0, 1, 0)
            glCallList(self.model.gl_list)
            glPopMatrix()