Cast withstand() before fleeing from Rogue Nerf Rocket Launchers
[TauBetaPyBot.git] / TauBetaPyBot.py
blobb8d0eb26adeaea24649ce0aa87147d3fb7e7222b
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 # Name: TauBetaPyBot
4 # Summary: a bot for playing TBP Hunt (http://spider.eecs.umich.edu/~tbp/michelle/michelle.php)
5 # Author: Elson Liu
6 # Author-email: "Elson Liu" <eyliu.dev@umich.edu>
7 # License: BSD
8 # Requires: httplib2
9 # Requires: lxml
12 import optparse
13 import csv
14 import getpass
15 import httplib2
16 import lxml.html
17 import urllib
18 import re
19 import sys
20 import time
22 attributes = [
23 "level",
24 "experience",
25 "neededexperience",
26 "health",
27 "maxhealth",
28 "integrity",
29 "maxintegrity",
30 "gold"
33 eattributes = [
34 "enemycurrenthp",
35 "enemymaxhp"
38 headers = {
39 "Content-Type": "application/x-www-form-urlencoded",
40 "User-Agent": "TauBetaPyBot (Watson; JamesOS 1.0)",
41 "Accept": "text/plain"
44 player = {}
46 enemy = {}
48 state = {}
50 loggedin = False
52 csvfile = None
54 def enable_colors(c):
55 global COLOR_RED
56 global COLOR_GREEN
57 global COLOR_YELLOW
58 global COLOR_WHITE
59 global COLOR_NONE
61 if c:
62 COLOR_RED ="\x1b[1;31m"
63 COLOR_GREEN ="\x1b[1;32m"
64 COLOR_YELLOW="\x1b[1;33m"
65 COLOR_WHITE ="\x1b[1;37m"
66 COLOR_NONE ="\x1b[m"
67 else:
68 COLOR_RED =""
69 COLOR_GREEN =""
70 COLOR_YELLOW=""
71 COLOR_WHITE =""
72 COLOR_NONE =""
74 def cprint(c, txt):
75 print "%s%s%s" % (c, txt, COLOR_NONE)
77 def csvhead():
78 global csvfile
80 if csvfile is None:
81 csvfile = file("stats-%d.csv" % int(time.time()), "w")
83 a = ["Date",]
84 a.extend(attributes)
85 a.extend(eattributes)
86 csvfile.write(",".join(a) + "\n")
88 def csvstats():
89 a = [str(time.time()),]
90 for k in attributes:
91 a.append(str(player.get(k,"NA")))
92 for k in eattributes:
93 a.append(str(enemy.get(k,"NA")))
94 csvfile.write(",".join(a) + "\n")
95 csvfile.flush()
97 def login():
98 cprint(COLOR_GREEN, "logging in...")
99 user = raw_input("Username: ")
100 pw = getpass.getpass("Password: ")
101 # user = "username" # hardcode username and password for testing
102 # pw = "password"
103 body = {
104 "loginS": "Login",
105 "username": user,
106 "password": pw
108 response, content = fetch_page(None,body)
109 if "set-cookie" in response:
110 headers["Cookie"] = response["set-cookie"]
111 else:
112 sys.exit()
113 parse(content,None,body)
114 loggedin = True
117 def explore():
118 cprint(COLOR_GREEN, "exploring...")
119 query = {"action": "explore"}
121 body = {"exploreS": "Explore"}
122 response, content = fetch_page(query, body)
124 time.sleep(8)
126 body = {"finishexploreS": "What Did I Find?!"}
127 response, content = fetch_page(query, body)
128 parse(content, query)
131 def nap():
132 cprint(COLOR_GREEN, "napping...")
133 query = {
134 "action": "bullpen",
135 "req": "nap"
137 response, content = fetch_page(query)
138 parse(content,query)
141 def fight():
142 cprint(COLOR_GREEN, "fighting...")
143 query = {
144 "baction": "fight"
146 response, content = fetch_page(query)
147 parse(content,query)
150 def flee():
151 cprint(COLOR_GREEN, "fleeing...")
152 query = {
153 "baction": "flee"
155 response, content = fetch_page(query)
156 parse(content,query)
159 def withstand():
160 cprint(COLOR_GREEN, "casting withstand...")
161 query = {
162 "baction": "Withstand"
164 response, content = fetch_page(query)
165 parse(content,query)
168 def donothing():
169 cprint(COLOR_GREEN, "doing nothing...")
170 query = {
171 "baction": "nothing"
173 response, content = fetch_page(query)
174 parse(content,query)
177 def fetch_page(query,body=None):
178 if query != None:
179 url = "?".join([
180 "http://spider.eecs.umich.edu/~tbp/michelle/michelle.php",
181 urllib.urlencode(query)
183 else:
184 url = "http://spider.eecs.umich.edu/~tbp/michelle/michelle.php"
185 http = httplib2.Http()
186 if body != None:
187 response, content = http.request(url, "POST", headers=headers,
188 body=urllib.urlencode(body))
189 else:
190 response, content = http.request(url, "GET", headers=headers)
191 if "set-cookie" in response:
192 print "Cookie: %s" % response["set-cookie"]
193 return response, content
196 def parse(page,query,body=None):
197 tree = lxml.html.document_fromstring(page)
198 if body != None and "loginS" in body or query != None:
199 for attribute in attributes:
200 search = "".join(["//span[@id='",attribute,"']"])
201 player[attribute] = float(tree.xpath(search)[0].text_content().strip())
202 if body != None and "finishexploreS" in body or query != None:
203 notification = tree.xpath("//p[@class='notify']")
204 # print notification
205 if notification != []:
206 state["event"] = notification[0].text_content().strip()
207 if query != None and "baction" in query:
208 for attribute in eattributes:
209 search = "".join(["//span[@id='",attribute,"']"])
210 results = tree.xpath(search)
211 if results != []:
212 enemy[attribute] = results[0].text_content().strip()
213 bnotifications = tree.xpath("//p[@class='fightnotify']")
214 mnotifications = tree.xpath("//p[@class='enchantnotify']")
215 bevents = []
216 mevents = []
217 for bnotify in bnotifications:
218 bevent = bnotify.text_content().strip()
219 print " Battle event: %s" % bevent
220 bevents.append(bevent)
221 for mnotify in mnotifications:
222 mevent = mnotify.text_content().strip()
223 print " Magical event: %s" % mevent
224 mevents.append(mevent)
225 state["bevents"] = bevents
226 state["mevents"] = mevents
228 if "event" in state:
229 cprint(COLOR_YELLOW, state["event"])
230 print_status()
233 def print_status():
234 _l = player["level"]
235 _xp = player["experience"]
236 _nxp = player["neededexperience"]
237 _hp = player["health"]
238 _mhp = player["maxhealth"]
239 _int = player["integrity"]
240 _mint = player["maxintegrity"]
241 _gold = player["gold"]
243 cprint(COLOR_NONE, "level %4d, xp %d / %d, health %d / %d (%d%%), integrity %d / %d, gold %d" %
244 (_l, _xp, _nxp, _hp, _mhp, int(100*_hp/_mhp), _int, _mint, _gold,))
245 csvstats()
247 def main():
248 wait_time = 0.5
249 parser = optparse.OptionParser()
250 parser.add_option('-n', action="store", dest="limit",
251 help="number of iterations", default=1000)
252 parser.add_option('-c', action="store_true", dest="color",
253 help="enable ANSI color escape codes", default=False)
254 options, args = parser.parse_args()
255 limit = int(options.limit)
256 enable_colors(bool(options.color))
258 csvhead()
259 print "Number of rounds: %d" % limit
260 login()
261 for n in xrange(limit):
262 cprint(COLOR_WHITE,"\nROUND %d" % (n+1,))
263 explore()
265 if "event" in state and state["event"].find("assailed") > -1:
266 battle_round = 1
267 aim_round = -1
268 reload_round = -1
269 while float(player["health"]) / float(player["maxhealth"]) > 0.6 and \
270 state["event"].find("defeated") < 0 and \
271 state["event"].find("Rebecca") < 0:
272 percentage = player["health"] / player["maxhealth"]
274 if "bevents" in state:
275 for bevent in state["bevents"]:
276 if bevent.find("taking aim") > -1:
277 aim_round = battle_round
278 cprint(COLOR_RED,"Danger, Will Robinson! Rogue Nerf Bow and Arrow is taking aim!")
280 if state["event"].find("Launcher") > -1:
281 withstand()
282 break
283 elif battle_round == aim_round:
284 withstand()
285 else:
286 donothing()
287 fight()
289 time.sleep(wait_time)
290 battle_round += 1
292 if float(player["health"]) / float(player["maxhealth"]) <= 0.6 or \
293 state["event"].find("Rebecca") > -1 or \
294 state["event"].find("Launcher") > -1:
295 donothing()
296 flee()
298 if float(player["health"]) / float(player["maxhealth"]) <= 0.6 or \
299 float(player["integrity"]) / float(player["maxintegrity"]) <= 0.8:
300 nap()
302 if int(player["health"]) <= 0:
303 death_timeout = 125
304 cprint(COLOR_RED, "TauBetaPyBot has died! :-( Sleeping for %d seconds..." % (death_timeout,))
305 time.sleep(death_timeout)
306 nap()
309 if __name__ == '__main__':
310 try:
311 main()
312 except KeyboardInterrupt:
313 cprint(COLOR_RED, "Bye, bye.")