Compare commits

..

188 Commits

Author SHA1 Message Date
7eed550797 Merge remote-tracking branch 'origin/master' 2023-08-24 09:43:27 +02:00
cc9789c65c ring fix 2023-08-24 09:43:13 +02:00
d64b704274 update menti 2023-08-06 16:36:52 +02:00
ed23f196a6 update menti 2023-08-06 16:32:45 +02:00
b8abdb690b update menti 2023-08-06 16:30:20 +02:00
8d2aad34b2 update menti 2023-08-06 16:25:52 +02:00
e70c7d2be9 update menti 2023-08-06 16:23:55 +02:00
5005670bd3 update menti 2023-08-06 16:21:48 +02:00
b1fc655c0b update menti 2023-08-06 16:12:13 +02:00
9cc4018747 update flappy 2023-07-30 18:46:40 +02:00
849aaf8e27 update flappy 2023-07-30 18:42:53 +02:00
804f178fbf update flappy 2023-07-30 15:08:29 +02:00
c1eecfd567 update flappy 2023-07-30 15:05:47 +02:00
99a2976b61 update flappy 2023-07-30 15:01:20 +02:00
cadcfe8103 update litris with board detection 2023-07-30 14:28:15 +02:00
ab0def9115 update litris with board detection 2023-07-30 10:57:43 +02:00
b24a835f18 update litris with board detection 2023-07-30 10:08:33 +02:00
0a15b57fe5 Merge remote-tracking branch 'origin/master' 2023-07-30 10:00:17 +02:00
a7d2a73b00 update litris with board detection 2023-07-30 10:00:07 +02:00
Thaloria@web.de
3d209ca811 litris update 2023-07-30 00:49:42 +02:00
Thaloria@web.de
01768dc115 litris update 2023-07-30 00:29:36 +02:00
f32cbb8f2d update litris with board detection 2023-07-30 00:08:39 +02:00
7a539e301b update litris with board detection 2023-07-29 21:43:48 +02:00
00461177de update litris with board detection 2023-07-29 21:36:31 +02:00
7c6af4411b update litris with board detection 2023-07-29 21:32:53 +02:00
c3e677ca0a update litris with board detection 2023-07-29 21:30:00 +02:00
332190394d update litris with board detection 2023-07-29 21:20:50 +02:00
d3ace50341 update litris with board detection 2023-07-29 21:14:13 +02:00
8918683e5a update litris with board detection 2023-07-29 21:07:22 +02:00
b08356b036 update litris with board detection 2023-07-29 21:01:51 +02:00
ffca884a25 update litris with board detection 2023-07-29 20:54:00 +02:00
d3d2e1e65e update litris with board detection 2023-07-29 20:46:25 +02:00
6ec1b71d28 update litris with board detection 2023-07-29 20:20:18 +02:00
07d00404d8 update litris with board detection 2023-07-29 20:20:11 +02:00
c9081bd371 update litris with board detection 2023-07-29 20:12:51 +02:00
a9b76cde97 flappy init 2023-07-29 19:42:17 +02:00
2fa0255761 flappy init 2023-07-29 19:34:12 +02:00
c7dd04590a flappy init 2023-07-28 15:31:16 +02:00
189b81b3a0 flappy init 2023-07-28 15:28:25 +02:00
545127dcbc flappy init 2023-07-28 13:26:54 +02:00
bfd8690535 flappy init 2023-07-28 13:13:20 +02:00
c43399ac2a flappy init 2023-07-27 21:16:19 +02:00
33c7400fa4 flappy init 2023-07-27 20:55:54 +02:00
862fbf8bc6 flappy init 2023-07-27 17:58:57 +02:00
8ded30d75a menti words init 2023-07-27 13:02:42 +02:00
eff65b3ca4 menti words init 2023-07-26 22:28:30 +02:00
ef7669f015 menti words init 2023-07-26 22:00:57 +02:00
2d23f8e311 menti words init 2023-07-26 17:11:30 +02:00
38ac30cc64 menti words init 2023-07-26 17:04:53 +02:00
fc965a5133 menti words init 2023-07-26 17:02:57 +02:00
e11b2b8e94 menti words init 2023-07-26 16:58:43 +02:00
a82c069048 menti words init 2023-07-26 16:55:41 +02:00
5c24629b85 menti words init 2023-07-26 16:52:43 +02:00
f1bb158b21 menti words init 2023-07-26 16:49:09 +02:00
95f87d1c2e menti words init 2023-07-26 16:46:15 +02:00
cde729f820 menti words init 2023-07-26 16:43:36 +02:00
9841d6fae4 menti words init 2023-07-26 16:41:08 +02:00
f4d7523c3d menti words init 2023-07-26 16:37:04 +02:00
fec2651930 menti words init 2023-07-26 16:30:14 +02:00
555d66c680 menti words init 2023-07-26 16:29:45 +02:00
2c4e51b44f menti words init 2023-07-26 16:29:15 +02:00
0fcf3d88a2 menti words init 2023-07-26 16:27:23 +02:00
12f86cc7fd menti words init 2023-07-26 16:19:41 +02:00
bdb448932d menti words init 2023-07-26 16:16:13 +02:00
1893d513f2 menti words init 2023-07-26 16:10:47 +02:00
5713422f49 threading update 2023-07-26 11:33:46 +02:00
1b9711a851 added async stone detection thread 2023-07-26 09:54:49 +02:00
7b63568fa5 added async stone detection thread 2023-07-26 09:46:33 +02:00
3c02d413a2 added async stone detection thread 2023-07-26 09:31:48 +02:00
84830e94a8 added async stone detection thread 2023-07-26 09:05:27 +02:00
d2c89cdc93 added async stone detection thread 2023-07-26 08:49:50 +02:00
3d2ce694e1 added async stone detection thread 2023-07-26 08:43:30 +02:00
e0a9cbc394 added async stone detection thread 2023-07-26 08:37:04 +02:00
fd6f17c3f8 added async stone detection thread 2023-07-26 08:25:39 +02:00
Thaloria@web.de
54cb23a923 litris update 2023-07-25 12:11:56 +02:00
Thaloria@web.de
de56e687f8 litris update 2023-07-25 11:54:05 +02:00
3fa581a935 added async stone detection thread 2023-07-25 10:02:32 +02:00
e7932f5762 added async stone detection thread 2023-07-25 09:59:20 +02:00
b570813c5a added async stone detection thread 2023-07-25 09:47:52 +02:00
8049e58e71 added async stone detection thread 2023-07-25 09:41:04 +02:00
5e201ea341 added async stone detection thread 2023-07-25 09:37:41 +02:00
37cf7f2f2f added async stone detection thread 2023-07-25 09:04:26 +02:00
e5cd8d6399 added async stone detection thread 2023-07-25 08:54:13 +02:00
Thaloria@web.de
3c723fb602 litris update 2023-07-25 08:43:04 +02:00
d3fa6fe807 added async stone detection thread 2023-07-24 13:54:42 +02:00
a2575370f9 added async stone detection thread 2023-07-24 13:51:16 +02:00
22edbe9a2f added async stone detection thread 2023-07-24 13:42:41 +02:00
e832ffe9ec added async stone detection thread 2023-07-24 13:34:49 +02:00
773aa5c765 added async stone detection thread 2023-07-24 13:33:41 +02:00
687218e29d added async stone detection thread 2023-07-24 13:22:44 +02:00
f35fe32264 litris fixes 2023-07-24 11:15:11 +02:00
a21f43fcfc added async stone detection thread 2023-07-24 10:14:41 +02:00
50ab6e17ef added async stone detection thread 2023-07-24 09:59:13 +02:00
761fa778c7 added async stone detection thread 2023-07-24 09:18:30 +02:00
62ff7cb40d added first draft litris 2023-07-23 18:38:50 +02:00
e614ba8dd0 added first draft litris 2023-07-23 18:13:21 +02:00
6d6081ec57 added first draft litris 2023-07-23 17:45:37 +02:00
c4f71f469b added first draft litris 2023-07-23 17:45:22 +02:00
17ff660069 added first draft litris 2023-07-23 17:25:03 +02:00
27f7638557 added first draft litris 2023-07-23 14:28:12 +02:00
Thaloria@web.de
6012a51538 litris update 2023-07-23 14:24:09 +02:00
ba2fd6c945 added first draft litris 2023-07-23 14:03:44 +02:00
f4b949c070 added first draft litris 2023-07-23 12:01:24 +02:00
0e265b0bb6 added first draft litris 2023-07-23 11:52:55 +02:00
b9d0e829bc added first draft litris 2023-07-23 11:32:23 +02:00
76d22227bf added first draft litris 2023-07-23 11:24:54 +02:00
ae752bdb7c added first draft litris 2023-07-22 21:22:44 +02:00
aa2662003d added first draft litris 2023-07-22 20:59:06 +02:00
47a7a50335 added first draft litris 2023-07-22 20:54:29 +02:00
2d35e032b5 added first draft litris 2023-07-22 20:52:36 +02:00
21237c3729 added first draft litris 2023-07-22 20:47:42 +02:00
1d4980eb95 added first draft litris 2023-07-22 20:45:30 +02:00
d78319a9f4 added first draft litris 2023-07-22 20:39:20 +02:00
fba0c2c506 litris fixes 2023-07-22 10:54:32 +02:00
704b1f462d added first draft litris 2023-07-22 09:49:15 +02:00
3176bf5269 added first draft litris 2023-07-22 09:44:48 +02:00
c2b5416542 added first draft litris 2023-07-21 15:28:22 +02:00
2906cb10e4 added first draft litris 2023-07-21 15:18:57 +02:00
93832d8bfc added first draft litris 2023-07-21 15:09:02 +02:00
ff173fea80 added first draft litris 2023-07-21 14:36:21 +02:00
d0f4937507 added first draft litris 2023-07-21 14:31:07 +02:00
403db80292 added first draft litris 2023-07-20 20:09:23 +02:00
b76ccf448e added first draft litris 2023-07-20 19:31:27 +02:00
b08b5fcb89 added first draft litris 2023-07-20 19:19:36 +02:00
0b97e346d8 added first draft litris 2023-07-20 19:17:38 +02:00
378259ab1c added first draft litris 2023-07-20 18:55:47 +02:00
597f7f426e added first draft litris 2023-07-20 18:51:12 +02:00
5eaa9ff5d4 added first draft litris 2023-07-19 21:30:52 +02:00
4d9ccbfd90 added first draft new pickaxe try 2023-07-17 20:44:03 +02:00
95abea3920 added first draft new pickaxe try 2023-07-17 20:33:14 +02:00
0df3f2d8a9 added first draft new pickaxe try 2023-07-17 20:31:24 +02:00
40fb6b7918 added first draft new pickaxe try 2023-07-17 14:18:45 +02:00
5cd1d63fc8 added first draft new pickaxe try 2023-07-17 14:14:46 +02:00
2d46fd65b9 added smaler mining area 2023-05-06 19:26:02 +02:00
Thaloria@web.de
a9e25527f5 update farm for 4.0 2023-05-05 19:17:40 +02:00
c7deaaf6c7 added sodoku to ui 2023-05-05 19:09:44 +02:00
f49087776e Merge remote-tracking branch 'origin/master' 2023-04-30 21:04:57 +02:00
b64dad8e5b added sodoku to ui 2023-04-30 21:04:40 +02:00
Thaloria@web.de
56cf726d4f timing changes 2023-04-30 20:31:41 +02:00
7af6f0c7ed fix equipment.py 2023-04-28 18:20:54 +02:00
71871d83f0 Merge branch 'master' of http://git.face-down.de/Thaloria/Litcraft_Python_B 2023-04-28 18:08:01 +02:00
bebcac9cf3 fix equipment.py 2023-04-28 17:59:55 +02:00
059712770a fix equipment.py 2023-04-28 17:58:51 +02:00
Thaloria@web.de
2264e0fb19 added fruit game support 2023-04-28 16:09:40 +02:00
86d2542edc added sodoku game first draft 2023-04-28 15:46:36 +02:00
088a4d9030 added sodoku game first draft 2023-04-28 15:42:03 +02:00
81d0c09003 added sodoku game first draft 2023-04-28 15:32:17 +02:00
07d3f5388e added sodoku game first draft 2023-04-28 15:25:03 +02:00
Thaloria@web.de
3772fbb843 Merge remote-tracking branch 'origin/master' 2023-04-28 15:12:10 +02:00
Thaloria@web.de
187cb80cf2 added fruit game support 2023-04-28 15:12:00 +02:00
33059b0a95 added sodoku game first draft 2023-04-28 15:11:21 +02:00
c4c6c34709 4.0 fixes to fruit game 2023-04-28 07:20:39 +02:00
4c6a3d04c7 added ok button check to magic 2023-04-28 06:47:12 +02:00
aa92f20758 added ok button check to magic 2022-11-17 12:28:18 +01:00
Thaloria@web.de
79db89b90b added fruit game support 2022-10-31 17:06:38 +01:00
ec7bdf6eb1 added fruit game support 2022-10-31 16:39:07 +01:00
90b7177273 added fruit game support 2022-10-31 16:29:41 +01:00
52e3fd001a added fruit game support 2022-10-31 16:24:21 +01:00
9931b9804e added fruit game support 2022-10-31 16:19:56 +01:00
25f9cb80e0 added fruit game support 2022-10-31 16:06:23 +01:00
60889a08c6 added fruit game support 2022-10-31 16:04:42 +01:00
16b34bf7b3 added fruit game support 2022-10-31 16:00:44 +01:00
2b425186d1 added fruit game support 2022-10-31 15:59:34 +01:00
8f7cc6a38e staff 1 fix revert 2022-10-24 19:41:52 +02:00
c10e4f94f2 staff 1 fix revert 2022-10-24 19:35:40 +02:00
70623a3e6f staff 1 fix 2022-10-24 19:18:59 +02:00
f1bde80746 refactoring
bug fix equip multi
2022-10-22 12:05:45 +02:00
4bfa9aa408 fixed instance bug with member variables 2022-10-19 17:05:11 +02:00
61fc1a2837 new ui elements for timing 2022-10-19 16:58:16 +02:00
ef3e9632f6 new ui elements for timing 2022-10-19 15:33:53 +02:00
81b7fe2871 new ui elements for timing 2022-10-19 08:58:58 +02:00
46aeba1b1b new ui elements for timing 2022-10-19 08:53:20 +02:00
8b8cc4f8e7 new ui elements for timing 2022-10-19 08:51:45 +02:00
22592e3a49 new ui elements for timing 2022-10-19 08:44:50 +02:00
84c1df4e9a new ui elements for timing 2022-10-19 00:36:37 +02:00
90ff452e10 new ui elements for timing 2022-10-19 00:25:59 +02:00
1992c549c1 new ui elements for timing 2022-10-18 23:27:41 +02:00
7a1cf3f009 new ui elements for timing 2022-10-18 23:19:33 +02:00
Thaloria@web.de
3a8c8568ac bug fix 5s 2022-10-18 23:07:43 +02:00
c5921b6657 added strategy parameter
new ui elements for timing
2022-10-18 22:19:14 +02:00
1d4d415a19 added strategy parameter
new ui elements for timing
2022-10-18 22:16:39 +02:00
a4617ed062 refactoring to game base class 2022-10-18 20:42:50 +02:00
90c6920296 refactoring to game base class 2022-10-17 22:17:16 +02:00
7723ca57c2 refactoring to game base class 2022-10-17 17:40:27 +02:00
c8e7c4d60c refactoring to game base class 2022-10-17 17:25:20 +02:00
d9b8434484 refactoring to game base class 2022-10-17 17:12:27 +02:00
14a5983d17 refactoring to game base class 2022-10-17 17:11:56 +02:00
433170b4c8 fixes 2022-10-17 12:02:47 +02:00
179 changed files with 3332 additions and 911 deletions

3
.idea/misc.xml generated
View File

@@ -1,7 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="ProjectPlainTextFileTypeManager">
<file url="file://$PROJECT_DIR$/sharpening.py" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.7 (lc-py-b)" project-jdk-type="Python SDK" /> <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.7 (lc-py-b)" project-jdk-type="Python SDK" />
</project> </project>

View File

@@ -7,6 +7,12 @@ from farm import Farm
from magic import Magic from magic import Magic
from craft import Craft from craft import Craft
from mine import Mine from mine import Mine
from sodoku import Sodoku
from fruit import Fruit
from pickaxe import Pickaxe_Field
from litris import Litris
from menti_words import MentiWords
from flappy import Flappy
def run(): def run():
@@ -30,7 +36,6 @@ def run():
overlay.run_mode = 'init' overlay.run_mode = 'init'
continue continue
elif overlay.run_mode == 'quit': elif overlay.run_mode == 'quit':
overlay.destroy()
return return
else: else:
break break
@@ -53,6 +58,26 @@ def run():
elif overlay.rb_int.get() == 6: elif overlay.rb_int.get() == 6:
mine = Mine(overlay) mine = Mine(overlay)
mine.execute_main_loop() mine.execute_main_loop()
elif overlay.rb_int.get() == 7:
fruit = Fruit(overlay)
fruit.execute_main_loop()
elif overlay.rb_int.get() == 8:
sodo = Sodoku(overlay)
sodo.execute_main_loop()
elif overlay.rb_int.get() == 9:
paxe = Pickaxe_Field(overlay)
paxe.execute_main_loop()
elif overlay.rb_int.get() == 10:
ltris = Litris(overlay)
ltris.execute_main_loop()
ltris.stone_id_thread.run_mode = 'stop'
elif overlay.rb_int.get() == 11:
menti = MentiWords(overlay)
menti.execute_main_loop()
elif overlay.rb_int.get() == 12:
flappy = Flappy(overlay)
flappy.execute_main_loop()
flappy.flappy_pos_disc.run_mode = 'stop'
if __name__ == "__main__": if __name__ == "__main__":
run() run()

View File

@@ -1,6 +1,7 @@
# Run tkinter code in another thread # Run tkinter code in another thread
import threading import threading
import tkinter as tk import tkinter as tk
import game_base_class
from tkinter import ttk from tkinter import ttk
from mine_overlay import DiggingOverlay from mine_overlay import DiggingOverlay
@@ -17,6 +18,7 @@ class PrimaryOverlay(threading.Thread):
self.ButtonFrame = tk.Frame self.ButtonFrame = tk.Frame
self.parameter_frame = tk.Frame self.parameter_frame = tk.Frame
self.parameter_label_frame = tk.Frame self.parameter_label_frame = tk.Frame
self.timing_frame = tk.Frame
self.rb_int = tk.IntVar self.rb_int = tk.IntVar
self.energy_use = tk.StringVar self.energy_use = tk.StringVar
@@ -31,35 +33,53 @@ class PrimaryOverlay(threading.Thread):
self.Emitter_Box = ttk.Combobox self.Emitter_Box = ttk.Combobox
self.RadioButtons = dict self.RadioButtons = dict
self.RadioButtonNames = ["Equip", "Crops", "Farm", "Magic", "Craft", "Mine"] self.RadioButtonNames = ["Equip", "Crops", "Farm", "Magic", "Craft", "Mine", "Fruit", "Sodo", "PAxe", "Ltris", "Menti", "Flapp"]
self.RadioButton1 = tk.Radiobutton self.RadioButton1 = tk.Radiobutton
self.RadioButton2 = tk.Radiobutton self.RadioButton2 = tk.Radiobutton
self.RadioButton3 = tk.Radiobutton self.RadioButton3 = tk.Radiobutton
self.RadioButton4 = tk.Radiobutton self.RadioButton4 = tk.Radiobutton
self.RadioButton5 = tk.Radiobutton self.RadioButton5 = tk.Radiobutton
self.RadioButton6 = tk.Radiobutton self.RadioButton6 = tk.Radiobutton
self.RadioButton7 = tk.Radiobutton
self.RadioButton8 = tk.Radiobutton
self.RadioButton9 = tk.Radiobutton
self.RadioButton10 = tk.Radiobutton
self.RadioButton11 = tk.Radiobutton
self.RadioButton12 = tk.Radiobutton
self.StartButton = tk.Button self.StartButton = tk.Button
self.StopButton = tk.Button self.StopButton = tk.Button
self.PauseButton = tk.Button self.PauseButton = tk.Button
self.QuitButton = tk.Button self.QuitButton = tk.Button
self.TkPosition = '133x239+60+600' self.TkPosition = '133x454+60+600'
self.setDaemon(True) self.setDaemon(True)
self.StatusLabel = tk.Label self.StatusLabel = tk.Label
self.global_timeout_label = tk.Label
self.hourly_breaks_label = tk.Label
self.break_duration_label = tk.Label
self.global_timeout_entry = tk.Entry
self.hourly_breaks_entry = tk.Entry
self.break_duration_entry = tk.Entry
self.global_timeout_use = tk.StringVar
self.hourly_breaks_use = tk.StringVar
self.break_duration_use = tk.StringVar
# self.TkPosition = config.returnEnemyPlayerOverlayPos() # self.TkPosition = config.returnEnemyPlayerOverlayPos()
# #
self.start() self.start()
def run(self): def run(self):
self.MiningOverlay = DiggingOverlay() self.MiningOverlay = DiggingOverlay(game_base_class.MINING_LARGE)
self.root = tk.Tk() self.root = tk.Tk()
self.rb_frame = tk.Frame(self.root) self.rb_frame = tk.Frame(self.root)
self.rb_int = tk.IntVar(self.root, value=1) self.rb_int = tk.IntVar(self.root, value=1)
self.RadioButtons = dict() self.RadioButtons = dict()
# var = tk.IntVar(value=1) # var = tk.IntVar(value=1)
for i in range(1, 7): for i in range(1, 13):
self.RadioButtons[i] = tk.Radiobutton(self.rb_frame, text=self.RadioButtonNames[i - 1], self.RadioButtons[i] = tk.Radiobutton(self.rb_frame, text=self.RadioButtonNames[i - 1],
variable=self.rb_int, variable=self.rb_int,
value=i, command=self.radio_button_callback) value=i, command=self.radio_button_callback)
@@ -109,10 +129,41 @@ class PrimaryOverlay(threading.Thread):
self.StatusLabel = tk.Label(self.root, text="Nothing to see here", font=("Helvetica", 10, "bold"), self.StatusLabel = tk.Label(self.root, text="Nothing to see here", font=("Helvetica", 10, "bold"),
background="grey", anchor=tk.CENTER) background="grey", anchor=tk.CENTER)
self.timing_frame = tk.Frame(self.root)
self.global_timeout_use = tk.StringVar(self.root, value='0')
self.hourly_breaks_use = tk.StringVar(self.root, value='0')
self.break_duration_use = tk.StringVar(self.root, value='1-3')
self.global_timeout_label = tk.Label(self.timing_frame, text="Stop after (h):", font=("Helvetica", 10, "bold"),
background="grey", width='12')
self.hourly_breaks_label = tk.Label(self.timing_frame, text="Breaks:", font=("Helvetica", 10, "bold"),
background="grey", width='12')
self.break_duration_label = tk.Label(self.timing_frame, text="Break time (m):", font=("Helvetica", 10, "bold"),
background="grey", width='12')
self.global_timeout_entry = tk.Entry(self.timing_frame, textvariable=self.global_timeout_use, font=("Helvetica", 10, "bold"),
width='3')
self.hourly_breaks_entry = tk.Entry(self.timing_frame, textvariable=self.hourly_breaks_use, font=("Helvetica", 10, "bold"),
width='3')
self.break_duration_entry = tk.Entry(self.timing_frame, textvariable=self.break_duration_use, font=("Helvetica", 10, "bold"),
width='3', state=tk.DISABLED)
self.global_timeout_label.grid(row=0, column=0, sticky='w', columnspan=2 )
self.global_timeout_entry.grid(row=0, column=3)
self.hourly_breaks_label.grid(row=1, column=0, sticky='w', columnspan=2)
self.hourly_breaks_entry.grid(row=1, column=3)
self.break_duration_label.grid(row=2, column=0, sticky='w', columnspan=2)
self.break_duration_entry.grid(row=2, column=3)
self.rb_frame.grid(row=0, column=0, sticky='w') self.rb_frame.grid(row=0, column=0, sticky='w')
self.ButtonFrame.grid(row=0, column=1, sticky='w') self.ButtonFrame.grid(row=0, column=1, sticky='w')
self.parameter_frame.grid(row=1, column=0, columnspan=2, sticky='w') self.parameter_frame.grid(row=1, column=0, columnspan=2, sticky='w')
self.StatusLabel.grid(row=2, column=0, columnspan=2) self.timing_frame.grid(row=2, column=0, columnspan=2, sticky='w')
self.StatusLabel.grid(row=3, column=0, columnspan=2)
# self.ClearButton.pack(side="top") # self.ClearButton.pack(side="top")
self.root.geometry(self.TkPosition) self.root.geometry(self.TkPosition)
@@ -129,6 +180,7 @@ class PrimaryOverlay(threading.Thread):
def destroy(self): def destroy(self):
self.hide_mining_overlay() self.hide_mining_overlay()
del self.MiningOverlay
self.root.destroy() self.root.destroy()
def start_button_callback(self): def start_button_callback(self):
@@ -136,7 +188,7 @@ class PrimaryOverlay(threading.Thread):
self.StopButton.configure(state=tk.NORMAL) self.StopButton.configure(state=tk.NORMAL)
self.PauseButton.configure(state=tk.NORMAL) self.PauseButton.configure(state=tk.NORMAL)
self.QuitButton.configure(state=tk.DISABLED) self.QuitButton.configure(state=tk.DISABLED)
for i in range(1, 7): for i in range(1, 9):
tt = self.rb_int.get() tt = self.rb_int.get()
if self.rb_int.get() != i: if self.rb_int.get() != i:
(self.RadioButtons[i]).configure(state=tk.DISABLED) (self.RadioButtons[i]).configure(state=tk.DISABLED)
@@ -148,7 +200,7 @@ class PrimaryOverlay(threading.Thread):
self.StopButton.configure(state=tk.DISABLED) self.StopButton.configure(state=tk.DISABLED)
self.PauseButton.configure(state=tk.DISABLED) self.PauseButton.configure(state=tk.DISABLED)
self.QuitButton.configure(state=tk.NORMAL) self.QuitButton.configure(state=tk.NORMAL)
for i in range(1, 7): for i in range(1, 9):
self.RadioButtons[i].configure(state=tk.NORMAL) self.RadioButtons[i].configure(state=tk.NORMAL)
self.run_mode = 'stopped' self.run_mode = 'stopped'
@@ -175,7 +227,19 @@ class PrimaryOverlay(threading.Thread):
self.EnergyLabel.configure(text="Runs:") self.EnergyLabel.configure(text="Runs:")
self.emitter_use.set('multi') self.emitter_use.set('multi')
self.hide_mining_overlay() self.hide_mining_overlay()
elif self.rb_int.get() == 2 or self.rb_int.get() == 3: elif self.rb_int.get() == 2:
self.EnergyEntry.configure(state=tk.DISABLED)
self.energy_use.set('')
self.SpawnEntry.configure(state=tk.DISABLED)
self.spawn_use.set('')
self.Emitter_Box.configure(state=tk.NORMAL)
self.Emitter_Box.configure(values=('rainbow', 'bigbomb', 'rocket', 'bomb'))
self.emitter_use.set('rainbow')
self.EmitterLabel.configure(text="Strat:")
self.SpawnLabel.configure(text="")
self.EnergyLabel.configure(text="")
self.hide_mining_overlay()
elif self.rb_int.get() == 3:
self.EnergyEntry.configure(state=tk.DISABLED) self.EnergyEntry.configure(state=tk.DISABLED)
self.energy_use.set('') self.energy_use.set('')
self.SpawnEntry.configure(state=tk.DISABLED) self.SpawnEntry.configure(state=tk.DISABLED)
@@ -220,8 +284,72 @@ class PrimaryOverlay(threading.Thread):
self.SpawnLabel.configure(text="") self.SpawnLabel.configure(text="")
self.EnergyLabel.configure(text="Runs:") self.EnergyLabel.configure(text="Runs:")
self.show_mining_overlay() self.show_mining_overlay()
elif self.rb_int.get() == 7:
# self.EnergyEntry.configure(state=tk.DISABLED)
self.energy_use.set('')
self.SpawnEntry.configure(state=tk.DISABLED)
self.spawn_use.set('')
self.Emitter_Box.configure(state=tk.DISABLED)
self.emitter_use.set('')
self.EmitterLabel.configure(text="")
self.SpawnLabel.configure(text="")
self.EnergyLabel.configure(text="")
self.hide_mining_overlay()
elif self.rb_int.get() == 8:
self.EnergyEntry.configure(state=tk.DISABLED)
self.energy_use.set('')
self.SpawnEntry.configure(state=tk.DISABLED)
self.spawn_use.set('')
self.Emitter_Box.configure(state=tk.DISABLED)
self.emitter_use.set('')
self.EmitterLabel.configure(text="")
self.SpawnLabel.configure(text="")
self.EnergyLabel.configure(text="")
self.hide_mining_overlay()
elif self.rb_int.get() == 9:
self.EnergyEntry.configure(state=tk.DISABLED)
self.energy_use.set('')
self.SpawnEntry.configure(state=tk.DISABLED)
self.spawn_use.set('')
self.Emitter_Box.configure(state=tk.DISABLED)
self.emitter_use.set('')
self.EmitterLabel.configure(text="")
self.SpawnLabel.configure(text="")
self.EnergyLabel.configure(text="")
self.hide_mining_overlay()
elif self.rb_int.get() == 10:
self.EnergyEntry.configure(state=tk.DISABLED)
self.energy_use.set('')
self.SpawnEntry.configure(state=tk.DISABLED)
self.spawn_use.set('')
self.Emitter_Box.configure(state=tk.DISABLED)
self.emitter_use.set('')
self.EmitterLabel.configure(text="")
self.SpawnLabel.configure(text="")
self.EnergyLabel.configure(text="")
self.hide_mining_overlay()
elif self.rb_int.get() == 11:
self.EnergyEntry.configure(state=tk.DISABLED)
self.energy_use.set('')
self.SpawnEntry.configure(state=tk.DISABLED)
self.spawn_use.set('')
self.Emitter_Box.configure(state=tk.DISABLED)
self.emitter_use.set('')
self.EmitterLabel.configure(text="")
self.SpawnLabel.configure(text="")
self.EnergyLabel.configure(text="")
self.hide_mining_overlay()
elif self.rb_int.get() == 12:
self.EnergyEntry.configure(state=tk.DISABLED)
self.energy_use.set('')
self.SpawnEntry.configure(state=tk.DISABLED)
self.spawn_use.set('')
self.Emitter_Box.configure(state=tk.DISABLED)
self.emitter_use.set('')
self.EmitterLabel.configure(text="")
self.SpawnLabel.configure(text="")
self.EnergyLabel.configure(text="")
self.hide_mining_overlay()
def get_run_mode(self): def get_run_mode(self):
return self.run_mode return self.run_mode
@@ -233,3 +361,15 @@ class PrimaryOverlay(threading.Thread):
def show_mining_overlay(self): def show_mining_overlay(self):
self.MiningOverlay.show_window() self.MiningOverlay.show_window()
def get_strategy_value_as_int(self):
if self.emitter_use.get() == "rainbow":
return 11
elif self.emitter_use.get() == "bigbomb":
return 9
elif self.emitter_use.get() == "rocket":
return 7
elif self.emitter_use.get() == "bomb":
return 5
else:
return 11

View File

@@ -59,9 +59,12 @@ class UserConfigs:
else: else:
pass pass
def returnDiggingWindowPos2(self): def returnDiggingWindowPos2(self, large=True):
if self.user == self.THALOUSER: if self.user == self.THALOUSER:
if large:
return [1440, 1150, 570, 22] return [1440, 1150, 570, 22]
else:
return [1440, 210, 560, 700]
elif self.user == self.ADWAUSER: elif self.user == self.ADWAUSER:
return [740, 450, 1625, 985] return [740, 450, 1625, 985]
elif self.user == self.EDDIEUSER: elif self.user == self.EDDIEUSER:

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
control_elements/play.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@@ -4,6 +4,7 @@ import pydirectinput
from config_file import UserConfigs from config_file import UserConfigs
from window_capture import WindowCapture from window_capture import WindowCapture
from vision import Vision from vision import Vision
from game_base_class import GameBase
MODE25X1 = "m25x1" MODE25X1 = "m25x1"
MODE10X2 = "m10x2" MODE10X2 = "m10x2"
@@ -14,11 +15,10 @@ MODE1X5_X = "m1x5_X"
MODE_HOUSE = "house" MODE_HOUSE = "house"
class Craft: class Craft(GameBase):
def __init__(self, overlay): def __init__(self, overlay):
self.overlay = overlay super().__init__(overlay)
self.config = UserConfigs()
self.mode = str(overlay.emitter_use.get()) self.mode = str(overlay.emitter_use.get())
self.run_target = int(overlay.energy_use.get()) self.run_target = int(overlay.energy_use.get())
@@ -26,19 +26,11 @@ class Craft:
self.run_counter = 0 self.run_counter = 0
self.dimension = 172 self.dimension = 172
def execute_main_loop(self): def assess_playfield_and_make_move(self):
while True:
if self.overlay.run_mode == 'paused':
cv.waitKey(1)
continue
elif self.overlay.run_mode == 'stopped':
break
if self.run_counter >= self.run_target: if self.run_counter >= self.run_target:
self.run_counter = 0 self.run_counter = 0
self.overlay.run_mode = 'finished' self.overlay.run_mode = 'finished'
break return
ab1 = [420, 1180, 142, 142] ab1 = [420, 1180, 142, 142]
ab2 = [562, 1180, 142, 142] ab2 = [562, 1180, 142, 142]
@@ -58,7 +50,9 @@ class Craft:
self.click_square_center( self.click_square_center(
[770 + (i * self.dimension), 160 + (e * self.dimension), self.dimension, self.dimension]) [770 + (i * self.dimension), 160 + (e * self.dimension), self.dimension, self.dimension])
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
return
self.click_craft_button() self.click_craft_button()
@@ -69,7 +63,9 @@ class Craft:
self.run_counter = self.run_counter + 1 self.run_counter = self.run_counter + 1
self.overlay.update_status_label(self.mode + ": " + str(self.run_target - self.run_counter)) self.overlay.update_status_label(self.mode + ": " + str(self.run_target - self.run_counter))
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
return
self.click_square_center(ab10) self.click_square_center(ab10)
elif self.mode == MODE10X2: elif self.mode == MODE10X2:
for r in range(0, 2, 1): for r in range(0, 2, 1):
@@ -90,7 +86,11 @@ class Craft:
[770 + (i * self.dimension), 160 + (e * self.dimension), self.dimension, [770 + (i * self.dimension), 160 + (e * self.dimension), self.dimension,
self.dimension]) self.dimension])
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
return
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
return
self.click_craft_button() self.click_craft_button()
@@ -101,24 +101,30 @@ class Craft:
self.run_counter = self.run_counter + 1 self.run_counter = self.run_counter + 1
self.overlay.update_status_label(self.mode + ": " + str(self.run_target - self.run_counter)) self.overlay.update_status_label(self.mode + ": " + str(self.run_target - self.run_counter))
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
return
self.click_square_center(ab10) self.click_square_center(ab10)
elif self.mode == MODE5X3: elif self.mode == MODE5X3:
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break
for r in range(0, 3, 1): for r in range(0, 3, 1):
# grid 770 1630 160 1020 172oo # grid 770 1630 160 1020 172oo
self.dimension = 172 self.dimension = 172
if r == 0: if r == 0:
self.click_square_center(ab1) self.click_square_center(ab1)
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
return
start = 0 start = 0
target = 1 target = 1
elif r == 1: elif r == 1:
self.click_square_center(ab2) self.click_square_center(ab2)
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
return
start = 1 start = 1
target = 2 target = 2
else: else:
self.click_square_center(ab3) self.click_square_center(ab3)
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
return
start = 2 start = 2
target = 3 target = 3
@@ -128,20 +134,26 @@ class Craft:
[770 + (i * self.dimension), 160 + (e * self.dimension), self.dimension, [770 + (i * self.dimension), 160 + (e * self.dimension), self.dimension,
self.dimension]) self.dimension])
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
return
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
return
self.click_craft_button() self.click_craft_button()
for i in range(0, 1, 1): for i in range(0, 1, 1):
if self.overlay.run_mode == 'stopped': if self.overlay.run_mode == 'stopped':
break return
for e in range(0, 5, 1): for e in range(0, 5, 1):
self.collect_grid_reverse_click( self.collect_grid_reverse_click(
[770 + (i * self.dimension), 160 + (e * self.dimension), self.dimension, self.dimension]) [770 + (i * self.dimension), 160 + (e * self.dimension), self.dimension, self.dimension])
self.run_counter = self.run_counter + 1 self.run_counter = self.run_counter + 1
self.overlay.update_status_label(self.mode + ": " + str(self.run_target - self.run_counter)) self.overlay.update_status_label(self.mode + ": " + str(self.run_target - self.run_counter))
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
return
self.click_square_center(ab10) self.click_square_center(ab10)
elif self.mode == MODE1X5_T: elif self.mode == MODE1X5_T:
tps = [ab1, tps = [ab1,
@@ -157,21 +169,21 @@ class Craft:
for tp in tps: for tp in tps:
self.click_square_center(tp) self.click_square_center(tp)
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
self.click_craft_button() self.click_craft_button()
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
self.click_square_center(result_tp) self.click_square_center(result_tp)
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
self.click_square_center(ab10) self.click_square_center(ab10)
self.run_counter = self.run_counter + 1 self.run_counter = self.run_counter + 1
self.overlay.update_status_label(self.mode + ": " + str(self.run_target - self.run_counter)) self.overlay.update_status_label(self.mode + ": " + str(self.run_target - self.run_counter))
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
elif self.mode == MODE1X5_X: elif self.mode == MODE1X5_X:
tps = [ab1, tps = [ab1,
[770 + (0 * self.dimension), 160 + (3 * self.dimension), self.dimension, self.dimension], [770 + (0 * self.dimension), 160 + (3 * self.dimension), self.dimension, self.dimension],
@@ -185,21 +197,21 @@ class Craft:
for tp in tps: for tp in tps:
self.click_square_center(tp) self.click_square_center(tp)
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
self.click_craft_button() self.click_craft_button()
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
self.click_square_center(result_tp) self.click_square_center(result_tp)
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
self.click_square_center(ab10) self.click_square_center(ab10)
self.run_counter = self.run_counter + 1 self.run_counter = self.run_counter + 1
self.overlay.update_status_label(self.mode + ": " + str(self.run_target - self.run_counter)) self.overlay.update_status_label(self.mode + ": " + str(self.run_target - self.run_counter))
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
elif self.mode == MODE_HOUSE: elif self.mode == MODE_HOUSE:
cements = [[770 + (0 * self.dimension), 160 + (4 * self.dimension), self.dimension, self.dimension], cements = [[770 + (0 * self.dimension), 160 + (4 * self.dimension), self.dimension, self.dimension],
[770 + (1 * self.dimension), 160 + (4 * self.dimension), self.dimension, self.dimension], [770 + (1 * self.dimension), 160 + (4 * self.dimension), self.dimension, self.dimension],
@@ -235,53 +247,53 @@ class Craft:
for cement in cements: for cement in cements:
self.click_square_center(cement) self.click_square_center(cement)
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
self.click_square_center(ab2) self.click_square_center(ab2)
for brick in bricks: for brick in bricks:
self.click_square_center(brick) self.click_square_center(brick)
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
self.click_square_center(ab3) self.click_square_center(ab3)
for board in boards: for board in boards:
self.click_square_center(board) self.click_square_center(board)
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
self.click_square_center(ab4) self.click_square_center(ab4)
for glass in glasses: for glass in glasses:
self.click_square_center(glass) self.click_square_center(glass)
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
self.click_square_center(ab5) self.click_square_center(ab5)
self.click_square_center(tp_hammer) self.click_square_center(tp_hammer)
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
self.click_square_center(ab6) self.click_square_center(ab6)
self.click_square_center(tp_nails) self.click_square_center(tp_nails)
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
self.click_craft_button() self.click_craft_button()
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
self.click_square_center(tp_result) self.click_square_center(tp_result)
self.click_square_center(ab10) self.click_square_center(ab10)
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
self.run_counter = self.run_counter + 1 self.run_counter = self.run_counter + 1
self.overlay.update_status_label(self.mode + ": " + str(self.run_target - self.run_counter)) self.overlay.update_status_label(self.mode + ": " + str(self.run_target - self.run_counter))
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
elif self.mode == MODE_SIMPLE_STACK: elif self.mode == MODE_SIMPLE_STACK:
# initialize the StunWindowCapture class # initialize the StunWindowCapture class
capture_config = UserConfigs() capture_config = UserConfigs()
@@ -291,9 +303,13 @@ class Craft:
# initialize the StunVision class # initialize the StunVision class
vision_stun = Vision() vision_stun = Vision()
# odig_overlay = DiggingOverlay(config) # dig_overlay = DiggingOverlay(config)
check_for_craft_button(capture_window2, vision_stun, capture_config) check_for_craft_button(capture_window2, vision_stun)
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
return
check_for_craft_ok_button(capture_window2, vision_stun) check_for_craft_ok_button(capture_window2, vision_stun)
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
return
self.run_counter = self.run_counter + 1 self.run_counter = self.run_counter + 1
self.overlay.update_status_label(self.mode + ": " + str(self.run_target - self.run_counter)) self.overlay.update_status_label(self.mode + ": " + str(self.run_target - self.run_counter))
# check_for_ok_button(capture_window, vision_stun, capture_config) # check_for_ok_button(capture_window, vision_stun, capture_config)

View File

@@ -10,7 +10,7 @@ from config_file import UserConfigs
# load the original input image and display it to our screen # load the original input image and display it to our screen
#filename = "equip/chests/chest_23_32" #filename = "equip/chests/chest_23_32"
path = "equip/wands/" path = "flappy/"
os.chdir(path) os.chdir(path)
for entry in os.listdir(): for entry in os.listdir():

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1013 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 986 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 761 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 726 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 597 KiB

237
crops.py
View File

@@ -2,12 +2,10 @@ import random
import cv2 as cv import cv2 as cv
import numpy as np import numpy as np
import pydirectinput import pydirectinput
from window_capture import WindowCapture
from vision import Vision
from config_file import UserConfigs
from utils import mse from utils import mse
from utils import get_click_point from utils import get_click_point
from hsvfilter import HsvFilter from hsvfilter import HsvFilter
from game_base_class import GameBase
GREEN = 1 GREEN = 1
YELLOW = 2 YELLOW = 2
@@ -40,59 +38,25 @@ BIGBOMB_STRATEGY = 9
ROCKET_STRATEGY = 7 ROCKET_STRATEGY = 7
BOMB_STRATEGY = 5 BOMB_STRATEGY = 5
class Crops:
class Crops(GameBase):
def __init__(self, overlay): def __init__(self, overlay):
self.overlay = overlay super().__init__(overlay)
self.data_value_grid = np.zeros((8, 14), dtype=int)
self.data_coordinates = np.zeros((8, 14), dtype=object)
self.data_score_map = np.zeros((8, 14), dtype=int)
self.observation = np.zeros((8, 14), dtype=int)
self.screenshot = [] self.screenshot = []
self.next_level = cv.imread("crop/next_level.jpg", cv.IMREAD_COLOR)
self.next_level_x = cv.imread("crop/next_level_x.jpg", cv.IMREAD_COLOR)
self.reset_board = cv.imread("crop/reset_button.jpg", cv.IMREAD_COLOR)
self.reset_confirm = cv.imread("crop/reset_confirm.jpg", cv.IMREAD_COLOR)
self.reset_counter = 0
self.colors_at_standard = True
self.needles = {} self.needles = {}
self.hsh_needles = {} self.hsh_needles = {}
self.explosives = [RAINBOW, ARROW_RIGHT, ARROW_DOWN, BIGBOMB, BOMB]
self.colors = [GREEN, YELLOW, RED, BLUE, PURPLE, MAGINENT, CHEMTRANT, TENESENT, CIBUTRANT, ARTISENT]
self.current_strategy = RAINBOW_STRATEGY self.colors.append(PURPLE)
# 230 to 2110 = 1883 / 14 = 134.5 self.current_strategy = overlay.get_strategy_value_as_int()
# 60 to 1130 = 1076 / 8 = 134.5
dim = 134.5
for e in range(0, 8, 1):
for i in range(0, 14, 1):
self.data_coordinates[e][i] = [i * dim, e * dim, dim, dim]
# initialize the user-class self.fill_data_coordinates()
self.config = UserConfigs()
# initialize the StunWindowCapture class
self.capture_window = WindowCapture(None, None, self.config)
# initialize the StunVision class
self.vision_stun = Vision()
self.set_color_order((GREEN, YELLOW, RED, BLUE, PURPLE)) self.set_color_order((GREEN, YELLOW, RED, BLUE, PURPLE))
def execute_main_loop(self):
while True:
if self.overlay.run_mode == 'paused':
cv.waitKey(1)
continue
elif self.overlay.run_mode == 'stopped':
break
self.assess_playfield_and_make_move()
def reset(self):
self.observation = []
def set_color_order(self, order): def set_color_order(self, order):
self.needles.clear() self.needles.clear()
self.needles = {order[0]: cv.imread("crop/green.jpg", cv.IMREAD_COLOR), self.needles = {order[0]: cv.imread("crop/green.jpg", cv.IMREAD_COLOR),
@@ -162,7 +126,8 @@ class Crops:
color_list = [PURPLE, BLUE, RED, YELLOW, GREEN] color_list = [PURPLE, BLUE, RED, YELLOW, GREEN]
random.shuffle(color_list) random.shuffle(color_list)
self.set_color_order(color_list) self.set_color_order(color_list)
self.current_strategy = random.choice([RAINBOW_STRATEGY, BIGBOMB_STRATEGY, ROCKET_STRATEGY, BOMB_STRATEGY]) self.current_strategy = random.choice([RAINBOW_STRATEGY, BIGBOMB_STRATEGY,
ROCKET_STRATEGY, BOMB_STRATEGY])
self.reset_counter = 0 self.reset_counter = 0
return return
else: else:
@@ -172,44 +137,12 @@ class Crops:
self.observation = new_observation self.observation = new_observation
return new_observation return new_observation
def move_to(self, x, y):
point_src = (1113, 598)
pydirectinput.moveTo(point_src[0], point_src[1])
pydirectinput.mouseDown()
w = random.randint(1, 100)
cv.waitKey(150 + w)
pydirectinput.moveTo(x, y)
pydirectinput.mouseUp()
cv.waitKey(500 + w)
def change_value(self, x, y, val):
self.data_value_grid[x][y] = val
def point_in_rect(self, point):
for e in range(0, 8, 1):
for i in range(0, 14, 1):
x1, y1, w, h = self.data_coordinates[e][i]
x2, y2 = x1 + w, y1 + h
x, y = point
if x1 < x and x < x2:
if y1 < y and y < y2:
return e, i
return None, None
def check_for_button_and_execute(self, screen, needle, offset_left=0, offset_down=0):
rectangles = self.vision_stun.find(screen, needle, 0.70, 1)
if len(rectangles) == 0:
return False
point = self.vision_stun.get_click_points(rectangles)[0]
self.dig_point(point[0] + offset_left, point[1] + offset_down, 500)
return True
def get_current_board_state(self): def get_current_board_state(self):
try:
# get an updated image of the game # get an updated image of the game
screenshot = self.capture_window.get_screenshot() screenshot = self.capture_window.get_screenshot()
# screenshot = cv.imread("playfield.jpg") # screenshot = cv.imread("playfield.jpg")
screenshot = screenshot[58:1134, 230:2113] # 1883,1076 screenshot = screenshot[190:1230, 260:2090]
self.screenshot = screenshot self.screenshot = screenshot
# gray = cv.cvtColor(screenshot, cv.COLOR_BGR2GRAY) # gray = cv.cvtColor(screenshot, cv.COLOR_BGR2GRAY)
# thresh = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)[1] # thresh = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)[1]
@@ -220,22 +153,17 @@ class Crops:
self.current_strategy = RAINBOW_STRATEGY self.current_strategy = RAINBOW_STRATEGY
cv.waitKey(500) cv.waitKey(500)
screenshot = self.capture_window.get_screenshot() screenshot = self.capture_window.get_screenshot()
screenshot = screenshot[58:1134, 230:2113] screenshot = screenshot[190:1230, 260:2090]
if self.check_for_button_and_execute(screenshot, self.next_level_x, offset_left, offset_down): if self.check_for_button_and_execute(screenshot, self.next_level_x, offset_left, offset_down):
cv.waitKey(500) cv.waitKey(500)
screenshot = self.capture_window.get_screenshot() screenshot = self.capture_window.get_screenshot()
screenshot = screenshot[58:1134, 230:2113] screenshot = screenshot[190:1230, 260:2090]
except:
# self.capture_window.release()
# print("Game window not available - shutting down application")
# return None
pass
# cv.imshow("screenshot", screenshot) # cv.imshow("screenshot", screenshot)
# cv.waitKey(150) # cv.waitKey(150)
# continue # continue
data_coords = np.zeros((8, 14), dtype=object) data_coords = np.zeros((8, 14), dtype=object)
# field = Field() # field = Pickaxe_Field()
for needle_key in self.needles.keys(): for needle_key in self.needles.keys():
# gray_needle = cv.cvtColor(self.needles[needle_key], cv.COLOR_BGR2GRAY) # gray_needle = cv.cvtColor(self.needles[needle_key], cv.COLOR_BGR2GRAY)
@@ -270,65 +198,15 @@ class Crops:
return data_coords, screenshot return data_coords, screenshot
def detonate_explosive_when_stuck(self, state):
for e in range(0, 8, 1):
for i in range(0, 14, 1):
for explosive in self.explosives:
if self.local_pos_check(state, e, i, 0, 0, explosive):
src_pt = self.get_click_point(self.data_coordinates[e, i])
if self.local_pos_checks(state, e, i, 1, 0, self.colors):
dest_pt = self.get_click_point(self.data_coordinates[e + 1, i])
self.move_tile(src_pt, dest_pt)
return True
elif self.local_pos_checks(state, e, i, 0, 1, self.colors):
dest_pt = self.get_click_point(self.data_coordinates[e, i + 1])
self.move_tile(src_pt, dest_pt)
return True
elif self.local_pos_checks(state, e, i, -1, 0, self.colors):
dest_pt = self.get_click_point(self.data_coordinates[e - 1, i])
self.move_tile(src_pt, dest_pt)
return True
elif self.local_pos_checks(state, e, i, 0, -1, self.colors):
dest_pt = self.get_click_point(self.data_coordinates[e, i - 1])
self.move_tile(src_pt, dest_pt)
return True
else:
continue
return False
def check_explosives(self, state, e, i):
for explosive in self.explosives:
if self.local_pos_check(state, e, i, 0, 0, explosive):
dest_pt = self.get_click_point(self.data_coordinates[e, i])
if self.local_pos_checks(state, e, i, 1, 0, self.explosives):
src_pt = self.get_click_point(self.data_coordinates[e + 1, i])
self.move_tile(src_pt, dest_pt)
elif self.local_pos_checks(state, e, i, 0, 1, self.explosives):
src_pt = self.get_click_point(self.data_coordinates[e, i + 1])
self.move_tile(src_pt, dest_pt)
elif self.local_pos_checks(state, e, i, -1, 0, self.explosives):
src_pt = self.get_click_point(self.data_coordinates[e - 1, i])
self.move_tile(src_pt, dest_pt)
elif self.local_pos_checks(state, e, i, 0, -1, self.explosives):
src_pt = self.get_click_point(self.data_coordinates[e, i - 1])
self.move_tile(src_pt, dest_pt)
else:
continue
return True
else:
continue
return False
def find_patterns_and_valid_moves(self, state): def find_patterns_and_valid_moves(self, state):
# score_map = np.zeros((8, 14), dtype=object) # score_map = np.zeros((8, 14), dtype=object)
for x in range(0, 8, 1): for x in range(0, 8, 1):
for y in range(0, 14, 1): for y in range(0, 14, 1):
self.data_score_map[x, y] = self.score_for_attached_same_color_all_directions(state, x, y) self.data_score_map[x, y] = self.score_for_attached_same_color_all_directions(state, x, y)
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
full_moves = [] full_moves = []
reserve_moves = [] reserve_moves = []
@@ -346,18 +224,18 @@ class Crops:
if len(path_option) >= 5: if len(path_option) >= 5:
full_moves.append((state[x, y], path_option)) full_moves.append((state[x, y], path_option))
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
if self.data_score_map[x, y] >= 1: if self.data_score_map[x, y] >= 1:
path_option = [[x, y]] path_option = [[x, y]]
self.find_next_same_color_all_directions_recursion2(state, x, y, path_option) self.find_next_same_color_all_directions_recursion2(state, x, y, path_option)
if len(path_option) >= 3: if len(path_option) >= 3:
reserve_moves.append((state[x, y], path_option)) reserve_moves.append((state[x, y], path_option))
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
# print(self.data_score_map) # print(self.data_score_map)
# screenshot = cv.imread("screenshot_scored.jpg") # screenshot = cv.imread("screenshot_scored.jpg")
@@ -379,7 +257,8 @@ class Crops:
self.execute_move(res_dic[key]) self.execute_move(res_dic[key])
break break
def convert_moves_to_dic_by_color(self, reserve_moves): @staticmethod
def convert_moves_to_dic_by_color(reserve_moves):
dic = {} dic = {}
for color, move in reserve_moves: for color, move in reserve_moves:
if color in dic: if color in dic:
@@ -418,7 +297,8 @@ class Crops:
pydirectinput.mouseUp() pydirectinput.mouseUp()
cv.waitKey(50) cv.waitKey(50)
def get_directions_array(self, current_x, current_y): @staticmethod
def get_directions_array(current_x, current_y):
left_x = current_x left_x = current_x
left_y = current_y - 1 left_y = current_y - 1
@@ -512,70 +392,3 @@ class Crops:
score = score + self.is_direction_in_bounce_and_same_color(state, direction, color) score = score + self.is_direction_in_bounce_and_same_color(state, direction, color)
return score return score
def is_direction_in_bounce_and_same_color(self, state, loc, color):
x, y = loc
if x <= 7 and x >= 0 and y <= 13 and y >= 0:
if state[x, y] == color:
return 1
return 0
def local_pos_check(self, state, e, i, e_check, i_check, needle):
if e + e_check >= 0 and e + e_check <= 7 and i + i_check >= 0 and i + i_check <= 13:
if state[e + e_check, i + i_check] == needle:
return True
else:
return False
def local_pos_checks(self, state, e, i, e_check, i_check, needles):
if e + e_check >= 0 and e + e_check <= 7 and i + i_check >= 0 and i + i_check <= 13:
for needle in needles:
if state[e + e_check, i + i_check] == needle:
return True
else:
continue
return False
def move_tile(self, point_source, point_dest):
offset_left = 230
offset_down = 58
pydirectinput.moveTo(point_source[0] + offset_left, point_source[1] + offset_down)
# pydirectinput.moveTo(0,0)
pydirectinput.mouseDown()
w = random.randint(25, 50)
cv.waitKey(100 + w)
pydirectinput.moveTo(point_dest[0] + offset_left, point_dest[1] + offset_down)
pydirectinput.mouseUp()
cv.waitKey(400 + w)
def check_for_button_and_click_it(self, button_url):
screenshot = self.capture_window.get_screenshot()
# gray = cv.cvtColor(screenshot, cv.COLOR_BGR2GRAY)
# thresh = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)[1]
# gray_needle = cv.cvtColor(cv.imread(button_url, cv.IMREAD_UNCHANGED), cv.COLOR_BGR2GRAY)
# thresh_needle = cv.threshold(gray_needle, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)[1]
needle = cv.imread(button_url, cv.IMREAD_UNCHANGED)
# rectangles = self.vision_stun.find(thresh, thresh_needle, 0.4, 1)
rectangles = self.vision_stun.find(screenshot, needle, 0.7, 1)
if len(rectangles) == 1:
pointis = self.vision_stun.get_click_points(rectangles)
for pointi in pointis:
self.dig_point(pointi[0], pointi[1], 150)
def dig_point(self, point1, point2, dig_time):
pydirectinput.moveTo(point1, point2)
cv.waitKey(dig_time)
pydirectinput.mouseDown()
w = random.randint(50, 100)
cv.waitKey(w)
pydirectinput.mouseUp()
def get_click_point(self, rectangle):
# Loop over all the rectangles
x, y, w, h = rectangle
# Determine the center position
center_x = x + int(w / 2)
center_y = y + int(h / 2)
# Save the points
return int(center_x), int(center_y)

View File

@@ -1,13 +1,12 @@
import random import random
from operator import itemgetter from operator import itemgetter
from time import time from time import time
from window_capture import WindowCapture
from vision import Vision
import cv2 as cv import cv2 as cv
from hsvfilter import HsvFilter from hsvfilter import HsvFilter
from config_file import UserConfigs
import pydirectinput import pydirectinput
from utils import dig_point from utils import dig_point
from game_base_class import GameBase
from window_capture import WindowCapture
EMITTER_MAIN = "main" EMITTER_MAIN = "main"
EMITTER_MUSH = "mushroom" EMITTER_MUSH = "mushroom"
@@ -21,71 +20,24 @@ EMITTER_MULTI = "multi"
HSV_DEFAULT = HsvFilter(0, 0, 0, 179, 255, 255, 0, 0, 0, 0) HSV_DEFAULT = HsvFilter(0, 0, 0, 179, 255, 255, 0, 0, 0, 0)
class Equipment: class Equipment(GameBase):
needles = []
hsvs = []
tresholds = []
masks = []
emitters = []
def __init__(self, overlay): def __init__(self, overlay):
self.overlay = overlay super().__init__(overlay)
self.config = UserConfigs()
self.needles = [] # initialize the StunWindowCapture class
self.hsvs = [] self.capture_window = WindowCapture(None, "equip", self.config)
self.tresholds = []
self.masks = []
self.emitters = []
self.EMITTER_TO_USE = str(overlay.emitter_use.get()) self.EMITTER_TO_USE = str(overlay.emitter_use.get())
self.SPAWN_COUNT = int(overlay.spawn_use.get()) self.SPAWN_COUNT = int(overlay.spawn_use.get())
self.ENERGY_TO_USE = int(overlay.energy_use.get()) self.ENERGY_TO_USE = int(overlay.energy_use.get())
# initialize the StunWindowCapture class self.init_emitters_to_use()
self.capture_window = WindowCapture(None, "equip", self.config)
# initialize the StunVision class
self.vision_stun = Vision()
if self.EMITTER_TO_USE == EMITTER_MULTI:
self.emitters.append(EMITTER_RING)
self.emitters.append(EMITTER_WAND)
self.emitters.append(EMITTER_SWORD)
self.emitters.append(EMITTER_AMU)
self.emitters.append(EMITTER_STAFF)
else:
self.emitters.append(self.EMITTER_TO_USE)
for emitter in self.emitters:
if emitter == EMITTER_MUSH:
self.include_books()
self.include_mushs()
self.include_pots()
self.include_bags()
elif emitter == EMITTER_AMU:
self.include_books()
self.include_amus()
self.include_bags()
elif emitter == EMITTER_MAIN:
self.include_books()
self.include_chests()
self.include_keys()
self.include_pots()
self.include_bags()
self.include_coins()
self.include_runes()
elif emitter == EMITTER_SWORD:
self.include_books()
self.include_swords()
self.include_bags()
elif emitter == EMITTER_STAFF:
self.include_books()
self.include_staffs()
self.include_bags()
elif emitter == EMITTER_RING:
self.include_books()
self.include_rings()
self.include_bags()
elif emitter == EMITTER_WAND:
self.include_books()
self.include_wands()
self.include_bags()
self.c_needle = cv.imread("equip/chests/chest_4_32.jpg", cv.IMREAD_UNCHANGED) self.c_needle = cv.imread("equip/chests/chest_4_32.jpg", cv.IMREAD_UNCHANGED)
self.c_mask = cv.imread("equip/chests/chest_4_32-mask.png", cv.IMREAD_COLOR) self.c_mask = cv.imread("equip/chests/chest_4_32-mask.png", cv.IMREAD_COLOR)
@@ -95,11 +47,55 @@ class Equipment:
self.energy_counter = 0 self.energy_counter = 0
def init_emitters_to_use(self):
self.emitters.clear()
if self.EMITTER_TO_USE == EMITTER_MULTI:
self.emitters.append(EMITTER_RING)
self.emitters.append(EMITTER_WAND)
self.emitters.append(EMITTER_SWORD)
self.emitters.append(EMITTER_AMU)
self.emitters.append(EMITTER_STAFF)
else:
self.emitters.append(self.EMITTER_TO_USE)
def init_needles_for_emitter_to_use(self, emitter):
self.needles.clear()
self.hsvs.clear()
self.tresholds.clear()
self.masks.clear()
self.include_books()
self.include_bags()
if emitter == EMITTER_MUSH:
self.include_mushs()
self.include_pots()
elif emitter == EMITTER_AMU:
self.include_amus()
elif emitter == EMITTER_MAIN:
self.include_chests()
self.include_keys()
self.include_pots()
#self.include_coins()
self.include_runes()
elif emitter == EMITTER_SWORD:
self.include_swords()
elif emitter == EMITTER_STAFF:
self.include_staffs()
elif emitter == EMITTER_RING:
self.include_rings()
elif emitter == EMITTER_WAND:
self.include_wands()
def execute_main_loop(self): def execute_main_loop(self):
start_time = time()
breaks = self.init_breaks()
for emitter in self.emitters: for emitter in self.emitters:
self.init_needles_for_emitter_to_use(emitter)
while True: while True:
self.check_breaks(start_time, breaks)
if self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'paused':
cv.waitKey(1) cv.waitKey(10)
continue continue
elif self.overlay.run_mode == 'stopped': elif self.overlay.run_mode == 'stopped':
break break
@@ -116,6 +112,9 @@ class Equipment:
spawn_1 = self.find_emitter(emitter, screenshot, 1) spawn_1 = self.find_emitter(emitter, screenshot, 1)
if len(spawn_1) == 1: if len(spawn_1) == 1:
#output_by_area = self.vision_stun.draw_rectangles(screenshot, spawn_1)
#cv.imshow("spawn_1", output_by_area)
#cv.waitKey(150)
points = self.vision_stun.get_click_points(spawn_1) points = self.vision_stun.get_click_points(spawn_1)
for i in range(0, self.SPAWN_COUNT, 1): for i in range(0, self.SPAWN_COUNT, 1):
self.click_point(points[0][0], points[0][1]) self.click_point(points[0][0], points[0][1])
@@ -126,17 +125,19 @@ class Equipment:
else: else:
spawn_0 = self.find_emitter(emitter, screenshot, 0) spawn_0 = self.find_emitter(emitter, screenshot, 0)
points = self.vision_stun.get_click_points(spawn_0) points = self.vision_stun.get_click_points(spawn_0)
for point in points: if len(points) >= 1:
self.click_point(points[0][0], points[0][1]) self.click_point(points[0][0], points[0][1])
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break continue
continue continue
cv.waitKey(500) cv.waitKey(500)
if emitter == EMITTER_MAIN: if emitter == EMITTER_MAIN:
loop_time = time()
while True: while True:
if (time() - loop_time) >= 10:
break
screenshot = self.capture_window.get_screenshot() screenshot = self.capture_window.get_screenshot()
c_rectangles = self.vision_stun.find(screenshot, self.c_needle, 0.95, 1, True, self.c_mask) c_rectangles = self.vision_stun.find(screenshot, self.c_needle, 0.95, 1, True, self.c_mask)
k_rectangles = self.vision_stun.find(screenshot, self.k_needle, 0.95, 1, True, self.k_mask) k_rectangles = self.vision_stun.find(screenshot, self.k_needle, 0.95, 1, True, self.k_mask)
@@ -144,13 +145,17 @@ class Equipment:
c_point = self.vision_stun.get_click_points(c_rectangles)[0] c_point = self.vision_stun.get_click_points(c_rectangles)[0]
k_point = self.vision_stun.get_click_points(k_rectangles)[0] k_point = self.vision_stun.get_click_points(k_rectangles)[0]
self.move_tile(k_point, c_point) self.move_tile(k_point, c_point)
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break
else: else:
break break
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
continue
for rer in range(0, len(self.needles), 1): for rer in range(0, len(self.needles), 1):
loop_time = time() loop_time = time()
while True: while True:
if (time() - loop_time) >= 60: if (time() - loop_time) >= 20:
break break
screenshot = self.capture_window.get_screenshot_by_area(self.config.returnOKWindowPos()) screenshot = self.capture_window.get_screenshot_by_area(self.config.returnOKWindowPos())
rectangles = self.vision_stun.find(screenshot, self.dig_button, 0.5, 1) rectangles = self.vision_stun.find(screenshot, self.dig_button, 0.5, 1)
@@ -208,7 +213,7 @@ class Equipment:
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break break
cv.waitKey(150) cv.waitKey(150)
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped':
break break
if self.overlay.run_mode == 'stopped': if self.overlay.run_mode == 'stopped':
break break
@@ -314,7 +319,7 @@ class Equipment:
else: else:
needle = cv.imread("equip/emitters/ring_e2_32.jpg", cv.IMREAD_UNCHANGED) needle = cv.imread("equip/emitters/ring_e2_32.jpg", cv.IMREAD_UNCHANGED)
mask = cv.imread("equip/emitters/ring_e2_32-mask.png", cv.IMREAD_COLOR) mask = cv.imread("equip/emitters/ring_e2_32-mask.png", cv.IMREAD_COLOR)
return self.vision_stun.find(screen, needle, 0.95, 1, True, mask) return self.vision_stun.find(screen, needle, 0.95, 1, False, mask)
elif emitter_to_use == EMITTER_WAND: elif emitter_to_use == EMITTER_WAND:
if layer == 0: if layer == 0:
needle = cv.imread("equip/emitters/wand_e1_32.jpg", cv.IMREAD_UNCHANGED) needle = cv.imread("equip/emitters/wand_e1_32.jpg", cv.IMREAD_UNCHANGED)
@@ -623,12 +628,12 @@ class Equipment:
def include_staffs(self): def include_staffs(self):
self.needles.append(cv.imread("equip/staffs/staff_1_32.jpg", cv.IMREAD_UNCHANGED)) self.needles.append(cv.imread("equip/staffs/staff_1_32.jpg", cv.IMREAD_UNCHANGED))
self.hsvs.append(HSV_DEFAULT) self.hsvs.append(HSV_DEFAULT)
self.tresholds.append(0.93) self.tresholds.append(0.94)
self.masks.append(cv.imread("equip/staffs/staff_1_32-mask.png", cv.IMREAD_COLOR)) self.masks.append(cv.imread("equip/staffs/staff_1_32-mask.png", cv.IMREAD_COLOR))
self.needles.append(cv.imread("equip/staffs/staff_2_32.jpg", cv.IMREAD_UNCHANGED)) self.needles.append(cv.imread("equip/staffs/staff_2_32.jpg", cv.IMREAD_UNCHANGED))
self.hsvs.append(HSV_DEFAULT) self.hsvs.append(HSV_DEFAULT)
self.tresholds.append(0.93) self.tresholds.append(0.94)
self.masks.append(cv.imread("equip/staffs/staff_2_32-mask.png", cv.IMREAD_COLOR)) self.masks.append(cv.imread("equip/staffs/staff_2_32-mask.png", cv.IMREAD_COLOR))
self.needles.append(cv.imread("equip/staffs/staff_3_32.jpg", cv.IMREAD_UNCHANGED)) self.needles.append(cv.imread("equip/staffs/staff_3_32.jpg", cv.IMREAD_UNCHANGED))

277
farm.py
View File

@@ -1,11 +1,7 @@
import random
import cv2 as cv import cv2 as cv
import numpy as np import numpy as np
import pydirectinput
from window_capture import WindowCapture
from vision import Vision
from config_file import UserConfigs
from utils import mse from utils import mse
from game_base_class import GameBase
GREEN = 1 GREEN = 1
YELLOW = 2 YELLOW = 2
@@ -30,52 +26,16 @@ CIBUTRANT = 24
ARTISENT = 25 ARTISENT = 25
class Farm: class Farm(GameBase):
def __init__(self, overlay): def __init__(self, overlay):
self.overlay = overlay super().__init__(overlay)
self.data_value_grid = np.zeros((8, 14), dtype=int)
self.data_coordinates = np.zeros((8, 14), dtype=object)
self.observation = np.zeros((8, 14), dtype=int)
self.next_level = cv.imread("farm/next_level.jpg", cv.IMREAD_COLOR) self.farm_reset_board = cv.imread("control_elements/farm_reset_button.jpg", cv.IMREAD_COLOR)
self.next_level_x = cv.imread("farm/next_level_x.jpg", cv.IMREAD_COLOR)
self.reset_board = cv.imread("farm/reset_button.jpg", cv.IMREAD_COLOR)
self.reset_confirm = cv.imread("farm/reset_confirm.jpg", cv.IMREAD_COLOR)
self.reset_counter = 0
self.explosives = []
self.explosives.append(RAINBOW)
self.explosives.append(ARROW_RIGHT)
self.explosives.append(ARROW_DOWN)
self.explosives.append(BIGBOMB)
self.explosives.append(BOMB)
self.colors = []
self.colors.append(GREEN)
self.colors.append(YELLOW)
self.colors.append(BLUE)
self.colors.append(RED)
self.colors.append(PINK) self.colors.append(PINK)
self.colors.append(MAGINENT)
self.colors.append(CHEMTRANT)
self.colors.append(TENESENT)
self.colors.append(CIBUTRANT)
self.colors.append(ARTISENT)
# 230 to 2110 = 1883 / 14 = 134.5 self.fill_data_coordinates()
# 60 to 1130 = 1076 / 8 = 134.5
dim = 134.5
for e in range(0, 8, 1):
for i in range(0, 14, 1):
self.data_coordinates[e][i] = [i * dim, e * dim, dim, dim]
# initialize the user-class
self.config = UserConfigs()
# initialize the StunWindowCapture class
self.capture_window = WindowCapture(None, None, self.config)
# initialize the StunVision class
self.vision_stun = Vision()
self.needles = {GREEN: cv.imread("farm/green.jpg", cv.IMREAD_COLOR), self.needles = {GREEN: cv.imread("farm/green.jpg", cv.IMREAD_COLOR),
YELLOW: cv.imread("farm/yellow.jpg", cv.IMREAD_COLOR), YELLOW: cv.imread("farm/yellow.jpg", cv.IMREAD_COLOR),
@@ -100,19 +60,6 @@ class Farm:
ARTISENT: cv.imread("farm/artisent.jpg", cv.IMREAD_COLOR) ARTISENT: cv.imread("farm/artisent.jpg", cv.IMREAD_COLOR)
} }
def execute_main_loop(self):
while True:
if self.overlay.run_mode == 'paused':
cv.waitKey(1)
continue
elif self.overlay.run_mode == 'stopped':
break
self.assess_playfield_and_make_move()
def reset(self):
self.observation = []
def assess_playfield_and_make_move(self): def assess_playfield_and_make_move(self):
new_observation, new_screenshot = self.get_current_board_state() new_observation, new_screenshot = self.get_current_board_state()
@@ -133,7 +80,7 @@ class Farm:
return return
elif self.reset_counter >= 3: elif self.reset_counter >= 3:
screenshot = self.capture_window.get_screenshot() screenshot = self.capture_window.get_screenshot()
if self.check_for_button_and_execute(screenshot, self.reset_board): if self.check_for_button_and_execute(screenshot, self.farm_reset_board):
cv.waitKey(500) cv.waitKey(500)
screenshot = self.capture_window.get_screenshot() screenshot = self.capture_window.get_screenshot()
if self.check_for_button_and_execute(screenshot, self.reset_confirm): if self.check_for_button_and_execute(screenshot, self.reset_confirm):
@@ -148,81 +95,38 @@ class Farm:
self.observation = new_observation self.observation = new_observation
return new_observation return new_observation
def check_for_button_and_execute(self, screen, needle, offset_left=0, offset_down=0):
rectangles = self.vision_stun.find(screen, needle, 0.70, 1)
if len(rectangles) == 0:
return False
point = self.vision_stun.get_click_points(rectangles)[0]
self.dig_point(point[0] + offset_left, point[1] + offset_down, 500)
return True
def move_to(self, x, y):
point_src = (1113, 598)
pydirectinput.moveTo(point_src[0], point_src[1])
pydirectinput.mouseDown()
w = random.randint(1, 100)
cv.waitKey(150 + w)
pydirectinput.moveTo(x, y)
pydirectinput.mouseUp()
cv.waitKey(500 + w)
def change_value(self, x, y, val):
self.data_value_grid[x][y] = val
def pointInRect(self, point):
for e in range(0, 8, 1):
for i in range(0, 14, 1):
x1, y1, w, h = self.data_coordinates[e][i]
x2, y2 = x1 + w, y1 + h
x, y = point
if x1 < x and x < x2:
if y1 < y and y < y2:
return e, i
return None, None
def check_for_next_level(self, screen, needle):
offset_left = 230
offset_down = 58
rectangles = self.vision_stun.find(screen, needle, 0.70, 1)
if len(rectangles) == 0:
return False
if self.detonate_explosive_when_stuck(self.observation):
return True
point = self.vision_stun.get_click_points(rectangles)[0]
self.dig_point(point[0] + offset_left, point[1] + offset_down, 500)
return True
def get_current_board_state(self): def get_current_board_state(self):
# get an updated image of the game # get an updated image of the game
screenshot = self.capture_window.get_screenshot() screenshot = self.capture_window.get_screenshot()
# screenshot = cv.imread("field_farm.jpg") # screenshot = cv.imread("field_farm.jpg")
screenshot = screenshot[58:1134, 230:2113] # 1883,1076 screenshot = screenshot[190:1230, 260:2090] # 1883,1076
# gray = cv.cvtColor(screenshot, cv.COLOR_BGR2GRAY) # gray = cv.cvtColor(screenshot, cv.COLOR_BGR2GRAY)
# thresh = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)[1] # thresh = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)[1]
if self.check_for_next_level(screenshot, self.next_level): if self.check_for_next_level(screenshot, self.next_level):
cv.waitKey(500) cv.waitKey(500)
screenshot = self.capture_window.get_screenshot() screenshot = self.capture_window.get_screenshot()
screenshot = screenshot[58:1134, 230:2113] screenshot = screenshot[190:1230, 260:2090]
if self.check_for_next_level(screenshot, self.next_level_x): if self.check_for_next_level(screenshot, self.next_level_x):
cv.waitKey(500) cv.waitKey(500)
screenshot = self.capture_window.get_screenshot() screenshot = self.capture_window.get_screenshot()
screenshot = screenshot[58:1134, 230:2113] screenshot = screenshot[190:1230, 260:2090]
# cv.imshow("screenshot", screenshot) #cv.imshow("screenshot", screenshot)
# cv.waitKey(150) #cv.waitKey(150)
# continue #return
#continue
data_coords = np.zeros((8, 14), dtype=object) data_coords = np.zeros((8, 14), dtype=object)
# field = Field() # field = Pickaxe_Field()
for needle_key in self.needles.keys(): for needle_key in self.needles.keys():
# gray_needle = cv.cvtColor(self.needles[needle_key], cv.COLOR_BGR2GRAY) # gray_needle = cv.cvtColor(self.needles[needle_key], cv.COLOR_BGR2GRAY)
# thresh_needle = cv.threshold(gray_needle, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)[1] # thresh_needle = cv.threshold(gray_needle, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)[1]
rectangles = self.vision_stun.find(screenshot, self.needles[needle_key], 0.70, 56) rectangles = self.vision_stun.find(screenshot, self.needles[needle_key], 0.74, 56)
if len(rectangles) == 0: if len(rectangles) == 0:
continue continue
points = self.vision_stun.get_click_points(rectangles) points = self.vision_stun.get_click_points(rectangles)
for point in points: for point in points:
x, y = self.pointInRect(point) x, y = self.point_in_rect(point)
if x is not None and y is not None: if x is not None and y is not None:
data_coords[x][y] = int(needle_key) data_coords[x][y] = int(needle_key)
# self.change_value(x, y, int(needle_key)) # self.change_value(x, y, int(needle_key))
@@ -239,23 +143,21 @@ class Farm:
if self.check_explosives(state, e, i): if self.check_explosives(state, e, i):
return return
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
for e in range(0, 8, 1): for e in range(0, 8, 1):
for i in range(0, 14, 1): for i in range(0, 14, 1):
for color in self.colors: for color in self.colors:
if self.check_5_horizontal(state, e, i, color): if self.check_5s(state, e, i, color):
return
if self.check_5_vertical(state, e, i, color):
return return
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
for e in range(0, 8, 1): for e in range(0, 8, 1):
for i in range(0, 14, 1): for i in range(0, 14, 1):
@@ -267,11 +169,11 @@ class Farm:
if self.check_3_with_gap(state, e, i, color): if self.check_3_with_gap(state, e, i, color):
return return
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
def detonate_explosive_when_stuck(self, state): def detonate_explosive_when_stuck(self, state):
for e in range(0, 8, 1): for e in range(0, 8, 1):
@@ -299,82 +201,33 @@ class Farm:
continue continue
return False return False
def check_explosives(self, state, e, i): def check_5s(self, state, e, i, color):
for explosive in self.explosives:
if self.local_pos_check(state, e, i, 0, 0, explosive):
dest_pt = self.get_click_point(self.data_coordinates[e, i])
if self.local_pos_checks(state, e, i, 1, 0, self.explosives):
src_pt = self.get_click_point(self.data_coordinates[e + 1, i])
self.move_tile(src_pt, dest_pt)
elif self.local_pos_checks(state, e, i, 0, 1, self.explosives):
src_pt = self.get_click_point(self.data_coordinates[e, i + 1])
self.move_tile(src_pt, dest_pt)
elif self.local_pos_checks(state, e, i, -1, 0, self.explosives):
src_pt = self.get_click_point(self.data_coordinates[e - 1, i])
self.move_tile(src_pt, dest_pt)
elif self.local_pos_checks(state, e, i, 0, -1, self.explosives):
src_pt = self.get_click_point(self.data_coordinates[e, i - 1])
self.move_tile(src_pt, dest_pt)
else:
continue
return True
else:
continue
return False
def local_pos_check(self, state, e, i, e_check, i_check, needle):
if e + e_check >= 0 and e + e_check <= 7 and i + i_check >= 0 and i + i_check <= 13:
if state[e + e_check, i + i_check] == needle:
return True
else:
return False
def local_pos_checks(self, state, e, i, e_check, i_check, needles):
if e + e_check >= 0 and e + e_check <= 7 and i + i_check >= 0 and i + i_check <= 13:
for needle in needles:
if state[e + e_check, i + i_check] == needle:
return True
else:
continue
return False
def check_5_horizontal(self, state, e, i, color):
try: try:
# #
if state[e, i] == color and state[e, i + 1] == color and state[e, i + 3] == color and state[ if state[e, i] == color and state[e + 1, i] == color and state[e + 3, i] == color and state[e + 4, i] == color:
e, i + 4] == color: if state[e + 2, i] in self.colors:
if state[e, i + 2] <= 0 or state[e, i + 2] >= 6: if self.is_direction_in_bounce_and_same_color(state, (e + 2, i - 1), color):
return False
#
if e - 1 >= 0 and i + 2 <= 13:
if state[e - 1, i + 2] == color:
return True
return False
except:
return False
def check_5_vertical(self, state, e, i, color):
try:
#
if state[e, i] == color and state[e + 1, i] == color and state[e + 3, i] == color and state[
e + 4, i] == color:
if state[e + 2, i] <= 0 or state[e + 2, i] >= 6:
return False
# third left upper
if e + 2 <= 7 and i - 1 >= 0:
if state[e + 2, i - 1] == color:
# print("upper left", color, e, i)
src_pt = self.get_click_point(self.data_coordinates[e + 2, i - 1]) src_pt = self.get_click_point(self.data_coordinates[e + 2, i - 1])
dest_pt = self.get_click_point(self.data_coordinates[e + 2, i]) dest_pt = self.get_click_point(self.data_coordinates[e + 2, i])
self.move_tile(src_pt, dest_pt) self.move_tile(src_pt, dest_pt)
return True return True
if e + 2 <= 7 and i + 1 <= 13: if self.is_direction_in_bounce_and_same_color(state, (e + 2, i + 1), color):
if state[e + 2, i + 1] == color:
# print("upper left", color, e, i)
src_pt = self.get_click_point(self.data_coordinates[e + 2, i + 1]) src_pt = self.get_click_point(self.data_coordinates[e + 2, i + 1])
dest_pt = self.get_click_point(self.data_coordinates[e + 2, i]) dest_pt = self.get_click_point(self.data_coordinates[e + 2, i])
self.move_tile(src_pt, dest_pt) self.move_tile(src_pt, dest_pt)
return True return True
elif state[e, i] == color and state[e, i + 1] == color and state[e, i + 3] == color and state[e, i + 4] == color:
if state[e, i + 2] in self.colors:
if self.is_direction_in_bounce_and_same_color(state, (e + 1, i +2), color):
src_pt = self.get_click_point(self.data_coordinates[e + 1, i + 2])
dest_pt = self.get_click_point(self.data_coordinates[e, i + 2])
self.move_tile(src_pt, dest_pt)
return True
if self.is_direction_in_bounce_and_same_color(state, (e - 1, i + 2), color):
src_pt = self.get_click_point(self.data_coordinates[e - 1, i + 2])
dest_pt = self.get_click_point(self.data_coordinates[e, i + 2])
self.move_tile(src_pt, dest_pt)
return True
return False return False
except: except:
return False return False
@@ -490,7 +343,7 @@ class Farm:
# third left lower # third left lower
if e + 2 <= 7 and i - 1 >= 0: if e + 2 <= 7 and i - 1 >= 0:
if state[e + 2, i - 1] == color and (state[e + 2, i] in self.colors): if state[e + 2, i - 1] == color and (state[e + 2, i] in self.colors):
print("lower left", color, e, i) # print("lower left", color, e, i)
src_pt = self.get_click_point(self.data_coordinates[e + 2, i - 1]) src_pt = self.get_click_point(self.data_coordinates[e + 2, i - 1])
dest_pt = self.get_click_point(self.data_coordinates[e + 2, i]) dest_pt = self.get_click_point(self.data_coordinates[e + 2, i])
self.move_tile(src_pt, dest_pt) self.move_tile(src_pt, dest_pt)
@@ -529,47 +382,3 @@ class Farm:
return True return True
except: except:
return False return False
def move_tile(self, point_source, point_dest):
offset_left = 230
offset_down = 58
pydirectinput.moveTo(point_source[0] + offset_left, point_source[1] + offset_down)
# pydirectinput.moveTo(0,0)
pydirectinput.mouseDown()
w = random.randint(25, 50)
cv.waitKey(100 + w)
pydirectinput.moveTo(point_dest[0] + offset_left, point_dest[1] + offset_down)
pydirectinput.mouseUp()
cv.waitKey(400 + w)
def check_for_button_and_click_it(self, button_url):
screenshot = self.capture_window.get_screenshot()
# gray = cv.cvtColor(screenshot, cv.COLOR_BGR2GRAY)
# thresh = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)[1]
# gray_needle = cv.cvtColor(cv.imread(button_url, cv.IMREAD_UNCHANGED), cv.COLOR_BGR2GRAY)
# thresh_needle = cv.threshold(gray_needle, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)[1]
needle = cv.imread(button_url, cv.IMREAD_UNCHANGED)
# rectangles = self.vision_stun.find(thresh, thresh_needle, 0.4, 1)
rectangles = self.vision_stun.find(screenshot, needle, 0.7, 1)
if len(rectangles) == 1:
pointis = self.vision_stun.get_click_points(rectangles)
for pointi in pointis:
self.dig_point(pointi[0], pointi[1], 150)
def dig_point(self, point1, point2, dig_time):
pydirectinput.moveTo(point1, point2)
cv.waitKey(dig_time)
pydirectinput.mouseDown()
w = random.randint(50, 100)
cv.waitKey(w)
pydirectinput.mouseUp()
def get_click_point(self, rectangle):
# Loop over all the rectangles
x, y, w, h = rectangle
# Determine the center position
center_x = x + int(w / 2)
center_y = y + int(h / 2)
# Save the points
return int(center_x), int(center_y)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 890 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 928 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

213
field.py Normal file
View File

@@ -0,0 +1,213 @@
#!/usr/bin/python
from copy import copy
from tetromino import Tetromino
class Field():
WIDTH = 20
HEIGHT = 20
def __init__(self, state=None):
if state:
self.state = state
else:
self.state = [[' ' for cols in range(Field.WIDTH)]
for rows in range(Field.HEIGHT)]
self.cleared_rows = 1
def __str__(self):
BAR = ' ' + '-' * (Field.WIDTH * 2 + 1) + '\n ' + \
' '.join(map(str, range(Field.WIDTH))) + '\n'
return BAR + '\n'.join([
'{:2d} |'.format(i) + ' '.join(row) + '|'
for i, row in enumerate(self.state)]) + '\n' + BAR
@staticmethod
def matrixflip(m, d):
tempm = m.copy()
if d == 'h':
for i in range(0, len(tempm), 1):
tempm[i].reverse()
elif d == 'v':
tempm.reverse()
return (tempm)
@staticmethod
def rotate_90_degree_anticlckwise(matrix):
new_matrix = []
for i in range(len(matrix[0]), 0, -1):
new_matrix.append(list(map(lambda x: x[i - 1], matrix)))
return new_matrix
@staticmethod
def rotate_90_degree_clckwise(matrix):
new_matrix = []
for i in range(len(matrix[0])):
li = list(map(lambda x: x[i], matrix))
li.reverse()
new_matrix.append(li)
return new_matrix
def reset_field(self):
self.state = [[' ' for cols in range(Field.WIDTH)]
for rows in range(Field.HEIGHT)]
def reset_half_field(self):
for row in range(int(self.HEIGHT/2)):
self.state[row] = [' ' for cols in range(Field.WIDTH)]
def rotate_state(self):
self.state = Field.rotate_90_degree_anticlckwise(self.state)
def get_line_count(self):
return self.cleared_rows
def _test_tetromino(self, tetromino, row, column):
"""
Tests to see if a tetromino can be placed at the specified row and
column. It performs the test with the bottom left corner of the
tetromino at the specified row and column.
"""
assert column >= 0
assert column + tetromino.width() <= Field.WIDTH
assert row - tetromino.height() + 1 >= 0
assert row < Field.HEIGHT
for ti, si in list(enumerate(range(row - tetromino.height() + 1,
row + 1)))[::-1]:
for tj, sj in enumerate(range(column, column + tetromino.width())):
if tetromino[ti][tj] != ' ' and self.state[si][sj] != ' ':
return False
return True
def _place_tetromino(self, tetromino, row, column):
"""
Place a tetromino at the specified row and column.
The bottom left corner of the tetromino will be placed at the specified
row and column. This function does not perform checks and will overwrite
filled spaces in the field.
"""
assert column >= 0
assert column + tetromino.width() <= Field.WIDTH
assert row - tetromino.height() + 1 >= 0
assert row < Field.HEIGHT
for ti, si in list(enumerate(range(row - tetromino.height() + 1,
row + 1)))[::-1]:
for tj, sj in enumerate(range(column, column + tetromino.width())):
if tetromino[ti][tj] != ' ':
self.state[si][sj] = tetromino[ti][tj]
def _get_tetromino_drop_row(self, tetromino, column):
"""
Given a tetromino and a column, return the row that the tetromino
would end up in if it were dropped in that column.
Assumes the leftmost column of the tetromino will be aligned with the
specified column.
"""
assert isinstance(tetromino, Tetromino)
assert column >= 0
assert column + tetromino.width() <= Field.WIDTH
last_fit = -1
for row in range(tetromino.height(), Field.HEIGHT):
if self._test_tetromino(tetromino, row, column):
last_fit = row
else:
return last_fit
return last_fit
def _line_clear(self):
"""
Checks and removes all filled lines.
"""
self.state = list(filter(lambda row: row.count(' ') != 0, self.state))
while len(self.state) < Field.HEIGHT:
self.state.insert(0, [' ' for col in range(Field.WIDTH)])
self.cleared_rows = self.cleared_rows + 1
print("cleared rows: ", self.cleared_rows)
def copy(self):
"""
Returns a shallow copy of the field.
"""
return Field([row[:] for row in self.state])
def drop(self, tetromino, column):
"""
Drops a tetromino in the specified column.
The leftmost column of the tetromino will be aligned with the specified
column.
Returns the row it was dropped in for computations.
"""
assert isinstance(tetromino, Tetromino)
assert column >= 0
assert column + tetromino.width() <= Field.WIDTH
row = self._get_tetromino_drop_row(tetromino, column)
assert row != -1
self._place_tetromino(tetromino, row, column)
self._line_clear()
return row
def check_crucial_pos_to_be_free(self):
if self.state[19][9] == ' ' and self.state[19][10] == ' ' and self.state[18][9] == ' ' and self.state[18][10] == ' ':
return True
return False
def predict_gaps_in_next_rotation(self):
tmp_state = copy(self.state)
tmp_state = Field.rotate_90_degree_anticlckwise(tmp_state)
for row in range(int(self.HEIGHT/2)):
tmp_state[row] = [' ' for cols in range(Field.WIDTH)]
return sum(
["".join([row[col] for row in tmp_state]).lstrip().count(' ')
for col in range(Field.WIDTH)])
def count_gaps(self):
"""
Check each column one by one to make sure there are no gaps in the
column.
"""
return sum(
["".join([row[col] for row in self.state]).lstrip().count(' ')
for col in range(Field.WIDTH)])
def height(self):
"""
Returns the height on the field of the highest placed tetromino on the
field.
"""
for i, row in enumerate(self.state):
if ''.join(row).strip():
return Field.HEIGHT - i
if __name__ == '__main__':
import sys
f = Field()
if len(sys.argv) > 1 and sys.argv[1] == 'sim':
from optimizer import Optimizer
i = input()
while i != 'q':
t = Tetromino.create(i)
opt = Optimizer.get_optimal_drop(f, t)
t.rotate(opt['orientation'])
f.drop(t, opt['column'])
print(f)
i = input()
t = Tetromino.JTetromino().rotate_right()
print(t)
f.drop(t, 0)
print(f)
# f.drop(Tetromino.LTetromino(), 2)
# print(f)
# f.drop(Tetromino.JTetromino().rotate_left(), 5)
# print(f)
# t = Tetromino.LTetromino().flip()
# f.drop(t, 0)
# f.drop(Tetromino.TTetromino().flip(), 0)
# f.drop(Tetromino.JTetromino(), 4)
# print(f)

49
flappy.py Normal file
View File

@@ -0,0 +1,49 @@
import cv2 as cv
import pydirectinput
from game_base_class import GameBase
from flappy_pos_discovery_thread import FlappyPosDiscovery
from keyboard_thread import KeyboardEvent
class Flappy(GameBase):
def __init__(self, overlay):
super().__init__(overlay)
self.litris_reset_board = cv.imread("control_elements/sodoku_reset_button.jpg", cv.IMREAD_COLOR)
self.flappy_pos_disc = FlappyPosDiscovery()
self.keyboard_listener = KeyboardEvent()
def assess_playfield_and_make_move(self):
#last_letter_received = time()
while True:
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
return
wait_timer = 380 + self.keyboard_listener.offset_value
self.click()
cv.waitKey(wait_timer)
'''
if self.flappy_pos_disc.next_gate_height[0] is not 0:
offset = (self.flappy_pos_disc.next_gate_height[0] + 120) - self.flappy_pos_disc.get_actual_pet_height()
if offset > 50:
self.click()
cv.waitKey(int(wait_timer -100))
print("pet_pos: ", self.flappy_pos_disc.get_actual_pet_height())
if self.flappy_pos_disc.next_gate_height[0] is not 0:
offset = (self.flappy_pos_disc.next_gate_height[0] + 120) - self.flappy_pos_disc.current_pet_height
if offset > 50:
offset = 50
elif offset < -50:
offset = -50
print(offset)
wait_timer = 380 + offset
print(wait_timer)
print("pet_pos: ", self.flappy_pos_disc.current_pet_height)
print("next gate: ", self.flappy_pos_disc.next_gate_height[0] + 120) '''
def click(self):
pydirectinput.mouseDown()
cv.waitKey(50)
pydirectinput.mouseUp()

BIN
flappy/flappy-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 716 B

BIN
flappy/flappy.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

BIN
flappy/flappy.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
flappy/gate-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
flappy/gate.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

BIN
flappy/gate.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 436 KiB

BIN
flappy/screen.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 530 KiB

View File

@@ -0,0 +1,83 @@
import threading
import cv2 as cv
from window_capture import WindowCapture
from vision import Vision
from config_file import UserConfigs
class FlappyPosDiscovery(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.config = UserConfigs()
self.capture_window = WindowCapture(None, None, self.config)
self.vision_stun = Vision()
self.needle_f = self.scale_picture(cv.imread("flappy/flappy.jpg"), 50)
self.mask_f = self.scale_picture(cv.imread("flappy/flappy-mask.png"), 50)
self.needle_g = self.scale_picture(cv.imread("flappy/gate.jpg"), 50)
self.mask_g = self.scale_picture(cv.imread("flappy/gate-mask.png"), 50)
self.run_mode = 'run'
self.current_pet_height = []
self.next_gate_height = [0,0,0]
self.offset_down = 90
self.start()
def run(self):
while self.run_mode == 'run':
screenshot_g = self.scale_picture(self.capture_window.get_screenshot_by_area([700, 1200, 1860, 90]), 50)
screenshot_f = self.scale_picture(self.capture_window.get_screenshot_by_area([200, 1250, 610, 90]), 50)
#cv.imshow("screenshot_g", screenshot_f)
#cv.waitKey(150)
rectangles_g = self.vision_stun.find(screenshot_g, self.needle_g, 0.8, 1)
rectangles_f = self.vision_stun.find(screenshot_f, self.needle_f, 0.7, 1) #, True, self.mask_f)
if len(rectangles_g) is not 0:
height = rectangles_g[0][1] + rectangles_g[0][3] + (self.offset_down /2)
if self.next_gate_height[2] is not height:
self.next_gate_height.append(height)
if len(self.next_gate_height) > 3:
self.next_gate_height.pop(0)
#pro_screen = self.vision_stun.draw_rectangles(screenshot_g, rectangles_g)
#cv.imshow("screenshot_g", pro_screen)
#cv.waitKey(150)
else:
pass
if len(rectangles_f) is not 0:
self.current_pet_height.append(rectangles_f[0][1] + rectangles_f[0][3] + self.offset_down)
if len(self.current_pet_height) > 5:
self.current_pet_height.pop(0)
#print("pet_pos: ", self.current_pet_height)
#print("next gate: ", self.next_gate_height)
def scale_picture(self, img, scale_percent):
width = int(img.shape[1] * scale_percent / 100)
height = int(img.shape[0] * scale_percent / 100)
resized_img = cv.resize(img, (width, height), interpolation=4)
gray = cv.cvtColor(resized_img, cv.COLOR_BGR2GRAY)
thresh = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)[1]
return thresh
def get_actual_pet_height(self):
return sum(self.current_pet_height) / len(self.current_pet_height)
def get_next_gate_height(self):
return self.next_gate_height

167
fruit.py Normal file
View File

@@ -0,0 +1,167 @@
import cv2 as cv
import numpy as np
from utils import mse
from game_base_class import GameBase
GREEN = 1
YELLOW = 2
RED = 3
BLUE = 4
ORANGE = 5
class Fruit(GameBase):
def __init__(self, overlay):
super().__init__(overlay)
self.data_coordinates = np.zeros((7, 11), dtype=object)
self.observation = np.zeros((7, 11), dtype=int)
self.colors = [GREEN, YELLOW, RED, BLUE, ORANGE]
self.offset_left = 390
self.offset_down = 188
self.fill_data_coordinates()
self.needles = {GREEN: cv.imread("fruit/green.jpg", cv.IMREAD_COLOR),
YELLOW: cv.imread("fruit/yellow.jpg", cv.IMREAD_COLOR),
BLUE: cv.imread("fruit/blue.jpg", cv.IMREAD_COLOR),
RED: cv.imread("fruit/red.jpg", cv.IMREAD_COLOR),
ORANGE: cv.imread("fruit/orange.jpg", cv.IMREAD_COLOR)
}
def fill_data_coordinates(self):
# 553 to 1861 = 1330 / 11 = 119
# 188 to 1022 = 1076 / 7 = 119
# 390 to 2000 = 1610 / 11 = 143
# 188 to 1210 = 1076 / 7 = 119
dim = 143
for e in range(0, 7, 1):
for i in range(0, 11, 1):
self.data_coordinates[e][i] = [i * dim, e * dim, dim, dim]
def assess_playfield_and_make_move(self):
new_observation, new_screenshot = self.get_current_board_state()
# wrong movement detection
# last board state is same as actual
if mse(new_observation, self.observation) == 0.0:
# no movement detected -> blow explosives or reset
self.reset_counter += 1
if self.reset_counter == 1:
pass
elif self.reset_counter == 2:
pass
elif self.reset_counter >= 3:
screenshot = self.capture_window.get_screenshot()
if self.check_for_button_and_execute(screenshot, self.reset_board):
cv.waitKey(500)
screenshot = self.capture_window.get_screenshot()
if self.check_for_button_and_execute(screenshot, self.reset_confirm):
cv.waitKey(500)
self.reset_counter = 0
return
else:
return
self.find_patterns_and_valid_moves(new_observation)
self.observation = new_observation
return new_observation
def get_current_board_state(self):
# get an updated image of the game
screenshot = self.capture_window.get_screenshot()
#screenshot = screenshot[900:1030, 540:1870]
# screenshot = cv.imread("field_farm.jpg")
# gray = cv.cvtColor(screenshot, cv.COLOR_BGR2GRAY)
# thresh = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)[1]
if self.check_for_button_and_execute(screenshot, self.ok_button):
cv.waitKey(500)
screenshot = self.capture_window.get_screenshot()
screenshot = screenshot[188:1210, 390:2000]
# 553 to 1861 = 1330 / 11 = 119
# 188 to 1022
#cv.imshow("screenshot", screenshot)
#cv.waitKey(150)
# continue
data_coords = np.zeros((7, 11), dtype=object)
# field = Pickaxe_Field()
for needle_key in self.needles.keys():
# gray_needle = cv.cvtColor(self.needles[needle_key], cv.COLOR_BGR2GRAY)
# thresh_needle = cv.threshold(gray_needle, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)[1]
rectangles = self.vision_stun.find(screenshot, self.needles[needle_key], 0.78, 56)
#output_image = self.vision_stun.draw_rectangles(screenshot, rectangles)
#cv.imshow("output_image", output_image)
#cv.waitKey(150)
if len(rectangles) == 0:
continue
points = self.vision_stun.get_click_points(rectangles)
for point in points:
x, y = self.point_in_rect(point)
if x is not None and y is not None:
data_coords[x][y] = int(needle_key)
# self.change_value(x, y, int(needle_key))
# print(field.data_value_grid)
# cv.circle(screenshot, points[0], 7, (0, 255, 0), -1)
# output_image = vision_stun.draw_rectangles(screenshot, rectangles)
# cv.imshow("output_image", output_image)
# cv.waitKey(150)
return data_coords, screenshot
def point_in_rect(self, point):
for e in range(0, 7, 1):
for i in range(0, 11, 1):
x1, y1, w, h = self.data_coordinates[e][i]
x2, y2 = x1 + w, y1 + h
x, y = point
if x1 < x and x < x2:
if y1 < y and y < y2:
return e, i
return None, None
def find_patterns_and_valid_moves(self, state):
for e in range(0, 7, 1):
for i in range(0, 11, 1):
if state[e, i] in self.colors:
#color in self.colors:
if self.check_pairs_h(state, e, i):
return
if self.check_pairs_v(state, e, i):
return
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
return
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
return
def check_pairs_h(self, state, e, i):
try:
#
if state[e, i] == state[e + 1, i]:
click_pt = self.get_click_point(self.data_coordinates[e, i])
self.dig_point(click_pt[0] + self.offset_left, click_pt[1] + self.offset_down, 100)
return True
return False
except:
return False
def check_pairs_v(self, state, e, i):
try:
#
if state[e, i] == state[e, i + 1]:
click_pt = self.get_click_point(self.data_coordinates[e, i])
self.dig_point(click_pt[0] + self.offset_left, click_pt[1] + self.offset_down, 100)
return True
return False
except:
return False

BIN
fruit/blue.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

BIN
fruit/green.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

BIN
fruit/orange.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

BIN
fruit/red.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

BIN
fruit/yellow.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

279
game_base_class.py Normal file
View File

@@ -0,0 +1,279 @@
import pydirectinput
import random
import cv2 as cv
import numpy as np
from window_capture import WindowCapture
from vision import Vision
from config_file import UserConfigs
from time import time
GREEN = 1
YELLOW = 2
RED = 3
BLUE = 4
PURPLE = 5
RAINBOW = 6
BIGBOMB = 7
BOMB = 8
ARROW_DOWN = 9
ARROW_RIGHT = 10
ROCK_1 = 11
ROCK_2 = 12
ROCK_3 = 13
BURGER = 14
PAB1 = 15
GOLDBAR = 16
MAGINENT = 21
CHEMTRANT = 22
TENESENT = 23
CIBUTRANT = 24
ARTISENT = 25
MINING_LARGE = True
class GameBase:
def __init__(self, overlay):
self.overlay = overlay
self.data_value_grid = np.zeros((8, 14), dtype=int)
self.data_coordinates = np.zeros((8, 14), dtype=object)
self.observation = np.zeros((8, 14), dtype=int)
self.data_score_map = np.zeros((8, 14), dtype=int)
self.explosives = [RAINBOW, ARROW_RIGHT, ARROW_DOWN, BIGBOMB, BOMB]
self.colors = [GREEN, YELLOW, RED, BLUE, MAGINENT, CHEMTRANT, TENESENT, CIBUTRANT, ARTISENT]
self.next_level = cv.imread("control_elements/next_level.jpg", cv.IMREAD_COLOR)
self.next_level_x = cv.imread("control_elements/next_level_x.jpg", cv.IMREAD_COLOR)
self.reset_board = cv.imread("control_elements/reset_button.jpg", cv.IMREAD_COLOR)
self.reset_confirm = cv.imread("control_elements/reset_confirm.jpg", cv.IMREAD_COLOR)
self.ok_button = cv.imread("control_elements/ok_button.jpg", cv.IMREAD_COLOR)
self.reset_counter = 0
self.stop_time = overlay.global_timeout_use.get()
self.breaks = overlay.hourly_breaks_use.get()
self.break_time = overlay.break_duration_use.get()
# initialize the user-class
self.config = UserConfigs()
# initialize the StunWindowCapture class
self.capture_window = WindowCapture(None, None, self.config)
# initialize the StunVision class
self.vision_stun = Vision()
def execute_main_loop(self):
start_time = time()
breaks = self.init_breaks()
while True:
self.check_breaks(start_time, breaks)
if self.overlay.run_mode == 'paused':
cv.waitKey(1)
continue
elif self.overlay.run_mode == 'stopped':
break
elif self.overlay.run_mode == 'finished':
break
self.assess_playfield_and_make_move()
cv.waitKey(500)
def init_breaks(self):
breaks = []
if int(self.breaks) == 0:
return breaks
#breaks.append(7)
for i in range(1, int(self.breaks) + 1, 1):
avr_in_sec = int(self.stop_time) * 60 * 60 / int(self.breaks)
breaks.append(random.randint(int(i * avr_in_sec * 0.60), int(i * avr_in_sec)))
return breaks
def check_breaks(self, start_time, breaks):
if int(self.stop_time) == 0:
return
if (time() - start_time) > float(self.stop_time) * 60 * 60:
self.overlay.run_mode = 'stopped'
for break_ in breaks:
elapsed = int(time() - start_time)
if elapsed > break_:
pause = random.randint(1, 3)
self.overlay.update_status_label("Break: " + str(pause) + "m")
cv.waitKey(pause * 60 * 1000)
breaks.remove(break_)
self.overlay.update_status_label("running")
def assess_playfield_and_make_move(self):
pass
#screenshot = screenshot[190:1230, 260:2090]
#[58: 1134, 230: 2113]
def fill_data_coordinates(self):
# 260 to 2090 = 1883 / 14 = 130
# 190 to 1230 = 1076 / 8 = 130
dim = 130
for e in range(0, 8, 1):
for i in range(0, 14, 1):
self.data_coordinates[e][i] = [i * dim, e * dim, dim, dim]
def check_for_button_and_execute(self, screen, needle, offset_left=0, offset_down=0):
rectangles = self.vision_stun.find(screen, needle, 0.70, 1)
if len(rectangles) == 0:
return False
point = self.vision_stun.get_click_points(rectangles)[0]
self.dig_point(point[0] + offset_left, point[1] + offset_down, 500)
return True
def check_for_next_level(self, screen, needle):
offset_left = 260
offset_down = 190
rectangles = self.vision_stun.find(screen, needle, 0.70, 1)
if len(rectangles) == 0:
return False
if self.detonate_explosive_when_stuck(self.observation):
return True
point = self.vision_stun.get_click_points(rectangles)[0]
self.dig_point(point[0] + offset_left, point[1] + offset_down, 500)
return True
def detonate_explosive_when_stuck(self, state):
for e in range(0, 8, 1):
for i in range(0, 14, 1):
for explosive in self.explosives:
if self.local_pos_check(state, e, i, 0, 0, explosive):
src_pt = self.get_click_point(self.data_coordinates[e, i])
if self.local_pos_checks(state, e, i, 1, 0, self.colors):
dest_pt = self.get_click_point(self.data_coordinates[e + 1, i])
self.move_tile(src_pt, dest_pt)
return True
elif self.local_pos_checks(state, e, i, 0, 1, self.colors):
dest_pt = self.get_click_point(self.data_coordinates[e, i + 1])
self.move_tile(src_pt, dest_pt)
return True
elif self.local_pos_checks(state, e, i, -1, 0, self.colors):
dest_pt = self.get_click_point(self.data_coordinates[e - 1, i])
self.move_tile(src_pt, dest_pt)
return True
elif self.local_pos_checks(state, e, i, 0, -1, self.colors):
dest_pt = self.get_click_point(self.data_coordinates[e, i - 1])
self.move_tile(src_pt, dest_pt)
return True
else:
continue
return False
def check_explosives(self, state, e, i):
for explosive in self.explosives:
if self.local_pos_check(state, e, i, 0, 0, explosive):
dest_pt = self.get_click_point(self.data_coordinates[e, i])
if self.local_pos_checks(state, e, i, 1, 0, self.explosives):
src_pt = self.get_click_point(self.data_coordinates[e + 1, i])
self.move_tile(src_pt, dest_pt)
elif self.local_pos_checks(state, e, i, 0, 1, self.explosives):
src_pt = self.get_click_point(self.data_coordinates[e, i + 1])
self.move_tile(src_pt, dest_pt)
elif self.local_pos_checks(state, e, i, -1, 0, self.explosives):
src_pt = self.get_click_point(self.data_coordinates[e - 1, i])
self.move_tile(src_pt, dest_pt)
elif self.local_pos_checks(state, e, i, 0, -1, self.explosives):
src_pt = self.get_click_point(self.data_coordinates[e, i - 1])
self.move_tile(src_pt, dest_pt)
else:
continue
return True
else:
continue
return False
@staticmethod
def is_direction_in_bounce_and_same_color(state, loc, color):
x, y = loc
if x <= 7 and x >= 0 and y <= 13 and y >= 0:
if state[x, y] == color:
return 1
return 0
@staticmethod
def local_pos_check(state, e, i, e_check, i_check, needle):
if e + e_check >= 0 and e + e_check <= 7 and i + i_check >= 0 and i + i_check <= 13:
if state[e + e_check, i + i_check] == needle:
return True
else:
return False
@staticmethod
def local_pos_checks(state, e, i, e_check, i_check, needles):
if e + e_check >= 0 and e + e_check <= 7 and i + i_check >= 0 and i + i_check <= 13:
for needle in needles:
if state[e + e_check, i + i_check] == needle:
return True
else:
continue
return False
@staticmethod
def get_click_point(rectangle):
# Loop over all the rectangles
x, y, w, h = rectangle
# Determine the center position
center_x = x + int(w / 2)
center_y = y + int(h / 2)
# Save the points
return int(center_x), int(center_y)
def move_tile(self, point_source, point_dest):
offset_left = 260
offset_down = 190
pydirectinput.moveTo(point_source[0] + offset_left, point_source[1] + offset_down)
# pydirectinput.moveTo(0,0)
pydirectinput.mouseDown()
w = random.randint(25, 50)
cv.waitKey(100 + w)
pydirectinput.moveTo(point_dest[0] + offset_left, point_dest[1] + offset_down)
pydirectinput.mouseUp()
cv.waitKey(400 + w)
def check_for_button_and_click_it(self, button_url):
screenshot = self.capture_window.get_screenshot()
# gray = cv.cvtColor(screenshot, cv.COLOR_BGR2GRAY)
# thresh = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)[1]
# gray_needle = cv.cvtColor(cv.imread(button_url, cv.IMREAD_UNCHANGED), cv.COLOR_BGR2GRAY)
# thresh_needle = cv.threshold(gray_needle, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)[1]
needle = cv.imread(button_url, cv.IMREAD_UNCHANGED)
# rectangles = self.vision_stun.find(thresh, thresh_needle, 0.4, 1)
rectangles = self.vision_stun.find(screenshot, needle, 0.7, 1)
if len(rectangles) == 1:
pointis = self.vision_stun.get_click_points(rectangles)
for pointi in pointis:
self.dig_point(pointi[0], pointi[1], 150)
@staticmethod
def dig_point(point1, point2, dig_time):
pydirectinput.moveTo(point1, point2)
cv.waitKey(dig_time)
pydirectinput.mouseDown()
w = random.randint(50, 100)
cv.waitKey(w)
pydirectinput.mouseUp()
@staticmethod
def move_to(x, y):
point_src = (1113, 598)
pydirectinput.moveTo(point_src[0], point_src[1])
pydirectinput.mouseDown()
w = random.randint(1, 100)
cv.waitKey(150 + w)
pydirectinput.moveTo(x, y)
pydirectinput.mouseUp()
cv.waitKey(500 + w)
def point_in_rect(self, point):
for e in range(0, 8, 1):
for i in range(0, 14, 1):
x1, y1, w, h = self.data_coordinates[e][i]
x2, y2 = x1 + w, y1 + h
x, y = point
if x1 < x and x < x2:
if y1 < y and y < y2:
return e, i
return None, None

32
keyboard_thread.py Normal file
View File

@@ -0,0 +1,32 @@
import threading
import cv2 as cv
import keyboard
class KeyboardEvent(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.run_mode = 'run'
self.offset_value = 0
self.start()
def run(self):
while self.run_mode == 'run':
if keyboard.is_pressed('up'): # if key 'q' is pressed
self.offset_value = -75
elif keyboard.is_pressed('down'):
self.offset_value = 75
elif keyboard.is_pressed('left') or keyboard.is_pressed('right'):
self.offset_value = 0
cv.waitKey(10)
def callback(self):
pass
def destroy(self):
self.destroy()
def get_run_mode(self):
return self.run_mode

235
litris.py Normal file
View File

@@ -0,0 +1,235 @@
from copy import copy
import cv2 as cv
import numpy as np
from time import time
from game_base_class import GameBase
from pynput.keyboard import Key, Controller
from field import Field
from tetromino import Tetromino
from optimizer import Optimizer
from litris_stone_id_thread import NewStoneID
class Litris(GameBase):
def __init__(self, overlay):
super().__init__(overlay)
self.keyboard = Controller()
self.offset_left = 610
self.offset_down = 40
self.field = Field()
self.litris_reset_board = cv.imread("control_elements/sodoku_reset_button.jpg", cv.IMREAD_COLOR)
self.stone_id_thread = NewStoneID()
self.move_mode = 1
self.moved_around_full = False
self.field_state_storage = {
1: self.field,
2: self.field,
3: self.field,
4: self.field
}
def reset(self):
self.field.reset_field()
self.field.cleared_rows = 1
self.move_mode = 1
self.moved_around_full = False
def assess_playfield_and_make_move(self):
last_letter_received = time()
while True:
if self.stone_id_thread.get_pick_up_status() == False:
if (time() - last_letter_received) >= 5:
self.reset()
last_letter_received = time()
self.dig_point(1500, 980, 100)
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
return
continue
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
return
cv.waitKey(25)
continue
current_letter = self.stone_id_thread.get_actual_letter()
print("current_letter: ", current_letter)
last_letter_received = time()
current_tetromino = Tetromino.create(current_letter)
if self.move_mode == 2:
current_tetromino.rotate(3)
elif self.move_mode == 3:
current_tetromino.rotate(2)
elif self.move_mode == 4:
current_tetromino.rotate(1)
opt = Optimizer.get_optimal_drop(self.field, current_tetromino)
rotation = opt['tetromino_rotation']
column = opt['tetromino_column']
print("Rota:", rotation)
print("column:", column)
current_tetromino.rotate(rotation)
offset_col = current_tetromino.get_offset_column(rotation, self.move_mode)
print("offset column:", offset_col)
self.field.drop(current_tetromino, column)
self.move_stone(column - offset_col, rotation)
self.drop_down()
print(self.field)
if self.field.get_line_count() >= 6 and self.field.height() <= 2 and self.field.check_crucial_pos_to_be_free():
if self.field.predict_gaps_in_next_rotation() <= 3:
self.field_state_storage[self.move_mode] = copy(self.field)
self.update_move_mode()
#self.field.state = self.stone_id_thread.get_current_board_state()
self.field.rotate_state()
#self.update_move_mode()
self.field.reset_half_field()
self.update_field_with_stored_edges()
#field_mem = copy(self.field)
#self.field = copy(self.field_mem)
#self.field_mem = copy(field_mem)
self.field.cleared_rows = 1
cv.waitKey(100)
self.stone_id_thread.set_pick_up_status(False)
def update_field_with_stored_edges(self):
if self.move_mode == 1 and self.moved_around_full:
state_copy = Field.rotate_90_degree_clckwise(copy(self.field_state_storage[2].state))
for i in range(11,20,1):
for e in range(0,2,1):
self.field.state[i][e] = state_copy[i][e]
elif self.move_mode == 2 and self.moved_around_full:
state_copy = Field.rotate_90_degree_clckwise(copy(self.field_state_storage[3].state))
for i in range(11,20,1):
for e in range(0,2,1):
self.field.state[i][e] = state_copy[i][e]
elif self.move_mode == 3 and self.moved_around_full:
state_copy = Field.rotate_90_degree_clckwise(copy(self.field_state_storage[4].state))
for i in range(11, 20, 1):
for e in range(0, 2, 1):
self.field.state[i][e] = state_copy[i][e]
elif self.move_mode == 4:
state_copy = Field.rotate_90_degree_clckwise(copy(self.field_state_storage[1].state))
for i in range(11,20,1):
for e in range(0,2,1):
self.field.state[i][e] = state_copy[i][e]
self.moved_around_full = True
def drop_down(self):
if self.move_mode == 1:
down = Key.down
left = Key.left
right = Key.right
elif self.move_mode == 2:
down = Key.left
left = Key.up
right = Key.down
elif self.move_mode == 3:
down = Key.up
left = Key.right
right = Key.left
elif self.move_mode == 4:
down = Key.right
left = Key.down
right = Key.up
for i in range(1, 10, 1):
self.keyboard.press(down)
self.keyboard.release(down)
print("drop down pressed:", down)
cv.waitKey(40)
def update_move_mode(self):
if self.move_mode <=3:
self.move_mode = self.move_mode + 1
elif self.move_mode == 4:
self.move_mode = 1
def move_stone(self, col_movement, rotation):
if col_movement is None:
return
if self.move_mode == 1:
down = Key.down
left = Key.left
right = Key.right
elif self.move_mode == 2:
down = Key.left
left = Key.up
right = Key.down
elif self.move_mode == 3:
down = Key.up
left = Key.right
right = Key.left
elif self.move_mode == 4:
down = Key.right
left = Key.down
right = Key.up
# Press and release space
self.keyboard.press(down)
self.keyboard.release(down)
print("direction pressed: ", down)
cv.waitKey(60)
if rotation == 3:
self.keyboard.press('e')
self.keyboard.release('e')
print("rotation 1 pressed: e")
cv.waitKey(30)
elif rotation == 2:
self.keyboard.press('e')
self.keyboard.release('e')
print("rotation 2 pressed: e 1")
cv.waitKey(30)
self.keyboard.press('e')
self.keyboard.release('e')
print("rotation 2 pressed: e 2")
cv.waitKey(30)
elif rotation == 1:
self.keyboard.press('e')
self.keyboard.release('e')
print("rotation 3 pressed: e 1")
cv.waitKey(30)
self.keyboard.press('e')
self.keyboard.release('e')
print("rotation 3 pressed: e 2")
cv.waitKey(30)
self.keyboard.press('e')
self.keyboard.release('e')
print("rotation 3 pressed: e 3")
cv.waitKey(30)
if col_movement < 0:
for i in range(0, col_movement, - 1):
self.keyboard.press(left)
self.keyboard.release(left)
print("move left 3 pressed:", left)
cv.waitKey(30)
else:
for i in range(0, col_movement, 1):
self.keyboard.press(right)
self.keyboard.release(right)
print("move right 3 pressed:", right)
cv.waitKey(30)
def point_in_rect(self, point):
for e in range(0, 20, 1):
for i in range(0, 20, 1):
x1, y1, w, h = self.data_coordinates[e][i]
x2, y2 = x1 + w, y1 + h
x, y = point
if x1 < x and x < x2:
if y1 < y and y < y2:
return e, i
return None, None

BIN
litris/A-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 B

BIN
litris/A.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
litris/A.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
litris/B-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 B

BIN
litris/B.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
litris/B.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
litris/C-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 B

BIN
litris/C.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
litris/C.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

BIN
litris/D-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 427 B

BIN
litris/D.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
litris/D.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
litris/I-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 B

BIN
litris/I.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

BIN
litris/I.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
litris/J-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 476 B

BIN
litris/J.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

BIN
litris/J.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
litris/L-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 473 B

BIN
litris/L.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

BIN
litris/L.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
litris/O-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 370 B

BIN
litris/O.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

BIN
litris/O.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
litris/S-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 553 B

BIN
litris/S.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

BIN
litris/S.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
litris/T-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 528 B

BIN
litris/T.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

BIN
litris/T.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
litris/Z-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 553 B

BIN
litris/Z.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

BIN
litris/Z.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
litris/blue_needle.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
litris/main_playfield.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 578 KiB

193
litris_stone_id_thread.py Normal file
View File

@@ -0,0 +1,193 @@
import threading
import cv2 as cv
import numpy as np
from window_capture import WindowCapture
from vision import Vision
from config_file import UserConfigs
O_FULL = [[0, 0, 0, 0], [0, 1, 1, 0], [0, 1, 1, 0], [0, 0, 0, 0]]
D_FULL = [[0, 0, 0, 0], [0, 1, 1, 0], [0, 0, 1, 0], [0, 0, 0, 0]]
L_FULL = [[0, 0, 0, 0], [0, 0, 1, 0], [1, 1, 1, 0], [0, 0, 0, 0]]
J_FULL = [[0, 0, 0, 0], [1, 1, 1, 0], [0, 0, 1, 0], [0, 0, 0, 0]]
I_FULL = [[0, 0, 0, 0], [1, 1, 1, 1], [0, 0, 0, 0], [0, 0, 0, 0]]
C_FULL = [[0, 0, 0, 0], [0, 0, 1, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
B_FULL = [[0, 0, 0, 0], [0, 1, 1, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
A_FULL = [[0, 0, 0, 0], [0, 1, 1, 1], [0, 0, 0, 0], [0, 0, 0, 0]]
S_FULL = [[0, 0, 0, 0], [0, 0, 1, 1], [0, 1, 1, 0], [0, 0, 0, 0]]
Z_FULL = [[0, 0, 0, 0], [0, 1, 1, 0], [0, 0, 1, 1], [0, 0, 0, 0]]
T_FULL = [[0, 0, 0, 0], [0, 1, 1, 1], [0, 0, 1, 0], [0, 0, 0, 0]]
class NewStoneID(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.config = UserConfigs()
self.capture_window = WindowCapture(None, None, self.config)
self.vision_stun = Vision()
self.stone_coordinates = np.zeros((4, 4), dtype=object)
self.data_coordinates = np.zeros((20, 20), dtype=object)
self.fill_data_coordinates()
self.needles = {'Q': cv.imread("litris/blue_needle.jpg", cv.IMREAD_UNCHANGED)}
self.run_mode = 'run'
self.actual_letter = ""
self.to_pick_up = False
self.start()
def run(self):
while self.run_mode == 'run':
current_stone = self.new_stone_detection()
if current_stone is None:
cv.waitKey(50)
continue
else:
current_letter = self.get_letter_for_stone(current_stone)
if current_letter is None:
continue
else:
self.actual_letter = current_letter
self.to_pick_up = True
while self.to_pick_up:
cv.waitKey(10)
self.actual_letter = ""
def get_actual_letter(self):
return self.actual_letter
def set_pick_up_status(self, status):
self.to_pick_up = status
def get_pick_up_status(self):
return self.to_pick_up
def callback(self):
pass
def destroy(self):
self.destroy()
def get_run_mode(self):
return self.run_mode
def new_stone_detection(self):
screenshot = self.capture_window.get_screenshot()
screenshot = screenshot[580:845, 1148:1412]
rectangles = self.vision_stun.find(screenshot, self.needles['Q'], 0.85, 16)
if len(rectangles) == 0:
return None
points = self.vision_stun.get_click_points(rectangles)
stone_coords = np.zeros((4, 4), dtype=object)
for point in points:
x, y = self.point_in_small_rect(point)
if x is not None and y is not None:
stone_coords[x][y] = 1
# self.change_value(x, y, int(needle_key))
# print(field.data_value_grid)
#cv.circle(screenshot, points[0], 7, (0, 255, 0), -1)
#output_image = self.vision_stun.draw_rectangles(screenshot, rectangles)
#cv.imshow("output_image", output_image)
#cv.waitKey(150)
return stone_coords
def get_letter_for_stone(self, stone):
if np.array_equal(stone, O_FULL):
return "O"
elif np.array_equal(stone, D_FULL):
return "D"
elif np.array_equal(stone, L_FULL):
return "L"
elif np.array_equal(stone, J_FULL):
return "J"
elif np.array_equal(stone, I_FULL):
return "I"
elif np.array_equal(stone, C_FULL):
return "C"
elif np.array_equal(stone, B_FULL):
return "B"
elif np.array_equal(stone, A_FULL):
return "A"
elif np.array_equal(stone, S_FULL):
return "S"
elif np.array_equal(stone, Z_FULL):
return "Z"
elif np.array_equal(stone, T_FULL):
return "T"
else:
return None
def point_in_small_rect(self, point):
for e in range(0, 4, 1):
for i in range(0, 4, 1):
x1, y1, w, h = self.stone_coordinates[e][i]
x2, y2 = x1 + w, y1 + h
x, y = point
if x1 < x and x < x2:
if y1 < y and y < y2:
return e, i
return None, None
def get_current_board_state(self):
# get an updated image of the game
screenshot = self.capture_window.get_screenshot()
#screenshot = cv.imread("litris/main_playfield.jpg")
screenshot = screenshot[40:1380, 610:1950] # 1000,1000
# cv.imshow("screenshot", screenshot)
# cv.waitKey(150)
# continue
#data_coords = np.zeros((20, 20), dtype=object)
data_coords = np.full((20, 20), ' ', dtype=object)
#field = Pickaxe_Field()
for needle_key in self.needles.keys():
#gray_needle = cv.cvtColor(self.needles[needle_key], cv.COLOR_BGR2GRAY)
#thresh_needle = cv.threshold(gray_needle, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)[1]
rectangles = self.vision_stun.find(screenshot, self.needles[needle_key], 0.8, 200)
if len(rectangles) == 0:
continue
points = self.vision_stun.get_click_points(rectangles)
for point in points:
x, y = self.point_in_rect(point)
if x is not None and y is not None:
data_coords[x][y] = needle_key
#self.change_value(x, y, int(needle_key))
# print(field.data_value_grid)
# cv.circle(screenshot, points[0], 7, (0, 255, 0), -1)
#output_image = self.vision_stun.draw_rectangles(screenshot, rectangles)
#cv.imshow("output_image", output_image)
#cv.waitKey(150)
return data_coords.tolist()
def point_in_rect(self, point):
for e in range(0, 20, 1):
for i in range(0, 20, 1):
x1, y1, w, h = self.data_coordinates[e][i]
x2, y2 = x1 + w, y1 + h
x, y = point
if x1 < x and x < x2:
if y1 < y and y < y2:
return e, i
return None, None
def fill_data_coordinates(self):
# 610 to 1950 = 1340 - 76 / 20 = 63
# 40 to 1380 = 1340 - 76 / 20 = 63
# spacing 19 * 4
dim = 63
e_spacing = 4
i_spacing = 4
for e in range(0, 4, 1):
for i in range(0, 4, 1):
self.stone_coordinates[e][i] = [(i * dim) + (i * i_spacing), (e * dim) + (e * e_spacing), dim, dim]
for e in range(0, 20, 1):
for i in range(0, 20, 1):
self.data_coordinates[e][i] = [(i * dim) + (i * i_spacing), (e * dim) + (e * e_spacing), dim, dim]

View File

@@ -1,25 +1,21 @@
import random import random
from window_capture import WindowCapture
from vision import Vision
import cv2 as cv import cv2 as cv
from hsvfilter import HsvFilter from hsvfilter import HsvFilter
from config_file import UserConfigs
import pydirectinput import pydirectinput
from game_base_class import GameBase
from window_capture import WindowCapture
from utils import dig_point
class Magic: class Magic(GameBase):
def __init__(self, overlay): def __init__(self, overlay):
self.overlay = overlay super().__init__(overlay)
self.config = UserConfigs()
self.SPAWN_COUNT = int(overlay.spawn_use.get()) self.SPAWN_COUNT = int(overlay.spawn_use.get())
self.capture_window = WindowCapture(None, "magic", self.config) self.capture_window = WindowCapture(None, "magic", self.config)
# initialize the StunVision class
self.vision_stun = Vision()
# initialize the StunOverlay class
hsv_filter_orange = HsvFilter(10, 156, 0, 17, 255, 255, 0, 0, 0, 0) hsv_filter_orange = HsvFilter(10, 156, 0, 17, 255, 255, 0, 0, 0, 0)
hsv_filter_p = HsvFilter(130, 156, 0, 179, 255, 255, 0, 0, 0, 0) hsv_filter_p = HsvFilter(130, 156, 0, 179, 255, 255, 0, 0, 0, 0)
hsv_filter_b = HsvFilter(88, 156, 0, 128, 255, 255, 0, 0, 0, 0) hsv_filter_b = HsvFilter(88, 156, 0, 128, 255, 255, 0, 0, 0, 0)
@@ -43,15 +39,7 @@ class Magic:
cv.IMREAD_UNCHANGED)) cv.IMREAD_UNCHANGED))
self.hsv_list.append(self.hsv_filter_list[key1]) self.hsv_list.append(self.hsv_filter_list[key1])
def execute_main_loop(self): def assess_playfield_and_make_move(self):
while True:
if self.overlay.run_mode == 'paused':
cv.waitKey(1)
continue
elif self.overlay.run_mode == 'stopped':
break
screenshot = self.capture_window.get_screenshot() screenshot = self.capture_window.get_screenshot()
# screenshot = cv.imread("buffbar.jpg") # screenshot = cv.imread("buffbar.jpg")
@@ -59,7 +47,7 @@ class Magic:
# cv.waitKey(150) # cv.waitKey(150)
# continue # continue
spawn_1 = self.vision_stun.find(screenshot, cv.imread("magic/spawn_1.jpg", cv.IMREAD_UNCHANGED), 0.4, 1) spawn_1 = self.vision_stun.find(screenshot, cv.imread("magic/spawn_1.jpg", cv.IMREAD_UNCHANGED), 0.25, 1) #TODO fix emitter threshold
if len(spawn_1) == 1: if len(spawn_1) == 1:
points = self.vision_stun.get_click_points(spawn_1) points = self.vision_stun.get_click_points(spawn_1)
for i in range(0, self.SPAWN_COUNT, 1): for i in range(0, self.SPAWN_COUNT, 1):
@@ -69,7 +57,7 @@ class Magic:
cv.waitKey(30 + w) cv.waitKey(30 + w)
pydirectinput.mouseUp() pydirectinput.mouseUp()
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
else: else:
spawn_0 = self.vision_stun.find(screenshot, cv.imread("magic/spawn_0.jpg", cv.IMREAD_UNCHANGED), 0.7, 1) spawn_0 = self.vision_stun.find(screenshot, cv.imread("magic/spawn_0.jpg", cv.IMREAD_UNCHANGED), 0.7, 1)
points = self.vision_stun.get_click_points(spawn_0) points = self.vision_stun.get_click_points(spawn_0)
@@ -79,12 +67,20 @@ class Magic:
cv.waitKey(500) cv.waitKey(500)
pydirectinput.mouseUp() pydirectinput.mouseUp()
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
continue return
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
# for needles in needle_list: # for needles in needle_list:
for rer in range(0, len(self.needle_list), 1): for rer in range(0, len(self.needle_list), 1):
screenshot = self.capture_window.get_screenshot_by_area(self.config.returnOKWindowPos())
rectangles = self.vision_stun.find(screenshot, self.ok_button, 0.5, 1)
if len(rectangles) == 1:
pointis = self.vision_stun.get_click_points(rectangles)
for pointi in pointis:
dig_point(pointi[0] + self.config.returnOKWindowPos()[2],
pointi[1] + self.config.returnOKWindowPos()[3], 150)
cv.waitKey(2000)
while True: while True:
screenshot = self.capture_window.get_screenshot() screenshot = self.capture_window.get_screenshot()
processed_screenshot = self.vision_stun.apply_hsv_filter(screenshot, self.hsv_list[rer]) processed_screenshot = self.vision_stun.apply_hsv_filter(screenshot, self.hsv_list[rer])
@@ -103,13 +99,13 @@ class Magic:
pydirectinput.moveTo(points[1][0], points[1][1]) pydirectinput.moveTo(points[1][0], points[1][1])
pydirectinput.mouseUp() pydirectinput.mouseUp()
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
else: else:
break break
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
needles_white = [cv.imread("magic/body_w.jpg", cv.IMREAD_UNCHANGED), needles_white = [cv.imread("magic/body_w.jpg", cv.IMREAD_UNCHANGED),
cv.imread("magic/finding_w.jpg", cv.IMREAD_UNCHANGED), cv.imread("magic/finding_w.jpg", cv.IMREAD_UNCHANGED),
@@ -150,6 +146,6 @@ class Magic:
pydirectinput.mouseUp() pydirectinput.mouseUp()
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
break return

144
menti_dic Normal file
View File

@@ -0,0 +1,144 @@
HIT
IT
HI
POT
TOP
TO
HAS
ASH
HA
AS
AH
NOW
NO
ON
OWN
WON
WHEN
NEW
HE
WE
FORM
OR
OF
FROM
FOR
HIST
HIS
HITS
THIS
SIT
ITS
FIND
IF
FIN
IN
BEST
BET
SET
BE
HAT
NAT
TAN
ANT
AN
THAN
RACE
ACE
ACER
CARE
ERA
ARC
CAR
EAR
TEA
LATE
LET
ATE
EAT
TALE
HIRE
TIRE
THEIR
TIE
TIER
TAB
BOAT
BUT
OUT
ABOUT
AUTO
HER
HERO
OTHER
TOE
HOT
RICE
PRICE
RIP
PIE
RIPE
ICE
FIRST
FIST
SIR
FIT
FITS
SAT
TASTE
STATE
SEA
EAST
TEST
MAIL
EMAIL
MALE
LIE
AIM
MILE
FEAR
ART
RATE
AFTER
FAR
ARE
DEAF
FACE
CAFE
FED
FACED
INK
LINK
LINKS
SIN
SKIN
SKI
HERO

185
menti_words.py Normal file
View File

@@ -0,0 +1,185 @@
import cv2 as cv
import numpy as np
import pydirectinput
from nltk.corpus import words
from pytesseract import pytesseract
import utils
from utils import mse
from game_base_class import GameBase
import random
GREEN = 1
YELLOW = 2
RED = 3
BLUE = 4
ORANGE = 5
class MentiWords(GameBase):
def __init__(self, overlay):
super().__init__(overlay)
pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'
self.observation = np.zeros((9, 9), dtype=int)
self.colors = [1, 2, 3, 4, 5, 6, 7, 8, 9]
self.offset_left = 1080
self.offset_down = 870
self.menti_play_button = cv.imread("control_elements/play.jpg", cv.IMREAD_COLOR)
self.needles = {
'A': cv.imread("menti_words/a.jpg", cv.IMREAD_COLOR),
'B': cv.imread("menti_words/b.jpg", cv.IMREAD_COLOR),
'C': cv.imread("menti_words/c.jpg", cv.IMREAD_COLOR),
'D': cv.imread("menti_words/d.jpg", cv.IMREAD_COLOR),
'E': cv.imread("menti_words/e.jpg", cv.IMREAD_COLOR),
'F': cv.imread("menti_words/f.jpg", cv.IMREAD_COLOR),
'H': cv.imread("menti_words/h.jpg", cv.IMREAD_COLOR),
'I': cv.imread("menti_words/i.jpg", cv.IMREAD_COLOR),
'L': cv.imread("menti_words/l.jpg", cv.IMREAD_COLOR),
'M': cv.imread("menti_words/m.jpg", cv.IMREAD_COLOR),
'N': cv.imread("menti_words/n.jpg", cv.IMREAD_COLOR),
'O': cv.imread("menti_words/o.jpg", cv.IMREAD_COLOR),
'P': cv.imread("menti_words/p.jpg", cv.IMREAD_COLOR),
'R': cv.imread("menti_words/r.jpg", cv.IMREAD_COLOR),
'S': cv.imread("menti_words/s.jpg", cv.IMREAD_COLOR),
'T': cv.imread("menti_words/t.jpg", cv.IMREAD_COLOR),
'U': cv.imread("menti_words/u.jpg", cv.IMREAD_COLOR),
'W': cv.imread("menti_words/w.jpg", cv.IMREAD_COLOR)
}
self.masks = {
'A': cv.imread("menti_words/a-mask.png", cv.IMREAD_COLOR),
'B': cv.imread("menti_words/b-mask.png", cv.IMREAD_COLOR),
'C': cv.imread("menti_words/c-mask.png", cv.IMREAD_COLOR),
'D': cv.imread("menti_words/d-mask.png", cv.IMREAD_COLOR),
'E': cv.imread("menti_words/e-mask.png", cv.IMREAD_COLOR),
'F': cv.imread("menti_words/f-mask.png", cv.IMREAD_COLOR),
'H': cv.imread("menti_words/h-mask.png", cv.IMREAD_COLOR),
'I': cv.imread("menti_words/i-mask.png", cv.IMREAD_COLOR),
'L': cv.imread("menti_words/l-mask.png", cv.IMREAD_COLOR),
'M': cv.imread("menti_words/m-mask.png", cv.IMREAD_COLOR),
'N': cv.imread("menti_words/n-mask.png", cv.IMREAD_COLOR),
'O': cv.imread("menti_words/o-mask.png", cv.IMREAD_COLOR),
'P': cv.imread("menti_words/p-mask.png", cv.IMREAD_COLOR),
'R': cv.imread("menti_words/r-mask.png", cv.IMREAD_COLOR),
'S': cv.imread("menti_words/s-mask.png", cv.IMREAD_COLOR),
'T': cv.imread("menti_words/t-mask.png", cv.IMREAD_COLOR),
'U': cv.imread("menti_words/u-mask.png", cv.IMREAD_COLOR),
'W': cv.imread("menti_words/w-mask.png", cv.IMREAD_COLOR)
}
self.current_letters = []
self.letter_coords = {}
with open("menti_dic") as file:
self.word_list = [line.rstrip() for line in file]
#self.word_list2 = words.words()
def reset_lists(self):
self.current_letters = []
self.letter_coords = {}
def assess_playfield_and_make_move(self):
if self.check_for_button_and_execute(self.capture_window.get_screenshot(), self.menti_play_button):
cv.waitKey(2000)
self.reset_lists()
self.get_current_board_state()
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
return
matches = self.possible_words(self.word_list, self.current_letters)
matches.sort()
new_matches = list(map(list,matches))
for letter_list in new_matches:
self.type_word_into_ui(letter_list)
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
return
def type_word_into_ui(self, letters):
for letter in letters:
pydirectinput.moveTo(self.letter_coords[letter][0] + self.offset_left, self.letter_coords[letter][1] + self.offset_down)
pydirectinput.mouseDown()
w = random.randint(25, 50)
cv.waitKey(100 + w)
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
return
pydirectinput.mouseUp()
cv.waitKey(400)
def get_current_board_state(self):
#screenshot = cv.imread("menti_words/screenshot.jpg")
screenshot = self.capture_window.get_screenshot()
screenshot = utils.scale_screenshot(screenshot[870:1270, 1080:1480], 200, False)
#cv.imshow("screenshot", screenshot)
#cv.waitKey(150)
#continue
for needle_key in self.needles.keys():
# gray_needle = cv.cvtColor(self.needles[needle_key], cv.COLOR_BGR2GRAY)
# thresh_needle = cv.threshold(gray_needle, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)[1]
thresh_needle = utils.scale_screenshot(self.needles[needle_key], 200, False)
rectangles = self.vision_stun.find(screenshot, thresh_needle , 0.85, 2)
#rectangles = self.vision_stun.find(screenshot, self.needles[needle_key], 0.95, 1 ,True, self.masks[needle_key])
if len(rectangles) == 0:
continue
points = self.vision_stun.get_click_points(rectangles)
for point in points:
self.current_letters.append(needle_key)
self.letter_coords[needle_key] = (int(point[0]/2), int(point[1]/2))
'''
cropped1 = self.vision_stun.draw_display_picture(screenshot, rectangles, 10)
#cropped1 = utils.scale_screenshot(cropped1)
cv.imshow("cropped1", cropped1)
cv.waitKey(150)
text_1 = pytesseract.image_to_string(cropped1, lang='eng', config='--psm 6').strip()
if str.isalpha(text_1):
#cv.imshow("cropped1", cropped1)
#cv.waitKey(150)
points = self.vision_stun.get_click_points(rectangles)
self.current_letters.append(text_1)
self.letter_coords[text_1] = points[0]'''
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
return
def possible_words(self, lwords, charSet):
lst = []
for word in lwords:
if len(word) <= 1:
continue
flag = 1
chars = self.charCount(word)
for key in chars:
if key not in charSet:
flag = 0
else:
if charSet.count(key) != chars[key]:
flag = 0
if flag == 1:
lst.append(word)
#print(word)
return list(set(lst))
def charCount(self, word):
dict = {}
for i in word:
dict[i] = dict.get(i, 0) + 1
return dict

BIN
menti_words/a-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 B

BIN
menti_words/a.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
menti_words/a.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
menti_words/b-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 B

BIN
menti_words/b.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
menti_words/b.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
menti_words/c-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

BIN
menti_words/c.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
menti_words/c.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
menti_words/d-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 B

BIN
menti_words/d.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
menti_words/d.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
menti_words/e-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

Some files were not shown because too many files have changed in this diff Show More