1+ import logging
2+ import itertools
3+ from JoycontrolPlugin import JoycontrolPlugin , JoycontrolPluginError
4+
5+ logger = logging .getLogger (__name__ )
6+
7+ class Keypad :
8+ def __init__ (self ):
9+ self .keypad = [
10+ [1 , 2 , 3 ],
11+ [4 , 5 , 6 ],
12+ [7 , 8 , 9 ],
13+ [- 1 ,0 ,- 1 ],
14+ ]
15+
16+
17+ def __num2pos (self , num : int ):
18+ max_x = len (self .keypad [0 ])
19+ max_y = len (self .keypad )
20+ for x , y in itertools .product (range (max_x ), range (max_y )):
21+ if self .keypad [y ][x ] == num :
22+ return {'x' :x , 'y' :y }
23+ return None
24+
25+
26+ def shortest_path (self , current_num : int , target_num : int ):
27+ current_pos = self .__num2pos (current_num )
28+ target_pos = self .__num2pos (target_num )
29+ max_x = len (self .keypad [0 ])
30+ max_y = len (self .keypad )
31+
32+ path = []
33+ while True :
34+ x = current_pos ['x' ]
35+ y = current_pos ['y' ]
36+ diff_x = target_pos ['x' ] - current_pos ['x' ]
37+ diff_y = target_pos ['y' ] - current_pos ['y' ]
38+
39+ if diff_x == diff_y == 0 :
40+ break
41+
42+ if diff_x > 0 and 0 <= x + 1 < max_x and self .keypad [y ][x + 1 ] != - 1 :
43+ path .append ('right' )
44+ current_pos ['x' ] += 1
45+ elif diff_x < 0 and 0 <= x - 1 < max_x and self .keypad [y ][x - 1 ] != - 1 :
46+ path .append ('left' )
47+ current_pos ['x' ] -= 1
48+ elif diff_y > 0 and 0 <= y + 1 < max_y and self .keypad [y + 1 ][x ] != - 1 :
49+ path .append ('down' )
50+ current_pos ['y' ] += 1
51+ elif diff_y < 0 and 0 <= y - 1 < max_y and self .keypad [y - 1 ][x ] != - 1 :
52+ path .append ('up' )
53+ current_pos ['y' ] -= 1
54+ return path
55+
56+
57+ class DistributeRaid (JoycontrolPlugin ):
58+ def __init__ (self , controller_state , options ):
59+ super ().__init__ (controller_state , options )
60+
61+ usage = 'Please use "--plugin-options <link_code> [backup]".'
62+
63+ if options is None :
64+ raise JoycontrolPluginError (f'Plugin option is not set. { usage } ' )
65+
66+ self .link_code = options [0 ] # require option
67+ self .backup_mode = False # default
68+
69+ if not self .link_code .isdecimal () or len (self .link_code ) != 8 :
70+ raise ValueError (f'Invalid link code ({ self .link_code } ). { usage } ' )
71+
72+ if len (options ) >= 2 :
73+ if options [1 ] != 'backup' :
74+ raise ValueError (f'Invalid backup mode ({ options [1 ]} ). { usage } ' )
75+ self .backup_mode = True
76+
77+
78+ async def push_linkcode (self , link_code ):
79+ keypad = Keypad ()
80+ current_num = 1 # init position
81+
82+ for num in link_code :
83+ target_num = int (num )
84+ path = keypad .shortest_path (current_num , target_num )
85+ current_num = target_num
86+
87+ # Move to target number
88+ for button in path :
89+ await self .button_push (button )
90+ await self .wait (0.5 )
91+
92+ # Push a number
93+ await self .button_push ('a' )
94+ await self .wait (0.5 )
95+
96+
97+ async def distribute_raid (self ):
98+ count = 0
99+ while True :
100+ # Start the game
101+ await self .button_push ('a' )
102+ await self .wait (1 )
103+ await self .button_push ('a' )
104+ await self .wait (20 )
105+
106+ if self .backup_mode :
107+ # Boot from backup
108+ await self .button_push ('up' , 'x' , 'b' )
109+ await self .wait (3 )
110+ await self .button_push ('a' )
111+ await self .wait (2 )
112+
113+ await self .button_push ('a' )
114+ await self .wait (10 )
115+
116+ # Connect to the Internet
117+ await self .button_push ('y' )
118+ await self .wait (1 )
119+ await self .button_push ('plus' )
120+ await self .wait (20 )
121+ await self .button_push ('b' )
122+ await self .wait (0.5 )
123+ await self .button_push ('b' )
124+ await self .wait (0.5 )
125+
126+ # Examine a den
127+ await self .button_push ('a' )
128+ await self .wait (4 )
129+
130+ # Set the link code
131+ await self .button_push ('plus' )
132+ await self .wait (1 )
133+ await self .push_linkcode (self .link_code )
134+ await self .button_push ('plus' )
135+ await self .wait (1 )
136+ await self .button_push ('a' )
137+ await self .wait (1 )
138+
139+ # Waiting for connection
140+ await self .button_push ('a' )
141+ await self .wait (60 )
142+
143+ # Start the battle
144+ await self .button_push ('up' )
145+ await self .wait (0.5 )
146+ await self .button_push ('a' )
147+ await self .wait (0.7 )
148+ await self .button_push ('a' )
149+ await self .wait (0.7 )
150+ await self .button_push ('a' )
151+ await self .wait (0.7 )
152+ await self .button_push ('a' )
153+ await self .wait (15 )
154+
155+ # Exit the game
156+ await self .button_push ('home' )
157+ await self .wait (1.5 )
158+ await self .button_push ('x' )
159+ await self .wait (0.5 )
160+ await self .button_push ('a' )
161+ await self .wait (5 )
162+
163+ count += 1
164+ logger .info (str (count ) + 'cycle finished.' )
165+
166+
167+ async def run (self ):
168+ logger .info ('Distribute Raid Plugin loaded!' )
169+ await self .distribute_raid ()
0 commit comments