File: defaultbot.py

package info (click to toggle)
tennix 1.1-2
  • links: PTS
  • area: main
  • in suites: wheezy
  • size: 6,720 kB
  • sloc: ansic: 2,906; cpp: 2,333; python: 275; objc: 245; makefile: 125
file content (159 lines) | stat: -rw-r--r-- 5,629 bytes parent folder | download | duplicates (5)
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

# Experimental implementation of a Python-based Tennix AI Bot

import random
import time
import threading
import math
import sys

import tennix

DEBUG = False

class BasicBot(object):
    name = 'Unnamed Bot'

    def say(self, *args):
        # FIXME: Expose debugging flag through "tennix" module
        global DEBUG
        if DEBUG:
            print self.name, 'says:', (' '.join(str(x) for x in args))

class DumbPythonBot(BasicBot):
    name = 'John McInpyre'

    GAME_Y_MID = 242
    DESIRED_POWER = { tennix.INPUT_KEY_HIT: 90, tennix.INPUT_KEY_TOPSPIN: 70, tennix.INPUT_KEY_SMASH: 70 }
    DEFAULT_APPROACH_DISTANCE = 40.0

    def __init__(self, gamestate, player_id):
        self.gamestate = gamestate
        self.player_id = player_id

        self.pressed_key = -1

        self.ball_approaching = False
        self.have_to_serve = False

        self.old_ball_x, self.old_ball_y = tennix.get_ball_pos(self.gamestate)
        self.ball_x, self.ball_y = self.old_ball_x, self.old_ball_y
        self.player_x, self.player_y = tennix.get_position(self.gamestate, self.player_id)
        self.power = tennix.get_power(self.gamestate, self.player_id)

        self.desired_y_position = self.GAME_Y_MID
        self.approach_distance = self.DEFAULT_APPROACH_DISTANCE
        self.think_about_y_position()

        self.cancelled = False
        self.t = threading.Thread(target=self.think)
        self.t.start()
        self.say(self.name, 'has been loaded')

    def distance(self, a, b):
        return math.sqrt((a[0]-b[0])**2 + (a[1]-b[1])**2)

    def look_at_power_bar(self):
        self.power = tennix.get_power(self.gamestate, self.player_id)

    def look_at_player(self):
        self.player_x, self.player_y = tennix.get_position(self.gamestate, self.player_id)

    def look_at_ball(self):
        self.old_ball_x, self.old_ball_y = self.ball_x, self.ball_y
        self.ball_x, self.ball_y = tennix.get_ball_pos(self.gamestate)
        old_distance = self.distance((self.player_x, self.player_y), (self.old_ball_x, self.old_ball_y))
        new_distance = self.distance((self.player_x, self.player_y), (self.ball_x, self.ball_y))

        self.ball_approaching = (old_distance > new_distance)
        self.have_to_serve = ((old_distance == new_distance) and abs(self.player_x - self.ball_x) < 50)

    def have_sufficient_power(self):
        return self.power > 90

    def think_about_y_position(self):
        if not self.ball_approaching and not self.have_to_serve:
            #self.desired_y_position = self.GAME_Y_MID
            return

        ball_x_speed = self.old_ball_x - self.ball_x

        ball_y_speed = self.old_ball_y - self.ball_y

        #self.say('My ball x speed is', ball_x_speed)
        #self.say('My ball y speed is', ball_y_speed)

        x_diff = self.player_x - self.ball_x
        if ball_x_speed != 0.0:
            self.approach_distance = abs(ball_x_speed*.6)
            y_diff = ball_y_speed * x_diff / ball_x_speed
        else:
            self.approach_distance = self.DEFAULT_APPROACH_DISTANCE
            y_diff = 0.0

        self.say('I have to move', y_diff, 'to catch the ball now', x_diff, 'away')

        self.desired_y_position = self.ball_y + y_diff + random.randint(-5,5)

    def am_positioned(self):
        return abs(self.desired_y_position - self.player_y) < 30

    def think(self):
        i = 0
        while not self.cancelled:
            time.sleep(.2)

            self.look_at_power_bar()
            self.look_at_player()
            self.look_at_ball()

            self.think_about_y_position()

            if self.pressed_key == -1:
                if self.ball_approaching or self.have_to_serve:
                    self.pressed_key = tennix.INPUT_KEY_HIT
            else:
                self.say('holding key with distance', abs(self.player_x - self.ball_x))
                self.say('my approach distance is', self.approach_distance)
                if not self.ball_approaching and not self.have_to_serve:
                    self.pressed_key = -1
                if abs(self.player_x - self.ball_x) < self.approach_distance and self.have_sufficient_power() and self.am_positioned():
                    self.pressed_key = -1

            #self.current_tactic = random.randint(tennix.INPUT_KEY_HIT, tennix.INPUT_KEY_SMASH)
            #self.desired_power = self.DESIRED_POWER[self.current_tactic]*(1.2-0.4*random.random())
            #print 'determined new tactic:', self.current_tactic
            i += 1
        self.say('Thread for', self.name, 'finished')

#        if math.sqrt((self.player_x - self.ball_x)**2 + (self.player_y - self.ball_y)**2) > 150:
#            return False
#
#        if self.power > self.desired_power and random.randint(0, 3)==0:
#            self.power_locked = True
#            return False
#        if key_id == self.current_tactic and not self.power_locked:
#            #if abs(self.player_x - self.ball_x) < 10 and self.power > self.desired_power:
#            return abs(self.player_x - self.ball_x) > 5 and self.power < self.desired_power + 0.3*random.random()
#        else:
#            return False

    def finish(self):
        self.say('I am going to be unloaded')
        self.cancelled = True
        if self.t is not None:
            self.t.join()

    def get_key(self, key_id):
        return self.pressed_key == key_id

    def get_axis(self, axis_id):
        self.look_at_player()
        if axis_id == tennix.INPUT_AXIS_Y:
            return max(-1.0, min(1.0, (self.desired_y_position - self.player_y)/4.))

        return 0.0


tennix.register_bot(DumbPythonBot)