├── .gitignore
├── .idea
├── IronBot.iml
├── markdown-navigator.xml
├── markdown-navigator
│ └── profiles_settings.xml
├── misc.xml
├── modules.xml
├── vcs.xml
└── workspace.xml
├── IronBot.py
├── README.md
├── find_cursor.py
└── triggers
├── attack.png
├── bank_deposit_box.png
├── bankslot.png
├── deposit_button.png
├── deposit_button_hover.png
├── enter_mysterious_entrance.png
├── exit_mysterious_door.png
├── mine_iron_ore_rocks.png
├── mine_rocks.png
├── reset_check.png
├── rock3_check.png
└── screenie.png
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | ### Python template
3 | # Byte-compiled / optimized / DLL files
4 | __pycache__/
5 | *.py[cod]
6 | *$py.class
7 |
8 | # C extensions
9 | *.so
10 |
11 | # Distribution / packaging
12 | .Python
13 | env/
14 | build/
15 | develop-eggs/
16 | dist/
17 | downloads/
18 | eggs/
19 | .eggs/
20 | lib/
21 | lib64/
22 | parts/
23 | sdist/
24 | var/
25 | wheels/
26 | *.egg-info/
27 | .installed.cfg
28 | *.egg
29 |
30 | # PyInstaller
31 | # Usually these files are written by a python script from a template
32 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
33 | *.manifest
34 | *.spec
35 |
36 | # Installer logs
37 | pip-log.txt
38 | pip-delete-this-directory.txt
39 |
40 | # Unit test / coverage reports
41 | htmlcov/
42 | .tox/
43 | .coverage
44 | .coverage.*
45 | .cache
46 | nosetests.xml
47 | coverage.xml
48 | *,cover
49 | .hypothesis/
50 |
51 | # Translations
52 | *.mo
53 | *.pot
54 |
55 | # Django stuff:
56 | *.log
57 | local_settings.py
58 |
59 | # Flask stuff:
60 | instance/
61 | .webassets-cache
62 |
63 | # Scrapy stuff:
64 | .scrapy
65 |
66 | # Sphinx documentation
67 | docs/_build/
68 |
69 | # PyBuilder
70 | target/
71 |
72 | # Jupyter Notebook
73 | .ipynb_checkpoints
74 |
75 | # pyenv
76 | .python-version
77 |
78 | # celery beat schedule file
79 | celerybeat-schedule
80 |
81 | # SageMath parsed files
82 | *.sage.py
83 |
84 | # dotenv
85 | .env
86 |
87 | # virtualenv
88 | .venv
89 | venv/
90 | ENV/
91 |
92 | # Spyder project settings
93 | .spyderproject
94 |
95 | # Rope project settings
96 | .ropeproject
97 |
98 |
--------------------------------------------------------------------------------
/.idea/IronBot.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/markdown-navigator.xml:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/.idea/markdown-navigator/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
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 |
77 |
78 |
79 |
80 | .png
81 | png
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 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 | 1494338938548
292 |
293 |
294 | 1494338938548
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
--------------------------------------------------------------------------------
/IronBot.py:
--------------------------------------------------------------------------------
1 | import math
2 | from random import randint, uniform
3 | import sys
4 | import time
5 |
6 | import cv2
7 | import numpy as np
8 | import pyautogui as pag
9 |
10 |
11 | class MineBot(object):
12 | """
13 | Iron mining bot for the Dwarven Mines, using 3/3 rocks. Currently
14 | Bot generates:
15 | One full run in ~155 seconds, for ~23.25 runs/hour
16 | ~22.8k xp/hr,
17 | ~650 iron ore/hr,
18 | ~190.5k gp/hr (assuming a 293gp/ore price)
19 | """
20 | def __init__(self):
21 | pass
22 |
23 | def mine_loop(self, rock_locations, triggers, mininglap):
24 | order = ['rock1', 'rock2', 'rock3']
25 | trigger_order = ['rock1iron', 'rock1noiron', 'rock2iron', 'rock2noiron', 'rock3iron', 'rock3noiron']
26 |
27 | for i in range(len(order)):
28 | # Checks for full inventory.
29 | if not self.image_match((2352, 682, 63, 55), 'triggers/bankslot.png'):
30 | return True
31 |
32 | # Checks for scorpions and moves to the location of rock #3.
33 | if i == 2:
34 | self.random_coordinate(rock_locations['movetorock3'])
35 | self.check_for_scorpion((rock_locations['movetorock3'][0], rock_locations['movetorock3'][1],
36 | rock_locations['movetorock3'][2] + 250, rock_locations['movetorock3'][3] + 250))
37 | pag.click()
38 |
39 | self.random_coordinate(rock_locations[order[i]])
40 | self.wait_for_trigger(triggers[trigger_order[(i*2)]]) # wait for iron
41 | pag.click()
42 | self.wait_for_trigger(triggers[trigger_order[(i*2)+1]]) # wait for success
43 | self.random_wait(0.05, 0.1)
44 |
45 | # Resets location for the beginning of the next loop.
46 | self.random_coordinate(rock_locations['reset'])
47 | self.check_for_scorpion((rock_locations['reset'][0], rock_locations['reset'][1],
48 | rock_locations['reset'][2] + 250, rock_locations['reset'][3] + 250))
49 | pag.click()
50 | self.wait_for_trigger((1700, 50, 150, 150, 'triggers/reset_check.png')) # check to make sure made it to right location
51 |
52 | return
53 |
54 | def bank_loop(self, bank_locations, triggers):
55 | """Makes a trip to the bank to deposit the iron ore. Takes 16-17 seconds"""
56 | order = ['dgdoordown', 'depositbox', 'depositbutton', 'dgdoorup', 'startlocation']
57 | waits = [(0.1, 0.2), (0.1, 0.2), (0.1, 0.2), (5, 6), (0.1, 0.2)]
58 |
59 | for i in range(len(order)):
60 | self.random_coordinate(bank_locations[order[i]])
61 | if i in range(4):
62 | self.wait_for_trigger(triggers[order[i]])
63 | if i == 4:
64 | self.check_for_scorpion((947, 1195, 250, 250))
65 | pag.click()
66 | self.random_wait(waits[i][0], waits[i][1])
67 |
68 | def drop_loop(self, keybind='0'):
69 | r = randint(28, 32)
70 | t = uniform(4.8, 7)
71 | clicktime = t/r
72 | for _ in range(r):
73 | pag.keyDown(keybind)
74 | self.random_wait(clicktime - .04, clicktime + .04)
75 |
76 | def bank_or_drop(self):
77 | while True:
78 | answer = input('Would you like to 1) bank (takes an extra ~10 seconds/inventory) or 2) drop the ore? ')
79 | if answer.lower() in ['b', 'ban', 'bnk', 'bakn', 'bnak', 'bank', 's', 'save', 'y', 'yes']:
80 | print('Banking selected.')
81 | return 'bank'
82 | elif answer.lower() in ['d', 'dro', 'drp', 'drpo', 'dorp', 'drop', 'n', 'no']:
83 | print('Dropping selected.')
84 | return 'drop'
85 | else:
86 | print('Not a valid option. Please try again.')
87 |
88 | def random_coordinate(self, location):
89 | """Moves cursor to random locaction still above the object to be clicked"""
90 | x = randint(location[0], location[0]+location[2])
91 | y = randint(location[1], location[1]+location[3])
92 | time = self.travel_time(x, y)
93 |
94 | return pag.moveTo(x, y, time)
95 |
96 | def travel_time(self, x2, y2):
97 | """Calculates cursor travel time in seconds per 240-270 pixels, based on a variable rate of movement"""
98 | rate = uniform(0.09, 0.15)
99 | x1, y1 = pag.position()
100 | distance = math.sqrt(math.pow(x2-x1, 2)+math.pow(y2-y1, 2))
101 |
102 | return max(uniform(.08, .12), rate * (distance/randint(250, 270)))
103 |
104 | def image_match(self, r, img):
105 | pag.screenshot('triggers/screenie.png', region=r)
106 | screen = cv2.imread('triggers/screenie.png')
107 | template = cv2.imread(img)
108 |
109 | res = cv2.matchTemplate(screen, template, cv2.TM_CCOEFF_NORMED)
110 | threshold = .80
111 | loc = np.where(res >= threshold)
112 | if len(loc[0]) > 0:
113 | return True
114 |
115 | return False
116 |
117 | def wait_for_trigger(self, triggers):
118 | """Checks to see if the proper message is on screen to indicate that the rock is ready to mine"""
119 | r = triggers[0], triggers[1], triggers[2], triggers[3]
120 | img = triggers[4]
121 | while self.image_match(r, img) == False:
122 | self.random_wait(0.1, 0.2)
123 |
124 | return self.image_match(r, img)
125 |
126 | def random_wait(self, min=0.25, max=0.50):
127 | """Waits a random number of seconds between two numbers (0.25 and 0.50 default) to mimic human reaction time"""
128 | return time.sleep(uniform(min, max))
129 |
130 | def check_for_scorpion(self, r):
131 | if self.image_match(r, 'triggers/attack.png'):
132 | pag.click(button='right')
133 | print("Successfully avoided a scorpion.")
134 | pag.moveRel(randint(-75, 75), randint(58, 78))
135 |
136 | def logout(self, logout_location=(1194, 955, 167, 14)):
137 | pag.keyDown('escape')
138 | self.random_wait()
139 | pag.click(self.random_coordinate(logout_location))
140 | sys.exit('Successful exit')
141 |
142 | def pause(self):
143 | pass
144 |
145 | if __name__ == '__main__':
146 |
147 | mb = MineBot()
148 | rock_locations = {'rock1': (1243, 569, 55, 62), 'rock2': (1138, 695, 34, 39),
149 | 'movetorock3': (962, 823, 50, 50), 'rock3': (1128, 691, 37, 56),
150 | 'reset': (1465, 570, 50, 50)}
151 |
152 | bank_locations = {'dgdoordown': (1630, 230, 70, 100), 'depositbox': (1079, 1086, 104, 71),
153 | 'depositbutton': (1333, 849, 30, 15), 'dgdoorup': (1625, 240, 45, 200),
154 | 'startlocation': (947, 1195, 71, 65)}
155 |
156 | rock_triggers = {'rock1iron': (1243, 569, 350, 200, 'triggers/mine_iron_ore_rocks.png'),
157 | 'rock1noiron': (1243, 569, 275, 200, 'triggers/mine_rocks.png'),
158 | 'rock2iron': (1144, 695, 350, 200, 'triggers/mine_iron_ore_rocks.png'),
159 | 'rock2noiron': (1144, 695, 275, 200, 'triggers/mine_rocks.png'),
160 | 'rock3iron': (1128, 691, 350, 200, 'triggers/mine_iron_ore_rocks.png'),
161 | 'rock3noiron': (1128, 691, 275, 200, 'triggers/mine_rocks.png')}
162 |
163 | bank_triggers = {'dgdoordown': (1630, 230, 470, 200, 'triggers/enter_mysterious_entrance.png'),
164 | 'depositbox': (1079, 1086, 500, 200, 'triggers/bank_deposit_box.png'),
165 | 'depositbutton': (1175, 750, 350, 100, 'triggers/deposit_button_hover.png'),
166 | 'dgdoorup': (1625, 240, 350, 300, 'triggers/exit_mysterious_door.png')}
167 |
168 | print('Your character must be in the NorthWest tile by the two iron ore rocks in the Dwarven Mines.\n'
169 | 'Also, the up arrow must be pushed as high as possible, and rotation must be the same as on first login.\n'
170 | 'Press Ctrl-F2 to exit.')
171 |
172 | answer = mb.bank_or_drop()
173 |
174 | time.sleep(5)
175 |
176 | try:
177 | lap = 0
178 | while True:
179 | start_time = time.time()
180 | mininglap = 1
181 | while True:
182 | full = mb.mine_loop(rock_locations, rock_triggers, mininglap)
183 | if full:
184 | break
185 | mininglap += 1
186 | if answer == 'bank':
187 | mb.bank_loop(bank_locations, bank_triggers)
188 | else:
189 | mb.drop_loop()
190 | lap += 1
191 | laptime = time.time()-start_time
192 | print("Trip number {tripno} took {time} seconds, which is a {xp} xp/hour and "
193 | "{ore} iron ore/hour pace.".format(tripno=lap, time=round(laptime, 2),
194 | xp=('{0:,.0f}'.format(60 / (laptime / 60) * 28 * 35)),
195 | ore=('{0:,.0f}'.format(60/(laptime/60)*28))))
196 | except KeyboardInterrupt:
197 | sys.exit()
198 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Runescape iron ore mining bot for the Dwarven Mines.
2 |
3 | Written with python (cy2, numpy, pyautogui).
4 |
5 | This code is for demonstration purposes only, to accompany an auto clicker creation guide found at [How to Write a Runescape Auto Clicker With Python](http://www.zaxrosenberg.com/how-to-write-a-runescape-auto-clicker-with-python-part-i/). Please use this program at your own risk.
6 |
7 | Also, note that this code is resolution specific. Use the included find_cursor.py script to locate the proper pixels/ranges on your resolution and Runescape screen layout to adjust the IronBot.
8 |
--------------------------------------------------------------------------------
/find_cursor.py:
--------------------------------------------------------------------------------
1 | import time
2 |
3 | import pyautogui
4 |
5 |
6 | if __name__ == '__main__':
7 | print('Press Ctrl-C to quit.')
8 | try:
9 | while True:
10 | # Get and print the mouse coordinates.
11 | x, y = pyautogui.position()
12 | positionStr = 'X: ' + str(x).rjust(4) + ' Y: ' + str(y).rjust(4)
13 | print("\r", positionStr, end="", flush=True)
14 | time.sleep(0.25)
15 | except KeyboardInterrupt:
16 | print('\nDone.')
17 |
--------------------------------------------------------------------------------
/triggers/attack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZaxR/IronBot/2930278b8e5fa75d313e50504c47749c496f5ee6/triggers/attack.png
--------------------------------------------------------------------------------
/triggers/bank_deposit_box.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZaxR/IronBot/2930278b8e5fa75d313e50504c47749c496f5ee6/triggers/bank_deposit_box.png
--------------------------------------------------------------------------------
/triggers/bankslot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZaxR/IronBot/2930278b8e5fa75d313e50504c47749c496f5ee6/triggers/bankslot.png
--------------------------------------------------------------------------------
/triggers/deposit_button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZaxR/IronBot/2930278b8e5fa75d313e50504c47749c496f5ee6/triggers/deposit_button.png
--------------------------------------------------------------------------------
/triggers/deposit_button_hover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZaxR/IronBot/2930278b8e5fa75d313e50504c47749c496f5ee6/triggers/deposit_button_hover.png
--------------------------------------------------------------------------------
/triggers/enter_mysterious_entrance.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZaxR/IronBot/2930278b8e5fa75d313e50504c47749c496f5ee6/triggers/enter_mysterious_entrance.png
--------------------------------------------------------------------------------
/triggers/exit_mysterious_door.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZaxR/IronBot/2930278b8e5fa75d313e50504c47749c496f5ee6/triggers/exit_mysterious_door.png
--------------------------------------------------------------------------------
/triggers/mine_iron_ore_rocks.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZaxR/IronBot/2930278b8e5fa75d313e50504c47749c496f5ee6/triggers/mine_iron_ore_rocks.png
--------------------------------------------------------------------------------
/triggers/mine_rocks.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZaxR/IronBot/2930278b8e5fa75d313e50504c47749c496f5ee6/triggers/mine_rocks.png
--------------------------------------------------------------------------------
/triggers/reset_check.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZaxR/IronBot/2930278b8e5fa75d313e50504c47749c496f5ee6/triggers/reset_check.png
--------------------------------------------------------------------------------
/triggers/rock3_check.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZaxR/IronBot/2930278b8e5fa75d313e50504c47749c496f5ee6/triggers/rock3_check.png
--------------------------------------------------------------------------------
/triggers/screenie.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZaxR/IronBot/2930278b8e5fa75d313e50504c47749c496f5ee6/triggers/screenie.png
--------------------------------------------------------------------------------