@@ -15,6 +15,12 @@ static void set_text_speed(bool fast_speed, bool save);
1515static void use_wishing_piece_and_pause (void );
1616static void restart_game (void );
1717static void change_raid (void );
18+ static void auto_breeding (void );
19+ static void reposition_player (bool first_time );
20+ static void go_to_nursery_helper (void );
21+ static void get_egg (void );
22+ static void move_in_circles (uint16_t cycles , bool go_up_first );
23+ static bool hatch_egg (void );
1824
1925int main (void )
2026{
@@ -39,7 +45,6 @@ int main(void)
3945 _delay_ms (100 );
4046 }
4147
42-
4348 switch (count ) {
4449 case 1 :
4550 temporary_control ();
@@ -53,6 +58,10 @@ int main(void)
5358 max_raid ();
5459 break ;
5560
61+ case 4 :
62+ auto_breeding ();
63+ break ;
64+
5665 default :
5766 /* Wrong selection */
5867 delay (100 , 200 , 1500 );
@@ -369,3 +378,251 @@ void change_raid(void)
369378 { BT_NONE , DP_NEUTRAL , SEQ_HOLD , 25 }, /* Wait */
370379 );
371380}
381+
382+
383+ /*
384+ * Automatically get Eggs from the Bridge Field Pokémon Nursery and hatch them.
385+ */
386+ void auto_breeding (void )
387+ {
388+ /* Hatching time for each Egg cycles */
389+ const struct {
390+ uint16_t hatch_time ; /* Time passed spinning for the Egg to hatch */
391+ uint16_t wait_time ; /* Time passed spinning to get another Egg */
392+ } egg_cycles [] = {
393+ { 350 , 150 }, /* 5 Egg cycles, approx. 64 Eggs/hour */
394+ { 560 , 0 }, /* 10 Egg cycles, approx. 60 Eggs/hour */
395+ { 1100 , 0 }, /* 15 Egg cycles, approx. 50 Eggs/hour */
396+ { 1400 , 0 }, /* 20 Egg cycles, approx. 40 Eggs/hour */
397+ { 1750 , 0 }, /* 25 Egg cycles, approx. 33 Eggs/hour */
398+ { 2050 , 0 }, /* 30 Egg cycles, approx. 30 Eggs/hour */
399+ { 2400 , 0 }, /* 35 Egg cycles, approx. 24 Eggs/hour */
400+ { 2700 , 0 }, /* 40 Egg cycles, approx. 22 Eggs/hour */
401+ };
402+
403+ /* Note that the automation is mashing B while on the bike, so its speed is irregular.
404+ This explains while the spin time is not linear compared to the Egg cycles. */
405+
406+ /* Select the egg cycle */
407+ uint16_t hatch_time ;
408+ uint16_t wait_time ;
409+
410+ for (;;) {
411+ uint8_t cycle_idx = count_button_presses (500 , 500 ) - 1 ;
412+
413+ if (cycle_idx < (sizeof (egg_cycles ) / sizeof (* egg_cycles ))) {
414+ /* Selection OK, beep once per press */
415+ for (uint8_t i = 0 ; i <= cycle_idx ; i += 1 ) {
416+ beep ();
417+ _delay_ms (200 );
418+ }
419+
420+ hatch_time = egg_cycles [cycle_idx ].hatch_time ;
421+ wait_time = egg_cycles [cycle_idx ].wait_time ;
422+
423+ break ;
424+ }
425+
426+ /* Wrong selection */
427+ delay (100 , 200 , 1500 );
428+ }
429+
430+ /* FIXME: Find a way to ensure the player character is on their bike instead of just
431+ toggling the state. For now, just require the player to start on the bike. */
432+ #ifdef PUT_PLAYER_ON_BIKE
433+ SEND_BUTTON_SEQUENCE (KEEP_LEDS ,
434+ { BT_P , DP_NEUTRAL , SEQ_HOLD , 1 }, /* Get on bike */
435+ { BT_NONE , DP_NEUTRAL , SEQ_HOLD , 25 }, /* Wait for bike animation to finish */
436+ );
437+ #endif
438+
439+ reposition_player (/* first_time */ true);
440+ go_to_nursery_helper ();
441+
442+ /* We do not known if an egg is already available, so we just spin the first time */
443+ move_in_circles (hatch_time + wait_time , /* go_up_first */ true);
444+
445+ for (;;) {
446+ reposition_player (/* first_time */ false);
447+ go_to_nursery_helper ();
448+ get_egg ();
449+ move_in_circles (hatch_time , /* go_up_first */ true);
450+
451+ if (hatch_egg ()) {
452+ /* Operation stopped by the user */
453+ break ;
454+ }
455+
456+ if (wait_time ) {
457+ move_in_circles (wait_time , /* go_up_first */ false);
458+ }
459+ }
460+
461+ /* Give temporary control before returning to the menu */
462+ temporary_control ();
463+ }
464+
465+
466+ /*
467+ * Use the Flying Taxi to warp to the current position (the nursery) to reposition the
468+ * player.
469+ *
470+ * first_time must be true the first time this function is called; it will then put the
471+ * X menu’s cursor on the Map icon. It will also set the text speed to Fast.
472+ */
473+ void reposition_player (bool first_time )
474+ {
475+ /* Uses held A button to makes the text go faster. */
476+
477+ set_leds (NO_LEDS );
478+
479+ if (first_time ) {
480+ SEND_BUTTON_SEQUENCE (KEEP_LEDS ,
481+ { BT_X , DP_NEUTRAL , SEQ_HOLD , 1 }, /* Open menu */
482+ { BT_NONE , DP_NEUTRAL , SEQ_HOLD , 25 }, /* Wait for menu */
483+ { BT_NONE , DP_TOPLEFT , SEQ_HOLD , 25 }, /* Move to top/left position */
484+ { BT_NONE , DP_NEUTRAL , SEQ_HOLD , 1 }, /* Release the buttons */
485+
486+ { BT_NONE , DP_BOTTOM , SEQ_MASH , 1 }, /* Move to Map position */
487+ { BT_NONE , DP_LEFT , SEQ_MASH , 1 }, /* Move to Parameters position */
488+
489+ { BT_A , DP_NEUTRAL , SEQ_HOLD , 1 }, /* Enter Parameters */
490+ { BT_NONE , DP_NEUTRAL , SEQ_HOLD , 26 }, /* Wait for menu */
491+
492+ { BT_NONE , DP_RIGHT , SEQ_MASH , 2 }, /* Select speed */
493+
494+ { BT_A , DP_NEUTRAL , SEQ_HOLD , 10 }, /* Validate parameters */
495+ { BT_NONE , DP_NEUTRAL , SEQ_HOLD , 1 }, /* Release A to advance */
496+ { BT_A , DP_NEUTRAL , SEQ_HOLD , 10 }, /* Validate parameters */
497+ { BT_NONE , DP_NEUTRAL , SEQ_HOLD , 1 }, /* Release A to advance */
498+ { BT_A , DP_NEUTRAL , SEQ_MASH , 1 }, /* Validate dialog */
499+ { BT_NONE , DP_NEUTRAL , SEQ_HOLD , 25 }, /* Wait for menu */
500+
501+ { BT_NONE , DP_RIGHT , SEQ_MASH , 1 }, /* Move to Map position */
502+ );
503+ } else {
504+ SEND_BUTTON_SEQUENCE (KEEP_LEDS ,
505+ { BT_X , DP_NEUTRAL , SEQ_HOLD , 1 }, /* Open menu */
506+ { BT_NONE , DP_NEUTRAL , SEQ_HOLD , 25 }, /* Wait for menu */
507+ );
508+ }
509+
510+ SEND_BUTTON_SEQUENCE (KEEP_LEDS ,
511+ { BT_A , DP_NEUTRAL , SEQ_HOLD , 1 }, /* Open map */
512+ { BT_NONE , DP_NEUTRAL , SEQ_HOLD , 55 }, /* Wait for map */
513+ { BT_A , DP_NEUTRAL , SEQ_HOLD , 15 }, /* Warp? */
514+ { BT_NONE , DP_NEUTRAL , SEQ_HOLD , 1 }, /* Release A */
515+ { BT_A , DP_NEUTRAL , SEQ_HOLD , 1 }, /* Accept */
516+ { BT_NONE , DP_NEUTRAL , SEQ_HOLD , 60 }, /* Wait for warp to complete */
517+ );
518+ }
519+
520+
521+ /*
522+ * Go in front of the nursery helper.
523+ * reposition_player must be called first.
524+ */
525+ void go_to_nursery_helper (void )
526+ {
527+ set_leds (TX_LED );
528+
529+ send_update (BT_NONE , DP_NEUTRAL , S_SCALED (S_BOTLEFT , 25 ), S_NEUTRAL );
530+
531+ for (uint8_t i = 0 ; i < 21 ; i += 1 ) {
532+ send_update (BT_NONE , DP_NEUTRAL , S_BOTTOM , S_NEUTRAL );
533+ }
534+
535+ send_update (BT_NONE , DP_NEUTRAL , S_RIGHT , S_NEUTRAL );
536+ send_update (BT_NONE , DP_NEUTRAL , S_RIGHT , S_NEUTRAL );
537+
538+ /* Reset the sticks and wait for the player to be standing still */
539+ pause_automation ();
540+ _delay_ms (400 );
541+ }
542+
543+
544+ /*
545+ * Get an Egg from the nursery helper.
546+ * go_to_nursery_helper must be called first.
547+ */
548+ void get_egg (void )
549+ {
550+ SEND_BUTTON_SEQUENCE (KEEP_LEDS ,
551+ { BT_NONE , DP_NEUTRAL , SEQ_HOLD , 10 }, /* Wait after movement */
552+ { BT_A , DP_NEUTRAL , SEQ_HOLD , 15 }, /* Open “accept egg” dialog */
553+ { BT_NONE , DP_NEUTRAL , SEQ_HOLD , 1 }, /* Release A */
554+ { BT_A , DP_NEUTRAL , SEQ_HOLD , 1 }, /* Accept egg */
555+ { BT_NONE , DP_NEUTRAL , SEQ_HOLD , 75 }, /* Wait for dialog */
556+ { BT_A , DP_NEUTRAL , SEQ_HOLD , 1 }, /* Open “what do you want” dialog */
557+ { BT_NONE , DP_NEUTRAL , SEQ_HOLD , 50 }, /* Wait for dialog */
558+ { BT_A , DP_NEUTRAL , SEQ_HOLD , 20 }, /* Choose “include in team” */
559+ { BT_NONE , DP_NEUTRAL , SEQ_HOLD , 1 }, /* Release A */
560+ { BT_A , DP_NEUTRAL , SEQ_HOLD , 1 }, /* Open team dialog */
561+ { BT_NONE , DP_NEUTRAL , SEQ_HOLD , 45 }, /* Wait for dialog */
562+ { BT_NONE , DP_BOTTOM , SEQ_MASH , 1 }, /* Go to second Pokémon */
563+ { BT_A , DP_BOTTOM , SEQ_HOLD , 65 }, /* Select second Pokémon */
564+ { BT_NONE , DP_NEUTRAL , SEQ_HOLD , 1 }, /* Release A */
565+ { BT_A , DP_BOTTOM , SEQ_HOLD , 35 }, /* Validate “… sent to box” dialog */
566+ { BT_NONE , DP_NEUTRAL , SEQ_HOLD , 1 }, /* Release A */
567+ { BT_A , DP_BOTTOM , SEQ_MASH , 1 }, /* Validate “Take care” dialog */
568+ { BT_NONE , DP_NEUTRAL , SEQ_HOLD , 25 }, /* Wait for dialog to close */
569+ );
570+ }
571+
572+ /*
573+ * Move in circle for the specified number of cycles.
574+ * go_to_nursery_helper must be called first for correct positioning.
575+ */
576+ void move_in_circles (uint16_t cycles , bool go_up_first )
577+ {
578+ set_leds (RX_LED );
579+
580+ if (go_up_first ) {
581+ send_update (BT_NONE , DP_NEUTRAL , S_SCALED (S_TOP , 25 ), S_NEUTRAL );
582+
583+ for (uint8_t i = 0 ; i < 10 ; i += 1 ) {
584+ send_update (BT_NONE , DP_NEUTRAL , S_TOP , S_NEUTRAL );
585+ send_update (BT_B , DP_NEUTRAL , S_TOP , S_NEUTRAL );
586+ }
587+
588+ for (uint8_t i = 0 ; i < 50 ; i += 1 ) {
589+ send_update (BT_NONE , DP_NEUTRAL , S_TOPRIGHT , S_NEUTRAL );
590+ }
591+ }
592+
593+ for (uint16_t i = 0 ; i < (cycles / 2 ) ; i += 1 ) {
594+ send_update (BT_NONE , DP_NEUTRAL , S_RIGHT , S_LEFT );
595+ send_update (BT_B , DP_NEUTRAL , S_RIGHT , S_LEFT );
596+ }
597+
598+ /* Reset sticks position */
599+ pause_automation ();
600+ }
601+
602+
603+ /*
604+ * Hatch an egg. The “What?” dialog must be shown on screen.
605+ * Returns true if the process was interrupted by the user.
606+ */
607+ bool hatch_egg (void )
608+ {
609+ set_leds (BOTH_LEDS );
610+
611+ SEND_BUTTON_SEQUENCE (KEEP_LEDS ,
612+ { BT_A , DP_NEUTRAL , SEQ_MASH , 1 }, /* Validate “What?” dialog */
613+ )
614+
615+ /* Egg hatching animation */
616+ if (delay (250 , 250 , 12500 )) {
617+ return true;
618+ }
619+
620+ SEND_BUTTON_SEQUENCE (KEEP_LEDS ,
621+ { BT_A , DP_NEUTRAL , SEQ_HOLD , 25 }, /* Speed up egg dialog text */
622+ { BT_NONE , DP_NEUTRAL , SEQ_HOLD , 1 }, /* Release A */
623+ { BT_A , DP_NEUTRAL , SEQ_HOLD , 1 }, /* Validate egg dialog */
624+ { BT_NONE , DP_NEUTRAL , SEQ_HOLD , 80 }, /* Wait for fadeout */
625+ )
626+
627+ return false;
628+ }
0 commit comments