From f76086f4d51b27e7a0409bda4af51dc804836c39 Mon Sep 17 00:00:00 2001 From: gelakinetic Date: Mon, 2 Dec 2024 10:09:08 -0500 Subject: [PATCH] Uttt pass and play (#334) #328 Add UTTT pass-and-play --- assets/ultimateTTT/sq_bl.png | Bin 552 -> 905 bytes assets/ultimateTTT/sq_bs.png | Bin 339 -> 346 bytes assets/ultimateTTT/sq_rl.png | Bin 553 -> 898 bytes assets/ultimateTTT/sq_rs.png | Bin 341 -> 343 bytes main/modes/games/ultimateTTT/ultimateTTT.c | 45 +++++++----- main/modes/games/ultimateTTT/ultimateTTT.h | 3 +- .../modes/games/ultimateTTT/ultimateTTTgame.c | 64 +++++++++++++----- .../games/ultimateTTT/ultimateTTTresult.c | 18 ++++- 8 files changed, 96 insertions(+), 34 deletions(-) diff --git a/assets/ultimateTTT/sq_bl.png b/assets/ultimateTTT/sq_bl.png index de378c2d178628e3e33c776a2adbf8d46b18a2cb..649fb8813e7129b547925a9c328a8efad236b7ea 100644 GIT binary patch delta 859 zcmV-h1El<@1c?Wb7#;`)0002v3F)u^000SaNLh0L04;a`04;a{bPeYjkwzzf0~Sd{ zK~#90?VQVQ#UKnsq3ZwtGF?TA(wpGN%-E?q%c=o$E;u%r%(d3|mrq~S2E0+<)dn1z zbC{<5T4SiQ8J%U2>4k|l{D8zKX2xw}5Sk*S9p?QpzgaZP5QqVd_@l4yO&|0KC26$dO!wLHv zfQ@0Z!|M-22|EKAb2+UwCNg$(FHa;eb=-xr9SY6dDIsG(^=)a#<U(vob-e}x{Qv$ciA~s)V9dA8bSd8&kf zT@EcX2-R%6_EQdxrRcVQxaI$3(C%i%&d^ML%F-jWZpL;Ie5Ns%MHfkZ+Ag>}!|S*# z549;&KGYS|S(FoYbmCkUTHI+1t-36Vv7eU}&8Jy*G&6wV#FfH0Dv=r?#TDplmQhLv)xu{HSn$6QBBY%`}7`i3}c5 zMuqf&(2T%SKk??BT(?hCAIw_BdKp1$IXZ#M0*ly6%Lu#&z0p2cZ9l=LoUot87#OPJ zF`U;bulbCTypsgH!jn35zCyb;#;gHjwViEu3w#I7YQ)YEmDs?>xcIbP0m@F5iM_Hi z5>nlLRzUrh7*NXA$ zrR&9Q`(8R7FO#pZ%Lih4O0#VK^fs2R^|%dzPru6 zq}=|VaqQo3$D8**{U!I#>v0>4xyla3gS?!19tF-#(n5D8JU|h$J0Wvvhhi^xW|T*Q zVqwjwV?cd>+MnVM*qTkE30kKZ=UDz|&PX}15@ zcSVcK=UiM7V4@|`%jLS*i5kog{rw>pivt&CglI^K-k)Fxi>ds)C(W$<+Mb6Mw< G&;$UVI@#?2 diff --git a/assets/ultimateTTT/sq_bs.png b/assets/ultimateTTT/sq_bs.png index 6b1b58e5c73e6ebcdb7a52ef0d908ad8c8aab17e..018447447bb06fd4df3c8d6b1b36ab1dccc138ce 100644 GIT binary patch delta 294 zcmV+>0onf30@?zQ7#;`)0002Q>4jqe000SaNLh0L01m?d01m?e$8V@)kwz$g=Sf6C zR7i=vmcb4KAqYfa)BpcvdZ`VvGXu71N%o@18&DTLBJ9`pm^itcR1#q>*Q-pr;8Pfd zWPnmyg&tc><#JEET8qAh#6&4!KbB_KgfI>CwGNG zw@gsUCdapf(oE_F`!owPuqX9`u`;naI2I95%}Fmo>$b5BsgoUy`O;tgv`HcB8rRlO sCSC3naD%Xg6O$+K+lRy`+kd>fp7A%h630Bq#sB~S07*qoM6N<$f;XgshX4Qo delta 287 zcmV+)0pR}H0@DJJ7%mV70005werdJ<000DYLP=Bz2nYy#2xN!=000SaNLh0L04^f{ z04^f|c%?sfkv1rQ&`Cr=R9J=WmhBCMFbIa>a?3b`>$sBDbsWNRxE~FdvzD~@b!d40 zU}NDeEhR+&03sp~c=1P^gvfR^K>|w>;shkh`-z%zDE^TyUyOu^07S*~BsM!1_e)R; zAw8n}k%gdMnn4HkE+r209PKn|mGiW1v`quQLPUMfMYq>xay*W|xx%zOPw28@P?xEe z_i{Ln$A<4Zb?2;QcZaRT1zg|;0^ge)FUBw&EpU1-I$hu@gtIQcu>NIveU*va4^PAz lo`^L(5o>rN)_BYlU7#;`)0002v3F)u^000SaNLh0L04;a`04;a{bPeYjkwzzf0}n|= zK~#90?OfZAEFlQgll}i+_B_p|<90W5H?I4iHA*};hJAmZjNsAKp zwm7D21F)o77ZqKEm&D+_7}BzT$tu<%PMSs8jC?9VpBQPKvv{IzT+$kpJSy^xdio3Y z69^kar-v~f`U-XiVN6$FYa(+;yL%!D%g(z%x?@SxE`m`ppypP{vBfmRVp$~?%DokG za3{BffNRE_i?Lho(32K*%giD^N}Mo0=eQe{rCa38xmanBZX<|T8OvRNGGf@nSnh3< zW~cI6gLW(-EW}8Qm_N#OqH-MJKqk%mr4ad?7KjjGK>lSht0qmfdOvB*W9g3!ZQjMy z>1JH+4ZGKkKEF3PIqB2Op|J#w<$0~m@ImmTdECG{ruZ!HowUyV7KL}KecUq(0J7^z zi!36`+O~P>Nn^o#EUrL*9%)ZjAt@TEPf2(ut(mf2fVVWFTXaEgOp}t!D|rpw@`FB& z${#c(>I%*cJGyW#N-drslUCgp#W>Fkf)~>?CmPbi7&RtfOf05JH$IvkijMuc0(6$v zF*vgiL0=Ge&x&K3;y8`KsxA2LrfUG{HO>MH*?y5EDaGyJc~!PQ2}Eh zwj!|fPaJ%bYmaHk7qcp`HX~>+MAbtGz z2aLAQtf5)wXi{F%=kD#%OxxVGA}BY6cn;h$r_0YxIK9@S3oKIK5=J{k9y zV2jWBGm|QmzV{TRG$fB0Piz0x3XP;)oA*zBnFJ=MIOqN=CuCtFea2t5cBnKis3YxQ e{N5KUMEnPjEjm2B(a{$G0000-x92|<51J<_fuBi-S_Y18$O%Y`%jB2OXnp}k$u!yc$vdzh|dCcT|(o%jG4tqh*7elF{r5}E*f CJ>WM0 diff --git a/assets/ultimateTTT/sq_rs.png b/assets/ultimateTTT/sq_rs.png index 89d9ffcd00869198c053300f11fee51304fbc87b..082095777d76fbde38ba3bc79a82c0d0c07237ce 100644 GIT binary patch delta 291 zcmV+;0o?x80@nhN7#;`)0002Q>4jqe000SaNLh0L01m?d01m?e$8V@)kwz$g0#OpS zH>_2`Gz39o`;_XR-v#NOCmenu = initMenu(tttName, tttMenuCb); addSingleItemToMenu(ttt->menu, tttMultiStr); + addSingleItemToMenu(ttt->menu, tttPassAndPlayStr); ttt->menu = startSubMenu(ttt->menu, tttSingleStr); addSingleItemToMenu(ttt->menu, tttDiffEasyStr); @@ -338,29 +340,40 @@ static void tttMenuCb(const char* label, bool selected, uint32_t value) { if (tttMultiStr == label) { - ttt->game.singlePlayer = false; + ttt->game.singleSystem = false; + ttt->game.passAndPlay = false; // Show connection UI tttShowUi(TUI_CONNECTING); // Start multiplayer p2pStartConnection(&ttt->game.p2p); } + else if (tttPassAndPlayStr == label) + { + ttt->game.singleSystem = true; + ttt->game.passAndPlay = true; + tttBeginGame(ttt); + tttShowUi(TUI_GAME); + } else if (tttDiffEasyStr == label) { - ttt->game.singlePlayer = true; + ttt->game.singleSystem = true; + ttt->game.passAndPlay = false; ttt->game.cpu.difficulty = TDIFF_EASY; tttBeginGame(ttt); tttShowUi(TUI_GAME); } else if (tttDiffMediumStr == label) { - ttt->game.singlePlayer = true; + ttt->game.singleSystem = true; + ttt->game.passAndPlay = false; ttt->game.cpu.difficulty = TDIFF_MEDIUM; tttBeginGame(ttt); tttShowUi(TUI_GAME); } else if (tttDiffHardStr == label) { - ttt->game.singlePlayer = true; + ttt->game.singleSystem = true; + ttt->game.passAndPlay = false; ttt->game.cpu.difficulty = TDIFF_HARD; tttBeginGame(ttt); tttShowUi(TUI_GAME); diff --git a/main/modes/games/ultimateTTT/ultimateTTT.h b/main/modes/games/ultimateTTT/ultimateTTT.h index 30b6152b4..a1c36ffb6 100644 --- a/main/modes/games/ultimateTTT/ultimateTTT.h +++ b/main/modes/games/ultimateTTT/ultimateTTT.h @@ -110,7 +110,8 @@ typedef struct typedef struct { - bool singlePlayer; + bool singleSystem; + bool passAndPlay; playOrder_t singlePlayerPlayOrder; p2pInfo p2p; tttGameState_t state; diff --git a/main/modes/games/ultimateTTT/ultimateTTTgame.c b/main/modes/games/ultimateTTT/ultimateTTTgame.c index 1d35836bb..bc7d8851e 100644 --- a/main/modes/games/ultimateTTT/ultimateTTTgame.c +++ b/main/modes/games/ultimateTTT/ultimateTTTgame.c @@ -93,7 +93,7 @@ void tttBeginGame(ultimateTTT_t* ttt) tttShowUi(TUI_GAME); // Randomly determine play order for single player - if (ttt->game.singlePlayer) + if (ttt->game.singleSystem) { ttt->game.singlePlayerPlayOrder = (esp_random() % 2) ? GOING_FIRST : GOING_SECOND; } @@ -108,12 +108,15 @@ void tttBeginGame(ultimateTTT_t* ttt) // Send it to the second player tttSendMarker(ttt, ttt->game.p1MarkerIdx); - if (ttt->game.singlePlayer) + if (ttt->game.singleSystem) { - ttt->game.state = TGS_PLACING_MARKER; - ttt->game.cpu.state = TCPU_INACTIVE; + ttt->game.state = TGS_PLACING_MARKER; + if (!ttt->game.passAndPlay) + { + ttt->game.cpu.state = TCPU_INACTIVE; + } - // Randomize CPU marker to be not the players + // Randomize markers to be not match ttt->game.p2MarkerIdx = esp_random() % ttt->numUnlockedMarkers; // While the markers match while (ttt->game.p1MarkerIdx == ttt->game.p2MarkerIdx) @@ -123,12 +126,19 @@ void tttBeginGame(ultimateTTT_t* ttt) } } } - else if (ttt->game.singlePlayer) + else if (ttt->game.singleSystem) { - ttt->game.state = TGS_WAITING; - ttt->game.cpu.state = TCPU_THINKING; + if (ttt->game.passAndPlay) + { + ttt->game.state = TGS_PLACING_MARKER; + } + else + { + ttt->game.state = TGS_WAITING; + ttt->game.cpu.state = TCPU_THINKING; + } - // Randomize CPU marker to be not the players + // Randomize markers to be not match ttt->game.p1MarkerIdx = esp_random() % ttt->numUnlockedMarkers; // While the markers match while (ttt->game.p1MarkerIdx == ttt->game.p2MarkerIdx) @@ -528,10 +538,13 @@ void tttReceiveCursor(ultimateTTT_t* ttt, const tttMsgMoveCursor_t* msg) */ void tttSendPlacedMarker(ultimateTTT_t* ttt) { - if (ttt->game.singlePlayer) + if (ttt->game.singleSystem) { - ttt->game.state = TGS_WAITING; - ttt->game.cpu.state = TCPU_THINKING; + ttt->game.state = TGS_WAITING; + if (!ttt->game.passAndPlay) + { + ttt->game.cpu.state = TCPU_THINKING; + } } else if (ttt->game.p2p.cnc.isConnected) { @@ -712,7 +725,7 @@ static void tttPlaceMarker(ultimateTTT_t* ttt, const vec_t* subgame, const vec_t ttt->lastResult = TTR_DRAW; } - if (!ttt->game.singlePlayer) + if (!ttt->game.singleSystem) { // Stop p2p p2pDeinit(&ttt->game.p2p); @@ -845,7 +858,7 @@ tttPlayer_t tttCheckSubgameWinner(tttSubgame_t* subgame) */ static playOrder_t tttGetPlayOrder(ultimateTTT_t* ttt) { - if (ttt->game.singlePlayer) + if (ttt->game.singleSystem) { return ttt->game.singlePlayerPlayOrder; } @@ -1002,9 +1015,28 @@ void tttDrawGame(ultimateTTT_t* ttt) } } - if (ttt->game.singlePlayer && ttt->game.state == TGS_WAITING) + if (ttt->game.singleSystem && ttt->game.state == TGS_WAITING) { - tttCpuNextMove(ttt); + if (!ttt->game.passAndPlay) + { + // Let CPU make the next move + tttCpuNextMove(ttt); + } + else + { + // Flip the active player + if (GOING_FIRST == ttt->game.singlePlayerPlayOrder) + { + ttt->game.singlePlayerPlayOrder = GOING_SECOND; + } + else + { + ttt->game.singlePlayerPlayOrder = GOING_FIRST; + } + + // Let the active player place a marker + ttt->game.state = TGS_PLACING_MARKER; + } } } diff --git a/main/modes/games/ultimateTTT/ultimateTTTresult.c b/main/modes/games/ultimateTTT/ultimateTTTresult.c index 0ec0ff512..16e84107a 100644 --- a/main/modes/games/ultimateTTT/ultimateTTTresult.c +++ b/main/modes/games/ultimateTTT/ultimateTTTresult.c @@ -8,6 +8,8 @@ // Variables //============================================================================== +static const char redStr[] = "Red wins!"; +static const char blueStr[] = "Blue wins!"; static const char winStr[] = "A winner is you!"; static const char lossStr[] = "You lost :("; static const char drawStr[] = "It is a draw."; @@ -60,7 +62,21 @@ void tttDrawResult(ultimateTTT_t* ttt, int64_t elapsedUs) { case TTR_WIN: { - resultStr = winStr; + if (ttt->game.singleSystem) + { + if (GOING_FIRST == ttt->game.singlePlayerPlayOrder) + { + resultStr = redStr; + } + else + { + resultStr = blueStr; + } + } + else + { + resultStr = winStr; + } break; } case TTR_LOSE: