From 6d03cdcdee5f49b1767b35fc756941cd2e6bd163 Mon Sep 17 00:00:00 2001 From: LucyLMM Date: Fri, 19 Dec 2025 16:04:23 +0100 Subject: [PATCH 001/102] Initial Push Sprites --- .../games/sprites/adventure/Bridge.npy | Bin 0 -> 6272 bytes .../sprites/adventure/Dragon_green_attack.npy | Bin 0 -> 1536 bytes .../sprites/adventure/Dragon_green_dead.npy | Bin 0 -> 1216 bytes .../sprites/adventure/Dragon_green_neutral.npy | Bin 0 -> 1408 bytes .../sprites/adventure/Dragon_yellow_attack.npy | Bin 0 -> 1536 bytes .../sprites/adventure/Dragon_yellow_dead.npy | Bin 0 -> 1352 bytes .../adventure/Dragon_yellow_neutral.npy | Bin 0 -> 1408 bytes .../games/sprites/adventure/Gate_closed.npy | Bin 0 -> 1024 bytes .../games/sprites/adventure/Gate_open.npy | Bin 0 -> 352 bytes .../games/sprites/adventure/Gate_opening.npy | Bin 0 -> 800 bytes .../games/sprites/adventure/Gate_opening_1.npy | Bin 0 -> 800 bytes .../games/sprites/adventure/Gate_opening_2.npy | Bin 0 -> 688 bytes .../games/sprites/adventure/Gate_opening_3.npy | Bin 0 -> 576 bytes .../games/sprites/adventure/Gate_opening_4.npy | Bin 0 -> 464 bytes src/jaxatari/games/sprites/adventure/Key.npy | Bin 0 -> 320 bytes .../games/sprites/adventure/Key_black.npy | Bin 0 -> 320 bytes .../games/sprites/adventure/Key_yellow.npy | Bin 0 -> 320 bytes .../games/sprites/adventure/Magnet.npy | Bin 0 -> 640 bytes .../games/sprites/adventure/Player.npy | Bin 0 -> 256 bytes .../games/sprites/adventure/Player_Black.npy | Bin 0 -> 256 bytes .../games/sprites/adventure/Player_Blue.npy | Bin 0 -> 256 bytes .../games/sprites/adventure/Player_Green.npy | Bin 0 -> 256 bytes .../sprites/adventure/Player_Green_Yellow.npy | Bin 0 -> 256 bytes .../games/sprites/adventure/Player_Magenta.npy | Bin 0 -> 256 bytes .../games/sprites/adventure/Player_Pink.npy | Bin 0 -> 256 bytes .../games/sprites/adventure/Player_Purple.npy | Bin 0 -> 256 bytes .../games/sprites/adventure/Player_Yellow.npy | Bin 0 -> 256 bytes .../sprites/adventure/Room_Black_Castle.npy | Bin 0 -> 160128 bytes .../games/sprites/adventure/Room_Green.npy | Bin 0 -> 160128 bytes .../sprites/adventure/Room_Green_Yellow.npy | Bin 0 -> 160128 bytes .../games/sprites/adventure/Room_Magenta.npy | Bin 0 -> 160128 bytes .../games/sprites/adventure/Room_Maze_1.npy | Bin 0 -> 160128 bytes .../games/sprites/adventure/Room_Maze_2.npy | Bin 0 -> 160128 bytes .../games/sprites/adventure/Room_Maze_3.npy | Bin 0 -> 160128 bytes .../games/sprites/adventure/Room_Maze_4.npy | Bin 0 -> 160128 bytes .../games/sprites/adventure/Room_Maze_5.npy | Bin 0 -> 160128 bytes .../games/sprites/adventure/Room_Pink.npy | Bin 0 -> 160128 bytes .../sprites/adventure/Room_Pink_Corridor.npy | Bin 0 -> 160128 bytes .../games/sprites/adventure/Room_Purple.npy | Bin 0 -> 160128 bytes .../games/sprites/adventure/Room_Yellow.npy | Bin 0 -> 160128 bytes .../sprites/adventure/Room_YellowCastle.npy | Bin 0 -> 160128 bytes src/jaxatari/games/sprites/adventure/Sword.npy | Bin 0 -> 448 bytes .../games/sprites/adventure/Trophy_Black.npy | Bin 0 -> 704 bytes .../sprites/adventure/Trophy_DarkBlue.npy | Bin 0 -> 704 bytes .../games/sprites/adventure/Trophy_Gray.npy | Bin 0 -> 704 bytes .../games/sprites/adventure/Trophy_Green.npy | Bin 0 -> 704 bytes .../sprites/adventure/Trophy_LightBlue.npy | Bin 0 -> 704 bytes .../games/sprites/adventure/Trophy_Pink.npy | Bin 0 -> 704 bytes .../games/sprites/adventure/Trophy_Purple.npy | Bin 0 -> 704 bytes .../games/sprites/adventure/Trophy_Red.npy | Bin 0 -> 704 bytes .../sprites/adventure/Trophy_Turquoise.npy | Bin 0 -> 704 bytes .../games/sprites/adventure/Trophy_Yellow.npy | Bin 0 -> 704 bytes 52 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/jaxatari/games/sprites/adventure/Bridge.npy create mode 100644 src/jaxatari/games/sprites/adventure/Dragon_green_attack.npy create mode 100644 src/jaxatari/games/sprites/adventure/Dragon_green_dead.npy create mode 100644 src/jaxatari/games/sprites/adventure/Dragon_green_neutral.npy create mode 100644 src/jaxatari/games/sprites/adventure/Dragon_yellow_attack.npy create mode 100644 src/jaxatari/games/sprites/adventure/Dragon_yellow_dead.npy create mode 100644 src/jaxatari/games/sprites/adventure/Dragon_yellow_neutral.npy create mode 100644 src/jaxatari/games/sprites/adventure/Gate_closed.npy create mode 100644 src/jaxatari/games/sprites/adventure/Gate_open.npy create mode 100644 src/jaxatari/games/sprites/adventure/Gate_opening.npy create mode 100644 src/jaxatari/games/sprites/adventure/Gate_opening_1.npy create mode 100644 src/jaxatari/games/sprites/adventure/Gate_opening_2.npy create mode 100644 src/jaxatari/games/sprites/adventure/Gate_opening_3.npy create mode 100644 src/jaxatari/games/sprites/adventure/Gate_opening_4.npy create mode 100644 src/jaxatari/games/sprites/adventure/Key.npy create mode 100644 src/jaxatari/games/sprites/adventure/Key_black.npy create mode 100644 src/jaxatari/games/sprites/adventure/Key_yellow.npy create mode 100644 src/jaxatari/games/sprites/adventure/Magnet.npy create mode 100644 src/jaxatari/games/sprites/adventure/Player.npy create mode 100644 src/jaxatari/games/sprites/adventure/Player_Black.npy create mode 100644 src/jaxatari/games/sprites/adventure/Player_Blue.npy create mode 100644 src/jaxatari/games/sprites/adventure/Player_Green.npy create mode 100644 src/jaxatari/games/sprites/adventure/Player_Green_Yellow.npy create mode 100644 src/jaxatari/games/sprites/adventure/Player_Magenta.npy create mode 100644 src/jaxatari/games/sprites/adventure/Player_Pink.npy create mode 100644 src/jaxatari/games/sprites/adventure/Player_Purple.npy create mode 100644 src/jaxatari/games/sprites/adventure/Player_Yellow.npy create mode 100644 src/jaxatari/games/sprites/adventure/Room_Black_Castle.npy create mode 100644 src/jaxatari/games/sprites/adventure/Room_Green.npy create mode 100644 src/jaxatari/games/sprites/adventure/Room_Green_Yellow.npy create mode 100644 src/jaxatari/games/sprites/adventure/Room_Magenta.npy create mode 100644 src/jaxatari/games/sprites/adventure/Room_Maze_1.npy create mode 100644 src/jaxatari/games/sprites/adventure/Room_Maze_2.npy create mode 100644 src/jaxatari/games/sprites/adventure/Room_Maze_3.npy create mode 100644 src/jaxatari/games/sprites/adventure/Room_Maze_4.npy create mode 100644 src/jaxatari/games/sprites/adventure/Room_Maze_5.npy create mode 100644 src/jaxatari/games/sprites/adventure/Room_Pink.npy create mode 100644 src/jaxatari/games/sprites/adventure/Room_Pink_Corridor.npy create mode 100644 src/jaxatari/games/sprites/adventure/Room_Purple.npy create mode 100644 src/jaxatari/games/sprites/adventure/Room_Yellow.npy create mode 100644 src/jaxatari/games/sprites/adventure/Room_YellowCastle.npy create mode 100644 src/jaxatari/games/sprites/adventure/Sword.npy create mode 100644 src/jaxatari/games/sprites/adventure/Trophy_Black.npy create mode 100644 src/jaxatari/games/sprites/adventure/Trophy_DarkBlue.npy create mode 100644 src/jaxatari/games/sprites/adventure/Trophy_Gray.npy create mode 100644 src/jaxatari/games/sprites/adventure/Trophy_Green.npy create mode 100644 src/jaxatari/games/sprites/adventure/Trophy_LightBlue.npy create mode 100644 src/jaxatari/games/sprites/adventure/Trophy_Pink.npy create mode 100644 src/jaxatari/games/sprites/adventure/Trophy_Purple.npy create mode 100644 src/jaxatari/games/sprites/adventure/Trophy_Red.npy create mode 100644 src/jaxatari/games/sprites/adventure/Trophy_Turquoise.npy create mode 100644 src/jaxatari/games/sprites/adventure/Trophy_Yellow.npy diff --git a/src/jaxatari/games/sprites/adventure/Bridge.npy b/src/jaxatari/games/sprites/adventure/Bridge.npy new file mode 100644 index 0000000000000000000000000000000000000000..d940371632d85d108811a889d3bf8b885eac3efc GIT binary patch literal 6272 zcmeH{F;BxV6ok#nukdD&yihV!`~buPVqxfnqSjRhM36(f0KbBrnSTk%R$irdIqads zi&UvEce;zeIR3nQxV>MTxSe|otJE)ZxboqBdl8}!>n^|M_W7~Pt2ExfZlC%z-0wH- zOB&|0W*+_JEc)g=`Vaq~>-78P>qq;!!b{7Zq7~M=DIJ=}`pXDtY^P{t?atmm`F+cG zQky@@v;M#5G2(@EmM81Cew_fzllANEhv#2yf9*V5zkUDvdjRb(r0-{q|7-he=dsUg z{W<}bC+pYS?fhkVvVP;Q6JU9=e!boHKg*N#8-JYu%air%?Z?0W<$C3e)`xVN$Id7p s>1?0$qkN>xJa$I;NN4+`ALS!m=CL!%M>^Xl{U{&lGLM~6KGIR&FV;{tPXGV_ literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Dragon_green_attack.npy b/src/jaxatari/games/sprites/adventure/Dragon_green_attack.npy new file mode 100644 index 0000000000000000000000000000000000000000..54492ee9106dc743c72890fc72f48a5078b79000 GIT binary patch literal 1536 zcmdszJqp4=5QSswDYjdMZG;r!0qhhT3qg=zRxHFwqBd&n0X&oE(oFH-F>K6F={ED` zeKT*9ea)A%#i|!wqnk~AvCZwo*!yKi`f=*Gtk%ucah)OadWZWEM+O+G_&D&mf}si%jT!i;O?cHV=OPEW znziLT&l>scvBtfaYuksi#DkBDd@$|f-maYYScmS_oO`W9-^DZkz^ncNZ`XwD8Qz7~ g?*^Z%%y6%@=9~%5JMg$_&b`*Mr#2SR8gUEp0CtLvg&@e{Ml3`nt2S!w0X&oE(oON@GbC9M8yCX- z`ET|o^O(%W(|Id9XBS=CYUT7$>FcSdjneDAJGx@G+`H0xe^hKMTl>|fIM}-H^mC&I zM&(_jZtAPAor!PpyubVr_NV<99@_!$4{vd22c{fs<3 HD;YB1yCsiR literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Dragon_green_neutral.npy b/src/jaxatari/games/sprites/adventure/Dragon_green_neutral.npy new file mode 100644 index 0000000000000000000000000000000000000000..32d76077a49fd976ab76e44f5d5ebcd492653b28 GIT binary patch literal 1408 zcmc(aF$%&!5Jh9_DYjdMEfi9S2e4CYECfMbDI{pHsKIwn} literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Dragon_yellow_attack.npy b/src/jaxatari/games/sprites/adventure/Dragon_yellow_attack.npy new file mode 100644 index 0000000000000000000000000000000000000000..aa2217f6c24dd13efae1a1aec1017c94b0d3fd6d GIT binary patch literal 1536 zcmdszF%H5o5ClWZE8H0*H%KWE51<3lP*9Pk~&q((2^kgc3Km zw{y2n{FpCii&ZbVBv+gJYE#;YvA6TcI%Bs*c`CERx+rrm{xsWHzV@qKcJy^WNK1N!Q2NEzA40kB4O3@E z&ZK>3Zl=}hCdzs~@)vzdR9XMbe0m$+RmUKwAHnPD#|U3C*lWsrYB_nF!A#CdPwwk_ zfa8k3+|z1sQaLL#?7v}%1&4E*{+gkF+8lnLwhZpdRnFoWujPE6p>AR@i+I%X4E!br UGoe}^WKfO4Jg(qLxzB6L-Vg@RMF0Q* literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Dragon_yellow_neutral.npy b/src/jaxatari/games/sprites/adventure/Dragon_yellow_neutral.npy new file mode 100644 index 0000000000000000000000000000000000000000..c953bf80ac7c4853479bbc36583bf7d52f816fc7 GIT binary patch literal 1408 zcmc(aF$%&!5Jh9_DYjdMEfi9S2e4CYEUYA$6$>%4Q5*FXUdWqx6wL@9hGEt(P*W6y`ab;ho$un)y{QH9b|J}Ne~Z}NIw?0n-pdC!@F zGkMpUi}~njXUcQGRS$X<^on8}3@UdZf2Zhw%K3M+i+efaEUvu6bId7DJ?fyZ>907y zn|4NwO9qeo!%HPDGwxGdc4Oy(X*)UlH|PI^ncolDHxzs2F67V@=RM4t(jJ~`K6aL5 S-1EIOb4Ihqk;yK6ia!CCE-vE$ literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Gate_closed.npy b/src/jaxatari/games/sprites/adventure/Gate_closed.npy new file mode 100644 index 0000000000000000000000000000000000000000..0a92bfb256ba9c16916ad8e6593219b979c56058 GIT binary patch literal 1024 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1JQ);NLqoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I%oMmh@SItnJ5ItsN4WC1P)28RC>V4zm8esmgSCb}4mKWZQDFo%T^Iz1Ym RxWf!zdO{CJ7=O@&Cjhml%Rc}B literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Gate_open.npy b/src/jaxatari/games/sprites/adventure/Gate_open.npy new file mode 100644 index 0000000000000000000000000000000000000000..36d45c0e63b92007d146a6adcca708b8df7c144f GIT binary patch literal 352 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1JQ);NLqoAIaUsO_*m=~X4l#&V(cT3DEP6dh= uXCxM+0{I#iItu1G3MQI53bhL40WJmxhW`{`pjNPcbQ)wPx)_X4SNi}rA4j$T literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Gate_opening.npy b/src/jaxatari/games/sprites/adventure/Gate_opening.npy new file mode 100644 index 0000000000000000000000000000000000000000..f7eef464ccae249ecd9934be067bc2bd86a2b0d3 GIT binary patch literal 800 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1JQ);NLqoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I$7COQh{ItnJ5ItsN4WC1P)28RC>V4zm8esmgSCb}4mKWZQDFo%T^Iz3{; F69D1tpKJgC literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Gate_opening_1.npy b/src/jaxatari/games/sprites/adventure/Gate_opening_1.npy new file mode 100644 index 0000000000000000000000000000000000000000..f7eef464ccae249ecd9934be067bc2bd86a2b0d3 GIT binary patch literal 800 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1JQ);NLqoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I$7COQh{ItnJ5ItsN4WC1P)28RC>V4zm8esmgSCb}4mKWZQDFo%T^Iz3{; F69D1tpKJgC literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Gate_opening_2.npy b/src/jaxatari/games/sprites/adventure/Gate_opening_2.npy new file mode 100644 index 0000000000000000000000000000000000000000..e6363a75aa17d3375f9d66fa154c2ed16bb6507a GIT binary patch literal 688 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1JQ);NLqoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I$7209AnItnJ5ItsN4WC1P)28RC>V4zm8esmgSCb}4mKWZQDFo%T^Iz4E@ F697)viGBb8 literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Gate_opening_3.npy b/src/jaxatari/games/sprites/adventure/Gate_opening_3.npy new file mode 100644 index 0000000000000000000000000000000000000000..3e27217390220a8a826699a4c17ddb69afefe49b GIT binary patch literal 576 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1JQ);NLqoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I$-W;zPyItnJ5ItsN4WC1P)28RC>V4zm8esmgSCb}4mKWZQDFo%T^I*l_t E0cbjNnE(I) literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Gate_opening_4.npy b/src/jaxatari/games/sprites/adventure/Gate_opening_4.npy new file mode 100644 index 0000000000000000000000000000000000000000..cb4608808b0caa630d09b9153a3a97e5aae3db5c GIT binary patch literal 464 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1JQ);NLqoAIaUsO_*m=~X4l#&V(cT3DEP6dh= wXCxM+0{I$-Mmh@SItnJ5ItsN4WC1P)28RC>V4zm8esmgSCb}4mKdkKo00t6Ws{jB1 literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Key.npy b/src/jaxatari/games/sprites/adventure/Key.npy new file mode 100644 index 0000000000000000000000000000000000000000..048e18e2472e8c817382c92dca637b09fecfee3d GIT binary patch literal 320 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1JQ);NLqoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I$dItms#3MQI53bhL40WJnC;QoR9|1gY2ngJ$F0x`iPZ>sfF2vt`Da?07Zp4 A!vFvP literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Key_yellow.npy b/src/jaxatari/games/sprites/adventure/Key_yellow.npy new file mode 100644 index 0000000000000000000000000000000000000000..048e18e2472e8c817382c92dca637b09fecfee3d GIT binary patch literal 320 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1JQ);NLqoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I$dItms#3MQI53bhL40WJnC;QoR9|1gY2ngJ$2tMS z)|-L4sZKX8?7W_fzF#YCMDJUF@%FTBedCfZ>@m3L;b6}$-bdBc$jr!OY~&$-t)c4I zD<1RRPrj#omd^PqXWV(iy=U H(~rLa+IC~A literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Player.npy b/src/jaxatari/games/sprites/adventure/Player.npy new file mode 100644 index 0000000000000000000000000000000000000000..bbe20e641d21515ead1bc16dcc0e65f2fc542adc GIT binary patch literal 256 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1JQ);NLqoAIaUsO_*m=~X4l#&V(cT3DEP6dh= fXCxM+0{I#iItnI0q^YA&t3V#$x_==5|3G2@2nl_E literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Player_Black.npy b/src/jaxatari/games/sprites/adventure/Player_Black.npy new file mode 100644 index 0000000000000000000000000000000000000000..3feb01d6bd52a52768fcddcaaded7aa74c5a7e1b GIT binary patch literal 256 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1JQ);NLqoAIaUsO_*m=~X4l#&V(cT3DEP6dh= fXCxM+0{I#iItnI0q^YA&t3V#$VqjqSKadyzM@l=t literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Player_Blue.npy b/src/jaxatari/games/sprites/adventure/Player_Blue.npy new file mode 100644 index 0000000000000000000000000000000000000000..1e5d6c6b294e8e04bfc0383a4054fc1d0e268d44 GIT binary patch literal 256 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1JQ);NLqoAIaUsO_*m=~X4l#&V(cT3DEP6dh= fXCxM+0{I#iItnI0q^YA&t3V#$^6)tHe;_dc^5A9v literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Player_Green.npy b/src/jaxatari/games/sprites/adventure/Player_Green.npy new file mode 100644 index 0000000000000000000000000000000000000000..6d54cbb3525e6dda67b6099f0c8b1f3543834bf9 GIT binary patch literal 256 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1JQ);NLqoAIaUsO_*m=~X4l#&V(cT3DEP6dh= fXCxM+0{I#iItnI0q^YA&t3V#$iaFZ;e;_dcx2i%ti literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Player_Pink.npy b/src/jaxatari/games/sprites/adventure/Player_Pink.npy new file mode 100644 index 0000000000000000000000000000000000000000..5718f3572add7b33f10ce740636cfd8efe832371 GIT binary patch literal 256 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1JQ);NLqoAIaUsO_*m=~X4l#&V(cT3DEP6dh= fXCxM+0{I#iItnI0q^YA&t3V#$+UAk>e;_dc-fw9? literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Player_Purple.npy b/src/jaxatari/games/sprites/adventure/Player_Purple.npy new file mode 100644 index 0000000000000000000000000000000000000000..7e58bcd85c29e4af1062305302bf9de623b75a20 GIT binary patch literal 256 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 literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Room_Green_Yellow.npy b/src/jaxatari/games/sprites/adventure/Room_Green_Yellow.npy new file mode 100644 index 0000000000000000000000000000000000000000..01bd23b80aa4e9ea756ab4ae82dcda31b9456bf3 GIT binary patch literal 160128 zcmeI%F=|v{7>3bn>nf%jg%n2A!UfnVHWoraf*G+8BNMezS7DJhOOb5ErHl!Z`k&xj zo&=9@1;dp$d^tV_^7F;3=PzI1nZ8cnmPf0Tx9jE8#q#@?{pH?b`R;iAd42ft&GGtZ zb@}mUhaXN>7au=)fB0#2@#lLFA3xYz>_55q?a}?c#gE1Hf8Cv?Y2$GN1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`>b|JA_R`N3w}=l8GU&E>Q0`?uk})6>&U`P_yZ-IULf zzujBCDPP;$@OkjZU+I)T{`lMe`_*l3RetYxxxLNj=$*e`bN$o5^4|h~{PE}i-_k(2 zt$+H*pZ=8w%5DAAKmPQuG*E8qpZ@Wuf2DzPTmSTrKm98Wl-v5Jf4lZ~ou9v7`Mb{F z@$T-;{;xOXkEPN+fBf;sKxv@d)<5?7W1uupZtEZW{4r1(D7W>Gef}6I4V2sZ$3A}y zlm^Oe{bQd$21*0vw*Ilt9|NUmU34 zF;E&PxAl*G{un3?l-v5pK7S092Fh*yW1l|;N(1G#{;|&=1Eqm-TmRVSkAc!axvhWf z^T$AGpxo9!_W5I=G*E8qAN%|Gef}6I4V2sZ$3A}ylm^Oe{bQd$21*0vw*Ilt9|NUmU34F;E&PxAl*G{un3?l-v5pK7S092Fh*yW1l|; zN(1G#{;|&=1Eqm-TmRVSkAc!axvhWf^T$AGpxo9!_W5I=G*E8qAN%|Gef}6I4V2sZ$3A}ylm^Oe z{bQd$21*0vw*Ilt9|NUmU34F;E&P zxAl*G{un3?l-v5pK7S092Fh*yW1l|;N(1G#{;|&=1EqmoZ=anXY_@%_`nT=--rN4R zZZ*CYf8!f*G~bQ*oA0*Vj&IA~_(mMfcO(AhyDhil+wwQQ5l8dgh`;%6%kB8K{EctK z(R?@JZ@$}dJH9P{;~Q}_-;Ma2@3!2IZ_D5KMjXv|BmU;QEw|&_@;AN_NAul?zxi&< z?fAC*jc>%!zu#z@rj5r97+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ J0S4wU@CO``Kehk> literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Room_Magenta.npy b/src/jaxatari/games/sprites/adventure/Room_Magenta.npy new file mode 100644 index 0000000000000000000000000000000000000000..dce78c9e25c67d281c60da8f58068f0ef06d1d89 GIT binary patch literal 160128 zcmeIyv1*fH7>42B)uYH3g$`EK!2=K%#l^u%ij6pkEs46QN8!+|vu7FG6ZpW?kGtX( z_yY}uyS%x0e!hJD;?g^f9&(eKxv?C+duaCW1uup zw(TGL{4r1(DBJdref}6I4U}#B$3A}ylm^PS{bQd$21)~E+y1f79|NUg^f9&(eKxv?C+duaCW1uupw(TGL{4r1(DBJdref}6I4U}#B$3A}ylm^PS z{bQd$21)~E+y1f79|NUxw4?lD7!{6Nd@;kmSf8+b`Gxt9H&Al(b-!FMs3v z@H6*5{LQ^DzvKJzH@*))bMM37-23u7zAt~{`|vaOKK#wS?;(DdW!Zb&fB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg lfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+_$Af!~skDXahh literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Room_Maze_1.npy b/src/jaxatari/games/sprites/adventure/Room_Maze_1.npy new file mode 100644 index 0000000000000000000000000000000000000000..3f2b0edc354f0ea19d654f330211a5a51e818431 GIT binary patch literal 160128 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 literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Room_Maze_2.npy b/src/jaxatari/games/sprites/adventure/Room_Maze_2.npy new file mode 100644 index 0000000000000000000000000000000000000000..51a55a9bcd3572c6748a449d40eb350173cbfe8f GIT binary patch literal 160128 zcmeI4J&t8(8HAgZRdm)MO@I*)umI!)L_$D>MtBeb!qyBpvAqg{*$*3Q=5FA78a-XA z@jYd!EqSWz?|aK9od5jcPrv`;pMUc3?ZbCZU%mVA*Y{7qeSG@<-(Nhvd3^fY*YE%J z{_Q{i^7Z?#-rfHEcW?jk;oYY{|M2&>-@NS@qy%HahuQb*Dw2h-+kQs+I`yhw|twQ_>_-u(of?ypXINg`~Q>PpYZhi zlfKPo`IOJ%HlO9&{KThxgp+<6xA`o8{r3GkZHV@9;@&Xgr*WIl^4tA>?D^^a*3W&v z=zR&N_a~h6)40uN`RnKQOYcv3`u$1Y=CgdtXK|a)@@; zc)EYupYpf;DWApL{m7s2bpNzJ8-}a|`7H{_>f5OxK)Bcpd z?N9kE-tI^Kgs1zb{V9LjpYmC}-H-eUPxnvzQ~tI;<+FIZANdoW?w|Ij{B3{AXYqDF z@+UmqKkZNX+y0c#;_ZIqPk6e2+Mn{b{VAWt+x^I&@O1yQKjm-xQ$CBg`;kB4>HcYd z%HQ^wc)K6@6Q1s$_NV-9f68a^c0ckbJl#L-Px;&al+WVre&kPh zx_{cA^0)mdpT*n#$e-|Z|Fl2lZ~Id|i?{ocKjG>AX@AP!_NROnZ}%gA!qffJ{*=G% zPx&m~?nnNFr~9Y#sykNgQw_fPv%{v z)%ofBkUrt|K52cM@9O;YeMp~hd!Mwv&3AQv`aYyjxV=wW-{!kIKYbt4C*0mAt#9*P zou9rB=@V}6lh(KSuFg;2hx7@z_ety9d{^hE??d{8+xw*TZN97X)Au2L!tH(1`ZnLy z`RV(RKH>I0X?>gT>iqP5NS|%+}HCmA;r2dheVgy<{PcZDpKyDhw7$)Eb$vRyE;F8AJQk>-Y2bZ^Ie^v zz7OdWZts)UxB0HlPv3|13Agu2>)U)+=cn&O`h?s2r1fpStMk+MA$`K_ebV|i-_`l) z`;b22_C9HSoA2uU^nFO5aC@J$zRh=ae)>M7Pq@8LTHofoIzN3M(kI;BC#`SuSw8h^ z1){ZsZEM*4(Xec}(_{!SaDeVn*AjQGR1zte_j zA1ChicitAg?G3l@OMJp#lJWFAq)+%s`!(K&^skPm?_>4pKBP~$)hGV&^EWbmAFEII zBYncHKJkZdf2R%7K2F>lM*QL1-)Td%j}v$MJ8z5L_J-T{B|hOV$$0u5(kJ|+{TlB> z`d7!(_p$nPAJQk>>JxwX`5T$OkJYF9kv`#8pZLSKztaY3A1Ce&BmVI1@3bM>$BDcB zowr4Ad&BMf5})vwWIX*2=@Wj^evS7b{j1~Y`&fOt59t$b^@%_H{EbZC$LiDlNS|=4 zPyFHA-)V!ij}!NX5r6phciIr`!>oi;@KIB~bX^S0=1Z@7J5;uHRojHllreZo)Lukk*le|0>4AFEII zA$`KFKJka2zme(tSbe%5=@V}CiQmSlKjD=BbLZQ9w!iiN-1(Hx;`aU9eCkj62q%5Q zt$v$N{Vd+@XZ@)^=@U-+gj@YKpZZz6-Ou_{f6^zM^a;26Z9et0c)OqVr~af*IO!8^ z_1k>vXYqDF>reejpK#JA-0HXa)X(DWe%7D*lRn|3Pq@`@^QoW3+x@IR^(TG8NuO}5 z-{w<4i?{n(f9g;Agp)quR=>@seim={v;Ned^a&?@!mWOrPyH<3?q~g}Kj{-r`h;8k zHlO-gyxq_GQ-9JYob(B|`fWb-vv|9o^{4)%PdMolZuQ%I>SytGKkHBZNuO}iC*10{ z`P9$i?S9su`jbB4q))ijZ}X|2#oPU?KlLYl!bzWStKa5RKa02fS%2zJ`h=4{;a0!R zr+yZ1_p|=gpY#bQeZsANn@{~L-tK4psXyrxPWpsf{WhQaS-joP`cr?>C!F*NxB6{9 z^|N@ppY^Byq)#~M6K?g}eClWMc0cP+{Yjs2(kI;NxB1l1;_ZIcpZb$N;iONv)o=5u zpT*n#tUvW9eZonfaI4?uQ$LHh`&obLPx^$DKH*ls&8L1AZ}+qQ)SvVTCw;=Lew$DI zEZ**C{i#3c6HfYsTm3el`dPf)&-zn;(kGns3Ag%fKJ~MByPx%^{-jSh=@V}C+kEP0 z@peD!PyI=saMCB->bLpS&*JTV)}Q*5KH;QKxYcj-sh`E${j5LrCw;<6pKz<+=G%Uh zpK$Bn=2Jh5xBFRt+ds{>{o4G!&-w4CO}~%TZ|}$Y+y2D2`PzKy*T&oLWBt?bXY;lB z>G!ev?f0?%wm^`xD>hYxAjJ8*jgl^-sT_&DZ9q-^c2=-^cpf{=~QW+I;HQ#@p{> z{nPJf^R@Zu_p$oz_p$!AKk;q8HlO;n@%H;z|MdIWd~JUEeXM@_eXPIjPkfuN&8L2C zy!}4bKmC3-Uz?wPAFJPfAM0=X6W``*^Qm7OZ@-WAPrskd*XF0+$LhD=$NJm;#JBm{ zeCpT6+wWuj)9+{VwfX7yvHI=zvHrF{@ol~~pZc}&_WM}>^!wR-ZGQTFtbY4_tiSC~ ze4DS$r+#g`{XW(|{eCuIo1cCktKWVf>u>uL-{x!csb3p!zmN4#zn{(5=BMAs>bKv= z`rH1*xB1$9>et5G?_>Sb?`QM1`RVtu`tA3z{${KGr||el}m5Z{LUVr*X z?nnOjj??|9f0|GF7H{_>|9i*je$+qBCw+^z`;q^><8(jjpXQUk#oPVJ|K4%BAN5c3 zN#Ek_e&m1eINgu>r}?CB@peD*zjvJONBz@$(zkfKANk)qPWPk!X+G&&yxoud?;WT6 zQU5fb^ex`*NB;MY)BUJ_nos%`Z}%hrd&lX1)IZH9eT%pIk^jBpbU*5!=99j~+x^J@ z-f_Ag^-uFj-{S3ln#5wt;P68`uW6fo)(L*ao(NZD1SN2DX81U>n#5wt;P68`uW6fo)(L z*ao(NZD1SN2DX81U>n#5wt;P68`uW6fo)(L*ao(NZD1SN2DX81U>n#5wt;P68`uW6 bfo)(L*ao(NZD1SN2DX81U>n#55*zp*fzp~) literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Room_Maze_3.npy b/src/jaxatari/games/sprites/adventure/Room_Maze_3.npy new file mode 100644 index 0000000000000000000000000000000000000000..3b1d56551fab4f589dfb7b8f358c3532f4562f0d GIT binary patch literal 160128 zcmeH{F|L@^6@*_}R`I$QBo_fC6j=bG0nwzOLRK)MKmpka4Pg~2ydQ7uVOB6oK7AT; z?^t@4{ElYMoVlO>|9tVc&%gZY4-Y>*{QUIIt2cjt{q)zzr+@$Jqo)^-Pv8FV`k${~ z{^RQ(UVroIx8HyI^7}Wh-v9p1cQ1c@_5R;~{P-__dhz(tC-49I^M@}Ue|h}x|9tT9 z@bJ8!bub3Tz!(?Fb2lJ7#IU% zU<{0bF)#+kz!(?Fb2lJ7#IU% zU<{0bF>osbpMCc3`R1RuZ{I#Qe{Sx6x4)~h_Z#$egDS(_!|RF2AaF~{Tut^ZwxdUXzt$kZ|sl1G0X`D}lBe_L<&WBb$o z?0mLAy}zxu`?39Le|A3GpWffr+x^)7v_Cta?N9G->+ODQf7+j&&-SPHxAk^EwmHTfJ-H+{0`?K@e{`CH~-tNctr~TRaY=3%xTW|Mc`_umH ze6~Nmzpc0XvHfX(c0Svm-rv^S{n-ArKRci8Pw#K*?S5>3+Mk`z_NVu^^>#nDKkd)X zXZzFp+j_en+n@Gl=d=Ck{cXM7kL^$Uv-8>h^!~Qq?#K40{n`0!e|mpgZ}(&S)Bfyy zwm-eUt+)HJ{b_%8KHHz(-`3mx*#5LXJD=@O?{Dkver$i*pPkS4r}ww@c0aa1?a$6< z`_uc|db=OnpY~_xv;FD)ZN1%(?N9r&^V$CN{UB?S9k!X>RAY{oD7o_qY2^_oum?-}Z0c*WTamH{GA+c7EHxeP4Tj zyWezwn%ntp|Mq?D{q26!{b_FJxBc7qwfDFCP4}m{o!|Cv-`C#X?l;|^=5~JDzkOeO zf4kpwf12C*ZU6Rt?fvb3)BR~~=ePaa_qF%8`%U+!xt-tkZ{OG6-|jcvpXPRc+rNEZ zdw;v%bbp%L`ECF9eeM12e$)MFZs)iC+xNBixBE@^r@5Wq_HWUB?S9k!X>RAI{pZedfxBE^0_MEb|J(I;zscX8)AvpJsQ>MHyWiw*&*}T7eANGT zz1?r}x99YIQ$Ff{yWZ|M`P*~)z9}E|zg=(loBZuLeczOi`rod%`%V7#oW5_$NBwWt z+x;egdrsds<)i+$>+OD%zdfh#oAOcr+x2$8$={yS_f7ez|LuCa-{f!4>HDU9)c$d&P5$qyD$+?S7NLJ*V%R@=^cW^>)9>-=5R=P5G$*?RvZ4VLc5?l<|{bNaq1AN9XoZ}*%0?Kyqll#lw~uDAP5{`Q={Z^}pgZ`a%X zCVzWQ-#6u>{zi z^0(*oeN#T_f4ko9H~DY=?wNEz`6aujWp8&vf8%cqG&vrB<8SkLpuCI#2o1obIQ3 znvd#f{-me*s6OSR^OP^m>3*uG`KX@ePkNe<>Qg>CPx;cE?x%X1kLqduq^J3)KINnH zlrPQceyXSWsGjCedYX^wQ$9LR`O=*3r+S)?>S_L@r}?Np<)ibIFU{$Gs;Bv=p5{+_ znvd#JJ~~hN(wy$6dYX^wY5t_A`KUhSqw|z6&FOxsr}?O!=1+Q>kLpuCI#2o1obIQ3 znvd#f{-me*s6OSR^OP^m>3*uG`KX@ePkNe<>Qg>CPx;cE?x%X1kLqduq^J3)KINnH zlrPQceyXSWsGjCedYX^wQ$9LR`O=*3r+S)?>i?Jg4-XH|`&kELU<{0bF)#+kz!(?< zV_*!7fiW-!#=saD17lzejDayQ2FAb`7z1Nq42*#>Fb2lJ7#IU%U<{0bF)#+kz!(?< zV_*!7fiW-!#=saD17lzejDayQ2FAb`7z1Nq42*#>Fb2lJ7#IU%U<{0bF)#+kz!(?< H1_QqWGb4F4 literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Room_Maze_4.npy b/src/jaxatari/games/sprites/adventure/Room_Maze_4.npy new file mode 100644 index 0000000000000000000000000000000000000000..8936427743da77f1c6f392d16dbdecfee87ac27c GIT binary patch literal 160128 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 VAOkWW12P~3G9UvoAOjN&{0Bn5lF$GE literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Room_Maze_5.npy b/src/jaxatari/games/sprites/adventure/Room_Maze_5.npy new file mode 100644 index 0000000000000000000000000000000000000000..51a55a9bcd3572c6748a449d40eb350173cbfe8f GIT binary patch literal 160128 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 bfo)(L*ao(NZD1SN2DX81U>n#55*zp*fzp~) literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Room_Pink.npy b/src/jaxatari/games/sprites/adventure/Room_Pink.npy new file mode 100644 index 0000000000000000000000000000000000000000..97c1df9c8274ddf39b70cee489cf5bc4cab1c461 GIT binary patch literal 160128 zcmeI&F^W@B6oBDp>ndIsg%pmcg$ody5gQ9D2~Na9GDD)%sH?EZPTXG1EJ1$cI=nA% z0}1>ba^J_P^6SmJ%eU_zOt;hb)z$X!ald*wuYP>HSgq&Pr|bRK{bu*!dVjUO`~KDD z%VB%|{_uHovps))^z`|Y^?dQ-{Pyhedj2{8{p;a0O((}4Fu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| z0}L?000Rs#zyJdbEY-m8*Sph_&+&LXjXX=fd%t}*)ZU$Y&%pk(|CViFU{nE_EVo9f6IRU)lcpDJ$6xVNTmJZ~hDy&Lf5lI2`Qxt|Dm{Pv6+gA*kH2cD^!)Kx z{M42|{;HwU^T%KDQ(OM{tAnfBY3cwdIe$YN+)5@mKuRmOuWgq0;lmU-460 z{`jkgO3xpE#ZPVdJ$6xVNTmJZ~hDy&L zf5lI2`Qxt|Dm{Pv6+gA*kH2cD^!)Kx{M42|{;HwU^T%KDQ(OM{tAnfBY3c zwdIe$YN+)5@mKuRmOuWgq0;lmU-460{`jkgO3xpE#ZPVdJ$6xVNTmJZ~hDy&Lf5lI2`Qxt|Dm{Pv6+gA*kH2cD^!)Kx{M42| z{;HwU^T%KDQ(OM{tAnfBY3cwdIe$YN+)5@mKuRmOuWgq0;lmU-460{`jkg zO3xpE#ZPVdJ$6xVNTmJZ~hDy&Lf5lI2 z`Qxt|Dm{Pv6+gA*kH2cD^!)Kx{M42|{;HwU^T%KDQ(OM{tAnfBY3cwdIe$ zYN+)5@mKuRmOuWgq0;lmU-460{`jkgO3xpE#ZPVdJ$6xVNTmJZ~hDy&Lf5lI2`Qxt|Dm{Pv6+gA*kH2cD^!)Kx{M42|{;HwU z^T%KDQ(OM{tAnfBY3cwdIe$YN+)5@mKuRmOuWgq0(1>`rXMLxB~_lV1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1R-9U|^c2lj9B;V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg ofB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_2L6SCKXlDzrT_o{ literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Room_Pink_Corridor.npy b/src/jaxatari/games/sprites/adventure/Room_Pink_Corridor.npy new file mode 100644 index 0000000000000000000000000000000000000000..97c8c1a42d299d6290198fedfc4bc6ee632dc0aa GIT binary patch literal 160128 zcmeI&F=`ZH7=Yom^%UE!LJA{l;Q_=(v9Yj{peq)#k&W7@r?ALPyxyABLcn=Pew}>+ z8*t^FalY@Fzw*cPm(O0jy0!YU`nq|$y?C?VJYH|UeLmfstT*q@_n-D>yVvLYx7+LQ zpPYTT*j{~q@&4@N_Ug}f?mxVDvOaxu_3OdillAxYpa0xmtyTvgGhl!L1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7&uk~KcDUn$NagxygZEj9P{iw`);VcYxj2G{B!;tw}Fvo zz({+}KkoTs!1>3(NCPA9?fhe(KL$n`7{m1_Q*gF4uw$%IU|8GBafBYTy{;Qwb^T%H` zRC@mSD}HLrAAi+Q>G|WY_^B;_{8dAx=a0YQr?&j@R}Gb(KmLlJ+VaO=HB@^3_$z*D z%O8K$Q0e*OulT7gfBaQLrRR^o;-|L!@mCF%oG|WY_^B;_{8dAx=a0YQ zr?&j@R}Gb(KmLlJ+VaO=HB@^3_$z*D%O8K$Q0e*OulT7gfBaQLrRR^o;-|L!@mCF% zoG|WY_^B;_{8dAx=a0YQr?&j@R}Gb(KmLlJ+VaO=HB@^3_$z*D%O8K$ zQ0e*OulT7gfBaQLrRR^o;-|L!@mCF%oG|WY_^B;_{8dAx=a0YQr?&j@ zR}Gb(KmLlJ+VaO=HB@^3_$z*D%O8K$Q0e*OulT7gfBaQLrRR^o;-|L!@mCF%oG|WY_^B;_{8dAx=a0YQr?&j@R}Gb(KmLlJ+VaO=HB@^3_$z*D%O8K$Q0e*O zulT7gfBaQLrRR^o;-|L!@mCF%oAPFP?24T^+9k};GfaPn<}g&QVRzGa zw}jahJ9D&4n4xEw{tnGys9eMDe&5|{wL18i0Rs#$zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| W0}L?000Rs#zyJdbFu=gyFz^d?+ZeR~ literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Room_Purple.npy b/src/jaxatari/games/sprites/adventure/Room_Purple.npy new file mode 100644 index 0000000000000000000000000000000000000000..d3821813addd373b7a611a5ca6320af5f5de8b90 GIT binary patch literal 160128 zcmeIyv1(*x0EXe%dKKxSkir$U@B-`<8w+7Uf*Y|ASF&oOR(lB+xvagU7>o4hh3~Mi z`wW~JX83rA^YhI7`^|S>fBXFh7k^&-b@k%*)sJ^qUtV7Q{l~Mb>&vU3Uf%tFck}BH zFYjL5{{Q(`H^02Pef<2@&o{r_KED6x)6YM-zI^t@snR^_zTQ@szxID#temlZ zTTagUUjFzy%hr)DfBYSBa@K}F{?4*>q{|uJU9bq zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| s0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3~UYj2kS8ZKL7v# literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Room_Yellow.npy b/src/jaxatari/games/sprites/adventure/Room_Yellow.npy new file mode 100644 index 0000000000000000000000000000000000000000..a637776f0f3cf8c3ea4b7e002c9f27ab83547b39 GIT binary patch literal 160128 zcmeIyF=~@>9Eb7O)l+1PLI*4A-~rqe7Y8RPHsTht~kvy08u-}fFqesHoneRB2o=>Ey-`|8hMcb8>3c-(*i1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+~OkHSp`__TX^?1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfPued;PUeF;BkZN8n~&$>vnyQ*`opeI4HM(KmPb* zpfpgn?H~L6F;E&P+xCxr{un3?lx_RRK7S092FkYmW1l|;N&{uv{;|&=1EqnoZU5Nk zkAc!a*|vY|^T$AGplsVe_W5I=G*GtfAN%|g^f9&(eKxv?C z+duaCW1uupw(TGL{4r1(DBJdref}6I4U}#B$3A}ylm^PS{bQd$21)~E+y1f79|NU< zvTgs^=Z}HXK-so`?DNM!X`pP|Klb@!pfpgn?H~L6F;E&P+xCxr{un3?lx_RRK7S09 z2FkYmW1l|;N&{uv{;|&=1EqnoZU5NkkAc!a*|vY|^T$AGplsVe_W5I=G*GtfAN%|< zP#P%P_K$u37$^;tZTrVQe+-lc%C`MupFajl17+L(vCkg^rGc_-|Jdh`fzm+PwtwvN z$3SVIY}-Hf`D36oP`2$K`}{Fb8YtWLkA40aC=HZt`^P?i43q}Sw*6zDKL$zzW!wI- z&mRM&fwFD?*yoRd(m>g^f9&(eKxv?C+duaCW1uupw(TGL{4r1(DBJdref}6I4U}#B z$3A}ylm^PS{bQd$21)~E+y1f79|NUZU27x+Z@}s{XYJ`?bP3hzq$A2cYI&|#`oc8?tS>1 zdtZLX_vLSVAAaWEhrhY^<#&8v{>Jy=XYPIYn|oh=$M@xLd>?-1-iN=r_vLqdU;f7T z;b-oB_?vrQe#iIaZ+stq=H7?Dx%cIFd|&>?_u*&mefXPu-|P5YmgV4a0|ppifB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ m0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1R)c27UufI(+^B literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Room_YellowCastle.npy b/src/jaxatari/games/sprites/adventure/Room_YellowCastle.npy new file mode 100644 index 0000000000000000000000000000000000000000..4582bdb6617ec1a1f828806ad3413e25f036c377 GIT binary patch literal 160128 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 literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Sword.npy b/src/jaxatari/games/sprites/adventure/Sword.npy new file mode 100644 index 0000000000000000000000000000000000000000..4223dcb867b558d343e23281003e93ba97d713f1 GIT binary patch literal 448 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1JQ);NLqoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I$-2098BItnJ5ItsN4WC1P)D7b$h|38e4jm9UBPYz@jK6#KFC76);#K;q) H2A3ZI7VBjs literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Trophy_Black.npy b/src/jaxatari/games/sprites/adventure/Trophy_Black.npy new file mode 100644 index 0000000000000000000000000000000000000000..53c2116bc0e2ff36e2ccf10b452590f12e972cf4 GIT binary patch literal 704 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1JQ);NLqoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I$-7CH(*WTL5~P^&-|;9_84_z%Rm07#A=^4RQv*$t!7-H0p>W24hBJ?P>v qKDFdQ=D^H^(J-@NG)x>u!^Dwkd~zUlw33IJi%!GbhAs}{GXMZ&qhGK9 literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Trophy_DarkBlue.npy b/src/jaxatari/games/sprites/adventure/Trophy_DarkBlue.npy new file mode 100644 index 0000000000000000000000000000000000000000..d0699bf8b4a1b3d8b44b33855c14538f7cb89d81 GIT binary patch literal 704 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1JQ);NLqoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I$-7CH(*WTL5~P^&-|;9_Vv@Sgz}0Ljrq9-AF7yJ0lC8t literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Trophy_LightBlue.npy b/src/jaxatari/games/sprites/adventure/Trophy_LightBlue.npy new file mode 100644 index 0000000000000000000000000000000000000000..3acd8ac05eb429760a7efc7a905d2e2eb995a97d GIT binary patch literal 704 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1JQ);NLqoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I$-7CH(*WTL5~P^&-|;OaQ>=RX4u0FtAJJT^OEcEf0NCnAf(*yuD&54t#v qPc3j_mqSG+9p^L-#Ab9{KuKVBs literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Trophy_Pink.npy b/src/jaxatari/games/sprites/adventure/Trophy_Pink.npy new file mode 100644 index 0000000000000000000000000000000000000000..c5d9c6f2187e32989d29d38f55c59c1cd2b771fb GIT binary patch literal 704 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1JQ);NLqoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I$-7CH(*WTL5~P^&-|;QG(-|33o`0FtAJJT^OEcEf0NCnAf(*yuD&54t#v qPc3j_mqSG+9p^L-#Ab9{~eCH?t literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Trophy_Purple.npy b/src/jaxatari/games/sprites/adventure/Trophy_Purple.npy new file mode 100644 index 0000000000000000000000000000000000000000..99d8f0b606f6f6f6af118fa1249ff07042f3851e GIT binary patch literal 704 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1JQ);NLqoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I$-7CH(*WTL5~P^&-|;A&_%@Sgz(0Ljrq9-AF7yJ0lC6OqMXY;+o?2VES- qrj_mqSG+9p^L-#KzRTmz~?9c literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Trophy_Yellow.npy b/src/jaxatari/games/sprites/adventure/Trophy_Yellow.npy new file mode 100644 index 0000000000000000000000000000000000000000..3d6accdd20b892fdeefec1b3270dbba6fd4ff2f4 GIT binary patch literal 704 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1JQ);NLqoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I$-7CH(*WTL5~P^&-|;QIfc;XeZo0FtAJJT^OEcEf0NCnAf(*yuD&54t#v qPc3j_mqSG+9p^L-#Ab9|(IOiw; literal 0 HcmV?d00001 From 9549ebdec8ceffd2b0f60006cd07d6b7b979242c Mon Sep 17 00:00:00 2001 From: DanielCress Date: Fri, 19 Dec 2025 16:25:41 +0100 Subject: [PATCH 002/102] Create adventure.py --- src/jaxatari/games/adventure.py | 212 ++++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 src/jaxatari/games/adventure.py diff --git a/src/jaxatari/games/adventure.py b/src/jaxatari/games/adventure.py new file mode 100644 index 000000000..b7370a182 --- /dev/null +++ b/src/jaxatari/games/adventure.py @@ -0,0 +1,212 @@ +from jax._src.pjit import JitWrapped +import os +from functools import partial +from typing import NamedTuple, Tuple +import jax +import jax.lax +import jax.numpy as jnp +import chex + +import jaxatari.spaces as spaces +from jaxatari.renderers import JAXGameRenderer +from jaxatari.rendering import jax_rendering_utils as render_utils +from jaxatari.environment import JaxEnvironment, JAXAtariAction as Action + +def _get_default_asset_config() -> tuple: + """ + Returns the default declarative asset manifest for Adventure. + Kept immutable (tuple of dicts) to fit NamedTuple defaults. + """ + return ( + {'name': 'background', 'type': 'background', 'file': 'Room_YellowCastle.npy'}, + {'name': 'player', 'type': 'single', 'file': 'player.npy'}, + ) + + +class AdventureConstants(NamedTuple): + WIDTH: int = 160 + HEIGHT: int = 250 + + # sset config baked into constants (immutable default) for asset overrides + ASSET_CONFIG: tuple = _get_default_asset_config() + + +# immutable state container + +class AdventureState(NamedTuple): + player_x: chex.Array + player_y:chex.Array + step_counter: chex.Array + + +class EntityPosition(NamedTuple): + x: jnp.ndarray + y: jnp.ndarray + width: jnp.ndarray + height: jnp.ndarray + + +class AdventureObservation(NamedTuple): + player: EntityPosition + + +class AdventureInfo(NamedTuple): + time: jnp.ndarray + + +class JaxPong(JaxEnvironment[AdventureState, AdventureObservation, AdventureInfo, AdventureConstants]): + def __init__(self, consts: AdventureConstants = None): + consts = consts or AdventureConstants() + super().__init__(consts) + self.renderer = AdventureRenderer(self.consts) + self.action_set = [ + Action.NOOP, + Action.FIRE, + Action.RIGHT, + Action.LEFT, + Action.UP, + Action.DOWN, + ] + + def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureState: + left = jnp.logical_or(action == Action.LEFT, action == Action.LEFTFIRE) + right = jnp.logical_or(action == Action.RIGHT, action == Action.RIGHTFIRE) + new_player_x = state.player_x + + + + return AdventureState( + player_x = new_player_x, + player_y = state.player_y, + step_counter = state.step_counter + ) + + + @partial(jax.jit, static_argnums=(0,)) + def step(self, state: AdventureState, action: chex.Array) -> Tuple[AdventureObservation, AdventureState, float, bool, AdventureInfo]: + previous_state = state + state = self._player_step(state, action) + + + def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureObservation, AdventureState]: + + state = AdventureState( + player_x=jnp.array(80).astype(jnp.int32), + player_y=jnp.array(180).astype(jnp.int32), + step_counter=jnp.array(0).astype(jnp.int32), + ) + initial_obs = self._get_observation(state) + + return initial_obs, state + + @partial(jax.jit, static_argnums=(0,)) + def step(self, state: AdventureState, action: chex.Array) -> Tuple[AdventureObservation, AdventureState, float, bool, AdventureInfo]: + # Split step key from state and keep a new key for the next state + previous_state = state + # Make per-step key available to helpers that may read state.key + state = AdventureState( + player_x = state.player_x, + player_y=state.player_y, + step_counter=state.step_counter, + ) + state = self._player_step(state, action) + + + done = self._get_done(state) + env_reward = self._get_reward(previous_state, state) + info = self._get_info(state) + observation = self._get_observation(state) + + return observation, state, env_reward, done, info + + + def render(self, state: AdventureState) -> jnp.ndarray: + return self.renderer.render(state) + + def _get_observation(self, state: AdventureState): + player = EntityPosition( + x=state.player_x, + y=state.player_y, + width=4, + height=8 + ) + + return AdventureObservation( + player=player, + ) + + @partial(jax.jit, static_argnums=(0,)) + def obs_to_flat_array(self, obs: AdventureObservation) -> jnp.ndarray: + return jnp.concatenate([ + obs.player.x.flatten(), + obs.player.y.flatten(), + obs.player.height.flatten(), + obs.player.width.flatten() + ] + ) + + def action_space(self) -> spaces.Discrete: + return spaces.Discrete(6) + + def observation_space(self) -> spaces: + return spaces.Dict({ + "player": spaces.Dict({ + "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), + "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), + "width": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), + "height": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), + }), + }) + + def image_space(self) -> spaces.Box: + return spaces.Box( + low=0, + high=255, + shape=(250, 160, 3), + dtype=jnp.uint8 + ) + + @partial(jax.jit, static_argnums=(0,)) + def _get_info(self, state: AdventureState, ) -> AdventureInfo: + return AdventureInfo(time=state.step_counter) + + @partial(jax.jit, static_argnums=(0,)) + def _get_reward(self, previous_state: AdventureState, state: AdventureState): + return 1 + + @partial(jax.jit, static_argnums=(0,)) + def _get_done(self, state: AdventureState) -> bool: + return 0 + +class AdventureRenderer(JAXGameRenderer): + def __init__(self, consts: AdventureConstants = None): + super().__init__(consts) + self.consts = consts or AdventureConstants() + self.config = render_utils.RendererConfig( + game_dimensions=(250, 160), + channels=3, + #downscale=(84, 84) + ) + self.jr = render_utils.JaxRenderingUtils(self.config) + + # 1. Start from (possibly modded) asset config provided via constants + final_asset_config = list(self.consts.ASSET_CONFIG) + + # 4. Bake assets once + sprite_path = f"{os.path.dirname(os.path.abspath(__file__))}/sprites/adventure" + ( + self.PALETTE, + self.SHAPE_MASKS, + self.BACKGROUND, + self.COLOR_TO_ID, + self.FLIP_OFFSETS + ) = self.jr.load_and_setup_assets(final_asset_config, sprite_path) + + @partial(jax.jit, static_argnums=(0,)) + def render(self, state): + raster = self.jr.create_object_raster(self.BACKGROUND) + + player_mask = self.SHAPE_MASKS["player"] + raster = self.jr.render_at(raster, state.player_x, state.player_y, player_mask) + + return self.jr.render_from_palette(raster, self.PALETTE) From 91102a6983506819fbc28eda774d0a8920f1dd5b Mon Sep 17 00:00:00 2001 From: DanielCress Date: Fri, 19 Dec 2025 16:26:38 +0100 Subject: [PATCH 003/102] Rename adventure.py to jax_adventure.py --- src/jaxatari/games/{adventure.py => jax_adventure.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/jaxatari/games/{adventure.py => jax_adventure.py} (100%) diff --git a/src/jaxatari/games/adventure.py b/src/jaxatari/games/jax_adventure.py similarity index 100% rename from src/jaxatari/games/adventure.py rename to src/jaxatari/games/jax_adventure.py From c165ef9566eac9aec34349f44352f125300b6f63 Mon Sep 17 00:00:00 2001 From: DanielCress Date: Fri, 19 Dec 2025 17:18:08 +0100 Subject: [PATCH 004/102] Move Player added Yellow Key --- src/jaxatari/games/jax_adventure.py | 59 +++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index b7370a182..f11b9eac7 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -20,6 +20,7 @@ def _get_default_asset_config() -> tuple: return ( {'name': 'background', 'type': 'background', 'file': 'Room_YellowCastle.npy'}, {'name': 'player', 'type': 'single', 'file': 'player.npy'}, + {'name': 'key_yellow', 'type': 'single', 'file': 'Key_yellow.npy'} ) @@ -36,6 +37,8 @@ class AdventureConstants(NamedTuple): class AdventureState(NamedTuple): player_x: chex.Array player_y:chex.Array + key_yellow_x:chex.Array + key_yellow_y:chex.Array step_counter: chex.Array @@ -48,6 +51,7 @@ class EntityPosition(NamedTuple): class AdventureObservation(NamedTuple): player: EntityPosition + key_yellow: EntityPosition class AdventureInfo(NamedTuple): @@ -71,13 +75,41 @@ def __init__(self, consts: AdventureConstants = None): def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureState: left = jnp.logical_or(action == Action.LEFT, action == Action.LEFTFIRE) right = jnp.logical_or(action == Action.RIGHT, action == Action.RIGHTFIRE) + up = jnp.logical_or(action == Action.UP, action == Action.UPFIRE) + down = jnp.logical_or(action == Action.DOWN, action == Action.DOWNFIRE) new_player_x = state.player_x - + new_player_x = jax.lax.cond( + left, + lambda x: x-1, + lambda x: x, + operand = new_player_x, + ) + new_player_x = jax.lax.cond( + right, + lambda x: x+1, + lambda x: x, + operand = new_player_x, + ) + new_player_y = state.player_y + new_player_y = jax.lax.cond( + down, + lambda y: y+1, + lambda y: y, + operand = new_player_y, + ) + new_player_y = jax.lax.cond( + up, + lambda y: y-1, + lambda y: y, + operand = new_player_y, + ) return AdventureState( player_x = new_player_x, - player_y = state.player_y, + player_y = new_player_y, + key_yellow_x = state.key_yellow_x, + key_yellow_y = state.key_yellow_y, step_counter = state.step_counter ) @@ -91,8 +123,10 @@ def step(self, state: AdventureState, action: chex.Array) -> Tuple[AdventureObse def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureObservation, AdventureState]: state = AdventureState( - player_x=jnp.array(80).astype(jnp.int32), - player_y=jnp.array(180).astype(jnp.int32), + player_x=jnp.array(78).astype(jnp.int32), + player_y=jnp.array(174).astype(jnp.int32), + key_yellow_x=jnp.array(31).astype(jnp.int32), + key_yellow_y=jnp.array(110).astype(jnp.int32), step_counter=jnp.array(0).astype(jnp.int32), ) initial_obs = self._get_observation(state) @@ -107,6 +141,8 @@ def step(self, state: AdventureState, action: chex.Array) -> Tuple[AdventureObse state = AdventureState( player_x = state.player_x, player_y=state.player_y, + key_yellow_x = state.key_yellow_x, + key_yellow_y = state.key_yellow_y, step_counter=state.step_counter, ) state = self._player_step(state, action) @@ -130,9 +166,16 @@ def _get_observation(self, state: AdventureState): width=4, height=8 ) + key_yellow = EntityPosition( + x=state.key_yellow_x, + y=state.key_yellow_y, + width=10, + height=4 + ) return AdventureObservation( player=player, + key_yellow=key_yellow ) @partial(jax.jit, static_argnums=(0,)) @@ -156,6 +199,12 @@ def observation_space(self) -> spaces: "width": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), "height": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), }), + "key_yellow": spaces.Dict({ + "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), + "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), + "width": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), + "height": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), + }), }) def image_space(self) -> spaces.Box: @@ -209,4 +258,6 @@ def render(self, state): player_mask = self.SHAPE_MASKS["player"] raster = self.jr.render_at(raster, state.player_x, state.player_y, player_mask) + key_yellow_mask = self.SHAPE_MASKS["key_yellow"] + raster = self.jr.render_at(raster, state.key_yellow_x, state.key_yellow_y, key_yellow_mask) return self.jr.render_from_palette(raster, self.PALETTE) From 9de9714f74c14db8c7cc63f19f7c4c6940badc98 Mon Sep 17 00:00:00 2001 From: LucyLMM Date: Fri, 19 Dec 2025 17:20:59 +0100 Subject: [PATCH 005/102] WIP BG and Player Layout - corrected Maze Sprite 5 - added npy files to default asset config --- Adventure_screenshots/Room_Maze_5.npy | Bin 0 -> 160128 bytes Adventure_screenshots/frame_00001.npy | Bin 0 -> 120128 bytes src/jaxatari/games/jax_adventure.py | 30 ++++++++++++++++-- .../games/sprites/adventure/Room_Maze_5.npy | Bin 160128 -> 160128 bytes 4 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 Adventure_screenshots/Room_Maze_5.npy create mode 100644 Adventure_screenshots/frame_00001.npy diff --git a/Adventure_screenshots/Room_Maze_5.npy b/Adventure_screenshots/Room_Maze_5.npy new file mode 100644 index 0000000000000000000000000000000000000000..cfe9be99054f59e30fb68ec0207dc20848c650fe GIT binary patch literal 160128 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 literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index b7370a182..98b6d33dc 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -18,8 +18,30 @@ def _get_default_asset_config() -> tuple: Kept immutable (tuple of dicts) to fit NamedTuple defaults. """ return ( - {'name': 'background', 'type': 'background', 'file': 'Room_YellowCastle.npy'}, - {'name': 'player', 'type': 'single', 'file': 'player.npy'}, + #all rooms in order + {'name': 'bg_yellow_castle', 'type': 'background', 'file': 'Room_YellowCastle.npy'}, + {'name': 'bg_yellow', 'type': 'background', 'file': 'Room_Yellow.npy'}, + {'name': 'bg_green', 'type': 'background', 'file': 'Room_Green.npy'}, + {'name': 'bg_purple', 'type': 'background', 'file': 'Room_Purple.npy'}, + {'name': 'bg_pink', 'type': 'background', 'file': 'Room_Pink.npy'}, + {'name': 'bg_green_yellow', 'type': 'background', 'file': 'Room_Green_Yellow.npy'}, + {'name': 'bg_maze_1', 'type': 'background', 'file': 'Room_Maze_1.npy'}, + {'name': 'bg_maze_2', 'type': 'background', 'file': 'Room_Maze_2.npy'}, + {'name': 'bg_maze_3', 'type': 'background', 'file': 'Room_Maze_3.npy'}, + {'name': 'bg_maze_4', 'type': 'background', 'file': 'Room_Maze_4.npy'}, + {'name': 'bg_maze_5', 'type': 'background', 'file': 'Room_Maze_5.npy'}, # wrong sprite + {'name': 'bg_black_castle', 'type': 'background', 'file': 'Room_Black_Castle.npy'}, + {'name': 'bg_ping_corridor', 'type': 'background', 'file': 'Room_Pink_Corridor.npy'}, + {'name': 'bg_magenta', 'type': 'background', 'file': 'Room_Magenta.npy'}, + #all player colors in order + {'name': 'player_yellow', 'type': 'single', 'file': 'Player_Yellow.npy'}, + {'name': 'player_green', 'type': 'single', 'file': 'Player_Green.npy'}, + {'name': 'player_purple', 'type': 'single', 'file': 'Player_Purple.npy'}, + {'name': 'player_pink', 'type': 'single', 'file': 'Player_Pink.npy'}, + {'name': 'player_green_yellow', 'type': 'single', 'file': 'Player_Green_Yellow.npy'}, + {'name': 'player_blue', 'type': 'single', 'file': 'Player_Blue.npy'}, + {'name': 'player_black', 'type': 'single', 'file': 'Player_Black.npy'}, + {'name': 'player_magenta', 'type': 'single', 'file': 'Player_Magenta.npy'}, ) @@ -204,9 +226,11 @@ def __init__(self, consts: AdventureConstants = None): @partial(jax.jit, static_argnums=(0,)) def render(self, state): + #set bg color here raster = self.jr.create_object_raster(self.BACKGROUND) - player_mask = self.SHAPE_MASKS["player"] + #set player color here + player_mask = self.SHAPE_MASKS["player_magenta"] raster = self.jr.render_at(raster, state.player_x, state.player_y, player_mask) return self.jr.render_from_palette(raster, self.PALETTE) diff --git a/src/jaxatari/games/sprites/adventure/Room_Maze_5.npy b/src/jaxatari/games/sprites/adventure/Room_Maze_5.npy index 51a55a9bcd3572c6748a449d40eb350173cbfe8f..cfe9be99054f59e30fb68ec0207dc20848c650fe 100644 GIT binary patch literal 160128 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 bfo)(L*ao(NZD1SN2DX81U>n#55*zp*fzp~) From 7ceaf352b1473cfe49ba57f6be9a51934717e784 Mon Sep 17 00:00:00 2001 From: LucyLMM Date: Fri, 19 Dec 2025 17:22:48 +0100 Subject: [PATCH 006/102] Update jax_adventure.py --- src/jaxatari/games/jax_adventure.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 0499221ed..4dc166710 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -42,6 +42,7 @@ def _get_default_asset_config() -> tuple: {'name': 'player_blue', 'type': 'single', 'file': 'Player_Blue.npy'}, {'name': 'player_black', 'type': 'single', 'file': 'Player_Black.npy'}, {'name': 'player_magenta', 'type': 'single', 'file': 'Player_Magenta.npy'}, + {'name': 'key_yellow', 'type': 'single', 'file': 'Key_yellow.npy'} ) From 472ca76f09e184cb7f8094a96f14694e55a40c67 Mon Sep 17 00:00:00 2001 From: LucyLMM Date: Fri, 19 Dec 2025 17:23:42 +0100 Subject: [PATCH 007/102] comment removed --- src/jaxatari/games/jax_adventure.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 4dc166710..c1d7a9f5d 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -29,7 +29,7 @@ def _get_default_asset_config() -> tuple: {'name': 'bg_maze_2', 'type': 'background', 'file': 'Room_Maze_2.npy'}, {'name': 'bg_maze_3', 'type': 'background', 'file': 'Room_Maze_3.npy'}, {'name': 'bg_maze_4', 'type': 'background', 'file': 'Room_Maze_4.npy'}, - {'name': 'bg_maze_5', 'type': 'background', 'file': 'Room_Maze_5.npy'}, # wrong sprite + {'name': 'bg_maze_5', 'type': 'background', 'file': 'Room_Maze_5.npy'}, {'name': 'bg_black_castle', 'type': 'background', 'file': 'Room_Black_Castle.npy'}, {'name': 'bg_ping_corridor', 'type': 'background', 'file': 'Room_Pink_Corridor.npy'}, {'name': 'bg_magenta', 'type': 'background', 'file': 'Room_Magenta.npy'}, @@ -42,7 +42,7 @@ def _get_default_asset_config() -> tuple: {'name': 'player_blue', 'type': 'single', 'file': 'Player_Blue.npy'}, {'name': 'player_black', 'type': 'single', 'file': 'Player_Black.npy'}, {'name': 'player_magenta', 'type': 'single', 'file': 'Player_Magenta.npy'}, - + {'name': 'key_yellow', 'type': 'single', 'file': 'Key_yellow.npy'} ) From 22e115dd516d895c7d457f96aa2f60013129d4bf Mon Sep 17 00:00:00 2001 From: Leif Schwass Date: Fri, 19 Dec 2025 17:46:05 +0100 Subject: [PATCH 008/102] AdventureState --- src/jaxatari/games/jax_adventure.py | 116 +++++++++++++++++++++++++--- 1 file changed, 105 insertions(+), 11 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index c1d7a9f5d..bdf7df1a6 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -58,11 +58,42 @@ class AdventureConstants(NamedTuple): # immutable state container class AdventureState(NamedTuple): + #position player player_x: chex.Array player_y:chex.Array - key_yellow_x:chex.Array - key_yellow_y:chex.Array + #step conter for performance indicator? step_counter: chex.Array + #positions dragons + dragon_yellow_x: chex.Array + dragon_yellow_y: chex.Array + dragon_green_x: chex.Array + dragon_green_y: chex.Array + #state dragons (alive, dead, attacking) + dragon_yellow: chex.Array + dragon_green: chex.Array + #positions keys + key_yellow_x: chex.Array + key_yellow_y: chex.Array + key_black_x: chex.Array + key_black_y: chex.Array + key_white_x: chex.Array + key_white_y: chex.Array + #state of gates (if open or closed) + gate_yellow: chex.Array + gate_black: chex.Array + gate_white: chex.Array + #position sword + sword_x: chex.Array + sword_y:chex.Array + #position bridge + bridge_x: chex.Array + bridge_y:chex.Array + #position magnet + magnet_x: chex.Array + magnet_y:chex.Array + #position chalice + chalice_x: chex.Array + chalice_y:chex.Array class EntityPosition(NamedTuple): @@ -131,9 +162,30 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt return AdventureState( player_x = new_player_x, player_y = new_player_y, + step_counter = state.step_counter, + dragon_yellow_x = state.dragon_yellow_x, + dragon_yellow_y = state.dragon_yellow_y, + dragon_green_x = state.dragon_green_x, + dragon_green_y = state.dragon_green_y, + dragon_yellow = state.dragon_yellow , + dragon_green = state.dragon_green, key_yellow_x = state.key_yellow_x, - key_yellow_y = state.key_yellow_y, - step_counter = state.step_counter + key_yellow_y = state.key_yellow_y , + key_black_x = state.key_black_x, + key_black_y = state.key_black_y, + key_white_x = state.key_white_x, + key_white_y = state.key_white_y, + gate_yellow = state.gate_yellow, + gate_black = state.gate_black, + gate_white = state.gate_white, + sword_x = state.sword_x, + sword_y = state.sword_y, + bridge_x = state.bridge_x, + bridge_y = state.bridge_y, + magnet_x = state.magnet_x, + magnet_y = state.magnet_y, + chalice_x = state.chalice_x, + chalice_y = state.chalice_y ) @@ -146,11 +198,32 @@ def step(self, state: AdventureState, action: chex.Array) -> Tuple[AdventureObse def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureObservation, AdventureState]: state = AdventureState( - player_x=jnp.array(78).astype(jnp.int32), - player_y=jnp.array(174).astype(jnp.int32), - key_yellow_x=jnp.array(31).astype(jnp.int32), - key_yellow_y=jnp.array(110).astype(jnp.int32), - step_counter=jnp.array(0).astype(jnp.int32), + player_x = jnp.array(78).astype(jnp.int32), + player_y = jnp.array(174).astype(jnp.int32), + step_counter = jnp.array(0).astype(jnp.int32), + dragon_yellow_x = jnp.array(0).astype(jnp.int32), #ToDo + dragon_yellow_y = jnp.array(0).astype(jnp.int32), #ToDo + dragon_green_x = jnp.array(0).astype(jnp.int32), #ToDo + dragon_green_y = jnp.array(0).astype(jnp.int32), #ToDo + dragon_yellow = jnp.array(0).astype(jnp.int32), #ToDo + dragon_green = jnp.array(0).astype(jnp.int32), #ToDo + key_yellow_x = jnp.array(31).astype(jnp.int32), + key_yellow_y = jnp.array(110).astype(jnp.int32), + key_black_x = jnp.array(0).astype(jnp.int32), #ToDo + key_black_y = jnp.array(0).astype(jnp.int32), #ToDo + key_white_x = jnp.array(0).astype(jnp.int32), #ToDo + key_white_y = jnp.array(0).astype(jnp.int32), #ToDo + gate_yellow = jnp.array(0).astype(jnp.int32), #ToDo + gate_black = jnp.array(0).astype(jnp.int32), #ToDo + gate_white = jnp.array(0).astype(jnp.int32), #ToDo + sword_x = jnp.array(0).astype(jnp.int32), #ToDo + sword_y = jnp.array(0).astype(jnp.int32), #ToDo + bridge_x = jnp.array(0).astype(jnp.int32), #ToDo + bridge_y = jnp.array(0).astype(jnp.int32), #ToDo + magnet_x = jnp.array(0).astype(jnp.int32), #ToDo + magnet_y = jnp.array(0).astype(jnp.int32), #ToDo + chalice_x = jnp.array(0).astype(jnp.int32), #ToDo + chalice_y = jnp.array(0).astype(jnp.int32) #ToDo ) initial_obs = self._get_observation(state) @@ -164,9 +237,30 @@ def step(self, state: AdventureState, action: chex.Array) -> Tuple[AdventureObse state = AdventureState( player_x = state.player_x, player_y=state.player_y, + step_counter = state.step_counter, + dragon_yellow_x = state.dragon_yellow_x, + dragon_yellow_y = state.dragon_yellow_y, + dragon_green_x = state.dragon_green_x, + dragon_green_y = state.dragon_green_y, + dragon_yellow = state.dragon_yellow , + dragon_green = state.dragon_green, key_yellow_x = state.key_yellow_x, - key_yellow_y = state.key_yellow_y, - step_counter=state.step_counter, + key_yellow_y = state.key_yellow_y , + key_black_x = state.key_black_x, + key_black_y = state.key_black_y, + key_white_x = state.key_white_x, + key_white_y = state.key_white_y, + gate_yellow = state.gate_yellow, + gate_black = state.gate_black, + gate_white = state.gate_white, + sword_x = state.sword_x, + sword_y = state.sword_y, + bridge_x = state.bridge_x, + bridge_y = state.bridge_y, + magnet_x = state.magnet_x, + magnet_y = state.magnet_y, + chalice_x = state.chalice_x, + chalice_y = state.chalice_y ) state = self._player_step(state, action) From efbc71d76901421745660945b9031a386ad81972 Mon Sep 17 00:00:00 2001 From: Leif Schwass Date: Fri, 19 Dec 2025 18:06:41 +0100 Subject: [PATCH 009/102] rendering black key --- src/jaxatari/games/jax_adventure.py | 31 ++++++++++++++++++----------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index bdf7df1a6..5338157d2 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -42,15 +42,22 @@ def _get_default_asset_config() -> tuple: {'name': 'player_blue', 'type': 'single', 'file': 'Player_Blue.npy'}, {'name': 'player_black', 'type': 'single', 'file': 'Player_Black.npy'}, {'name': 'player_magenta', 'type': 'single', 'file': 'Player_Magenta.npy'}, + #dragons - {'name': 'key_yellow', 'type': 'single', 'file': 'Key_yellow.npy'} + #keys + {'name': 'key_yellow', 'type': 'single', 'file': 'Key_yellow.npy'}, + {'name': 'key_black', 'type': 'single', 'file': 'Key_black.npy'} + #gates + + #items ) class AdventureConstants(NamedTuple): WIDTH: int = 160 HEIGHT: int = 250 - + #upper left corner is 0, 0 + # sset config baked into constants (immutable default) for asset overrides ASSET_CONFIG: tuple = _get_default_asset_config() @@ -76,8 +83,6 @@ class AdventureState(NamedTuple): key_yellow_y: chex.Array key_black_x: chex.Array key_black_y: chex.Array - key_white_x: chex.Array - key_white_y: chex.Array #state of gates (if open or closed) gate_yellow: chex.Array gate_black: chex.Array @@ -173,8 +178,6 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt key_yellow_y = state.key_yellow_y , key_black_x = state.key_black_x, key_black_y = state.key_black_y, - key_white_x = state.key_white_x, - key_white_y = state.key_white_y, gate_yellow = state.gate_yellow, gate_black = state.gate_black, gate_white = state.gate_white, @@ -209,10 +212,8 @@ def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureOb dragon_green = jnp.array(0).astype(jnp.int32), #ToDo key_yellow_x = jnp.array(31).astype(jnp.int32), key_yellow_y = jnp.array(110).astype(jnp.int32), - key_black_x = jnp.array(0).astype(jnp.int32), #ToDo - key_black_y = jnp.array(0).astype(jnp.int32), #ToDo - key_white_x = jnp.array(0).astype(jnp.int32), #ToDo - key_white_y = jnp.array(0).astype(jnp.int32), #ToDo + key_black_x = jnp.array(41).astype(jnp.int32), #ToDo + key_black_y = jnp.array(120).astype(jnp.int32), #ToDo gate_yellow = jnp.array(0).astype(jnp.int32), #ToDo gate_black = jnp.array(0).astype(jnp.int32), #ToDo gate_white = jnp.array(0).astype(jnp.int32), #ToDo @@ -248,8 +249,6 @@ def step(self, state: AdventureState, action: chex.Array) -> Tuple[AdventureObse key_yellow_y = state.key_yellow_y , key_black_x = state.key_black_x, key_black_y = state.key_black_y, - key_white_x = state.key_white_x, - key_white_y = state.key_white_y, gate_yellow = state.gate_yellow, gate_black = state.gate_black, gate_white = state.gate_white, @@ -377,6 +376,14 @@ def render(self, state): player_mask = self.SHAPE_MASKS["player_magenta"] raster = self.jr.render_at(raster, state.player_x, state.player_y, player_mask) + #dragons + + #keys key_yellow_mask = self.SHAPE_MASKS["key_yellow"] raster = self.jr.render_at(raster, state.key_yellow_x, state.key_yellow_y, key_yellow_mask) + key_black_mask = self.SHAPE_MASKS["key_black"] + raster = self.jr.render_at(raster, state.key_black_x, state.key_black_y, key_black_mask) + #items + + return self.jr.render_from_palette(raster, self.PALETTE) From 957bf5f3509ad4a8f783802e5baa9705a7119fbf Mon Sep 17 00:00:00 2001 From: Leif Schwass Date: Fri, 19 Dec 2025 23:28:36 +0100 Subject: [PATCH 010/102] loading off assets, missing everthing else, marked withh ToDos --- src/jaxatari/games/jax_adventure.py | 63 ++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 18 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 5338157d2..e98fbd14a 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -43,13 +43,24 @@ def _get_default_asset_config() -> tuple: {'name': 'player_black', 'type': 'single', 'file': 'Player_Black.npy'}, {'name': 'player_magenta', 'type': 'single', 'file': 'Player_Magenta.npy'}, #dragons + {'name': 'dragon_yellow_neutral', 'type': 'single', 'file': 'Dragon_yellow_neutral.npy'}, + {'name': 'dragon_green-neutral', 'type': 'single', 'file': 'Dragon_green_neutral.npy'}, + #ToDo remaining dragon animations #keys {'name': 'key_yellow', 'type': 'single', 'file': 'Key_yellow.npy'}, - {'name': 'key_black', 'type': 'single', 'file': 'Key_black.npy'} + {'name': 'key_black', 'type': 'single', 'file': 'Key_black.npy'}, #gates + + #ToDo gates animation #items + {'name': 'sword', 'type': 'single', 'file': 'Sword.npy'}, + {'name': 'bridge', 'type': 'single', 'file': 'Bridge.npy'}, + {'name': 'magnet', 'type': 'single', 'file': 'Magnet.npy'}, + #Chalice + {'name': 'chalice', 'type': 'single', 'file': 'Trophy_Pink.npy'} + #ToDo remaining chalice colors for blinking ) @@ -204,27 +215,27 @@ def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureOb player_x = jnp.array(78).astype(jnp.int32), player_y = jnp.array(174).astype(jnp.int32), step_counter = jnp.array(0).astype(jnp.int32), - dragon_yellow_x = jnp.array(0).astype(jnp.int32), #ToDo - dragon_yellow_y = jnp.array(0).astype(jnp.int32), #ToDo - dragon_green_x = jnp.array(0).astype(jnp.int32), #ToDo - dragon_green_y = jnp.array(0).astype(jnp.int32), #ToDo + dragon_yellow_x = jnp.array(120).astype(jnp.int32), #ToDo + dragon_yellow_y = jnp.array(50).astype(jnp.int32), #ToDo + dragon_green_x = jnp.array(120).astype(jnp.int32), #ToDo + dragon_green_y = jnp.array(70).astype(jnp.int32), #ToDo dragon_yellow = jnp.array(0).astype(jnp.int32), #ToDo dragon_green = jnp.array(0).astype(jnp.int32), #ToDo key_yellow_x = jnp.array(31).astype(jnp.int32), key_yellow_y = jnp.array(110).astype(jnp.int32), - key_black_x = jnp.array(41).astype(jnp.int32), #ToDo - key_black_y = jnp.array(120).astype(jnp.int32), #ToDo + key_black_x = jnp.array(120).astype(jnp.int32), #ToDo + key_black_y = jnp.array(90).astype(jnp.int32), #ToDo gate_yellow = jnp.array(0).astype(jnp.int32), #ToDo gate_black = jnp.array(0).astype(jnp.int32), #ToDo gate_white = jnp.array(0).astype(jnp.int32), #ToDo - sword_x = jnp.array(0).astype(jnp.int32), #ToDo - sword_y = jnp.array(0).astype(jnp.int32), #ToDo - bridge_x = jnp.array(0).astype(jnp.int32), #ToDo - bridge_y = jnp.array(0).astype(jnp.int32), #ToDo - magnet_x = jnp.array(0).astype(jnp.int32), #ToDo - magnet_y = jnp.array(0).astype(jnp.int32), #ToDo - chalice_x = jnp.array(0).astype(jnp.int32), #ToDo - chalice_y = jnp.array(0).astype(jnp.int32) #ToDo + sword_x = jnp.array(120).astype(jnp.int32), #ToDo + sword_y = jnp.array(110).astype(jnp.int32), #ToDo + bridge_x = jnp.array(120).astype(jnp.int32), #ToDo + bridge_y = jnp.array(130).astype(jnp.int32), #ToDo + magnet_x = jnp.array(120).astype(jnp.int32), #ToDo + magnet_y = jnp.array(150).astype(jnp.int32), #ToDo + chalice_x = jnp.array(120).astype(jnp.int32), #ToDo + chalice_y = jnp.array(170).astype(jnp.int32) #ToDo ) initial_obs = self._get_observation(state) @@ -289,9 +300,12 @@ def _get_observation(self, state: AdventureState): height=4 ) + #ToDo for the rest of the dragons, items etc..... + return AdventureObservation( player=player, key_yellow=key_yellow + #ToDo for the rest of the dragons, items etc..... ) @partial(jax.jit, static_argnums=(0,)) @@ -321,6 +335,8 @@ def observation_space(self) -> spaces: "width": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), "height": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), }), + + #ToDo for the rest of the dragons, items etc..... }) def image_space(self) -> spaces.Box: @@ -350,7 +366,7 @@ def __init__(self, consts: AdventureConstants = None): self.config = render_utils.RendererConfig( game_dimensions=(250, 160), channels=3, - #downscale=(84, 84) + #downscale=(200, 128) ) self.jr = render_utils.JaxRenderingUtils(self.config) @@ -377,13 +393,24 @@ def render(self, state): raster = self.jr.render_at(raster, state.player_x, state.player_y, player_mask) #dragons - + dragon_yellow_mask = self.SHAPE_MASKS["dragon_yellow_neutral"] + raster = self.jr.render_at(raster, state.dragon_yellow_x, state.dragon_yellow_y, dragon_yellow_mask) + dragon_green_mask = self.SHAPE_MASKS["dragon_green-neutral"] + raster = self.jr.render_at(raster, state.dragon_green_x, state.dragon_green_y, dragon_green_mask) #keys key_yellow_mask = self.SHAPE_MASKS["key_yellow"] raster = self.jr.render_at(raster, state.key_yellow_x, state.key_yellow_y, key_yellow_mask) key_black_mask = self.SHAPE_MASKS["key_black"] raster = self.jr.render_at(raster, state.key_black_x, state.key_black_y, key_black_mask) #items - + sword_mask = self.SHAPE_MASKS["sword"] + raster = self.jr.render_at(raster, state.sword_x, state.sword_y, sword_mask) + bridge_mask = self.SHAPE_MASKS["bridge"] + raster = self.jr.render_at(raster, state.bridge_x, state.bridge_y, bridge_mask) + magnet_mask = self.SHAPE_MASKS["magnet"] + raster = self.jr.render_at(raster, state.magnet_x, state.magnet_y, magnet_mask) + #chalice + chalice_mask = self.SHAPE_MASKS["chalice"] + raster = self.jr.render_at(raster, state.chalice_x, state.chalice_y, chalice_mask) return self.jr.render_from_palette(raster, self.PALETTE) From d09086de6147930c782fa20a875a719855cb6c18 Mon Sep 17 00:00:00 2001 From: Leif Schwass Date: Sat, 20 Dec 2025 11:48:01 +0100 Subject: [PATCH 011/102] Added Tile state --- src/jaxatari/games/jax_adventure.py | 79 ++++++++++++++++++++++------- 1 file changed, 60 insertions(+), 19 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index e98fbd14a..e528e6239 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -76,45 +76,55 @@ class AdventureConstants(NamedTuple): # immutable state container class AdventureState(NamedTuple): - #position player - player_x: chex.Array - player_y:chex.Array #step conter for performance indicator? step_counter: chex.Array + #position player + player_x: chex.Array + player_y: chex.Array + player_tile: chex.Array #positions dragons dragon_yellow_x: chex.Array dragon_yellow_y: chex.Array + dragon_yellow_tile: chex.Array dragon_green_x: chex.Array dragon_green_y: chex.Array + dragon_green_tile: chex.Array #state dragons (alive, dead, attacking) dragon_yellow: chex.Array dragon_green: chex.Array #positions keys key_yellow_x: chex.Array key_yellow_y: chex.Array + key_yellow_tile: chex.Array key_black_x: chex.Array key_black_y: chex.Array + key_black_tile: chex.Array #state of gates (if open or closed) gate_yellow: chex.Array gate_black: chex.Array gate_white: chex.Array #position sword sword_x: chex.Array - sword_y:chex.Array + sword_y: chex.Array + sword_tile: chex.Array #position bridge bridge_x: chex.Array - bridge_y:chex.Array + bridge_y: chex.Array + bridge_tile: chex.Array #position magnet magnet_x: chex.Array - magnet_y:chex.Array + magnet_y: chex.Array + magnet_tile: chex.Array #position chalice chalice_x: chex.Array - chalice_y:chex.Array + chalice_y: chex.Array + chalice_tile: chex.Array class EntityPosition(NamedTuple): x: jnp.ndarray y: jnp.ndarray + tile: jnp.ndarray width: jnp.ndarray height: jnp.ndarray @@ -128,7 +138,7 @@ class AdventureInfo(NamedTuple): time: jnp.ndarray -class JaxPong(JaxEnvironment[AdventureState, AdventureObservation, AdventureInfo, AdventureConstants]): +class JaxAdventure(JaxEnvironment[AdventureState, AdventureObservation, AdventureInfo, AdventureConstants]): def __init__(self, consts: AdventureConstants = None): consts = consts or AdventureConstants() super().__init__(consts) @@ -176,30 +186,39 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt ) return AdventureState( + step_counter = state.step_counter, player_x = new_player_x, player_y = new_player_y, - step_counter = state.step_counter, + player_tile = state.player_tile, dragon_yellow_x = state.dragon_yellow_x, dragon_yellow_y = state.dragon_yellow_y, + dragon_yellow_tile = state.dragon_yellow_tile, dragon_green_x = state.dragon_green_x, dragon_green_y = state.dragon_green_y, - dragon_yellow = state.dragon_yellow , + dragon_green_tile=state.dragon_green_tile, + dragon_yellow = state.dragon_yellow, dragon_green = state.dragon_green, key_yellow_x = state.key_yellow_x, - key_yellow_y = state.key_yellow_y , + key_yellow_y = state.key_yellow_y, + key_yellow_tile=state.key_yellow_tile, key_black_x = state.key_black_x, key_black_y = state.key_black_y, + key_black_tile=state.key_black_tile, gate_yellow = state.gate_yellow, gate_black = state.gate_black, gate_white = state.gate_white, sword_x = state.sword_x, sword_y = state.sword_y, + sword_tile=state.sword_tile, bridge_x = state.bridge_x, bridge_y = state.bridge_y, + bridge_tile=state.bridge_tile, magnet_x = state.magnet_x, magnet_y = state.magnet_y, + magnet_tile=state.magnet_tile, chalice_x = state.chalice_x, - chalice_y = state.chalice_y + chalice_y = state.chalice_y, + chalice_tile=state.chalice_tile ) @@ -212,30 +231,41 @@ def step(self, state: AdventureState, action: chex.Array) -> Tuple[AdventureObse def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureObservation, AdventureState]: state = AdventureState( - player_x = jnp.array(78).astype(jnp.int32), - player_y = jnp.array(174).astype(jnp.int32), step_counter = jnp.array(0).astype(jnp.int32), + #player + player_x = jnp.array(78).astype(jnp.int32), #spawn X + player_y = jnp.array(174).astype(jnp.int32), #spawn Y + player_tile = jnp.array(1).astype(jnp.int32), #Spawn Tile + #Dragons dragon_yellow_x = jnp.array(120).astype(jnp.int32), #ToDo dragon_yellow_y = jnp.array(50).astype(jnp.int32), #ToDo + dragon_yellow_tile = jnp.array(1).astype(jnp.int32), #ToDo dragon_green_x = jnp.array(120).astype(jnp.int32), #ToDo dragon_green_y = jnp.array(70).astype(jnp.int32), #ToDo + dragon_green_tile = jnp.array(70).astype(jnp.int32), #ToDo dragon_yellow = jnp.array(0).astype(jnp.int32), #ToDo dragon_green = jnp.array(0).astype(jnp.int32), #ToDo key_yellow_x = jnp.array(31).astype(jnp.int32), key_yellow_y = jnp.array(110).astype(jnp.int32), + key_yellow_tile = jnp.array(1).astype(jnp.int32), key_black_x = jnp.array(120).astype(jnp.int32), #ToDo key_black_y = jnp.array(90).astype(jnp.int32), #ToDo + key_black_tile = jnp.array(1).astype(jnp.int32), #ToDo gate_yellow = jnp.array(0).astype(jnp.int32), #ToDo gate_black = jnp.array(0).astype(jnp.int32), #ToDo gate_white = jnp.array(0).astype(jnp.int32), #ToDo sword_x = jnp.array(120).astype(jnp.int32), #ToDo sword_y = jnp.array(110).astype(jnp.int32), #ToDo + sword_tile = jnp.array(1).astype(jnp.int32), #ToDo bridge_x = jnp.array(120).astype(jnp.int32), #ToDo bridge_y = jnp.array(130).astype(jnp.int32), #ToDo + bridge_tile = jnp.array(1).astype(jnp.int32), #ToDo magnet_x = jnp.array(120).astype(jnp.int32), #ToDo magnet_y = jnp.array(150).astype(jnp.int32), #ToDo + magnet_tile = jnp.array(1).astype(jnp.int32), #ToDo chalice_x = jnp.array(120).astype(jnp.int32), #ToDo - chalice_y = jnp.array(170).astype(jnp.int32) #ToDo + chalice_y = jnp.array(170).astype(jnp.int32), #ToDo + chalice_tile = jnp.array(170).astype(jnp.int32) #ToDo ) initial_obs = self._get_observation(state) @@ -247,30 +277,39 @@ def step(self, state: AdventureState, action: chex.Array) -> Tuple[AdventureObse previous_state = state # Make per-step key available to helpers that may read state.key state = AdventureState( + step_counter = state.step_counter, player_x = state.player_x, player_y=state.player_y, - step_counter = state.step_counter, + player_tile = state.player_tile, dragon_yellow_x = state.dragon_yellow_x, dragon_yellow_y = state.dragon_yellow_y, + dragon_yellow_tile = state.dragon_yellow_tile, dragon_green_x = state.dragon_green_x, dragon_green_y = state.dragon_green_y, - dragon_yellow = state.dragon_yellow , + dragon_green_tile=state.dragon_green_tile, + dragon_yellow = state.dragon_yellow, dragon_green = state.dragon_green, key_yellow_x = state.key_yellow_x, - key_yellow_y = state.key_yellow_y , + key_yellow_y = state.key_yellow_y, + key_yellow_tile=state.key_yellow_tile, key_black_x = state.key_black_x, key_black_y = state.key_black_y, + key_black_tile=state.key_black_tile, gate_yellow = state.gate_yellow, gate_black = state.gate_black, gate_white = state.gate_white, sword_x = state.sword_x, sword_y = state.sword_y, + sword_tile=state.sword_tile, bridge_x = state.bridge_x, bridge_y = state.bridge_y, + bridge_tile=state.bridge_tile, magnet_x = state.magnet_x, magnet_y = state.magnet_y, + magnet_tile=state.magnet_tile, chalice_x = state.chalice_x, - chalice_y = state.chalice_y + chalice_y = state.chalice_y, + chalice_tile=state.chalice_tile ) state = self._player_step(state, action) @@ -290,12 +329,14 @@ def _get_observation(self, state: AdventureState): player = EntityPosition( x=state.player_x, y=state.player_y, + tile=1, #ToDO width=4, height=8 ) key_yellow = EntityPosition( x=state.key_yellow_x, y=state.key_yellow_y, + tile=1, #ToDO width=10, height=4 ) From de4646d7dbcd1e56a05c03e638a72e168a08ed32 Mon Sep 17 00:00:00 2001 From: LucyLMM Date: Sat, 20 Dec 2025 11:49:28 +0100 Subject: [PATCH 012/102] Room Numeration --- .../adventure/{Room_YellowCastle.npy => Room_1.npy} | Bin .../adventure/{Room_Maze_5.npy => Room_10.npy} | Bin .../adventure/{Room_Maze_3.npy => Room_11.npy} | Bin .../{Room_Black_Castle.npy => Room_12.npy} | Bin .../{Room_Pink_Corridor.npy => Room_13.npy} | Bin .../adventure/{Room_Magenta.npy => Room_14.npy} | Bin .../adventure/{Room_Yellow.npy => Room_2.npy} | Bin .../adventure/{Room_Green.npy => Room_3.npy} | Bin .../adventure/{Room_Purple.npy => Room_4.npy} | Bin .../sprites/adventure/{Room_Pink.npy => Room_5.npy} | Bin .../adventure/{Room_Green_Yellow.npy => Room_6.npy} | Bin .../adventure/{Room_Maze_1.npy => Room_7.npy} | Bin .../adventure/{Room_Maze_2.npy => Room_8.npy} | Bin .../adventure/{Room_Maze_4.npy => Room_9.npy} | Bin 14 files changed, 0 insertions(+), 0 deletions(-) rename src/jaxatari/games/sprites/adventure/{Room_YellowCastle.npy => Room_1.npy} (100%) rename src/jaxatari/games/sprites/adventure/{Room_Maze_5.npy => Room_10.npy} (100%) rename src/jaxatari/games/sprites/adventure/{Room_Maze_3.npy => Room_11.npy} (100%) rename src/jaxatari/games/sprites/adventure/{Room_Black_Castle.npy => Room_12.npy} (100%) rename src/jaxatari/games/sprites/adventure/{Room_Pink_Corridor.npy => Room_13.npy} (100%) rename src/jaxatari/games/sprites/adventure/{Room_Magenta.npy => Room_14.npy} (100%) rename src/jaxatari/games/sprites/adventure/{Room_Yellow.npy => Room_2.npy} (100%) rename src/jaxatari/games/sprites/adventure/{Room_Green.npy => Room_3.npy} (100%) rename src/jaxatari/games/sprites/adventure/{Room_Purple.npy => Room_4.npy} (100%) rename src/jaxatari/games/sprites/adventure/{Room_Pink.npy => Room_5.npy} (100%) rename src/jaxatari/games/sprites/adventure/{Room_Green_Yellow.npy => Room_6.npy} (100%) rename src/jaxatari/games/sprites/adventure/{Room_Maze_1.npy => Room_7.npy} (100%) rename src/jaxatari/games/sprites/adventure/{Room_Maze_2.npy => Room_8.npy} (100%) rename src/jaxatari/games/sprites/adventure/{Room_Maze_4.npy => Room_9.npy} (100%) diff --git a/src/jaxatari/games/sprites/adventure/Room_YellowCastle.npy b/src/jaxatari/games/sprites/adventure/Room_1.npy similarity index 100% rename from src/jaxatari/games/sprites/adventure/Room_YellowCastle.npy rename to src/jaxatari/games/sprites/adventure/Room_1.npy diff --git a/src/jaxatari/games/sprites/adventure/Room_Maze_5.npy b/src/jaxatari/games/sprites/adventure/Room_10.npy similarity index 100% rename from src/jaxatari/games/sprites/adventure/Room_Maze_5.npy rename to src/jaxatari/games/sprites/adventure/Room_10.npy diff --git a/src/jaxatari/games/sprites/adventure/Room_Maze_3.npy b/src/jaxatari/games/sprites/adventure/Room_11.npy similarity index 100% rename from src/jaxatari/games/sprites/adventure/Room_Maze_3.npy rename to src/jaxatari/games/sprites/adventure/Room_11.npy diff --git a/src/jaxatari/games/sprites/adventure/Room_Black_Castle.npy b/src/jaxatari/games/sprites/adventure/Room_12.npy similarity index 100% rename from src/jaxatari/games/sprites/adventure/Room_Black_Castle.npy rename to src/jaxatari/games/sprites/adventure/Room_12.npy diff --git a/src/jaxatari/games/sprites/adventure/Room_Pink_Corridor.npy b/src/jaxatari/games/sprites/adventure/Room_13.npy similarity index 100% rename from src/jaxatari/games/sprites/adventure/Room_Pink_Corridor.npy rename to src/jaxatari/games/sprites/adventure/Room_13.npy diff --git a/src/jaxatari/games/sprites/adventure/Room_Magenta.npy b/src/jaxatari/games/sprites/adventure/Room_14.npy similarity index 100% rename from src/jaxatari/games/sprites/adventure/Room_Magenta.npy rename to src/jaxatari/games/sprites/adventure/Room_14.npy diff --git a/src/jaxatari/games/sprites/adventure/Room_Yellow.npy b/src/jaxatari/games/sprites/adventure/Room_2.npy similarity index 100% rename from src/jaxatari/games/sprites/adventure/Room_Yellow.npy rename to src/jaxatari/games/sprites/adventure/Room_2.npy diff --git a/src/jaxatari/games/sprites/adventure/Room_Green.npy b/src/jaxatari/games/sprites/adventure/Room_3.npy similarity index 100% rename from src/jaxatari/games/sprites/adventure/Room_Green.npy rename to src/jaxatari/games/sprites/adventure/Room_3.npy diff --git a/src/jaxatari/games/sprites/adventure/Room_Purple.npy b/src/jaxatari/games/sprites/adventure/Room_4.npy similarity index 100% rename from src/jaxatari/games/sprites/adventure/Room_Purple.npy rename to src/jaxatari/games/sprites/adventure/Room_4.npy diff --git a/src/jaxatari/games/sprites/adventure/Room_Pink.npy b/src/jaxatari/games/sprites/adventure/Room_5.npy similarity index 100% rename from src/jaxatari/games/sprites/adventure/Room_Pink.npy rename to src/jaxatari/games/sprites/adventure/Room_5.npy diff --git a/src/jaxatari/games/sprites/adventure/Room_Green_Yellow.npy b/src/jaxatari/games/sprites/adventure/Room_6.npy similarity index 100% rename from src/jaxatari/games/sprites/adventure/Room_Green_Yellow.npy rename to src/jaxatari/games/sprites/adventure/Room_6.npy diff --git a/src/jaxatari/games/sprites/adventure/Room_Maze_1.npy b/src/jaxatari/games/sprites/adventure/Room_7.npy similarity index 100% rename from src/jaxatari/games/sprites/adventure/Room_Maze_1.npy rename to src/jaxatari/games/sprites/adventure/Room_7.npy diff --git a/src/jaxatari/games/sprites/adventure/Room_Maze_2.npy b/src/jaxatari/games/sprites/adventure/Room_8.npy similarity index 100% rename from src/jaxatari/games/sprites/adventure/Room_Maze_2.npy rename to src/jaxatari/games/sprites/adventure/Room_8.npy diff --git a/src/jaxatari/games/sprites/adventure/Room_Maze_4.npy b/src/jaxatari/games/sprites/adventure/Room_9.npy similarity index 100% rename from src/jaxatari/games/sprites/adventure/Room_Maze_4.npy rename to src/jaxatari/games/sprites/adventure/Room_9.npy From 7560017c8a4a4903434dc059fac6697a319eba83 Mon Sep 17 00:00:00 2001 From: LucyLMM Date: Sat, 20 Dec 2025 11:52:12 +0100 Subject: [PATCH 013/102] Updated BG functional with numeration --- src/jaxatari/games/jax_adventure.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index e528e6239..b2842b272 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -19,20 +19,20 @@ def _get_default_asset_config() -> tuple: """ return ( #all rooms in order - {'name': 'bg_yellow_castle', 'type': 'background', 'file': 'Room_YellowCastle.npy'}, - {'name': 'bg_yellow', 'type': 'background', 'file': 'Room_Yellow.npy'}, - {'name': 'bg_green', 'type': 'background', 'file': 'Room_Green.npy'}, - {'name': 'bg_purple', 'type': 'background', 'file': 'Room_Purple.npy'}, - {'name': 'bg_pink', 'type': 'background', 'file': 'Room_Pink.npy'}, - {'name': 'bg_green_yellow', 'type': 'background', 'file': 'Room_Green_Yellow.npy'}, - {'name': 'bg_maze_1', 'type': 'background', 'file': 'Room_Maze_1.npy'}, - {'name': 'bg_maze_2', 'type': 'background', 'file': 'Room_Maze_2.npy'}, - {'name': 'bg_maze_3', 'type': 'background', 'file': 'Room_Maze_3.npy'}, - {'name': 'bg_maze_4', 'type': 'background', 'file': 'Room_Maze_4.npy'}, - {'name': 'bg_maze_5', 'type': 'background', 'file': 'Room_Maze_5.npy'}, - {'name': 'bg_black_castle', 'type': 'background', 'file': 'Room_Black_Castle.npy'}, - {'name': 'bg_ping_corridor', 'type': 'background', 'file': 'Room_Pink_Corridor.npy'}, - {'name': 'bg_magenta', 'type': 'background', 'file': 'Room_Magenta.npy'}, + {'name': 'bg_yellow_castle', 'type': 'background', 'file': 'Room_1.npy'}, + {'name': 'bg_yellow', 'type': 'background', 'file': 'Room_2.npy'}, + {'name': 'bg_green', 'type': 'background', 'file': 'Room_3.npy'}, + {'name': 'bg_purple', 'type': 'background', 'file': 'Room_4.npy'}, + {'name': 'bg_pink', 'type': 'background', 'file': 'Room_5.npy'}, + {'name': 'bg_green_yellow', 'type': 'background', 'file': 'Room_6.npy'}, + {'name': 'bg_maze_1', 'type': 'background', 'file': 'Room_7.npy'}, + {'name': 'bg_maze_2', 'type': 'background', 'file': 'Room_8.npy'}, + {'name': 'bg_maze_3', 'type': 'background', 'file': 'Room_9.npy'}, + {'name': 'bg_maze_4', 'type': 'background', 'file': 'Room_10.npy'}, + {'name': 'bg_maze_5', 'type': 'background', 'file': 'Room_11.npy'}, + {'name': 'bg_black_castle', 'type': 'background', 'file': 'Room_12.npy'}, + {'name': 'bg_ping_corridor', 'type': 'background', 'file': 'Room_13.npy'}, + {'name': 'bg_magenta', 'type': 'background', 'file': 'Room_14.npy'}, #all player colors in order {'name': 'player_yellow', 'type': 'single', 'file': 'Player_Yellow.npy'}, {'name': 'player_green', 'type': 'single', 'file': 'Player_Green.npy'}, From 11e29499c37fcfd07b043fd24aa45e02f89afa04 Mon Sep 17 00:00:00 2001 From: LucyLMM Date: Sat, 20 Dec 2025 12:12:11 +0100 Subject: [PATCH 014/102] Trophy -> Chalice --- src/jaxatari/games/jax_adventure.py | 2 +- .../{Trophy_Black.npy => Chalice_Black.npy} | Bin .../{Trophy_DarkBlue.npy => Chalice_DarkBlue.npy} | Bin .../adventure/{Trophy_Gray.npy => Chalice_Gray.npy} | Bin .../{Trophy_Green.npy => Chalice_Green.npy} | Bin .../{Trophy_LightBlue.npy => Chalice_LightBlue.npy} | Bin .../adventure/{Trophy_Pink.npy => Chalice_Pink.npy} | Bin .../{Trophy_Purple.npy => Chalice_Purple.npy} | Bin .../adventure/{Trophy_Red.npy => Chalice_Red.npy} | Bin .../{Trophy_Turquoise.npy => Chalice_Turquoise.npy} | Bin .../{Trophy_Yellow.npy => Chalice_Yellow.npy} | Bin 11 files changed, 1 insertion(+), 1 deletion(-) rename src/jaxatari/games/sprites/adventure/{Trophy_Black.npy => Chalice_Black.npy} (100%) rename src/jaxatari/games/sprites/adventure/{Trophy_DarkBlue.npy => Chalice_DarkBlue.npy} (100%) rename src/jaxatari/games/sprites/adventure/{Trophy_Gray.npy => Chalice_Gray.npy} (100%) rename src/jaxatari/games/sprites/adventure/{Trophy_Green.npy => Chalice_Green.npy} (100%) rename src/jaxatari/games/sprites/adventure/{Trophy_LightBlue.npy => Chalice_LightBlue.npy} (100%) rename src/jaxatari/games/sprites/adventure/{Trophy_Pink.npy => Chalice_Pink.npy} (100%) rename src/jaxatari/games/sprites/adventure/{Trophy_Purple.npy => Chalice_Purple.npy} (100%) rename src/jaxatari/games/sprites/adventure/{Trophy_Red.npy => Chalice_Red.npy} (100%) rename src/jaxatari/games/sprites/adventure/{Trophy_Turquoise.npy => Chalice_Turquoise.npy} (100%) rename src/jaxatari/games/sprites/adventure/{Trophy_Yellow.npy => Chalice_Yellow.npy} (100%) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index b2842b272..f53c21449 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -59,7 +59,7 @@ def _get_default_asset_config() -> tuple: {'name': 'bridge', 'type': 'single', 'file': 'Bridge.npy'}, {'name': 'magnet', 'type': 'single', 'file': 'Magnet.npy'}, #Chalice - {'name': 'chalice', 'type': 'single', 'file': 'Trophy_Pink.npy'} + {'name': 'chalice', 'type': 'single', 'file': 'Chalice_Pink.npy'} #ToDo remaining chalice colors for blinking ) diff --git a/src/jaxatari/games/sprites/adventure/Trophy_Black.npy b/src/jaxatari/games/sprites/adventure/Chalice_Black.npy similarity index 100% rename from src/jaxatari/games/sprites/adventure/Trophy_Black.npy rename to src/jaxatari/games/sprites/adventure/Chalice_Black.npy diff --git a/src/jaxatari/games/sprites/adventure/Trophy_DarkBlue.npy b/src/jaxatari/games/sprites/adventure/Chalice_DarkBlue.npy similarity index 100% rename from src/jaxatari/games/sprites/adventure/Trophy_DarkBlue.npy rename to src/jaxatari/games/sprites/adventure/Chalice_DarkBlue.npy diff --git a/src/jaxatari/games/sprites/adventure/Trophy_Gray.npy b/src/jaxatari/games/sprites/adventure/Chalice_Gray.npy similarity index 100% rename from src/jaxatari/games/sprites/adventure/Trophy_Gray.npy rename to src/jaxatari/games/sprites/adventure/Chalice_Gray.npy diff --git a/src/jaxatari/games/sprites/adventure/Trophy_Green.npy b/src/jaxatari/games/sprites/adventure/Chalice_Green.npy similarity index 100% rename from src/jaxatari/games/sprites/adventure/Trophy_Green.npy rename to src/jaxatari/games/sprites/adventure/Chalice_Green.npy diff --git a/src/jaxatari/games/sprites/adventure/Trophy_LightBlue.npy b/src/jaxatari/games/sprites/adventure/Chalice_LightBlue.npy similarity index 100% rename from src/jaxatari/games/sprites/adventure/Trophy_LightBlue.npy rename to src/jaxatari/games/sprites/adventure/Chalice_LightBlue.npy diff --git a/src/jaxatari/games/sprites/adventure/Trophy_Pink.npy b/src/jaxatari/games/sprites/adventure/Chalice_Pink.npy similarity index 100% rename from src/jaxatari/games/sprites/adventure/Trophy_Pink.npy rename to src/jaxatari/games/sprites/adventure/Chalice_Pink.npy diff --git a/src/jaxatari/games/sprites/adventure/Trophy_Purple.npy b/src/jaxatari/games/sprites/adventure/Chalice_Purple.npy similarity index 100% rename from src/jaxatari/games/sprites/adventure/Trophy_Purple.npy rename to src/jaxatari/games/sprites/adventure/Chalice_Purple.npy diff --git a/src/jaxatari/games/sprites/adventure/Trophy_Red.npy b/src/jaxatari/games/sprites/adventure/Chalice_Red.npy similarity index 100% rename from src/jaxatari/games/sprites/adventure/Trophy_Red.npy rename to src/jaxatari/games/sprites/adventure/Chalice_Red.npy diff --git a/src/jaxatari/games/sprites/adventure/Trophy_Turquoise.npy b/src/jaxatari/games/sprites/adventure/Chalice_Turquoise.npy similarity index 100% rename from src/jaxatari/games/sprites/adventure/Trophy_Turquoise.npy rename to src/jaxatari/games/sprites/adventure/Chalice_Turquoise.npy diff --git a/src/jaxatari/games/sprites/adventure/Trophy_Yellow.npy b/src/jaxatari/games/sprites/adventure/Chalice_Yellow.npy similarity index 100% rename from src/jaxatari/games/sprites/adventure/Trophy_Yellow.npy rename to src/jaxatari/games/sprites/adventure/Chalice_Yellow.npy From b0fb466513ea35ac431d39307ffafc257430c795 Mon Sep 17 00:00:00 2001 From: Leif Schwass Date: Sat, 20 Dec 2025 12:14:17 +0100 Subject: [PATCH 015/102] Extended Adventure observer --- src/jaxatari/games/jax_adventure.py | 148 ++++++++++++++++++++++------ 1 file changed, 118 insertions(+), 30 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index e528e6239..c32455e75 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -90,8 +90,8 @@ class AdventureState(NamedTuple): dragon_green_y: chex.Array dragon_green_tile: chex.Array #state dragons (alive, dead, attacking) - dragon_yellow: chex.Array - dragon_green: chex.Array + dragon_yellow_state: chex.Array + dragon_green_state: chex.Array #positions keys key_yellow_x: chex.Array key_yellow_y: chex.Array @@ -100,9 +100,8 @@ class AdventureState(NamedTuple): key_black_y: chex.Array key_black_tile: chex.Array #state of gates (if open or closed) - gate_yellow: chex.Array - gate_black: chex.Array - gate_white: chex.Array + gate_yellow_state: chex.Array + gate_black_state: chex.Array #position sword sword_x: chex.Array sword_y: chex.Array @@ -127,11 +126,21 @@ class EntityPosition(NamedTuple): tile: jnp.ndarray width: jnp.ndarray height: jnp.ndarray + state: jnp.ndarray class AdventureObservation(NamedTuple): player: EntityPosition + dragon_yellow: EntityPosition + dragon_green: EntityPosition key_yellow: EntityPosition + key_black: EntityPosition + gate_yellow: EntityPosition + gate_black: EntityPosition + sword: EntityPosition + bridge: EntityPosition + magnet: EntityPosition + chalice: EntityPosition class AdventureInfo(NamedTuple): @@ -196,17 +205,16 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt dragon_green_x = state.dragon_green_x, dragon_green_y = state.dragon_green_y, dragon_green_tile=state.dragon_green_tile, - dragon_yellow = state.dragon_yellow, - dragon_green = state.dragon_green, + dragon_yellow_state = state.dragon_yellow_state, + dragon_green_state = state.dragon_green_state, key_yellow_x = state.key_yellow_x, key_yellow_y = state.key_yellow_y, key_yellow_tile=state.key_yellow_tile, key_black_x = state.key_black_x, key_black_y = state.key_black_y, key_black_tile=state.key_black_tile, - gate_yellow = state.gate_yellow, - gate_black = state.gate_black, - gate_white = state.gate_white, + gate_yellow_state = state.gate_yellow_state, + gate_black_state = state.gate_black_state, sword_x = state.sword_x, sword_y = state.sword_y, sword_tile=state.sword_tile, @@ -243,17 +251,18 @@ def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureOb dragon_green_x = jnp.array(120).astype(jnp.int32), #ToDo dragon_green_y = jnp.array(70).astype(jnp.int32), #ToDo dragon_green_tile = jnp.array(70).astype(jnp.int32), #ToDo - dragon_yellow = jnp.array(0).astype(jnp.int32), #ToDo - dragon_green = jnp.array(0).astype(jnp.int32), #ToDo + dragon_yellow_state = jnp.array(0).astype(jnp.int32), #ToDo + dragon_green_state = jnp.array(0).astype(jnp.int32), #ToDo + #Keys key_yellow_x = jnp.array(31).astype(jnp.int32), key_yellow_y = jnp.array(110).astype(jnp.int32), key_yellow_tile = jnp.array(1).astype(jnp.int32), key_black_x = jnp.array(120).astype(jnp.int32), #ToDo key_black_y = jnp.array(90).astype(jnp.int32), #ToDo key_black_tile = jnp.array(1).astype(jnp.int32), #ToDo - gate_yellow = jnp.array(0).astype(jnp.int32), #ToDo - gate_black = jnp.array(0).astype(jnp.int32), #ToDo - gate_white = jnp.array(0).astype(jnp.int32), #ToDo + gate_yellow_state = jnp.array(0).astype(jnp.int32), #ToDo + gate_black_state = jnp.array(0).astype(jnp.int32), #ToDo + #Items sword_x = jnp.array(120).astype(jnp.int32), #ToDo sword_y = jnp.array(110).astype(jnp.int32), #ToDo sword_tile = jnp.array(1).astype(jnp.int32), #ToDo @@ -280,24 +289,23 @@ def step(self, state: AdventureState, action: chex.Array) -> Tuple[AdventureObse step_counter = state.step_counter, player_x = state.player_x, player_y=state.player_y, - player_tile = state.player_tile, + player_tile = state.player_tile, dragon_yellow_x = state.dragon_yellow_x, dragon_yellow_y = state.dragon_yellow_y, dragon_yellow_tile = state.dragon_yellow_tile, dragon_green_x = state.dragon_green_x, dragon_green_y = state.dragon_green_y, dragon_green_tile=state.dragon_green_tile, - dragon_yellow = state.dragon_yellow, - dragon_green = state.dragon_green, + dragon_yellow_state = state.dragon_yellow_state, + dragon_green_state = state.dragon_green_state, key_yellow_x = state.key_yellow_x, key_yellow_y = state.key_yellow_y, key_yellow_tile=state.key_yellow_tile, key_black_x = state.key_black_x, key_black_y = state.key_black_y, key_black_tile=state.key_black_tile, - gate_yellow = state.gate_yellow, - gate_black = state.gate_black, - gate_white = state.gate_white, + gate_yellow_state = state.gate_yellow_state, + gate_black_state = state.gate_black_state, sword_x = state.sword_x, sword_y = state.sword_y, sword_tile=state.sword_tile, @@ -329,24 +337,104 @@ def _get_observation(self, state: AdventureState): player = EntityPosition( x=state.player_x, y=state.player_y, - tile=1, #ToDO - width=4, - height=8 + tile=state.player_tile, + width=4, #ToDO + height=8, #ToDO + state=1 #ToDO + ) + dragon_yellow = EntityPosition( + x=state.dragon_yellow_x, + y=state.dragon_yellow_y, + tile=state.dragon_yellow_tile, + width=10, #ToDO + height=4, #ToDO + state=1 #ToDO + ) + dragon_green = EntityPosition( + x=state.dragon_green_x, + y=state.dragon_green_y, + tile=state.dragon_green_tile, + width=10, #ToDO + height=4, #ToDO + state=1 #ToDO ) key_yellow = EntityPosition( x=state.key_yellow_x, y=state.key_yellow_y, + tile=state.key_yellow_tile, + width=10, #ToDO + height=4, #ToDO + state=1 #ToDO + ) + key_black = EntityPosition( + x=state.key_black_x, + y=state.key_black_y, + tile=state.key_black_tile, + width=10, #ToDO + height=4, #ToDO + state=1 #ToDO + ) + gate_yellow = EntityPosition( + x=80, #ToDO + y=80, #ToDO tile=1, #ToDO - width=10, - height=4 + width=10, #ToDO + height=4, #ToDO + state=state.gate_yellow_state #ToDO + ) + gate_black = EntityPosition( + x=100, #ToDO + y=100, #ToDO + tile=1, #ToDO + width=10, #ToDO + height=4, #ToDO + state=state.gate_black_state #ToDO + ) + sword = EntityPosition( + x=state.sword_x, + y=state.sword_y, + tile=state.sword_tile, + width=10, #ToDO + height=4, #ToDO + state=1 #ToDO + ) + bridge = EntityPosition( + x=state.bridge_x, + y=state.bridge_y, + tile=state.bridge_tile, + width=10, #ToDO + height=4, #ToDO + state=1 #ToDO + ) + magnet = EntityPosition( + x=state.magnet_x, + y=state.magnet_y, + tile=state.magnet_tile, + width=10, #ToDO + height=4, #ToDO + state=1 #ToDO + ) + chalice = EntityPosition( + x=state.chalice_x, + y=state.chalice_y, + tile=state.chalice_tile, + width=10, #ToDO + height=4, #ToDO + state=1 #ToDO ) - - #ToDo for the rest of the dragons, items etc..... return AdventureObservation( player=player, - key_yellow=key_yellow - #ToDo for the rest of the dragons, items etc..... + dragon_yellow=dragon_yellow, + dragon_green=dragon_green, + key_yellow=key_yellow, + key_black=key_black, + gate_yellow=gate_yellow, + gate_black=gate_black, + sword=sword, + bridge=bridge, + magnet=magnet, + chalice=chalice ) @partial(jax.jit, static_argnums=(0,)) From 4e4639604de5927bcc8a2b7ad2d66ca45c3a17a7 Mon Sep 17 00:00:00 2001 From: DanielCress Date: Sat, 20 Dec 2025 12:41:34 +0100 Subject: [PATCH 016/102] Update jax_adventure.py --- src/jaxatari/games/jax_adventure.py | 49 +++++++++++------------------ 1 file changed, 19 insertions(+), 30 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 91297b900..7ff9abacf 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -19,29 +19,12 @@ def _get_default_asset_config() -> tuple: """ return ( #all rooms in order - {'name': 'bg_yellow_castle', 'type': 'background', 'file': 'Room_1.npy'}, - {'name': 'bg_yellow', 'type': 'background', 'file': 'Room_2.npy'}, - {'name': 'bg_green', 'type': 'background', 'file': 'Room_3.npy'}, - {'name': 'bg_purple', 'type': 'background', 'file': 'Room_4.npy'}, - {'name': 'bg_pink', 'type': 'background', 'file': 'Room_5.npy'}, - {'name': 'bg_green_yellow', 'type': 'background', 'file': 'Room_6.npy'}, - {'name': 'bg_maze_1', 'type': 'background', 'file': 'Room_7.npy'}, - {'name': 'bg_maze_2', 'type': 'background', 'file': 'Room_8.npy'}, - {'name': 'bg_maze_3', 'type': 'background', 'file': 'Room_9.npy'}, - {'name': 'bg_maze_4', 'type': 'background', 'file': 'Room_10.npy'}, - {'name': 'bg_maze_5', 'type': 'background', 'file': 'Room_11.npy'}, - {'name': 'bg_black_castle', 'type': 'background', 'file': 'Room_12.npy'}, - {'name': 'bg_ping_corridor', 'type': 'background', 'file': 'Room_13.npy'}, - {'name': 'bg_magenta', 'type': 'background', 'file': 'Room_14.npy'}, + {'name': 'room_number', 'type': 'group', 'files': ['Room_1.npy', 'Room_2.npy', 'Room_3.npy', 'Room_4.npy', 'Room_5.npy', 'Room_6.npy', 'Room_7.npy', 'Room_8.npy', 'Room_9.npy', 'Room_10.npy', 'Room_11.npy', 'Room_12.npy', 'Room_13.npy', 'Room_14.npy']}, + {'name': 'bg', 'type': 'background', 'file': 'Room_1.npy'}, + #all player colors in order - {'name': 'player_yellow', 'type': 'single', 'file': 'Player_Yellow.npy'}, - {'name': 'player_green', 'type': 'single', 'file': 'Player_Green.npy'}, - {'name': 'player_purple', 'type': 'single', 'file': 'Player_Purple.npy'}, - {'name': 'player_pink', 'type': 'single', 'file': 'Player_Pink.npy'}, - {'name': 'player_green_yellow', 'type': 'single', 'file': 'Player_Green_Yellow.npy'}, - {'name': 'player_blue', 'type': 'single', 'file': 'Player_Blue.npy'}, - {'name': 'player_black', 'type': 'single', 'file': 'Player_Black.npy'}, - {'name': 'player_magenta', 'type': 'single', 'file': 'Player_Magenta.npy'}, + {'name': 'player_colors', 'type': 'group', 'files': ["Player_Yellow.npy", "Player_Green.npy", "Player_Purple.npy", "Player_Pink.npy", "Player_Green_yellow.npy", "Player_Blue.npy", "Player_Black.npy", "Player_Magenta.npy"]}, + #dragons {'name': 'dragon_yellow_neutral', 'type': 'single', 'file': 'Dragon_yellow_neutral.npy'}, {'name': 'dragon_green-neutral', 'type': 'single', 'file': 'Dragon_green_neutral.npy'}, @@ -81,6 +64,7 @@ class AdventureState(NamedTuple): #position player player_x: chex.Array player_y: chex.Array + player_color:chex.Array player_tile: chex.Array #positions dragons dragon_yellow_x: chex.Array @@ -198,6 +182,7 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt step_counter = state.step_counter, player_x = new_player_x, player_y = new_player_y, + player_color= state.player_color, player_tile = state.player_tile, dragon_yellow_x = state.dragon_yellow_x, dragon_yellow_y = state.dragon_yellow_y, @@ -243,11 +228,12 @@ def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureOb #player player_x = jnp.array(78).astype(jnp.int32), #spawn X player_y = jnp.array(174).astype(jnp.int32), #spawn Y - player_tile = jnp.array(1).astype(jnp.int32), #Spawn Tile + player_tile = jnp.array(0).astype(jnp.int32), #Spawn Tile + player_color= jnp.array(0).astype(jnp.int32), #Spawn Color #Dragons dragon_yellow_x = jnp.array(120).astype(jnp.int32), #ToDo dragon_yellow_y = jnp.array(50).astype(jnp.int32), #ToDo - dragon_yellow_tile = jnp.array(1).astype(jnp.int32), #ToDo + dragon_yellow_tile = jnp.array(0).astype(jnp.int32), #ToDo dragon_green_x = jnp.array(120).astype(jnp.int32), #ToDo dragon_green_y = jnp.array(70).astype(jnp.int32), #ToDo dragon_green_tile = jnp.array(70).astype(jnp.int32), #ToDo @@ -256,22 +242,22 @@ def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureOb #Keys key_yellow_x = jnp.array(31).astype(jnp.int32), key_yellow_y = jnp.array(110).astype(jnp.int32), - key_yellow_tile = jnp.array(1).astype(jnp.int32), + key_yellow_tile = jnp.array(0).astype(jnp.int32), key_black_x = jnp.array(120).astype(jnp.int32), #ToDo key_black_y = jnp.array(90).astype(jnp.int32), #ToDo - key_black_tile = jnp.array(1).astype(jnp.int32), #ToDo + key_black_tile = jnp.array(0).astype(jnp.int32), #ToDo gate_yellow_state = jnp.array(0).astype(jnp.int32), #ToDo gate_black_state = jnp.array(0).astype(jnp.int32), #ToDo #Items sword_x = jnp.array(120).astype(jnp.int32), #ToDo sword_y = jnp.array(110).astype(jnp.int32), #ToDo - sword_tile = jnp.array(1).astype(jnp.int32), #ToDo + sword_tile = jnp.array(0).astype(jnp.int32), #ToDo bridge_x = jnp.array(120).astype(jnp.int32), #ToDo bridge_y = jnp.array(130).astype(jnp.int32), #ToDo - bridge_tile = jnp.array(1).astype(jnp.int32), #ToDo + bridge_tile = jnp.array(0).astype(jnp.int32), #ToDo magnet_x = jnp.array(120).astype(jnp.int32), #ToDo magnet_y = jnp.array(150).astype(jnp.int32), #ToDo - magnet_tile = jnp.array(1).astype(jnp.int32), #ToDo + magnet_tile = jnp.array(0).astype(jnp.int32), #ToDo chalice_x = jnp.array(120).astype(jnp.int32), #ToDo chalice_y = jnp.array(170).astype(jnp.int32), #ToDo chalice_tile = jnp.array(170).astype(jnp.int32) #ToDo @@ -289,6 +275,7 @@ def step(self, state: AdventureState, action: chex.Array) -> Tuple[AdventureObse step_counter = state.step_counter, player_x = state.player_x, player_y=state.player_y, + player_color= state.player_color, player_tile = state.player_tile, dragon_yellow_x = state.dragon_yellow_x, dragon_yellow_y = state.dragon_yellow_y, @@ -516,9 +503,11 @@ def __init__(self, consts: AdventureConstants = None): def render(self, state): #set bg color here raster = self.jr.create_object_raster(self.BACKGROUND) + room_mask =self.SHAPE_MASKS["room_number"][state.player_tile] + raster = self.jr.render_at(raster, 0, 0, room_mask) #set player color here - player_mask = self.SHAPE_MASKS["player_magenta"] + player_mask = self.SHAPE_MASKS["player_colors"][state.player_color] raster = self.jr.render_at(raster, state.player_x, state.player_y, player_mask) #dragons From 51b8a9183e4f855329efcf48e82a4a34ba0d0edb Mon Sep 17 00:00:00 2001 From: LucyLMM Date: Sat, 20 Dec 2025 12:47:56 +0100 Subject: [PATCH 017/102] Added Hitbox size --- src/jaxatari/games/jax_adventure.py | 44 ++++++++++++++--------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 7ff9abacf..254723eae 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -325,88 +325,88 @@ def _get_observation(self, state: AdventureState): x=state.player_x, y=state.player_y, tile=state.player_tile, - width=4, #ToDO - height=8, #ToDO + width=4, + height=8, state=1 #ToDO ) dragon_yellow = EntityPosition( x=state.dragon_yellow_x, y=state.dragon_yellow_y, tile=state.dragon_yellow_tile, - width=10, #ToDO - height=4, #ToDO + width=8, + height=44, state=1 #ToDO ) dragon_green = EntityPosition( x=state.dragon_green_x, y=state.dragon_green_y, tile=state.dragon_green_tile, - width=10, #ToDO - height=4, #ToDO + width=8, + height=44, state=1 #ToDO ) key_yellow = EntityPosition( x=state.key_yellow_x, y=state.key_yellow_y, tile=state.key_yellow_tile, - width=10, #ToDO - height=4, #ToDO + width=8, + height=6, state=1 #ToDO ) key_black = EntityPosition( x=state.key_black_x, y=state.key_black_y, tile=state.key_black_tile, - width=10, #ToDO - height=4, #ToDO + width=8, + height=6, state=1 #ToDO ) gate_yellow = EntityPosition( x=80, #ToDO y=80, #ToDO tile=1, #ToDO - width=10, #ToDO - height=4, #ToDO + width=7, + height=32, state=state.gate_yellow_state #ToDO ) gate_black = EntityPosition( x=100, #ToDO y=100, #ToDO tile=1, #ToDO - width=10, #ToDO - height=4, #ToDO + width=7, + height=32, state=state.gate_black_state #ToDO ) sword = EntityPosition( x=state.sword_x, y=state.sword_y, tile=state.sword_tile, - width=10, #ToDO - height=4, #ToDO + width=8, + height=10, state=1 #ToDO ) bridge = EntityPosition( x=state.bridge_x, y=state.bridge_y, tile=state.bridge_tile, - width=10, #ToDO - height=4, #ToDO + width=32, + height=48, state=1 #ToDO ) magnet = EntityPosition( x=state.magnet_x, y=state.magnet_y, tile=state.magnet_tile, - width=10, #ToDO - height=4, #ToDO + width=8, + height=16, state=1 #ToDO ) chalice = EntityPosition( x=state.chalice_x, y=state.chalice_y, tile=state.chalice_tile, - width=10, #ToDO - height=4, #ToDO + width=8, + height=18, state=1 #ToDO ) From 653b7a4a6e356d6da7327e8f5b77682f9ce103be Mon Sep 17 00:00:00 2001 From: Leif Schwass Date: Sat, 20 Dec 2025 13:05:58 +0100 Subject: [PATCH 018/102] gates assets loaded --- src/jaxatari/games/jax_adventure.py | 42 +++++++++++++++--- .../{Gate_opening.npy => Gate_opening_0.npy} | Bin 2 files changed, 37 insertions(+), 5 deletions(-) rename src/jaxatari/games/sprites/adventure/{Gate_opening.npy => Gate_opening_0.npy} (100%) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 7ff9abacf..171067cdf 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -19,11 +19,31 @@ def _get_default_asset_config() -> tuple: """ return ( #all rooms in order - {'name': 'room_number', 'type': 'group', 'files': ['Room_1.npy', 'Room_2.npy', 'Room_3.npy', 'Room_4.npy', 'Room_5.npy', 'Room_6.npy', 'Room_7.npy', 'Room_8.npy', 'Room_9.npy', 'Room_10.npy', 'Room_11.npy', 'Room_12.npy', 'Room_13.npy', 'Room_14.npy']}, + {'name': 'room_number', 'type': 'group', 'files': ['Room_1.npy', + 'Room_2.npy', + 'Room_3.npy', + 'Room_4.npy', + 'Room_5.npy', + 'Room_6.npy', + 'Room_7.npy', + 'Room_8.npy', + 'Room_9.npy', + 'Room_10.npy', + 'Room_11.npy', + 'Room_12.npy', + 'Room_13.npy', + 'Room_14.npy']}, {'name': 'bg', 'type': 'background', 'file': 'Room_1.npy'}, #all player colors in order - {'name': 'player_colors', 'type': 'group', 'files': ["Player_Yellow.npy", "Player_Green.npy", "Player_Purple.npy", "Player_Pink.npy", "Player_Green_yellow.npy", "Player_Blue.npy", "Player_Black.npy", "Player_Magenta.npy"]}, + {'name': 'player_colors', 'type': 'group', 'files': ["Player_Yellow.npy", + "Player_Green.npy", + "Player_Purple.npy", + "Player_Pink.npy", + "Player_Green_yellow.npy", + "Player_Blue.npy", + "Player_Black.npy", + "Player_Magenta.npy"]}, #dragons {'name': 'dragon_yellow_neutral', 'type': 'single', 'file': 'Dragon_yellow_neutral.npy'}, @@ -34,7 +54,13 @@ def _get_default_asset_config() -> tuple: {'name': 'key_yellow', 'type': 'single', 'file': 'Key_yellow.npy'}, {'name': 'key_black', 'type': 'single', 'file': 'Key_black.npy'}, #gates - + {'name': 'gate_state', 'type': 'group', 'files': ['Gate_closed.npy', + 'Gate_opening_0.npy', + 'Gate_opening_1.npy', + 'Gate_opening_2.npy', + 'Gate_opening_3.npy', + 'Gate_opening_4.npy', + 'Gate_open.npy']}, #ToDo gates animation #items @@ -247,7 +273,7 @@ def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureOb key_black_y = jnp.array(90).astype(jnp.int32), #ToDo key_black_tile = jnp.array(0).astype(jnp.int32), #ToDo gate_yellow_state = jnp.array(0).astype(jnp.int32), #ToDo - gate_black_state = jnp.array(0).astype(jnp.int32), #ToDo + gate_black_state = jnp.array(3).astype(jnp.int32), #ToDo #Items sword_x = jnp.array(120).astype(jnp.int32), #ToDo sword_y = jnp.array(110).astype(jnp.int32), #ToDo @@ -452,7 +478,7 @@ def observation_space(self) -> spaces: "height": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), }), - #ToDo for the rest of the dragons, items etc..... + #ToDo for the rest of the dragons, items etc..... ? }) def image_space(self) -> spaces.Box: @@ -520,6 +546,12 @@ def render(self, state): raster = self.jr.render_at(raster, state.key_yellow_x, state.key_yellow_y, key_yellow_mask) key_black_mask = self.SHAPE_MASKS["key_black"] raster = self.jr.render_at(raster, state.key_black_x, state.key_black_y, key_black_mask) + #Gates + gate_yellow_mask = self.SHAPE_MASKS["gate_state"][state.gate_yellow_state] + raster = self.jr.render_at(raster, 77, 140, gate_yellow_mask) + gate_black_mask = self.SHAPE_MASKS["gate_state"][state.gate_black_state] + raster = self.jr.render_at(raster, 30, 30, gate_black_mask)#ToDO + #items sword_mask = self.SHAPE_MASKS["sword"] raster = self.jr.render_at(raster, state.sword_x, state.sword_y, sword_mask) diff --git a/src/jaxatari/games/sprites/adventure/Gate_opening.npy b/src/jaxatari/games/sprites/adventure/Gate_opening_0.npy similarity index 100% rename from src/jaxatari/games/sprites/adventure/Gate_opening.npy rename to src/jaxatari/games/sprites/adventure/Gate_opening_0.npy From 3721413e861e4fd51044b1d82d356cf66e72986d Mon Sep 17 00:00:00 2001 From: Leif Schwass Date: Sat, 20 Dec 2025 13:38:58 +0100 Subject: [PATCH 019/102] changed state to arrays --- src/jaxatari/games/jax_adventure.py | 289 ++++++++++------------------ 1 file changed, 102 insertions(+), 187 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 88fe42c84..bdde69582 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -87,47 +87,25 @@ class AdventureConstants(NamedTuple): class AdventureState(NamedTuple): #step conter for performance indicator? step_counter: chex.Array - #position player - player_x: chex.Array - player_y: chex.Array - player_color:chex.Array - player_tile: chex.Array - #positions dragons - dragon_yellow_x: chex.Array - dragon_yellow_y: chex.Array - dragon_yellow_tile: chex.Array - dragon_green_x: chex.Array - dragon_green_y: chex.Array - dragon_green_tile: chex.Array - #state dragons (alive, dead, attacking) - dragon_yellow_state: chex.Array - dragon_green_state: chex.Array - #positions keys - key_yellow_x: chex.Array - key_yellow_y: chex.Array - key_yellow_tile: chex.Array - key_black_x: chex.Array - key_black_y: chex.Array - key_black_tile: chex.Array - #state of gates (if open or closed) - gate_yellow_state: chex.Array - gate_black_state: chex.Array - #position sword - sword_x: chex.Array - sword_y: chex.Array - sword_tile: chex.Array - #position bridge - bridge_x: chex.Array - bridge_y: chex.Array - bridge_tile: chex.Array - #position magnet - magnet_x: chex.Array - magnet_y: chex.Array - magnet_tile: chex.Array - #position chalice - chalice_x: chex.Array - chalice_y: chex.Array - chalice_tile: chex.Array + #position player: x ,y ,tile , color + player: chex.Array + #positions dragons: x, y ,tile ,state + dragon_yellow: chex.Array + dragon_green: chex.Array + #positions keys: x, y, tile + key_yellow: chex.Array + key_black: chex.Array + #gates: state + gate_yellow: chex.Array + gate_black: chex.Array + #position sword: x, y, tile + sword: chex.Array + #position bridge: x, y, tile + bridge: chex.Array + #position magnet: x, y, tile + magnet: chex.Array + #position chalice: x, y, tile + chalice: chex.Array class EntityPosition(NamedTuple): @@ -176,7 +154,7 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt right = jnp.logical_or(action == Action.RIGHT, action == Action.RIGHTFIRE) up = jnp.logical_or(action == Action.UP, action == Action.UPFIRE) down = jnp.logical_or(action == Action.DOWN, action == Action.DOWNFIRE) - new_player_x = state.player_x + new_player_x = state.player[0] new_player_x = jax.lax.cond( left, lambda x: x-1, @@ -190,7 +168,7 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt operand = new_player_x, ) - new_player_y = state.player_y + new_player_y = state.player[1] new_player_y = jax.lax.cond( down, lambda y: y+1, @@ -206,38 +184,17 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt return AdventureState( step_counter = state.step_counter, - player_x = new_player_x, - player_y = new_player_y, - player_color= state.player_color, - player_tile = state.player_tile, - dragon_yellow_x = state.dragon_yellow_x, - dragon_yellow_y = state.dragon_yellow_y, - dragon_yellow_tile = state.dragon_yellow_tile, - dragon_green_x = state.dragon_green_x, - dragon_green_y = state.dragon_green_y, - dragon_green_tile=state.dragon_green_tile, - dragon_yellow_state = state.dragon_yellow_state, - dragon_green_state = state.dragon_green_state, - key_yellow_x = state.key_yellow_x, - key_yellow_y = state.key_yellow_y, - key_yellow_tile=state.key_yellow_tile, - key_black_x = state.key_black_x, - key_black_y = state.key_black_y, - key_black_tile=state.key_black_tile, - gate_yellow_state = state.gate_yellow_state, - gate_black_state = state.gate_black_state, - sword_x = state.sword_x, - sword_y = state.sword_y, - sword_tile=state.sword_tile, - bridge_x = state.bridge_x, - bridge_y = state.bridge_y, - bridge_tile=state.bridge_tile, - magnet_x = state.magnet_x, - magnet_y = state.magnet_y, - magnet_tile=state.magnet_tile, - chalice_x = state.chalice_x, - chalice_y = state.chalice_y, - chalice_tile=state.chalice_tile + player = jnp.array([new_player_x,new_player_y,state.player[3],state.player[4]]).astype(jnp.int32), #SEEMS NOT GOOD + dragon_yellow = state.dragon_yellow, + dragon_green = state.dragon_green, + key_yellow=state.key_yellow, + key_black=state.key_black, + gate_yellow=state.gate_yellow, + gate_black=state.gate_black, + sword=state.sword, + bridge=state.bridge, + magnet=state.magnet, + chalice=state.chalice ) @@ -251,42 +208,22 @@ def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureOb state = AdventureState( step_counter = jnp.array(0).astype(jnp.int32), - #player - player_x = jnp.array(78).astype(jnp.int32), #spawn X - player_y = jnp.array(174).astype(jnp.int32), #spawn Y - player_tile = jnp.array(0).astype(jnp.int32), #Spawn Tile - player_color= jnp.array(0).astype(jnp.int32), #Spawn Color - #Dragons - dragon_yellow_x = jnp.array(120).astype(jnp.int32), #ToDo - dragon_yellow_y = jnp.array(50).astype(jnp.int32), #ToDo - dragon_yellow_tile = jnp.array(0).astype(jnp.int32), #ToDo - dragon_green_x = jnp.array(120).astype(jnp.int32), #ToDo - dragon_green_y = jnp.array(70).astype(jnp.int32), #ToDo - dragon_green_tile = jnp.array(70).astype(jnp.int32), #ToDo - dragon_yellow_state = jnp.array(0).astype(jnp.int32), #ToDo - dragon_green_state = jnp.array(0).astype(jnp.int32), #ToDo - #Keys - key_yellow_x = jnp.array(31).astype(jnp.int32), - key_yellow_y = jnp.array(110).astype(jnp.int32), - key_yellow_tile = jnp.array(0).astype(jnp.int32), - key_black_x = jnp.array(120).astype(jnp.int32), #ToDo - key_black_y = jnp.array(90).astype(jnp.int32), #ToDo - key_black_tile = jnp.array(0).astype(jnp.int32), #ToDo - gate_yellow_state = jnp.array(0).astype(jnp.int32), #ToDo - gate_black_state = jnp.array(3).astype(jnp.int32), #ToDo - #Items - sword_x = jnp.array(120).astype(jnp.int32), #ToDo - sword_y = jnp.array(110).astype(jnp.int32), #ToDo - sword_tile = jnp.array(0).astype(jnp.int32), #ToDo - bridge_x = jnp.array(120).astype(jnp.int32), #ToDo - bridge_y = jnp.array(130).astype(jnp.int32), #ToDo - bridge_tile = jnp.array(0).astype(jnp.int32), #ToDo - magnet_x = jnp.array(120).astype(jnp.int32), #ToDo - magnet_y = jnp.array(150).astype(jnp.int32), #ToDo - magnet_tile = jnp.array(0).astype(jnp.int32), #ToDo - chalice_x = jnp.array(120).astype(jnp.int32), #ToDo - chalice_y = jnp.array(170).astype(jnp.int32), #ToDo - chalice_tile = jnp.array(170).astype(jnp.int32) #ToDo + #Player Spawn: x, y, tile, color + player = jnp.array([78,174,0,0]).astype(jnp.int32), + #Dragons: x, y ,tile ,state + dragon_yellow = jnp.array([120,50,0,0]).astype(jnp.int32), #ToDo + dragon_green = jnp.array([120,80,0,0]).astype(jnp.int32), #ToDo + #Keys: x ,y, tile + key_yellow = jnp.array([31,110,0]).astype(jnp.int32), + key_black = jnp.array([31,80,0]).astype(jnp.int32), + #Gate: state + gate_yellow=jnp.array([0]).astype(jnp.int32), + gate_black=jnp.array([0]).astype(jnp.int32), + #Items: x, y, tile + sword = jnp.array([120,120,0]).astype(jnp.int32), #ToDo + bridge= jnp.array([120,120,0]).astype(jnp.int32), #ToDo + magnet= jnp.array([120,120,0]).astype(jnp.int32), #ToDo + chalice= jnp.array([120,120,0]).astype(jnp.int32), #ToDo ) initial_obs = self._get_observation(state) @@ -298,43 +235,21 @@ def step(self, state: AdventureState, action: chex.Array) -> Tuple[AdventureObse previous_state = state # Make per-step key available to helpers that may read state.key state = AdventureState( - step_counter = state.step_counter, - player_x = state.player_x, - player_y=state.player_y, - player_color= state.player_color, - player_tile = state.player_tile, - dragon_yellow_x = state.dragon_yellow_x, - dragon_yellow_y = state.dragon_yellow_y, - dragon_yellow_tile = state.dragon_yellow_tile, - dragon_green_x = state.dragon_green_x, - dragon_green_y = state.dragon_green_y, - dragon_green_tile=state.dragon_green_tile, - dragon_yellow_state = state.dragon_yellow_state, - dragon_green_state = state.dragon_green_state, - key_yellow_x = state.key_yellow_x, - key_yellow_y = state.key_yellow_y, - key_yellow_tile=state.key_yellow_tile, - key_black_x = state.key_black_x, - key_black_y = state.key_black_y, - key_black_tile=state.key_black_tile, - gate_yellow_state = state.gate_yellow_state, - gate_black_state = state.gate_black_state, - sword_x = state.sword_x, - sword_y = state.sword_y, - sword_tile=state.sword_tile, - bridge_x = state.bridge_x, - bridge_y = state.bridge_y, - bridge_tile=state.bridge_tile, - magnet_x = state.magnet_x, - magnet_y = state.magnet_y, - magnet_tile=state.magnet_tile, - chalice_x = state.chalice_x, - chalice_y = state.chalice_y, - chalice_tile=state.chalice_tile + step_counter=state.step_counter, + player=state.player, + dragon_yellow=state.dragon_yellow, + dragon_green=state.dragon_green, + key_yellow=state.key_yellow, + key_black=state.key_black, + gate_yellow=state.gate_yellow, + gate_black=state.gate_black, + sword=state.sword, + bridge=state.bridge, + magnet=state.magnet, + chalice=state.chalice ) state = self._player_step(state, action) - done = self._get_done(state) env_reward = self._get_reward(previous_state, state) info = self._get_info(state) @@ -348,41 +263,41 @@ def render(self, state: AdventureState) -> jnp.ndarray: def _get_observation(self, state: AdventureState): player = EntityPosition( - x=state.player_x, - y=state.player_y, - tile=state.player_tile, + x=state.player[0], + y=state.player[1], + tile=state.player[2], width=4, height=8, state=1 #ToDO ) dragon_yellow = EntityPosition( - x=state.dragon_yellow_x, - y=state.dragon_yellow_y, - tile=state.dragon_yellow_tile, + x=state.dragon_yellow[0], + y=state.dragon_yellow[1], + tile=state.dragon_yellow[2], width=8, height=44, state=1 #ToDO ) dragon_green = EntityPosition( - x=state.dragon_green_x, - y=state.dragon_green_y, - tile=state.dragon_green_tile, + x=state.dragon_green[0], + y=state.dragon_green[1], + tile=state.dragon_green[2], width=8, height=44, state=1 #ToDO ) key_yellow = EntityPosition( - x=state.key_yellow_x, - y=state.key_yellow_y, - tile=state.key_yellow_tile, + x=state.key_yellow[0], + y=state.key_yellow[1], + tile=state.key_yellow[2], width=8, height=6, state=1 #ToDO ) key_black = EntityPosition( - x=state.key_black_x, - y=state.key_black_y, - tile=state.key_black_tile, + x=state.key_black[0], + y=state.key_black[1], + tile=state.key_black[2], width=8, height=6, state=1 #ToDO @@ -393,7 +308,7 @@ def _get_observation(self, state: AdventureState): tile=1, #ToDO width=7, height=32, - state=state.gate_yellow_state #ToDO + state=state.gate_yellow[0] #ToDO ) gate_black = EntityPosition( x=100, #ToDO @@ -401,36 +316,36 @@ def _get_observation(self, state: AdventureState): tile=1, #ToDO width=7, height=32, - state=state.gate_black_state #ToDO + state=state.gate_black[0] #ToDO ) sword = EntityPosition( - x=state.sword_x, - y=state.sword_y, - tile=state.sword_tile, + x=state.sword[0], + y=state.sword[1], + tile=state.sword[2], width=8, height=10, state=1 #ToDO ) bridge = EntityPosition( - x=state.bridge_x, - y=state.bridge_y, - tile=state.bridge_tile, + x=state.bridge[0], + y=state.bridge[1], + tile=state.bridge[2], width=32, height=48, state=1 #ToDO ) magnet = EntityPosition( - x=state.magnet_x, - y=state.magnet_y, - tile=state.magnet_tile, + x=state.magnet[0], + y=state.magnet[1], + tile=state.magnet[2], width=8, height=16, state=1 #ToDO ) chalice = EntityPosition( - x=state.chalice_x, - y=state.chalice_y, - tile=state.chalice_tile, + x=state.chalice[0], + y=state.chalice[1], + tile=state.chalice[2], width=8, height=18, state=1 #ToDO @@ -529,38 +444,38 @@ def __init__(self, consts: AdventureConstants = None): def render(self, state): #set bg color here raster = self.jr.create_object_raster(self.BACKGROUND) - room_mask =self.SHAPE_MASKS["room_number"][state.player_tile] + room_mask =self.SHAPE_MASKS["room_number"][state.player[2]] raster = self.jr.render_at(raster, 0, 0, room_mask) #set player color here - player_mask = self.SHAPE_MASKS["player_colors"][state.player_color] - raster = self.jr.render_at(raster, state.player_x, state.player_y, player_mask) + player_mask = self.SHAPE_MASKS["player_colors"][state.player[3]] + raster = self.jr.render_at(raster, state.player[0], state.player[1], player_mask) #dragons dragon_yellow_mask = self.SHAPE_MASKS["dragon_yellow_neutral"] - raster = self.jr.render_at(raster, state.dragon_yellow_x, state.dragon_yellow_y, dragon_yellow_mask) + raster = self.jr.render_at(raster, state.dragon_yellow[0], state.dragon_yellow[1], dragon_yellow_mask) dragon_green_mask = self.SHAPE_MASKS["dragon_green-neutral"] - raster = self.jr.render_at(raster, state.dragon_green_x, state.dragon_green_y, dragon_green_mask) + raster = self.jr.render_at(raster, state.dragon_green[0], state.dragon_green[1], dragon_green_mask) #keys key_yellow_mask = self.SHAPE_MASKS["key_yellow"] - raster = self.jr.render_at(raster, state.key_yellow_x, state.key_yellow_y, key_yellow_mask) + raster = self.jr.render_at(raster, state.key_yellow[0], state.key_yellow[1], key_yellow_mask) key_black_mask = self.SHAPE_MASKS["key_black"] - raster = self.jr.render_at(raster, state.key_black_x, state.key_black_y, key_black_mask) + raster = self.jr.render_at(raster, state.key_black[0], state.key_black[1], key_black_mask) #Gates - gate_yellow_mask = self.SHAPE_MASKS["gate_state"][state.gate_yellow_state] + gate_yellow_mask = self.SHAPE_MASKS["gate_state"][state.gate_yellow[0]] raster = self.jr.render_at(raster, 77, 140, gate_yellow_mask) - gate_black_mask = self.SHAPE_MASKS["gate_state"][state.gate_black_state] + gate_black_mask = self.SHAPE_MASKS["gate_state"][state.gate_black[0]] raster = self.jr.render_at(raster, 30, 30, gate_black_mask)#ToDO #items sword_mask = self.SHAPE_MASKS["sword"] - raster = self.jr.render_at(raster, state.sword_x, state.sword_y, sword_mask) + raster = self.jr.render_at(raster, state.sword[0], state.sword[1], sword_mask) bridge_mask = self.SHAPE_MASKS["bridge"] - raster = self.jr.render_at(raster, state.bridge_x, state.bridge_y, bridge_mask) + raster = self.jr.render_at(raster, state.bridge[0], state.bridge[1], bridge_mask) magnet_mask = self.SHAPE_MASKS["magnet"] - raster = self.jr.render_at(raster, state.magnet_x, state.magnet_y, magnet_mask) + raster = self.jr.render_at(raster, state.magnet[0], state.magnet[1], magnet_mask) #chalice chalice_mask = self.SHAPE_MASKS["chalice"] - raster = self.jr.render_at(raster, state.chalice_x, state.chalice_y, chalice_mask) + raster = self.jr.render_at(raster, state.chalice[0], state.chalice[1], chalice_mask) return self.jr.render_from_palette(raster, self.PALETTE) From f691a2ace506a8cf0fdf92afb1bfc056c39a08ad Mon Sep 17 00:00:00 2001 From: Leif Schwass Date: Sat, 20 Dec 2025 14:02:40 +0100 Subject: [PATCH 020/102] all assets imported, changeable via states --- src/jaxatari/games/jax_adventure.py | 57 ++++++++++++++++------------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index bdde69582..869ddfa91 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -18,7 +18,7 @@ def _get_default_asset_config() -> tuple: Kept immutable (tuple of dicts) to fit NamedTuple defaults. """ return ( - #all rooms in order + #all rooms in order ToDo pt overview map into the readme? {'name': 'room_number', 'type': 'group', 'files': ['Room_1.npy', 'Room_2.npy', 'Room_3.npy', @@ -34,8 +34,7 @@ def _get_default_asset_config() -> tuple: 'Room_13.npy', 'Room_14.npy']}, {'name': 'bg', 'type': 'background', 'file': 'Room_1.npy'}, - - #all player colors in order + #Player in all the different colors {'name': 'player_colors', 'type': 'group', 'files': ["Player_Yellow.npy", "Player_Green.npy", "Player_Purple.npy", @@ -44,16 +43,17 @@ def _get_default_asset_config() -> tuple: "Player_Blue.npy", "Player_Black.npy", "Player_Magenta.npy"]}, - - #dragons - {'name': 'dragon_yellow_neutral', 'type': 'single', 'file': 'Dragon_yellow_neutral.npy'}, - {'name': 'dragon_green-neutral', 'type': 'single', 'file': 'Dragon_green_neutral.npy'}, - #ToDo remaining dragon animations - - #keys + #Dragons and their animations + {'name': 'dragon_yellow', 'type': 'group', 'files': ['Dragon_yellow_neutral.npy', + 'Dragon_yellow_attack.npy', + 'Dragon_yellow_dead.npy']}, + {'name': 'dragon_green', 'type': 'group', 'files': ['Dragon_green_neutral.npy', + 'Dragon_green_attack.npy', + 'Dragon_green_dead.npy']}, + #Keys {'name': 'key_yellow', 'type': 'single', 'file': 'Key_yellow.npy'}, {'name': 'key_black', 'type': 'single', 'file': 'Key_black.npy'}, - #gates + #Gate and its animation {'name': 'gate_state', 'type': 'group', 'files': ['Gate_closed.npy', 'Gate_opening_0.npy', 'Gate_opening_1.npy', @@ -61,15 +61,21 @@ def _get_default_asset_config() -> tuple: 'Gate_opening_3.npy', 'Gate_opening_4.npy', 'Gate_open.npy']}, - #ToDo gates animation - - #items + #Items {'name': 'sword', 'type': 'single', 'file': 'Sword.npy'}, {'name': 'bridge', 'type': 'single', 'file': 'Bridge.npy'}, {'name': 'magnet', 'type': 'single', 'file': 'Magnet.npy'}, #Chalice - {'name': 'chalice', 'type': 'single', 'file': 'Chalice_Pink.npy'} - #ToDo remaining chalice colors for blinking + {'name': 'chalice', 'type': 'group', 'files': ['Chalice_Black.npy', + 'Chalice_DarkBlue.npy', + 'Chalice_Gray.npy', + 'Chalice_Green.npy', + 'Chalice_LightBlue.npy', + 'Chalice_Pink.npy', + 'Chalice_Purple.npy', + 'Chalice_Red.npy', + 'Chalice_Turquoise.npy', + 'Chalice_Yellow.npy']}, ) @@ -104,7 +110,7 @@ class AdventureState(NamedTuple): bridge: chex.Array #position magnet: x, y, tile magnet: chex.Array - #position chalice: x, y, tile + #position chalice: x, y, tile, color chalice: chex.Array @@ -184,7 +190,7 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt return AdventureState( step_counter = state.step_counter, - player = jnp.array([new_player_x,new_player_y,state.player[3],state.player[4]]).astype(jnp.int32), #SEEMS NOT GOOD + player = jnp.array([new_player_x,new_player_y,state.player[2],state.player[3]]).astype(jnp.int32), #SEEMS NOT GOOD dragon_yellow = state.dragon_yellow, dragon_green = state.dragon_green, key_yellow=state.key_yellow, @@ -212,7 +218,7 @@ def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureOb player = jnp.array([78,174,0,0]).astype(jnp.int32), #Dragons: x, y ,tile ,state dragon_yellow = jnp.array([120,50,0,0]).astype(jnp.int32), #ToDo - dragon_green = jnp.array([120,80,0,0]).astype(jnp.int32), #ToDo + dragon_green = jnp.array([120,80,0,2]).astype(jnp.int32), #ToDo #Keys: x ,y, tile key_yellow = jnp.array([31,110,0]).astype(jnp.int32), key_black = jnp.array([31,80,0]).astype(jnp.int32), @@ -223,7 +229,8 @@ def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureOb sword = jnp.array([120,120,0]).astype(jnp.int32), #ToDo bridge= jnp.array([120,120,0]).astype(jnp.int32), #ToDo magnet= jnp.array([120,120,0]).astype(jnp.int32), #ToDo - chalice= jnp.array([120,120,0]).astype(jnp.int32), #ToDo + #Chalice: x, y, tile, color + chalice= jnp.array([120,120,0,0]).astype(jnp.int32), #ToDo ) initial_obs = self._get_observation(state) @@ -276,7 +283,7 @@ def _get_observation(self, state: AdventureState): tile=state.dragon_yellow[2], width=8, height=44, - state=1 #ToDO + state=state.dragon_yellow[3] #ToDO ) dragon_green = EntityPosition( x=state.dragon_green[0], @@ -284,7 +291,7 @@ def _get_observation(self, state: AdventureState): tile=state.dragon_green[2], width=8, height=44, - state=1 #ToDO + state=state.dragon_green[3] #ToDO ) key_yellow = EntityPosition( x=state.key_yellow[0], @@ -452,9 +459,9 @@ def render(self, state): raster = self.jr.render_at(raster, state.player[0], state.player[1], player_mask) #dragons - dragon_yellow_mask = self.SHAPE_MASKS["dragon_yellow_neutral"] + dragon_yellow_mask = self.SHAPE_MASKS["dragon_yellow"][state.dragon_yellow[3]] raster = self.jr.render_at(raster, state.dragon_yellow[0], state.dragon_yellow[1], dragon_yellow_mask) - dragon_green_mask = self.SHAPE_MASKS["dragon_green-neutral"] + dragon_green_mask = self.SHAPE_MASKS["dragon_green"][state.dragon_green[3]] raster = self.jr.render_at(raster, state.dragon_green[0], state.dragon_green[1], dragon_green_mask) #keys key_yellow_mask = self.SHAPE_MASKS["key_yellow"] @@ -475,7 +482,7 @@ def render(self, state): magnet_mask = self.SHAPE_MASKS["magnet"] raster = self.jr.render_at(raster, state.magnet[0], state.magnet[1], magnet_mask) #chalice - chalice_mask = self.SHAPE_MASKS["chalice"] + chalice_mask = self.SHAPE_MASKS["chalice"][state.chalice[3]] raster = self.jr.render_at(raster, state.chalice[0], state.chalice[1], chalice_mask) return self.jr.render_from_palette(raster, self.PALETTE) From be80660971a6eada9e3a0504772d35b35d5677ae Mon Sep 17 00:00:00 2001 From: DanielCress Date: Sat, 20 Dec 2025 14:38:17 +0100 Subject: [PATCH 021/102] Items nur im Raum --- src/jaxatari/games/jax_adventure.py | 105 ++++++++++++++++++++++------ 1 file changed, 83 insertions(+), 22 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 869ddfa91..8d27fc5ad 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -163,13 +163,13 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt new_player_x = state.player[0] new_player_x = jax.lax.cond( left, - lambda x: x-1, + lambda x: x-4, lambda x: x, operand = new_player_x, ) new_player_x = jax.lax.cond( right, - lambda x: x+1, + lambda x: x+4, lambda x: x, operand = new_player_x, ) @@ -177,20 +177,27 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt new_player_y = state.player[1] new_player_y = jax.lax.cond( down, - lambda y: y+1, + lambda y: y+8, lambda y: y, operand = new_player_y, ) new_player_y = jax.lax.cond( up, - lambda y: y-1, + lambda y: y-8, lambda y: y, operand = new_player_y, ) + new_player_tile = state.player[2] + new_player_y, new_player_tile = jax.lax.cond( + jnp.logical_and(new_player_y >=212, new_player_tile == 0), + lambda _: (27, 2), + lambda _: (new_player_y, new_player_tile), + operand = None, + ) return AdventureState( step_counter = state.step_counter, - player = jnp.array([new_player_x,new_player_y,state.player[2],state.player[3]]).astype(jnp.int32), #SEEMS NOT GOOD + player = jnp.array([new_player_x,new_player_y,new_player_tile,state.player[3]]).astype(jnp.int32), #SEEMS NOT GOOD dragon_yellow = state.dragon_yellow, dragon_green = state.dragon_green, key_yellow=state.key_yellow, @@ -217,20 +224,20 @@ def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureOb #Player Spawn: x, y, tile, color player = jnp.array([78,174,0,0]).astype(jnp.int32), #Dragons: x, y ,tile ,state - dragon_yellow = jnp.array([120,50,0,0]).astype(jnp.int32), #ToDo - dragon_green = jnp.array([120,80,0,2]).astype(jnp.int32), #ToDo + dragon_yellow = jnp.array([120,50,2,0]).astype(jnp.int32), #ToDo + dragon_green = jnp.array([120,80,2,2]).astype(jnp.int32), #ToDo #Keys: x ,y, tile key_yellow = jnp.array([31,110,0]).astype(jnp.int32), - key_black = jnp.array([31,80,0]).astype(jnp.int32), + key_black = jnp.array([31,80,2]).astype(jnp.int32), #Gate: state gate_yellow=jnp.array([0]).astype(jnp.int32), gate_black=jnp.array([0]).astype(jnp.int32), #Items: x, y, tile - sword = jnp.array([120,120,0]).astype(jnp.int32), #ToDo - bridge= jnp.array([120,120,0]).astype(jnp.int32), #ToDo - magnet= jnp.array([120,120,0]).astype(jnp.int32), #ToDo + sword = jnp.array([120,120,2]).astype(jnp.int32), #ToDo + bridge= jnp.array([120,120,2]).astype(jnp.int32), #ToDo + magnet= jnp.array([120,120,2]).astype(jnp.int32), #ToDo #Chalice: x, y, tile, color - chalice= jnp.array([120,120,0,0]).astype(jnp.int32), #ToDo + chalice= jnp.array([120,120,2,0]).astype(jnp.int32), #ToDo ) initial_obs = self._get_observation(state) @@ -460,29 +467,83 @@ def render(self, state): #dragons dragon_yellow_mask = self.SHAPE_MASKS["dragon_yellow"][state.dragon_yellow[3]] - raster = self.jr.render_at(raster, state.dragon_yellow[0], state.dragon_yellow[1], dragon_yellow_mask) + raster = jax.lax.cond( + state.dragon_yellow[2]==state.player[2], + lambda r : self.jr.render_at(raster, state.dragon_yellow[0], state.dragon_yellow[1], dragon_yellow_mask), + lambda r : r, + operand = raster, + ) dragon_green_mask = self.SHAPE_MASKS["dragon_green"][state.dragon_green[3]] - raster = self.jr.render_at(raster, state.dragon_green[0], state.dragon_green[1], dragon_green_mask) + raster = jax.lax.cond( + state.dragon_green[2]==state.player[2], + lambda r : self.jr.render_at(raster, state.dragon_green[0], state.dragon_green[1], dragon_green_mask), + lambda r : r, + operand = raster, + ) + #keys key_yellow_mask = self.SHAPE_MASKS["key_yellow"] - raster = self.jr.render_at(raster, state.key_yellow[0], state.key_yellow[1], key_yellow_mask) + raster = jax.lax.cond( + state.key_yellow[2]==state.player[2], + lambda r : self.jr.render_at(raster, state.key_yellow[0], state.key_yellow[1], key_yellow_mask), + lambda r : r, + operand = raster, + ) key_black_mask = self.SHAPE_MASKS["key_black"] - raster = self.jr.render_at(raster, state.key_black[0], state.key_black[1], key_black_mask) + raster = jax.lax.cond( + state.key_black[2]==state.player[2], + lambda r : self.jr.render_at(raster, state.key_black[0], state.key_black[1], key_black_mask), + lambda r : r, + operand = raster, + ) + #Gates gate_yellow_mask = self.SHAPE_MASKS["gate_state"][state.gate_yellow[0]] - raster = self.jr.render_at(raster, 77, 140, gate_yellow_mask) + raster = jax.lax.cond( + 0==state.player[2], + lambda r : self.jr.render_at(raster, 77, 140, gate_yellow_mask), + lambda r : r, + operand = raster, + ) gate_black_mask = self.SHAPE_MASKS["gate_state"][state.gate_black[0]] - raster = self.jr.render_at(raster, 30, 30, gate_black_mask)#ToDO + raster = jax.lax.cond( + 10==state.player[2], + lambda r : self.jr.render_at(raster, 30, 30, gate_black_mask),#ToDO + lambda r : r, + operand = raster, + ) + #items sword_mask = self.SHAPE_MASKS["sword"] - raster = self.jr.render_at(raster, state.sword[0], state.sword[1], sword_mask) + raster = jax.lax.cond( + state.sword[2]==state.player[2], + lambda r : self.jr.render_at(raster, state.sword[0], state.sword[1], sword_mask), + lambda r : r, + operand = raster, + ) bridge_mask = self.SHAPE_MASKS["bridge"] - raster = self.jr.render_at(raster, state.bridge[0], state.bridge[1], bridge_mask) + raster = jax.lax.cond( + state.bridge[2]==state.player[2], + lambda r : self.jr.render_at(raster, state.bridge[0], state.bridge[1], bridge_mask), + lambda r : r, + operand = raster, + ) magnet_mask = self.SHAPE_MASKS["magnet"] - raster = self.jr.render_at(raster, state.magnet[0], state.magnet[1], magnet_mask) + raster = jax.lax.cond( + state.magnet[2]==state.player[2], + lambda r : self.jr.render_at(raster, state.magnet[0], state.magnet[1], magnet_mask), + lambda r : r, + operand = raster, + ) + #chalice chalice_mask = self.SHAPE_MASKS["chalice"][state.chalice[3]] - raster = self.jr.render_at(raster, state.chalice[0], state.chalice[1], chalice_mask) + raster = jax.lax.cond( + state.chalice[2]==state.player[2], + lambda r : self.jr.render_at(raster, state.chalice[0], state.chalice[1], chalice_mask), + lambda r : r, + operand = raster, + ) return self.jr.render_from_palette(raster, self.PALETTE) From 208ea301b6109cd4ffe4274f71eeaa4c4901f781 Mon Sep 17 00:00:00 2001 From: DanielCress Date: Sat, 20 Dec 2025 15:24:10 +0100 Subject: [PATCH 022/102] Room Change --- src/jaxatari/games/jax_adventure.py | 39 +++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 8d27fc5ad..45b1ee566 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -189,11 +189,29 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt ) new_player_tile = state.player[2] new_player_y, new_player_tile = jax.lax.cond( - jnp.logical_and(new_player_y >=212, new_player_tile == 0), - lambda _: (27, 2), + new_player_y > 212, + lambda _: (27, jax.lax.switch( new_player_tile, [lambda:2,lambda:0,lambda:0, lambda:4, lambda:0, lambda:0, lambda:5, lambda:8, lambda:0, lambda: 6, lambda:7, lambda:10, lambda:11, lambda:12])), lambda _: (new_player_y, new_player_tile), operand = None, ) + new_player_y, new_player_tile = jax.lax.cond( + new_player_y < 27, + lambda _: (212, jax.lax.switch( new_player_tile, [lambda:1,lambda:0,lambda:0, lambda:0, lambda:3, lambda:6, lambda:9, lambda:10, lambda:7, lambda: 0, lambda:11, lambda:12, lambda:14, lambda:0])), + lambda _: (new_player_y, new_player_tile), + operand = None, + ) + new_player_x, new_player_tile = jax.lax.cond( + new_player_x > 160, + lambda _: (0, jax.lax.switch( new_player_tile, [lambda:0,lambda:0,lambda:3, lambda:0, lambda:0, lambda:2, lambda:7, lambda:6, lambda:10, lambda: 8, lambda:9, lambda:0, lambda:0, lambda:0])), + lambda _: (new_player_x, new_player_tile), + operand = None, + ) + new_player_x, new_player_tile = jax.lax.cond( + new_player_x < 0, + lambda _: (160, jax.lax.switch( new_player_tile, [lambda:0,lambda:0,lambda:5, lambda:2, lambda:0, lambda:0, lambda:7, lambda:6, lambda:9, lambda: 10, lambda:8, lambda:0, lambda:0, lambda:0])), + lambda _: (new_player_x, new_player_tile), + operand = None, + ) return AdventureState( step_counter = state.step_counter, @@ -224,20 +242,20 @@ def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureOb #Player Spawn: x, y, tile, color player = jnp.array([78,174,0,0]).astype(jnp.int32), #Dragons: x, y ,tile ,state - dragon_yellow = jnp.array([120,50,2,0]).astype(jnp.int32), #ToDo - dragon_green = jnp.array([120,80,2,2]).astype(jnp.int32), #ToDo + dragon_yellow = jnp.array([120,50,5,0]).astype(jnp.int32), #ToDo + dragon_green = jnp.array([120,80,4,2]).astype(jnp.int32), #ToDo #Keys: x ,y, tile key_yellow = jnp.array([31,110,0]).astype(jnp.int32), - key_black = jnp.array([31,80,2]).astype(jnp.int32), + key_black = jnp.array([31,80,4]).astype(jnp.int32), #Gate: state gate_yellow=jnp.array([0]).astype(jnp.int32), gate_black=jnp.array([0]).astype(jnp.int32), #Items: x, y, tile - sword = jnp.array([120,120,2]).astype(jnp.int32), #ToDo - bridge= jnp.array([120,120,2]).astype(jnp.int32), #ToDo - magnet= jnp.array([120,120,2]).astype(jnp.int32), #ToDo + sword = jnp.array([120,120,1]).astype(jnp.int32), #ToDo + bridge= jnp.array([120,120,10]).astype(jnp.int32), #ToDo + magnet= jnp.array([120,120,12]).astype(jnp.int32), #ToDo #Chalice: x, y, tile, color - chalice= jnp.array([120,120,2,0]).astype(jnp.int32), #ToDo + chalice= jnp.array([120,120,13,0]).astype(jnp.int32), #ToDo ) initial_obs = self._get_observation(state) @@ -499,6 +517,7 @@ def render(self, state): #Gates gate_yellow_mask = self.SHAPE_MASKS["gate_state"][state.gate_yellow[0]] + raster = jax.lax.cond( 0==state.player[2], lambda r : self.jr.render_at(raster, 77, 140, gate_yellow_mask), @@ -507,7 +526,7 @@ def render(self, state): ) gate_black_mask = self.SHAPE_MASKS["gate_state"][state.gate_black[0]] raster = jax.lax.cond( - 10==state.player[2], + 11==state.player[2], lambda r : self.jr.render_at(raster, 30, 30, gate_black_mask),#ToDO lambda r : r, operand = raster, From d438beeedf018117474541af0ece8287bd6dca4c Mon Sep 17 00:00:00 2001 From: LucyLMM Date: Sat, 20 Dec 2025 16:22:08 +0100 Subject: [PATCH 023/102] First Walls Functional --- src/jaxatari/games/jax_adventure.py | 65 ++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 45b1ee566..e219141ff 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -155,20 +155,81 @@ def __init__(self, consts: AdventureConstants = None): Action.DOWN, ] + def _check_for_wall(self, state: AdventureState, direction: int) -> bool: + room = state.player[2] + + # direction 0: left, 1: right, 2: up, 3: down + player_x = state.player[0] + player_x = jax.lax.cond( + direction == 0, + lambda x: x-4, + lambda x: x, + operand = player_x, + ) + player_x = jax.lax.cond( + direction == 1, + lambda x: x+4, + lambda x: x, + operand = player_x, + ) + + player_y = state.player[1] + player_y = jax.lax.cond( + direction == 2, + lambda y: y-8, + lambda y: y, + operand = player_y, + ) + player_y = jax.lax.cond( + direction == 3, + lambda y: y+8, + lambda y: y, + operand = player_y, + ) + + room_1_clear = jnp.logical_or( + jnp.logical_not(room == 0), #either it is not room 1 or + jnp.logical_and( + player_x >= 8, #left wall + player_x <= 148 #right wall + ) + ) + + room_2_clear = jnp.logical_or( + jnp.logical_not(room == 1), #either it is not room 2 or + jnp.logical_and( + player_x >= 8, #left wall + player_x <= 148 #right wall + ) + ) + + return_bool = jnp.logical_and(room_1_clear, room_2_clear) + + return return_bool + def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureState: left = jnp.logical_or(action == Action.LEFT, action == Action.LEFTFIRE) right = jnp.logical_or(action == Action.RIGHT, action == Action.RIGHTFIRE) up = jnp.logical_or(action == Action.UP, action == Action.UPFIRE) down = jnp.logical_or(action == Action.DOWN, action == Action.DOWNFIRE) + + + + #check for no wall before walking + left_no_wall = jnp.logical_and(left,self._check_for_wall(state, 0)) + right_no_wall = jnp.logical_and(right,self._check_for_wall(state, 1)) + up_no_wall = jnp.logical_and(up,self._check_for_wall(state, 2)) + down_no_wall = jnp.logical_and(down,self._check_for_wall(state, 3)) + new_player_x = state.player[0] new_player_x = jax.lax.cond( - left, + left_no_wall, lambda x: x-4, lambda x: x, operand = new_player_x, ) new_player_x = jax.lax.cond( - right, + right_no_wall, lambda x: x+4, lambda x: x, operand = new_player_x, From 15f9e11bd6080973f195ce6dfd2111c024da0e2d Mon Sep 17 00:00:00 2001 From: Leif Schwass Date: Sat, 20 Dec 2025 17:01:21 +0100 Subject: [PATCH 024/102] Changed to more Constant usage --- src/jaxatari/games/jax_adventure.py | 59 ++++++++++++++++++----------- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index e219141ff..09ce3cde3 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -83,7 +83,20 @@ class AdventureConstants(NamedTuple): WIDTH: int = 160 HEIGHT: int = 250 #upper left corner is 0, 0 - + PLAYER_SIZE: Tuple[int, int] = (4, 8) + KEY_SIZE: Tuple[int, int] = (8, 6) + DRAGON_SIZE: Tuple[int, int] = (8, 44) + GATE_SIZE: Tuple[int, int] = (7, 32) + SWORD_SIZE: Tuple[int, int] = (8, 10) + BRIDGE_SIZE: Tuple[int, int] = (32, 48) + MAGNET_SIZE: Tuple[int, int] = (8, 16) + CHALICE_SIZE: Tuple[int, int] = (8, 18) + KEY_YELLOW_ID: int = 0 + KEY_BLACK_ID: int = 1 + SWORD_ID: int = 2 + BRIDGE_ID: int = 3 + MAGNET_ID: int = 4 + CHALICE_ID: int = 5 # sset config baked into constants (immutable default) for asset overrides ASSET_CONFIG: tuple = _get_default_asset_config() @@ -359,88 +372,88 @@ def _get_observation(self, state: AdventureState): x=state.player[0], y=state.player[1], tile=state.player[2], - width=4, - height=8, + width=self.consts.PLAYER_SIZE[0], + height=self.consts.PLAYER_SIZE[1], state=1 #ToDO ) dragon_yellow = EntityPosition( x=state.dragon_yellow[0], y=state.dragon_yellow[1], tile=state.dragon_yellow[2], - width=8, - height=44, + width=self.consts.DRAGON_SIZE[0], + height=self.consts.DRAGON_SIZE[1], state=state.dragon_yellow[3] #ToDO ) dragon_green = EntityPosition( x=state.dragon_green[0], y=state.dragon_green[1], tile=state.dragon_green[2], - width=8, - height=44, + width=self.consts.DRAGON_SIZE[0], + height=self.consts.DRAGON_SIZE[1], state=state.dragon_green[3] #ToDO ) key_yellow = EntityPosition( x=state.key_yellow[0], y=state.key_yellow[1], tile=state.key_yellow[2], - width=8, - height=6, + width=self.consts.KEY_SIZE[0], + height=self.consts.KEY_SIZE[1], state=1 #ToDO ) key_black = EntityPosition( x=state.key_black[0], y=state.key_black[1], tile=state.key_black[2], - width=8, - height=6, + width=self.consts.KEY_SIZE[0], + height=self.consts.KEY_SIZE[1], state=1 #ToDO ) gate_yellow = EntityPosition( x=80, #ToDO y=80, #ToDO tile=1, #ToDO - width=7, - height=32, + width=self.consts.GATE_SIZE[0], + height=self.consts.GATE_SIZE[1], state=state.gate_yellow[0] #ToDO ) gate_black = EntityPosition( x=100, #ToDO y=100, #ToDO tile=1, #ToDO - width=7, - height=32, + width=self.consts.GATE_SIZE[0], + height=self.consts.GATE_SIZE[1], state=state.gate_black[0] #ToDO ) sword = EntityPosition( x=state.sword[0], y=state.sword[1], tile=state.sword[2], - width=8, - height=10, + width=self.consts.SWORD_SIZE[0], + height=self.consts.SWORD_SIZE[1], state=1 #ToDO ) bridge = EntityPosition( x=state.bridge[0], y=state.bridge[1], tile=state.bridge[2], - width=32, - height=48, + width=self.consts.BRIDGE_SIZE[0], + height=self.consts.BRIDGE_SIZE[1], state=1 #ToDO ) magnet = EntityPosition( x=state.magnet[0], y=state.magnet[1], tile=state.magnet[2], - width=8, - height=16, + width=self.consts.MAGNET_SIZE[0], + height=self.consts.MAGNET_SIZE[1], state=1 #ToDO ) chalice = EntityPosition( x=state.chalice[0], y=state.chalice[1], tile=state.chalice[2], - width=8, - height=18, + width=self.consts.CHALICE_SIZE[0], + height=self.consts.CHALICE_SIZE[1], state=1 #ToDO ) From ca6ad870c0f20eab6aa1a9a79ef85f34f7beff6b Mon Sep 17 00:00:00 2001 From: Leif Schwass Date: Sat, 20 Dec 2025 17:31:44 +0100 Subject: [PATCH 025/102] further use of constants --- src/jaxatari/games/jax_adventure.py | 65 +++++++++++++++-------------- 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 09ce3cde3..93c18939e 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -91,12 +91,15 @@ class AdventureConstants(NamedTuple): BRIDGE_SIZE: Tuple[int, int] = (32, 48) MAGNET_SIZE: Tuple[int, int] = (8, 16) CHALICE_SIZE: Tuple[int, int] = (8, 18) - KEY_YELLOW_ID: int = 0 - KEY_BLACK_ID: int = 1 - SWORD_ID: int = 2 - BRIDGE_ID: int = 3 - MAGNET_ID: int = 4 - CHALICE_ID: int = 5 + EMPTY_HAND_ID: int = 0 + KEY_YELLOW_ID: int = 1 + KEY_BLACK_ID: int = 2 + SWORD_ID: int = 3 + BRIDGE_ID: int = 4 + MAGNET_ID: int = 5 + CHALICE_ID: int = 6 + YELLOW_GATE_POS: Tuple[int, int, int] = (77, 140, 0) + BLACK_GATE_POS: Tuple[int, int, int] = (77, 140, 11) # sset config baked into constants (immutable default) for asset overrides ASSET_CONFIG: tuple = _get_default_asset_config() @@ -106,7 +109,7 @@ class AdventureConstants(NamedTuple): class AdventureState(NamedTuple): #step conter for performance indicator? step_counter: chex.Array - #position player: x ,y ,tile , color + #position player: x ,y ,tile , color, inventory player: chex.Array #positions dragons: x, y ,tile ,state dragon_yellow: chex.Array @@ -313,8 +316,8 @@ def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureOb state = AdventureState( step_counter = jnp.array(0).astype(jnp.int32), - #Player Spawn: x, y, tile, color - player = jnp.array([78,174,0,0]).astype(jnp.int32), + #Player Spawn: x, y, tile, color, inventory + player = jnp.array([78,174,0,0,self.consts.EMPTY_HAND_ID]).astype(jnp.int32), #Dragons: x, y ,tile ,state dragon_yellow = jnp.array([120,50,5,0]).astype(jnp.int32), #ToDo dragon_green = jnp.array([120,80,4,2]).astype(jnp.int32), #ToDo @@ -329,7 +332,7 @@ def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureOb bridge= jnp.array([120,120,10]).astype(jnp.int32), #ToDo magnet= jnp.array([120,120,12]).astype(jnp.int32), #ToDo #Chalice: x, y, tile, color - chalice= jnp.array([120,120,13,0]).astype(jnp.int32), #ToDo + chalice= jnp.array([120,120,15,7]).astype(jnp.int32), #ToDo ) initial_obs = self._get_observation(state) @@ -374,7 +377,7 @@ def _get_observation(self, state: AdventureState): tile=state.player[2], width=self.consts.PLAYER_SIZE[0], height=self.consts.PLAYER_SIZE[1], - state=1 #ToDO + state=state.player[4] ) dragon_yellow = EntityPosition( x=state.dragon_yellow[0], @@ -382,7 +385,7 @@ def _get_observation(self, state: AdventureState): tile=state.dragon_yellow[2], width=self.consts.DRAGON_SIZE[0], height=self.consts.DRAGON_SIZE[1], - state=state.dragon_yellow[3] #ToDO + state=state.dragon_yellow[3] ) dragon_green = EntityPosition( x=state.dragon_green[0], @@ -390,7 +393,7 @@ def _get_observation(self, state: AdventureState): tile=state.dragon_green[2], width=self.consts.DRAGON_SIZE[0], height=self.consts.DRAGON_SIZE[1], - state=state.dragon_green[3] #ToDO + state=state.dragon_green[3] ) key_yellow = EntityPosition( x=state.key_yellow[0], @@ -398,7 +401,7 @@ def _get_observation(self, state: AdventureState): tile=state.key_yellow[2], width=self.consts.KEY_SIZE[0], height=self.consts.KEY_SIZE[1], - state=1 #ToDO + state=0 #Key has no relevant state ) key_black = EntityPosition( x=state.key_black[0], @@ -406,23 +409,23 @@ def _get_observation(self, state: AdventureState): tile=state.key_black[2], width=self.consts.KEY_SIZE[0], height=self.consts.KEY_SIZE[1], - state=1 #ToDO + state=0 #Key has no relevant state ) gate_yellow = EntityPosition( - x=80, #ToDO - y=80, #ToDO - tile=1, #ToDO + x=self.consts.YELLOW_GATE_POS[0], + y=self.consts.YELLOW_GATE_POS[1], + tile=self.consts.YELLOW_GATE_POS[2], width=self.consts.GATE_SIZE[0], height=self.consts.GATE_SIZE[1], - state=state.gate_yellow[0] #ToDO + state=state.gate_yellow[0] ) gate_black = EntityPosition( - x=100, #ToDO - y=100, #ToDO - tile=1, #ToDO + x=self.consts.BLACK_GATE_POS[0], + y=self.consts.BLACK_GATE_POS[1], + tile=self.consts.BLACK_GATE_POS[2], width=self.consts.GATE_SIZE[0], height=self.consts.GATE_SIZE[1], - state=state.gate_black[0] #ToDO + state=state.gate_black[0] ) sword = EntityPosition( x=state.sword[0], @@ -430,7 +433,7 @@ def _get_observation(self, state: AdventureState): tile=state.sword[2], width=self.consts.SWORD_SIZE[0], height=self.consts.SWORD_SIZE[1], - state=1 #ToDO + state=0 #Sword has no relevant state ) bridge = EntityPosition( x=state.bridge[0], @@ -438,7 +441,7 @@ def _get_observation(self, state: AdventureState): tile=state.bridge[2], width=self.consts.BRIDGE_SIZE[0], height=self.consts.BRIDGE_SIZE[1], - state=1 #ToDO + state=0 #Bridge has no relevant state ) magnet = EntityPosition( x=state.magnet[0], @@ -446,7 +449,7 @@ def _get_observation(self, state: AdventureState): tile=state.magnet[2], width=self.consts.MAGNET_SIZE[0], height=self.consts.MAGNET_SIZE[1], - state=1 #ToDO + state=0 #Magnet has no relevant state ) chalice = EntityPosition( x=state.chalice[0], @@ -454,7 +457,7 @@ def _get_observation(self, state: AdventureState): tile=state.chalice[2], width=self.consts.CHALICE_SIZE[0], height=self.consts.CHALICE_SIZE[1], - state=1 #ToDO + state=0 #Chalice has no relevant state ) return AdventureObservation( @@ -593,15 +596,15 @@ def render(self, state): gate_yellow_mask = self.SHAPE_MASKS["gate_state"][state.gate_yellow[0]] raster = jax.lax.cond( - 0==state.player[2], - lambda r : self.jr.render_at(raster, 77, 140, gate_yellow_mask), + self.consts.YELLOW_GATE_POS[2]==state.player[2], + lambda r : self.jr.render_at(raster, self.consts.YELLOW_GATE_POS[0], self.consts.YELLOW_GATE_POS[1], gate_yellow_mask), lambda r : r, operand = raster, ) gate_black_mask = self.SHAPE_MASKS["gate_state"][state.gate_black[0]] raster = jax.lax.cond( - 11==state.player[2], - lambda r : self.jr.render_at(raster, 30, 30, gate_black_mask),#ToDO + self.consts.BLACK_GATE_POS[2]==state.player[2], + lambda r : self.jr.render_at(raster, self.consts.BLACK_GATE_POS[0], self.consts.BLACK_GATE_POS[1], gate_black_mask),#ToDO lambda r : r, operand = raster, ) From 620b9d654af6127da2e8b22d8adcc66bf6db4b45 Mon Sep 17 00:00:00 2001 From: DanielCress Date: Sat, 20 Dec 2025 17:42:05 +0100 Subject: [PATCH 026/102] Change Player Color --- src/jaxatari/games/jax_adventure.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 93c18939e..b2c40166a 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -35,13 +35,19 @@ def _get_default_asset_config() -> tuple: 'Room_14.npy']}, {'name': 'bg', 'type': 'background', 'file': 'Room_1.npy'}, #Player in all the different colors - {'name': 'player_colors', 'type': 'group', 'files': ["Player_Yellow.npy", - "Player_Green.npy", - "Player_Purple.npy", - "Player_Pink.npy", - "Player_Green_yellow.npy", - "Player_Blue.npy", - "Player_Black.npy", + {'name': 'player_colors', 'type': 'group', 'files': ["Player_Yellow.npy", + "Player_Yellow.npy", + "Player_Green.npy", + "Player_Purple.npy", + "Player_Pink.npy", + "Player_Green_yellow.npy", + "Player_Blue.npy", + "Player_Blue.npy", + "Player_Blue.npy", + "Player_Blue.npy", + "Player_Blue.npy", + "Player_Black.npy", + "Player_Pink.npy", "Player_Magenta.npy"]}, #Dragons and their animations {'name': 'dragon_yellow', 'type': 'group', 'files': ['Dragon_yellow_neutral.npy', @@ -557,7 +563,7 @@ def render(self, state): raster = self.jr.render_at(raster, 0, 0, room_mask) #set player color here - player_mask = self.SHAPE_MASKS["player_colors"][state.player[3]] + player_mask = self.SHAPE_MASKS["player_colors"][state.player[2]] raster = self.jr.render_at(raster, state.player[0], state.player[1], player_mask) #dragons From 77f116ac172147d359a2849bb5b8e3e1ddf5d471 Mon Sep 17 00:00:00 2001 From: Leif Schwass Date: Sat, 20 Dec 2025 17:59:03 +0100 Subject: [PATCH 027/102] Even More Constants --- src/jaxatari/games/jax_adventure.py | 51 +++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 93c18939e..2749131fb 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -98,8 +98,18 @@ class AdventureConstants(NamedTuple): BRIDGE_ID: int = 4 MAGNET_ID: int = 5 CHALICE_ID: int = 6 + #Spawn Locations of all Entities: (X, Y, Room/Tile) YELLOW_GATE_POS: Tuple[int, int, int] = (77, 140, 0) BLACK_GATE_POS: Tuple[int, int, int] = (77, 140, 11) + PLAYER_SPAWN: Tuple[int, int, int] = (78, 174, 0) #ToDO + DRAGON_YELLOW_SPAWN: Tuple[int, int, int] = (120, 50, 5, 0) #ToDO + DRAGON_GREEN_SPAWN: Tuple[int, int, int] = (120, 80, 4, 0) #ToDO + KEY_YELLOW_SPAWN: Tuple[int, int, int] = (31, 80, 0) #ToDO + KEY_BLACK_SPAWN: Tuple[int, int, int] = (31, 80, 4) #ToDO + SWORD_SPAWN: Tuple[int, int, int] = (120,120,1) #ToDO + BRIDGE_SPAWN: Tuple[int, int, int] = (120,120,10) #ToDO + MAGNET_SPAWN: Tuple[int, int, int] = (120,120,12) #ToDO + CHALICE_SPAWN: Tuple[int, int, int] = (120,120,14) #ToDO # sset config baked into constants (immutable default) for asset overrides ASSET_CONFIG: tuple = _get_default_asset_config() @@ -273,7 +283,7 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt ) new_player_y, new_player_tile = jax.lax.cond( new_player_y < 27, - lambda _: (212, jax.lax.switch( new_player_tile, [lambda:1,lambda:0,lambda:0, lambda:0, lambda:3, lambda:6, lambda:9, lambda:10, lambda:7, lambda: 0, lambda:11, lambda:12, lambda:14, lambda:0])), + lambda _: (212, jax.lax.switch( new_player_tile, [lambda:1,lambda:0,lambda:0, lambda:0, lambda:3, lambda:6, lambda:9, lambda:10, lambda:7, lambda: 0, lambda:11, lambda:12, lambda:13, lambda:0])), lambda _: (new_player_y, new_player_tile), operand = None, ) @@ -317,22 +327,43 @@ def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureOb state = AdventureState( step_counter = jnp.array(0).astype(jnp.int32), #Player Spawn: x, y, tile, color, inventory - player = jnp.array([78,174,0,0,self.consts.EMPTY_HAND_ID]).astype(jnp.int32), + player = jnp.array([self.consts.PLAYER_SPAWN[0], + self.consts.PLAYER_SPAWN[1], + self.consts.PLAYER_SPAWN[2],0, + self.consts.EMPTY_HAND_ID]).astype(jnp.int32), #Dragons: x, y ,tile ,state - dragon_yellow = jnp.array([120,50,5,0]).astype(jnp.int32), #ToDo - dragon_green = jnp.array([120,80,4,2]).astype(jnp.int32), #ToDo + dragon_yellow = jnp.array([self.consts.DRAGON_YELLOW_SPAWN[0], + self.consts.DRAGON_YELLOW_SPAWN[1], + self.consts.DRAGON_YELLOW_SPAWN[2], + self.consts.DRAGON_YELLOW_SPAWN[3]]).astype(jnp.int32), #ToDo + dragon_green = jnp.array([self.consts.DRAGON_GREEN_SPAWN[0], + self.consts.DRAGON_GREEN_SPAWN[1], + self.consts.DRAGON_GREEN_SPAWN[2], + self.consts.DRAGON_GREEN_SPAWN[3]]).astype(jnp.int32), #ToDo #Keys: x ,y, tile - key_yellow = jnp.array([31,110,0]).astype(jnp.int32), - key_black = jnp.array([31,80,4]).astype(jnp.int32), + key_yellow = jnp.array([self.consts.KEY_YELLOW_SPAWN[0], + self.consts.KEY_YELLOW_SPAWN[1], + self.consts.KEY_YELLOW_SPAWN[2]]).astype(jnp.int32), + key_black = jnp.array([self.consts.KEY_BLACK_SPAWN[0], + self.consts.KEY_BLACK_SPAWN[1], + self.consts.KEY_BLACK_SPAWN[2]]).astype(jnp.int32), #Gate: state gate_yellow=jnp.array([0]).astype(jnp.int32), gate_black=jnp.array([0]).astype(jnp.int32), #Items: x, y, tile - sword = jnp.array([120,120,1]).astype(jnp.int32), #ToDo - bridge= jnp.array([120,120,10]).astype(jnp.int32), #ToDo - magnet= jnp.array([120,120,12]).astype(jnp.int32), #ToDo + sword = jnp.array([self.consts.SWORD_SPAWN[0], + self.consts.SWORD_SPAWN[1], + self.consts.SWORD_SPAWN[2]]).astype(jnp.int32), #ToDo + bridge = jnp.array([self.consts.BRIDGE_SPAWN[0], + self.consts.BRIDGE_SPAWN[1], + self.consts.BRIDGE_SPAWN[2]]).astype(jnp.int32), #ToDo + magnet= jnp.array([self.consts.MAGNET_SPAWN[0], + self.consts.MAGNET_SPAWN[1], + self.consts.MAGNET_SPAWN[2]]).astype(jnp.int32), #ToDo #Chalice: x, y, tile, color - chalice= jnp.array([120,120,15,7]).astype(jnp.int32), #ToDo + chalice = jnp.array([self.consts.CHALICE_SPAWN[0], + self.consts.CHALICE_SPAWN[1], + self.consts.CHALICE_SPAWN[2],7]).astype(jnp.int32), #ToDo ) initial_obs = self._get_observation(state) From 36378e0711038dd45ea8ea8692c44e67b5e44cfb Mon Sep 17 00:00:00 2001 From: Leif Schwass Date: Sat, 20 Dec 2025 18:00:45 +0100 Subject: [PATCH 028/102] Chalice spawn fixed --- src/jaxatari/games/jax_adventure.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index dc3eae8e0..6c6e6523b 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -115,7 +115,7 @@ class AdventureConstants(NamedTuple): SWORD_SPAWN: Tuple[int, int, int] = (120,120,1) #ToDO BRIDGE_SPAWN: Tuple[int, int, int] = (120,120,10) #ToDO MAGNET_SPAWN: Tuple[int, int, int] = (120,120,12) #ToDO - CHALICE_SPAWN: Tuple[int, int, int] = (120,120,14) #ToDO + CHALICE_SPAWN: Tuple[int, int, int] = (120,120,13) #ToDO # sset config baked into constants (immutable default) for asset overrides ASSET_CONFIG: tuple = _get_default_asset_config() From bbd95013089328ddc806e53ae3d8897418277336 Mon Sep 17 00:00:00 2001 From: LucyLMM Date: Sat, 20 Dec 2025 18:10:23 +0100 Subject: [PATCH 029/102] Update jax_adventure.py --- src/jaxatari/games/jax_adventure.py | 198 ++++++++++++++++++++++++++-- 1 file changed, 188 insertions(+), 10 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 6c6e6523b..ea05d9aae 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -88,6 +88,20 @@ def _get_default_asset_config() -> tuple: class AdventureConstants(NamedTuple): WIDTH: int = 160 HEIGHT: int = 250 + # Wall coordinates the player cannot pass through + LEFT_WALL_X: int = 8 + RIGHT_WALL_X: int = 148 + UPPER_WALL_Y: int = 43 + LOWER_WALL_Y: int = 199 + #special black borders to the left and right + SPECIAL_WALL_LEFT: int = 12 + SPECIAL_WALL_RIGHT: int = 145 + # Path South and North to another Room, X-Coordinates that offer hole in the wall + PATH_VERTICAL_LEFT: int = 60 + PATH_VERTICAL_RIGHT: int = 95 + # Path East and West, Y-Coordinates that offer hole in the wall + PATH_HORIZONTAL_UP: int = 40 + PATH_HORIZONTAL_DOWN: int = 200 #upper left corner is 0, 0 PLAYER_SIZE: Tuple[int, int] = (4, 8) KEY_SIZE: Tuple[int, int] = (8, 6) @@ -219,23 +233,187 @@ def _check_for_wall(self, state: AdventureState, direction: int) -> bool: operand = player_y, ) + ### Left Wall with and without Path + left_wall = self.consts.LEFT_WALL_X + upper_edge = self.consts.PATH_HORIZONTAL_UP + lower_edge = self.consts.PATH_HORIZONTAL_DOWN + collision_left_wall = player_x >= left_wall + collision_left_wall_path = jnp.logical_or(collision_left_wall, jnp.logical_and(player_y>=upper_edge, player_y<=lower_edge)) + collision_left_special = player_x >= self.consts.SPECIAL_WALL_LEFT + + ### Right Wall with and without Path + right_wall = self.consts.RIGHT_WALL_X + upper_edge = self.consts.PATH_HORIZONTAL_UP + lower_edge = self.consts.PATH_HORIZONTAL_DOWN + collision_right_wall = player_x <= right_wall + collision_right_wall_path = jnp.logical_or(collision_right_wall, jnp.logical_and(player_y>=upper_edge, player_y<=lower_edge)) + collision_right_special = player_x <= self.consts.SPECIAL_WALL_RIGHT + + ### Upper Wall with and without Path + upper_wall = self.consts.UPPER_WALL_Y + edge_left = self.consts.PATH_VERTICAL_LEFT + edge_right = self.consts.PATH_VERTICAL_RIGHT + collision_upper_wall = player_y >= upper_wall + collision_upper_wall_path = jnp.logical_or(collision_upper_wall, jnp.logical_and(player_x>=edge_left, player_x<=edge_right)) + + ### Lower Wall with and without Path + lower_wall = self.consts.LOWER_WALL_Y + edge_left = self.consts.PATH_VERTICAL_LEFT + edge_right = self.consts.PATH_VERTICAL_RIGHT + collision_lower_wall = player_y <= lower_wall + collision_lower_wall_path = jnp.logical_or(collision_lower_wall, jnp.logical_and(player_x>=edge_left, player_x<=edge_right)) + + + ## Rooms: room_1_clear = jnp.logical_or( jnp.logical_not(room == 0), #either it is not room 1 or - jnp.logical_and( - player_x >= 8, #left wall - player_x <= 148 #right wall + jnp.logical_and( #walls of the room are not being crossed + jnp.logical_and( + collision_left_wall, + collision_right_wall + ), + jnp.logical_and( + collision_upper_wall_path, + collision_lower_wall_path + ) ) ) room_2_clear = jnp.logical_or( - jnp.logical_not(room == 1), #either it is not room 2 or - jnp.logical_and( - player_x >= 8, #left wall - player_x <= 148 #right wall + jnp.logical_not(room == 1), #either it is not room 1 or + jnp.logical_and( #walls of the room are not being crossed + jnp.logical_and( + collision_left_wall, + collision_right_wall + ), + jnp.logical_and( + collision_upper_wall, + collision_lower_wall_path + ) ) ) - return_bool = jnp.logical_and(room_1_clear, room_2_clear) + room_3_clear = jnp.logical_or( + jnp.logical_not(room == 2), #either it is not room 1 or + jnp.logical_and( #walls of the room are not being crossed + jnp.logical_and( + collision_left_wall_path, + collision_right_wall_path + ), + jnp.logical_and( + collision_upper_wall_path, + collision_lower_wall + ) + ) + ) + + room_4_clear = jnp.logical_or( + jnp.logical_not(room == 3), #either it is not room 1 or + jnp.logical_and( #walls of the room are not being crossed + jnp.logical_and( + collision_left_wall_path, + collision_right_special + ), + jnp.logical_and( + collision_upper_wall, + collision_lower_wall_path + ) + ) + ) + + room_5_clear = jnp.logical_or( + jnp.logical_not(room == 4), #either it is not room 1 or + jnp.logical_and( #walls of the room are not being crossed + jnp.logical_and( + collision_left_wall, + collision_right_wall + ), + jnp.logical_and( + collision_upper_wall_path, + collision_lower_wall + ) + ) + ) + + room_6_clear = jnp.logical_or( + jnp.logical_not(room == 5), #either it is not room 1 or + jnp.logical_and( #walls of the room are not being crossed + jnp.logical_and( + collision_left_special, + collision_right_wall_path + ), + jnp.logical_and( + collision_upper_wall_path, + collision_lower_wall + ) + ) + ) + + room_7_clear = True + room_8_clear = True + room_9_clear = True + room_10_clear = True + room_11_clear = True + + room_12_clear = jnp.logical_or( + jnp.logical_not(room == 11), #either it is not room 1 or + jnp.logical_and( #walls of the room are not being crossed + jnp.logical_and( + collision_left_wall, + collision_right_wall + ), + jnp.logical_and( + collision_upper_wall_path, + collision_lower_wall_path + ) + ) + ) + + room_13_clear = jnp.logical_or( + jnp.logical_not(room == 12), #either it is not room 1 or + jnp.logical_and( #walls of the room are not being crossed + jnp.logical_and( + collision_left_wall, + collision_right_wall + ), + jnp.logical_and( + collision_upper_wall_path, + collision_lower_wall_path + ) + ) + ) + + room_14_clear = jnp.logical_or( + jnp.logical_not(room == 13), #either it is not room 1 or + jnp.logical_and( #walls of the room are not being crossed + jnp.logical_and( + collision_left_wall, + collision_right_wall + ), + jnp.logical_and( + collision_upper_wall, + collision_lower_wall_path + ) + ) + ) + + room_1_and_2 = jnp.logical_and(room_1_clear, room_2_clear) + room_3_and_4 = jnp.logical_and(room_3_clear, room_4_clear) + room_1_to_4 = jnp.logical_and(room_1_and_2, room_3_and_4) + room_5_and_6 = jnp.logical_and(room_5_clear, room_6_clear) + room_7_and_8 = jnp.logical_and(room_7_clear, room_8_clear) + room_5_to_8 = jnp.logical_and(room_5_and_6, room_7_and_8) + room_9_and_10 = jnp.logical_and(room_9_clear, room_10_clear) + room_11_and_12= jnp.logical_and(room_11_clear, room_12_clear) + room_9_to_12 = jnp.logical_and(room_9_and_10, room_11_and_12) + room_13_and_14 = jnp.logical_and(room_13_clear, room_14_clear) + + room_1_to_8 = jnp.logical_and(room_1_to_4,room_5_to_8) + room_9_to_14 = jnp.logical_and(room_9_to_12, room_13_and_14) + + base_rooms = jnp.logical_and(room_1_to_8, room_9_to_14) + + return_bool = base_rooms # todo return return_bool @@ -269,13 +447,13 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt new_player_y = state.player[1] new_player_y = jax.lax.cond( - down, + down_no_wall, lambda y: y+8, lambda y: y, operand = new_player_y, ) new_player_y = jax.lax.cond( - up, + up_no_wall, lambda y: y-8, lambda y: y, operand = new_player_y, From bb91af9c8f814a948326870d3cc172ec2ff8f5d3 Mon Sep 17 00:00:00 2001 From: DanielCress Date: Sat, 20 Dec 2025 18:35:12 +0100 Subject: [PATCH 030/102] Spawn Locations Items --- src/jaxatari/games/jax_adventure.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index ea05d9aae..cdb636bd6 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -119,17 +119,17 @@ class AdventureConstants(NamedTuple): MAGNET_ID: int = 5 CHALICE_ID: int = 6 #Spawn Locations of all Entities: (X, Y, Room/Tile) - YELLOW_GATE_POS: Tuple[int, int, int] = (77, 140, 0) - BLACK_GATE_POS: Tuple[int, int, int] = (77, 140, 11) - PLAYER_SPAWN: Tuple[int, int, int] = (78, 174, 0) #ToDO - DRAGON_YELLOW_SPAWN: Tuple[int, int, int] = (120, 50, 5, 0) #ToDO - DRAGON_GREEN_SPAWN: Tuple[int, int, int] = (120, 80, 4, 0) #ToDO - KEY_YELLOW_SPAWN: Tuple[int, int, int] = (31, 80, 0) #ToDO - KEY_BLACK_SPAWN: Tuple[int, int, int] = (31, 80, 4) #ToDO - SWORD_SPAWN: Tuple[int, int, int] = (120,120,1) #ToDO - BRIDGE_SPAWN: Tuple[int, int, int] = (120,120,10) #ToDO - MAGNET_SPAWN: Tuple[int, int, int] = (120,120,12) #ToDO - CHALICE_SPAWN: Tuple[int, int, int] = (120,120,13) #ToDO + YELLOW_GATE_POS: Tuple[int, int, int] = (76, 140, 0) + BLACK_GATE_POS: Tuple[int, int, int] = (76, 140, 11) + PLAYER_SPAWN: Tuple[int, int, int] = (78, 174, 0) + DRAGON_YELLOW_SPAWN: Tuple[int, int, int] = (80, 170, 5, 0) + DRAGON_GREEN_SPAWN: Tuple[int, int, int] = (80, 130, 4, 0) + KEY_YELLOW_SPAWN: Tuple[int, int, int] = (31, 110, 0) + KEY_BLACK_SPAWN: Tuple[int, int, int] = (31, 100, 4) + SWORD_SPAWN: Tuple[int, int, int] = (31,180,1) + BRIDGE_SPAWN: Tuple[int, int, int] = (40,130,10) + MAGNET_SPAWN: Tuple[int, int, int] = (120,180,12) + CHALICE_SPAWN: Tuple[int, int, int] = (35,180,13) # sset config baked into constants (immutable default) for asset overrides ASSET_CONFIG: tuple = _get_default_asset_config() From 9a6caac8a212788749d205d7014602b83aefcc56 Mon Sep 17 00:00:00 2001 From: LucyLMM Date: Sat, 20 Dec 2025 19:00:59 +0100 Subject: [PATCH 031/102] Added Castle_Hitboxes --- src/jaxatari/games/jax_adventure.py | 33 ++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index cdb636bd6..1ed22f528 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -102,6 +102,14 @@ class AdventureConstants(NamedTuple): # Path East and West, Y-Coordinates that offer hole in the wall PATH_HORIZONTAL_UP: int = 40 PATH_HORIZONTAL_DOWN: int = 200 + # Castle Edges + CASTLE_TOWER_LEFT_X: int = 35 + CASTLE_TOWER_RIGHT_X: int = 120 + CASTLE_BASE_LEFT_X: int = 45 + CASTLE_BASE_RIGHT_X: int = 113 + CASTLE_TOWER_CORNER_Y: int = 105 + CASTLE_BASE_CORNER_Y: int = 170 + #upper left corner is 0, 0 PLAYER_SIZE: Tuple[int, int] = (4, 8) KEY_SIZE: Tuple[int, int] = (8, 6) @@ -397,6 +405,29 @@ def _check_for_wall(self, state: AdventureState, direction: int) -> bool: ) ) + #Castle Collisions + castle_tower_left = self.consts.CASTLE_TOWER_LEFT_X + castle_tower_right = self.consts.CASTLE_TOWER_RIGHT_X + castle_tower_height = self.consts.CASTLE_TOWER_CORNER_Y + castle_base_left = self.consts.CASTLE_BASE_LEFT_X + castle_base_right = self.consts.CASTLE_BASE_RIGHT_X + castle_base_height = self.consts.CASTLE_BASE_CORNER_Y + + castle_towers_out = jnp.logical_or(player_x<=castle_tower_left, player_x>=castle_tower_right) + castle_towers_in = jnp.logical_and(player_x>=edge_left, player_x<=edge_right) + castle_towers = jnp.logical_or(player_y >= castle_tower_height, jnp.logical_or(castle_towers_in, castle_towers_out)) + + castle_base_out = jnp.logical_or(player_x<=castle_base_left, player_x>=castle_base_right) + castle_base_in = jnp.logical_and(player_x>=edge_left, player_x<=edge_right) + castle_base = jnp.logical_or(player_y >= castle_base_height, jnp.logical_or(castle_base_in, castle_base_out)) + #castle_towers = player_y >= castle_tower_height + #castle_towers = player_y >= castle_tower_height + + castle_collision = jnp.logical_or( + jnp.logical_not(jnp.logical_or(room==0, room==11)), #either it is not a castle tile, or + jnp.logical_and(castle_towers, castle_base) + ) + room_1_and_2 = jnp.logical_and(room_1_clear, room_2_clear) room_3_and_4 = jnp.logical_and(room_3_clear, room_4_clear) room_1_to_4 = jnp.logical_and(room_1_and_2, room_3_and_4) @@ -413,7 +444,7 @@ def _check_for_wall(self, state: AdventureState, direction: int) -> bool: base_rooms = jnp.logical_and(room_1_to_8, room_9_to_14) - return_bool = base_rooms # todo + return_bool = jnp.logical_and(base_rooms, castle_collision )# todo return return_bool From 34b7b4e7bf639b6a410ec1095e2390726e425035 Mon Sep 17 00:00:00 2001 From: DanielCress Date: Sat, 20 Dec 2025 19:30:26 +0100 Subject: [PATCH 032/102] The Dragon starts Chasing you --- src/jaxatari/games/jax_adventure.py | 43 +++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 1ed22f528..79a3306e3 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -530,11 +530,43 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt chalice=state.chalice ) - - @partial(jax.jit, static_argnums=(0,)) - def step(self, state: AdventureState, action: chex.Array) -> Tuple[AdventureObservation, AdventureState, float, bool, AdventureInfo]: - previous_state = state - state = self._player_step(state, action) + def _dragon_step(self, state: AdventureState) -> AdventureState: + direction_x = jnp.sign(state.player[0] - state.dragon_yellow[0]) + direction_y = jnp.sign(state.player[1]- state.dragon_yellow[1]) + dragon_yellow_x = state.dragon_yellow[0] + dragon_yellow_y = state.dragon_yellow[1] + dragon_yellow_x, dragon_yellow_y = jax.lax.cond( + state.player[2]==state.dragon_yellow[2], + lambda _: ((dragon_yellow_x + direction_x*2, dragon_yellow_y + direction_y*2)), + lambda _: (dragon_yellow_x, dragon_yellow_y), + operand = None + ) + direction_x = jnp.sign(state.player[0] - state.dragon_green[0]) + direction_y = jnp.sign(state.player[1]- state.dragon_green[1]) + dragon_green_x = state.dragon_green[0] + dragon_green_y = state.dragon_green[1] + dragon_green_x, dragon_green_y = jax.lax.cond( + state.player[2]==state.dragon_green[2], + lambda _: ((dragon_green_x + direction_x*2, dragon_green_y + direction_y*2)), + lambda _: (dragon_green_x, dragon_green_y), + operand = None + ) + + + return AdventureState( + step_counter = state.step_counter, + player = state.player, + dragon_yellow = jnp.array([dragon_yellow_x,dragon_yellow_y,state.dragon_yellow[2]]).astype(jnp.int32), + dragon_green = jnp.array([dragon_green_x,dragon_green_y,state.dragon_green[2]]).astype(jnp.int32), + key_yellow=state.key_yellow, + key_black=state.key_black, + gate_yellow=state.gate_yellow, + gate_black=state.gate_black, + sword=state.sword, + bridge=state.bridge, + magnet=state.magnet, + chalice=state.chalice + ) def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureObservation, AdventureState]: @@ -604,6 +636,7 @@ def step(self, state: AdventureState, action: chex.Array) -> Tuple[AdventureObse chalice=state.chalice ) state = self._player_step(state, action) + state = self._dragon_step(state) done = self._get_done(state) env_reward = self._get_reward(previous_state, state) From 2871032a0ee7ae259c1891b57a28b981c5213712 Mon Sep 17 00:00:00 2001 From: DanielCress Date: Sat, 20 Dec 2025 19:32:31 +0100 Subject: [PATCH 033/102] Typo fix --- src/jaxatari/games/jax_adventure.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 79a3306e3..deb0fcbf7 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -530,7 +530,7 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt chalice=state.chalice ) - def _dragon_step(self, state: AdventureState) -> AdventureState: + def _dragon_step(self, state: AdventureState) -> AdventureState: direction_x = jnp.sign(state.player[0] - state.dragon_yellow[0]) direction_y = jnp.sign(state.player[1]- state.dragon_yellow[1]) dragon_yellow_x = state.dragon_yellow[0] From 69df1e1fc6b4c072d504ca83b4e57eef3a6bd6c3 Mon Sep 17 00:00:00 2001 From: Leif Schwass Date: Sat, 20 Dec 2025 22:47:03 +0100 Subject: [PATCH 034/102] Items in player inventory moving same as players --- src/jaxatari/games/jax_adventure.py | 143 +++++++++++++++++++++++----- 1 file changed, 121 insertions(+), 22 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index ea05d9aae..5596afde1 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -431,55 +431,103 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt up_no_wall = jnp.logical_and(up,self._check_for_wall(state, 2)) down_no_wall = jnp.logical_and(down,self._check_for_wall(state, 3)) + #chek for item + #has_item = jax.lax.cond( + # pred=state.player[3]==self.consts.EMPTY_HAND_ID, + # true_fun=False, + # false_fun=True + #) + + new_item_x = jax.lax.switch( + state.player[3], + [lambda:0, + lambda:state.key_yellow[0], + lambda:state.key_black[0], + lambda:state.sword[0], + lambda:state.bridge[0], + lambda:state.magnet[0], + lambda:state.chalice[0] + ] + ) + new_player_x = state.player[0] - new_player_x = jax.lax.cond( + new_player_x, new_item_x = jax.lax.cond( left_no_wall, - lambda x: x-4, - lambda x: x, - operand = new_player_x, + lambda y: (y[0]-4,y[1]-4), + lambda y: y, + operand = (new_player_x,new_item_x), ) - new_player_x = jax.lax.cond( + new_player_x, new_item_x = jax.lax.cond( right_no_wall, - lambda x: x+4, - lambda x: x, - operand = new_player_x, + lambda y: (y[0]+4,y[1]+4), + lambda y: y, + operand = (new_player_x,new_item_x), + ) + + + new_item_y = jax.lax.switch( + state.player[3], + [lambda:0, + lambda:state.key_yellow[1], + lambda:state.key_black[1], + lambda:state.sword[1], + lambda:state.bridge[1], + lambda:state.magnet[1], + lambda:state.chalice[1] + ] ) new_player_y = state.player[1] - new_player_y = jax.lax.cond( + new_player_y, new_item_y = jax.lax.cond( down_no_wall, - lambda y: y+8, + lambda y: (y[0]+8,y[1]+8), lambda y: y, - operand = new_player_y, + operand = (new_player_y,new_item_y) ) - new_player_y = jax.lax.cond( + new_player_y, new_item_y = jax.lax.cond( up_no_wall, - lambda y: y-8, + lambda y: (y[0]-8,y[1]-8), lambda y: y, - operand = new_player_y, + operand = (new_player_y,new_item_y) ) new_player_tile = state.player[2] new_player_y, new_player_tile = jax.lax.cond( new_player_y > 212, - lambda _: (27, jax.lax.switch( new_player_tile, [lambda:2,lambda:0,lambda:0, lambda:4, lambda:0, lambda:0, lambda:5, lambda:8, lambda:0, lambda: 6, lambda:7, lambda:10, lambda:11, lambda:12])), + lambda _: (27, jax.lax.switch( new_player_tile, [lambda:2,lambda:0,lambda:0, + lambda:4, lambda:0, lambda:0, + lambda:5, lambda:8, lambda:0, + lambda: 6, lambda:7, lambda:10, + lambda:11, lambda:12])), lambda _: (new_player_y, new_player_tile), operand = None, ) new_player_y, new_player_tile = jax.lax.cond( new_player_y < 27, - lambda _: (212, jax.lax.switch( new_player_tile, [lambda:1,lambda:0,lambda:0, lambda:0, lambda:3, lambda:6, lambda:9, lambda:10, lambda:7, lambda: 0, lambda:11, lambda:12, lambda:13, lambda:0])), + lambda _: (212, jax.lax.switch( new_player_tile, [lambda:1,lambda:0,lambda:0, + lambda:0, lambda:3, lambda:6, + lambda:9, lambda:10, lambda:7, + lambda: 0, lambda:11, lambda:12, + lambda:13, lambda:0])), lambda _: (new_player_y, new_player_tile), operand = None, ) new_player_x, new_player_tile = jax.lax.cond( new_player_x > 160, - lambda _: (0, jax.lax.switch( new_player_tile, [lambda:0,lambda:0,lambda:3, lambda:0, lambda:0, lambda:2, lambda:7, lambda:6, lambda:10, lambda: 8, lambda:9, lambda:0, lambda:0, lambda:0])), + lambda _: (0, jax.lax.switch( new_player_tile, [lambda:0,lambda:0,lambda:3, + lambda:0, lambda:0, lambda:2, + lambda:7, lambda:6, lambda:10, + lambda: 8, lambda:9, lambda:0, + lambda:0, lambda:0])), lambda _: (new_player_x, new_player_tile), operand = None, ) new_player_x, new_player_tile = jax.lax.cond( new_player_x < 0, - lambda _: (160, jax.lax.switch( new_player_tile, [lambda:0,lambda:0,lambda:5, lambda:2, lambda:0, lambda:0, lambda:7, lambda:6, lambda:9, lambda: 10, lambda:8, lambda:0, lambda:0, lambda:0])), + lambda _: (160, jax.lax.switch( new_player_tile, [lambda:0,lambda:0,lambda:5, + lambda:2, lambda:0, lambda:0, + lambda:7, lambda:6, lambda:9, + lambda: 10, lambda:8, lambda:0, + lambda:0, lambda:0])), lambda _: (new_player_x, new_player_tile), operand = None, ) @@ -489,6 +537,58 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt player = jnp.array([new_player_x,new_player_y,new_player_tile,state.player[3]]).astype(jnp.int32), #SEEMS NOT GOOD dragon_yellow = state.dragon_yellow, dragon_green = state.dragon_green, + key_yellow = jax.lax.cond(state.player[3]==self.consts.KEY_YELLOW_ID, + lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: op[3], + operand=(new_item_x,new_item_y,state.key_yellow[2],state.key_yellow), + ), + key_black= jax.lax.cond(state.player[3]==self.consts.KEY_BLACK_ID, + lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: op[3], + operand=(new_item_x,new_item_y,state.key_black[2],state.key_black) + ), + gate_yellow=state.gate_yellow, + gate_black=state.gate_black, + sword= jax.lax.cond(state.player[3]==self.consts.SWORD_ID, + lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: op[3], + operand=(new_item_x,new_item_y,state.sword[2],state.sword) + ), + bridge= jax.lax.cond(state.player[3]==self.consts.BRIDGE_ID, + lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: op[3], + operand=(new_item_x,new_item_y,state.bridge[2],state.bridge) + ), + magnet= jax.lax.cond(state.player[3]==self.consts.MAGNET_ID, + lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: op[3], + operand=(new_item_x,new_item_y,state.magnet[2],state.magnet) + ), + chalice= jax.lax.cond(state.player[3]==self.consts.CHALICE_ID, + lambda op: jnp.array([op[0],op[1],op[2],op[3]]).astype(jnp.int32), + lambda op: op[4], + operand=(new_item_x,new_item_y,state.chalice[2],state.chalice[3],state.chalice) + ) + ) + """ + def _item_pickup(self, state: AdventureState) -> AdventureState: + + #ToDo if the player holds an item skip + new_player_inventory = jax.lax.cond( + state.player[3] != self.consts.EMPTY_HAND_ID, + lambda op: op[3], + lambda _: None, + operand=(state.player[0],state.player[1],state.player[2],state.player[3]) + ) + #ToDo check around the player, if there is an item + + #if yes pick it up + + return AdventureState( + step_counter=state.step_counter, + player = jnp.array([state.player[0],state.player[1],state.player[2],new_player_inventory]).astype(jnp.int32), + dragon_yellow=state.dragon_yellow, + dragon_green=state.dragon_green, key_yellow=state.key_yellow, key_black=state.key_black, gate_yellow=state.gate_yellow, @@ -498,8 +598,7 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt magnet=state.magnet, chalice=state.chalice ) - - + """ @partial(jax.jit, static_argnums=(0,)) def step(self, state: AdventureState, action: chex.Array) -> Tuple[AdventureObservation, AdventureState, float, bool, AdventureInfo]: previous_state = state @@ -510,10 +609,10 @@ def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureOb state = AdventureState( step_counter = jnp.array(0).astype(jnp.int32), - #Player Spawn: x, y, tile, color, inventory + #Player Spawn: x, y, tile, inventory player = jnp.array([self.consts.PLAYER_SPAWN[0], self.consts.PLAYER_SPAWN[1], - self.consts.PLAYER_SPAWN[2],0, + self.consts.PLAYER_SPAWN[2], self.consts.EMPTY_HAND_ID]).astype(jnp.int32), #Dragons: x, y ,tile ,state dragon_yellow = jnp.array([self.consts.DRAGON_YELLOW_SPAWN[0], From 15f35acecb4b7054855f0eaca2e0545e5fc168ee Mon Sep 17 00:00:00 2001 From: LucyLMM Date: Sun, 21 Dec 2025 00:33:15 +0100 Subject: [PATCH 035/102] Room 7 Full Walls First Room of the Maze will full wall functionality --- src/jaxatari/games/jax_adventure.py | 83 +++++++++++++++++++++++++++-- 1 file changed, 79 insertions(+), 4 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index deb0fcbf7..c39de432e 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -97,7 +97,7 @@ class AdventureConstants(NamedTuple): SPECIAL_WALL_LEFT: int = 12 SPECIAL_WALL_RIGHT: int = 145 # Path South and North to another Room, X-Coordinates that offer hole in the wall - PATH_VERTICAL_LEFT: int = 60 + PATH_VERTICAL_LEFT: int = 64 PATH_VERTICAL_RIGHT: int = 95 # Path East and West, Y-Coordinates that offer hole in the wall PATH_HORIZONTAL_UP: int = 40 @@ -357,7 +357,84 @@ def _check_for_wall(self, state: AdventureState, direction: int) -> bool: ) ) - room_7_clear = True + ### extra maze walls + + room_7_walls = jnp.logical_or( + player_y >= 170, # either below lowest thick wall or + jnp.logical_or( + jnp.logical_or( # the two corridors up + jnp.logical_and(player_x>=30, player_x <= 38), #left corridor + jnp.logical_and(player_x>=120, player_x <= 126) #right corridor + ), + jnp.logical_or( + jnp.logical_or( + jnp.logical_and( + jnp.logical_and(player_y <= 135, player_y >= 105), + jnp.logical_or( + jnp.logical_or( + jnp.logical_and(player_x >=45, player_x <= 110), + player_x <= 20 + ), + player_x >=135 + ) + ), + jnp.logical_and( + jnp.logical_and(player_y <= 105, player_y >= 75), + jnp.logical_or( + jnp.logical_or( + jnp.logical_and(player_x >= 45, player_x <=53), + jnp.logical_and(player_x >= 15, player_x <= 20) + ), + jnp.logical_or( + jnp.logical_and(player_x >= 102, player_x <= 110), + jnp.logical_and(player_x >= 135, player_x <= 143) + ) + ) + ) + ), + jnp.logical_or( + jnp.logical_and( + jnp.logical_and(player_y <= 70, player_y >= 40), + jnp.logical_or( + jnp.logical_or( + jnp.logical_and(player_x >= 62, player_x <= 94), + jnp.logical_or(player_x <= 20, player_x >=135) + ), + jnp.logical_or( + jnp.logical_and(player_x >= 102, player_x <= 110), + jnp.logical_and(player_x >= 45, player_x <= 53) + ) + ) + ), + jnp.logical_and( + player_y <= 40, + jnp.logical_or( + jnp.logical_or( + jnp.logical_and(player_x >= 62, player_x <= 70), #todo smaller + jnp.logical_and(player_x >= 86, player_x <= 94) #todo smaller + ), + jnp.logical_or( + jnp.logical_and(player_x >= 102, player_x <= 110), + jnp.logical_and(player_x >= 45, player_x <= 53) + ) + ) + ) + ) + ) + ) + ) + + + ### end extra maze walls + + room_7_clear = jnp.logical_or( + jnp.logical_not(room == 6), + jnp.logical_and( + collision_lower_wall_path, + room_7_walls + ) + + ) room_8_clear = True room_9_clear = True room_10_clear = True @@ -420,8 +497,6 @@ def _check_for_wall(self, state: AdventureState, direction: int) -> bool: castle_base_out = jnp.logical_or(player_x<=castle_base_left, player_x>=castle_base_right) castle_base_in = jnp.logical_and(player_x>=edge_left, player_x<=edge_right) castle_base = jnp.logical_or(player_y >= castle_base_height, jnp.logical_or(castle_base_in, castle_base_out)) - #castle_towers = player_y >= castle_tower_height - #castle_towers = player_y >= castle_tower_height castle_collision = jnp.logical_or( jnp.logical_not(jnp.logical_or(room==0, room==11)), #either it is not a castle tile, or From 762b6b914085365b7bc4d5fd7711a648a6790e6f Mon Sep 17 00:00:00 2001 From: Leif Schwass Date: Sun, 21 Dec 2025 01:23:11 +0100 Subject: [PATCH 036/102] very wonky woking pickup for yellow key --- src/jaxatari/games/jax_adventure.py | 89 ++++++++++++++++++++++++++--- 1 file changed, 81 insertions(+), 8 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index daa31d93c..e421d5d3d 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -147,7 +147,7 @@ class AdventureConstants(NamedTuple): class AdventureState(NamedTuple): #step conter for performance indicator? step_counter: chex.Array - #position player: x ,y ,tile , color, inventory + #position player: x ,y ,tile, inventory player: chex.Array #positions dragons: x, y ,tile ,state dragon_yellow: chex.Array @@ -601,19 +601,89 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt operand=(new_item_x,new_item_y,state.chalice[2],state.chalice[3],state.chalice) ) ) - """ + def _item_pickup(self, state: AdventureState) -> AdventureState: + def check_for_item(self, state: AdventureState, item_ID: int) -> bool: + item_x, item_y, tile, item_width, item_height = jax.lax.switch( + item_ID, + [lambda:(0,0,0,0,0), #this should never occour + lambda:(state.key_yellow[0],state.key_yellow[1],state.key_yellow[2],self.consts.KEY_SIZE[0],self.consts.KEY_SIZE[1]), + lambda:(state.key_black[0],state.key_yellow[1],state.key_yellow[2],self.consts.KEY_SIZE[0],self.consts.KEY_SIZE[1]), + lambda:(state.sword[0],state.sword[1],state.sword[2],self.consts.SWORD_SIZE[0],self.consts.SWORD_SIZE[1]), + lambda:(state.bridge[0],state.bridge[1],state.bridge[2],self.consts.BRIDGE_SIZE[0],self.consts.BRIDGE_SIZE[1]), + lambda:(state.magnet[0],state.magnet[1],state.magnet[2],self.consts.MAGNET_SIZE[0],self.consts.MAGNET_SIZE[1]), + lambda:(state.chalice[0],state.chalice[1],state.chalice[2],self.consts.CHALICE_SIZE[0],self.consts.CHALICE_SIZE[1]) + ]) + + #HARDCODED BAAAAAD, but i dont care right now (performance?)(items smaler then 4 pixels would be buggy) + on_same_tile = (tile==state.player[2]) + player_hitbox_nw = (state.player[0]-1,state.player[1]-1) + player_hitbox_ne = (state.player[0]+self.consts.PLAYER_SIZE[0]+1,state.player[1]-1) + player_hitbox_se = (state.player[0]+self.consts.PLAYER_SIZE[0]+1,state.player[1]+self.consts.PLAYER_SIZE[1]+1) + player_hitbox_sw = (state.player[0]-1,state.player[1]+self.consts.PLAYER_SIZE[1]+1) + + nw_close_in_x = jnp.logical_and(player_hitbox_nw[0]>=item_x,player_hitbox_nw[0]<=(item_x+item_width)) + nw_close_in_y = jnp.logical_and(player_hitbox_nw[1]>=item_y,player_hitbox_nw[1]<=(item_y+item_height)) + nw_touches_item = jnp.logical_and(nw_close_in_x,nw_close_in_y) + + ne_close_in_x = jnp.logical_and(player_hitbox_ne[0]>=item_x,player_hitbox_ne[0]<=(item_x+item_width)) + ne_close_in_y = jnp.logical_and(player_hitbox_ne[1]>=item_y,player_hitbox_ne[1]<=(item_y+item_height)) + ne_touches_item = jnp.logical_and(ne_close_in_x,ne_close_in_y) + + se_close_in_x = jnp.logical_and(player_hitbox_se[0]>=item_x,player_hitbox_se[0]<=(item_x+item_width)) + se_close_in_y = jnp.logical_and(player_hitbox_se[1]>=item_y,player_hitbox_se[1]<=(item_y+item_height)) + se_touches_item = jnp.logical_and(se_close_in_x,se_close_in_y) + + sw_close_in_x = jnp.logical_and(player_hitbox_sw[0]>=item_x,player_hitbox_sw[0]<=(item_x+item_width)) + sw_close_in_y = jnp.logical_and(player_hitbox_sw[1]>=item_y,player_hitbox_sw[1]<=(item_y+item_height)) + sw_touches_item = jnp.logical_and(sw_close_in_x,sw_close_in_y) + + item_touches = jnp.logical_and(on_same_tile, + jnp.logical_or(jnp.logical_or(nw_touches_item, + ne_touches_item), + jnp.logical_or(se_touches_item, + sw_touches_item))) + + return item_touches + #ToDo if the player holds an item skip new_player_inventory = jax.lax.cond( - state.player[3] != self.consts.EMPTY_HAND_ID, - lambda op: op[3], - lambda _: None, - operand=(state.player[0],state.player[1],state.player[2],state.player[3]) + check_for_item(self=self, state=state, item_ID=self.consts.KEY_YELLOW_ID), + lambda _: self.consts.KEY_YELLOW_ID, + lambda op: op, + operand=state.player[3] ) + #ToDo check around the player, if there is an item - #if yes pick it up + #check clockwise if an item is near the player + #picking up the FIRST item it sees and according to a certain priority + + + return AdventureState( + step_counter=state.step_counter, + player = jnp.array([state.player[0],state.player[1],state.player[2],new_player_inventory]).astype(jnp.int32), + dragon_yellow=state.dragon_yellow, + dragon_green=state.dragon_green, + key_yellow=state.key_yellow, + key_black=state.key_black, + gate_yellow=state.gate_yellow, + gate_black=state.gate_black, + sword=state.sword, + bridge=state.bridge, + magnet=state.magnet, + chalice=state.chalice + ) + + def _item_drop(self, state: AdventureState, action: chex.Array) -> AdventureState: + + new_player_inventory = jax.lax.cond( + action == Action.FIRE, + lambda _: self.consts.EMPTY_HAND_ID, + lambda op: op, + operand=state.player[3] + ) return AdventureState( step_counter=state.step_counter, @@ -629,7 +699,7 @@ def _item_pickup(self, state: AdventureState) -> AdventureState: magnet=state.magnet, chalice=state.chalice ) - """ + def _dragon_step(self, state: AdventureState) -> AdventureState: direction_x = jnp.sign(state.player[0] - state.dragon_yellow[0]) @@ -669,6 +739,7 @@ def _dragon_step(self, state: AdventureState) -> AdventureState: chalice=state.chalice ) + #Did Yo delete this Daniel? @partial(jax.jit, static_argnums=(0,)) def step(self, state: AdventureState, action: chex.Array) -> Tuple[AdventureObservation, AdventureState, float, bool, AdventureInfo]: previous_state = state @@ -742,6 +813,8 @@ def step(self, state: AdventureState, action: chex.Array) -> Tuple[AdventureObse chalice=state.chalice ) state = self._player_step(state, action) + state = self._item_pickup(state) + state = self._item_drop(state, action) state = self._dragon_step(state) done = self._get_done(state) From bd3f7ac46e2325149bc6f8713408c264d11a59ef Mon Sep 17 00:00:00 2001 From: LucyLMM Date: Sun, 21 Dec 2025 02:32:07 +0100 Subject: [PATCH 037/102] Progress Maze Room 2 --- src/jaxatari/games/jax_adventure.py | 92 ++++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 2 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index e305c418d..f62ee55a7 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -422,7 +422,91 @@ def _check_for_wall(self, state: AdventureState, direction: int) -> bool: ) ) ) + ) + + room_8_walls = jnp.logical_or( + jnp.logical_or( + jnp.logical_and( + player_y >= 199, + jnp.logical_or( + jnp.logical_or( + jnp.logical_and(player_x >= 30, player_x <= 38), + jnp.logical_and(player_x >= 120, player_x <= 126) + ), + jnp.logical_or( + jnp.logical_or( + jnp.logical_and(player_x >= 102, player_x <= 110), + jnp.logical_and(player_x >= 45, player_x <= 53) + ), + jnp.logical_and(player_x>=edge_left, player_x<=edge_right) + ) + ) + ), + jnp.logical_and( + jnp.logical_and(player_y >= 170, player_y <= 199), + jnp.logical_or( + jnp.logical_or( + jnp.logical_or( + jnp.logical_and(player_x >= 30, player_x <= 38), + jnp.logical_and(player_x >= 120, player_x <= 126) + ), + jnp.logical_or( + jnp.logical_or( + jnp.logical_and(player_x >= 102, player_x <= 110), + jnp.logical_and(player_x >= 45, player_x <= 53) + ), + jnp.logical_and(player_x>=edge_left, player_x<=edge_right) + ) + ), + jnp.logical_or( + player_x <= 20, + player_x >= 135 + ) + ) + ) + ), + jnp.logical_or( + jnp.logical_and( + jnp.logical_and(player_y >= 135, player_y <= 170), + jnp.logical_or( + jnp.logical_or( + jnp.logical_or( + jnp.logical_and(player_x >= 30, player_x <= 38), + jnp.logical_and(player_x >= 120, player_x <= 126) + ), + jnp.logical_or( + jnp.logical_or( + jnp.logical_and(player_x >= 102, player_x <= 110), + jnp.logical_and(player_x >= 45, player_x <= 53) + ), + jnp.logical_and(player_x>=72, player_x<=84) + ) + ), + jnp.logical_or( + jnp.logical_and(player_x <= 20, player_x >= 14), + jnp.logical_and(player_x >= 135, player_x <= 142) + ) + ) + ), + jnp.logical_and( + jnp.logical_and(player_y >= 105, player_y <= 135), + jnp.logical_or( + jnp.logical_or( + player_x <= 38, + player_x >= 120 + ), + jnp.logical_or( + jnp.logical_or( + jnp.logical_and(player_x >= 102, player_x <= 110), + jnp.logical_and(player_x >= 45, player_x <= 53) + ), + jnp.logical_and(player_x>=72, player_x<=84) + ) + ) + ) + ) ) + ### end extra maze walls @@ -433,9 +517,13 @@ def _check_for_wall(self, state: AdventureState, direction: int) -> bool: collision_lower_wall_path, room_7_walls ) - ) - room_8_clear = True + + room_8_clear = jnp.logical_or( + jnp.logical_not(room == 7), + room_8_walls + ) + room_9_clear = True room_10_clear = True room_11_clear = True From 9c4f61c66444f581ccb8f9e31e825bde79556f30 Mon Sep 17 00:00:00 2001 From: LucyLMM Date: Sun, 21 Dec 2025 10:31:49 +0100 Subject: [PATCH 038/102] Maze Room 2 Functional --- src/jaxatari/games/jax_adventure.py | 136 +++++++++++++++++++--------- 1 file changed, 93 insertions(+), 43 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index f62ee55a7..a6ab4d0aa 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -410,8 +410,8 @@ def _check_for_wall(self, state: AdventureState, direction: int) -> bool: player_y <= 40, jnp.logical_or( jnp.logical_or( - jnp.logical_and(player_x >= 62, player_x <= 70), #todo smaller - jnp.logical_and(player_x >= 86, player_x <= 94) #todo smaller + jnp.logical_and(player_x >= 62, player_x <= 70), + jnp.logical_and(player_x >= 86, player_x <= 94) ), jnp.logical_or( jnp.logical_and(player_x >= 102, player_x <= 110), @@ -426,25 +426,9 @@ def _check_for_wall(self, state: AdventureState, direction: int) -> bool: room_8_walls = jnp.logical_or( jnp.logical_or( - jnp.logical_and( - player_y >= 199, - jnp.logical_or( - jnp.logical_or( - jnp.logical_and(player_x >= 30, player_x <= 38), - jnp.logical_and(player_x >= 120, player_x <= 126) - ), - jnp.logical_or( - jnp.logical_or( - jnp.logical_and(player_x >= 102, player_x <= 110), - jnp.logical_and(player_x >= 45, player_x <= 53) - ), - jnp.logical_and(player_x>=edge_left, player_x<=edge_right) - ) - ) - ), - jnp.logical_and( - jnp.logical_and(player_y >= 170, player_y <= 199), - jnp.logical_or( + jnp.logical_or( + jnp.logical_and( + player_y >= 199, jnp.logical_or( jnp.logical_or( jnp.logical_and(player_x >= 30, player_x <= 38), @@ -457,56 +441,122 @@ def _check_for_wall(self, state: AdventureState, direction: int) -> bool: ), jnp.logical_and(player_x>=edge_left, player_x<=edge_right) ) - ), + ) + ), + jnp.logical_and( + jnp.logical_and(player_y >= 170, player_y <= 199), + jnp.logical_or( jnp.logical_or( - player_x <= 20, - player_x >= 135 + jnp.logical_or( + jnp.logical_and(player_x >= 30, player_x <= 38), + jnp.logical_and(player_x >= 120, player_x <= 126) + ), + jnp.logical_or( + jnp.logical_or( + jnp.logical_and(player_x >= 102, player_x <= 110), + jnp.logical_and(player_x >= 45, player_x <= 53) + ), + jnp.logical_and(player_x>=edge_left, player_x<=edge_right) + ) + ), + jnp.logical_or( + player_x <= 20, + player_x >= 135 + ) ) ) - ) + ), + + jnp.logical_or( + jnp.logical_and( + jnp.logical_and(player_y >= 135, player_y <= 170), + jnp.logical_or( + jnp.logical_or( + jnp.logical_or( + jnp.logical_and(player_x >= 30, player_x <= 38), + jnp.logical_and(player_x >= 120, player_x <= 126) + ), + jnp.logical_or( + jnp.logical_or( + jnp.logical_and(player_x >= 102, player_x <= 110), + jnp.logical_and(player_x >= 45, player_x <= 53) + ), + jnp.logical_and(player_x>=72, player_x<=84) + ) + ), + jnp.logical_or( + jnp.logical_and(player_x <= 20, player_x >= 14), + jnp.logical_and(player_x >= 135, player_x <= 142) + ) + ) + ), + jnp.logical_and( + jnp.logical_and(player_y >= 105, player_y <= 135), + jnp.logical_or( + jnp.logical_or( + player_x <= 38, + player_x >= 120 + ), + jnp.logical_or( + jnp.logical_or( + jnp.logical_and(player_x >= 102, player_x <= 110), + jnp.logical_and(player_x >= 45, player_x <= 53) + ), + jnp.logical_and(player_x>=72, player_x<=84) + ) + ) + ) + ), ), jnp.logical_or( - jnp.logical_and( - jnp.logical_and(player_y >= 135, player_y <= 170), jnp.logical_or( + jnp.logical_and( + jnp.logical_and(player_y >= 75, player_y <= 105), jnp.logical_or( jnp.logical_or( - jnp.logical_and(player_x >= 30, player_x <= 38), - jnp.logical_and(player_x >= 120, player_x <= 126) + jnp.logical_and(player_x >= 102, player_x <= 110), + jnp.logical_and(player_x >= 45, player_x <= 53) ), + jnp.logical_and(player_x>=72, player_x<=84) + ), + ), + jnp.logical_and( + jnp.logical_and(player_y >= 40, player_y <= 70), + jnp.logical_or( jnp.logical_or( jnp.logical_or( - jnp.logical_and(player_x >= 102, player_x <= 110), - jnp.logical_and(player_x >= 45, player_x <= 53) + jnp.logical_and(player_x >= 30, player_x <= 53), + jnp.logical_and(player_x >= 102, player_x <= 126) ), jnp.logical_and(player_x>=72, player_x<=84) - ) - ), - jnp.logical_or( - jnp.logical_and(player_x <= 20, player_x >= 14), - jnp.logical_and(player_x >= 135, player_x <= 142) + ), + jnp.logical_or( + player_x <= 20, + player_x >= 135 + ) ) ) ), jnp.logical_and( - jnp.logical_and(player_y >= 105, player_y <= 135), - jnp.logical_or( + player_y <= 40, + jnp.logical_or( jnp.logical_or( - player_x <= 38, - player_x >= 120 + jnp.logical_and(player_x >= 30, player_x <= 38), + jnp.logical_and(player_x >= 120, player_x <= 126) ), jnp.logical_or( jnp.logical_or( - jnp.logical_and(player_x >= 102, player_x <= 110), - jnp.logical_and(player_x >= 45, player_x <= 53) + jnp.logical_and(player_x <= 20, player_x >= 14), + jnp.logical_and(player_x >= 135, player_x <= 142) ), jnp.logical_and(player_x>=72, player_x<=84) ) ) - ) + ) ) ) + ### end extra maze walls From 385b2052697c439fb70f3aad4abaa37019853d99 Mon Sep 17 00:00:00 2001 From: LucyLMM Date: Sun, 21 Dec 2025 10:49:11 +0100 Subject: [PATCH 039/102] Maze Room 3 Functional --- src/jaxatari/games/jax_adventure.py | 94 ++++++++++++++++++++++++++++- 1 file changed, 93 insertions(+), 1 deletion(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index a6ab4d0aa..7c65e79a6 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -556,6 +556,94 @@ def _check_for_wall(self, state: AdventureState, direction: int) -> bool: ) ) + room_9_walls = jnp.logical_or( + jnp.logical_or( + jnp.logical_or( + jnp.logical_and( + player_y >= 199, + False + ), + jnp.logical_and( + jnp.logical_and(player_y >= 170, player_y <= 199), + jnp.logical_or( + + jnp.logical_and( + player_x >= 30, + player_x <= 126 + ), + + jnp.logical_or( + player_x <= 20, + player_x >= 135 + ) + ) + ) + ), + + jnp.logical_or( + jnp.logical_and( + jnp.logical_and(player_y >= 135, player_y <= 170), + jnp.logical_and( + player_x >= 30, + player_x <= 126 + ) + ), + jnp.logical_and( + jnp.logical_and(player_y >= 105, player_y <= 135), + jnp.logical_and( + player_x >= 14, + player_x <= 142 + ) + ) + ), + ), + jnp.logical_or( + jnp.logical_or( + jnp.logical_and( + jnp.logical_and(player_y >= 75, player_y <= 105), + jnp.logical_or( + jnp.logical_or( + jnp.logical_and(player_x <= 20, player_x >= 14), + jnp.logical_and(player_x >= 135, player_x <= 142) + ), + jnp.logical_and(player_x>=edge_left, player_x<=edge_right) + ), + ), + jnp.logical_and( + jnp.logical_and(player_y >= 40, player_y <= 70), + jnp.logical_or( + jnp.logical_or( + jnp.logical_or( + jnp.logical_and(player_x >= 30, player_x <= 53), + jnp.logical_and(player_x >= 102, player_x <= 126) + ), + jnp.logical_and(player_x>=edge_left, player_x<=edge_right) + ), + jnp.logical_or( + player_x <= 20, + player_x >= 135 + ) + ) + ) + ), + jnp.logical_and( + player_y <= 40, + jnp.logical_or( + jnp.logical_or( + jnp.logical_and(player_x >= 30, player_x <= 38), + jnp.logical_and(player_x >= 120, player_x <= 126) + ), + jnp.logical_or( + jnp.logical_or( + jnp.logical_and(player_x >= 102, player_x <= 110), + jnp.logical_and(player_x >= 45, player_x <= 53) + ), + jnp.logical_and(player_x>=edge_left, player_x<=edge_right) + ) + ) + ) + ) + ) @@ -574,7 +662,11 @@ def _check_for_wall(self, state: AdventureState, direction: int) -> bool: room_8_walls ) - room_9_clear = True + room_9_clear = jnp.logical_or( + jnp.logical_not(room == 8), + room_9_walls + ) + room_10_clear = True room_11_clear = True From e4eccfeae08c5f429f5f8d065d2db844d8b610fb Mon Sep 17 00:00:00 2001 From: LucyLMM Date: Sun, 21 Dec 2025 11:51:36 +0100 Subject: [PATCH 040/102] Maze Room 4 FUnctional --- src/jaxatari/games/jax_adventure.py | 121 ++++++++++++++++++++++++---- 1 file changed, 106 insertions(+), 15 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 7c65e79a6..51427a0e2 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -470,25 +470,25 @@ def _check_for_wall(self, state: AdventureState, direction: int) -> bool: jnp.logical_or( jnp.logical_and( jnp.logical_and(player_y >= 135, player_y <= 170), - jnp.logical_or( jnp.logical_or( - jnp.logical_or( - jnp.logical_and(player_x >= 30, player_x <= 38), - jnp.logical_and(player_x >= 120, player_x <= 126) - ), jnp.logical_or( jnp.logical_or( - jnp.logical_and(player_x >= 102, player_x <= 110), - jnp.logical_and(player_x >= 45, player_x <= 53) + jnp.logical_and(player_x >= 30, player_x <= 38), + jnp.logical_and(player_x >= 120, player_x <= 126) ), - jnp.logical_and(player_x>=72, player_x<=84) - ) - ), - jnp.logical_or( - jnp.logical_and(player_x <= 20, player_x >= 14), - jnp.logical_and(player_x >= 135, player_x <= 142) + jnp.logical_or( + jnp.logical_or( + jnp.logical_and(player_x >= 102, player_x <= 110), + jnp.logical_and(player_x >= 45, player_x <= 53) + ), + jnp.logical_and(player_x>=72, player_x<=84) + ) + ), + jnp.logical_or( + jnp.logical_and(player_x <= 20, player_x >= 14), + jnp.logical_and(player_x >= 135, player_x <= 142) + ) ) - ) ), jnp.logical_and( jnp.logical_and(player_y >= 105, player_y <= 135), @@ -645,6 +645,93 @@ def _check_for_wall(self, state: AdventureState, direction: int) -> bool: ) ) + room_10_walls = jnp.logical_or( + jnp.logical_or( + jnp.logical_or( + jnp.logical_and( + player_y >= 199, + jnp.logical_or( + jnp.logical_or( + jnp.logical_or( + jnp.logical_and(player_x >= 62, player_x <= 70), + jnp.logical_and(player_x >= 86, player_x <= 94) + ), + jnp.logical_or( + jnp.logical_and(player_x >= 102, player_x <= 110), + jnp.logical_and(player_x >= 45, player_x <= 53) + ) + ), + jnp.logical_or( # the two corridors up + jnp.logical_and(player_x>=30, player_x <= 38), #left corridor + jnp.logical_and(player_x>=120, player_x <= 126) #right corridor + ) + ) + ), + jnp.logical_and( + jnp.logical_and(player_y >= 170, player_y <= 199), + jnp.logical_or( + jnp.logical_or( + jnp.logical_or( + jnp.logical_and(player_x >= 30, player_x <= 53), + jnp.logical_and(player_x >= 102, player_x <= 126) + ), + jnp.logical_or( + jnp.logical_and(player_x >= 62, player_x <= 70), + jnp.logical_and(player_x >= 86, player_x <= 94) + ) + ), + jnp.logical_or( + player_x <= 20, + player_x >= 135 + ) + ) + ) + ), + + jnp.logical_or( + jnp.logical_and( + jnp.logical_and(player_y >= 135, player_y <= 170), + jnp.logical_or( + jnp.logical_or( + jnp.logical_and(player_x >= 62, player_x <= 70), + jnp.logical_and(player_x >= 86, player_x <= 94) + ), + jnp.logical_or( + jnp.logical_and(player_x <= 20, player_x >= 14), + jnp.logical_and(player_x >= 135, player_x <= 142) + ) + ) + ), + jnp.logical_and( + jnp.logical_and(player_y >= 105, player_y <= 135), + jnp.logical_or( + jnp.logical_and(player_x >=14, player_x <= 70), + jnp.logical_and(player_x >= 86, player_x <= 142) + ) + ) + ), + ), + jnp.logical_or( + jnp.logical_or( + jnp.logical_and( + jnp.logical_and(player_y >= 75, player_y <= 105), + jnp.logical_or( + jnp.logical_and(player_x >= 38, player_x <= 44), + jnp.logical_and(player_x >= 112, player_x <= 118) + ), + ), + jnp.logical_and( + player_y >= 40, + player_y <= 70 + ) + ), + jnp.logical_and( + player_y <= 40, + False + ) + ) + ) + ### end extra maze walls @@ -667,7 +754,11 @@ def _check_for_wall(self, state: AdventureState, direction: int) -> bool: room_9_walls ) - room_10_clear = True + room_10_clear = jnp.logical_or( + jnp.logical_not(room == 9), + room_10_walls + ) + room_11_clear = True room_12_clear = jnp.logical_or( From 4e3573ac5348f388dbfe526888bee4df72526cb7 Mon Sep 17 00:00:00 2001 From: Leif Schwass Date: Sun, 21 Dec 2025 12:41:51 +0100 Subject: [PATCH 041/102] Yellow key prmitive pickup --- src/jaxatari/games/jax_adventure.py | 51 +++++++++++++++++++---------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 7c65e79a6..8baef1780 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -129,10 +129,10 @@ class AdventureConstants(NamedTuple): #Spawn Locations of all Entities: (X, Y, Room/Tile) YELLOW_GATE_POS: Tuple[int, int, int] = (76, 140, 0) BLACK_GATE_POS: Tuple[int, int, int] = (76, 140, 11) - PLAYER_SPAWN: Tuple[int, int, int] = (78, 174, 0) + PLAYER_SPAWN: Tuple[int, int, int] = (78, 174, 0) #Changed from (78, 174, 0) DRAGON_YELLOW_SPAWN: Tuple[int, int, int] = (80, 170, 5, 0) DRAGON_GREEN_SPAWN: Tuple[int, int, int] = (80, 130, 4, 0) - KEY_YELLOW_SPAWN: Tuple[int, int, int] = (31, 110, 0) + KEY_YELLOW_SPAWN: Tuple[int, int, int] = (31, 110, 0) #Changed from (31, 110, 0) for Testing KEY_BLACK_SPAWN: Tuple[int, int, int] = (31, 100, 4) SWORD_SPAWN: Tuple[int, int, int] = (31,180,1) BRIDGE_SPAWN: Tuple[int, int, int] = (40,130,10) @@ -909,7 +909,7 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt def _item_pickup(self, state: AdventureState) -> AdventureState: - def check_for_item(self, state: AdventureState, item_ID: int) -> bool: + def check_for_item(self:JaxAdventure, state: AdventureState, item_ID: int) -> bool: item_x, item_y, tile, item_width, item_height = jax.lax.switch( item_ID, [lambda:(0,0,0,0,0), #this should never occour @@ -920,28 +920,37 @@ def check_for_item(self, state: AdventureState, item_ID: int) -> bool: lambda:(state.magnet[0],state.magnet[1],state.magnet[2],self.consts.MAGNET_SIZE[0],self.consts.MAGNET_SIZE[1]), lambda:(state.chalice[0],state.chalice[1],state.chalice[2],self.consts.CHALICE_SIZE[0],self.consts.CHALICE_SIZE[1]) ]) - + #jax.debug.print("Hitbox values item:{a},{b},{c},{d},{e}",a=item_x,b=item_y,c=tile,d=item_width,e=item_height) #HARDCODED BAAAAAD, but i dont care right now (performance?)(items smaler then 4 pixels would be buggy) on_same_tile = (tile==state.player[2]) player_hitbox_nw = (state.player[0]-1,state.player[1]-1) - player_hitbox_ne = (state.player[0]+self.consts.PLAYER_SIZE[0]+1,state.player[1]-1) - player_hitbox_se = (state.player[0]+self.consts.PLAYER_SIZE[0]+1,state.player[1]+self.consts.PLAYER_SIZE[1]+1) - player_hitbox_sw = (state.player[0]-1,state.player[1]+self.consts.PLAYER_SIZE[1]+1) + player_hitbox_ne = (state.player[0]+self.consts.PLAYER_SIZE[0],state.player[1]-1) + player_hitbox_se = (state.player[0]+self.consts.PLAYER_SIZE[0],state.player[1]+self.consts.PLAYER_SIZE[1]) + player_hitbox_sw = (state.player[0]-1,state.player[1]+self.consts.PLAYER_SIZE[1]) + + #jax.debug.print("Hitbox values Player:{a},{b}|{c},{d}|{e},{f}|{g},{h}", + # a=player_hitbox_nw[0],b=player_hitbox_nw[1], + # c=player_hitbox_ne[0],d=player_hitbox_ne[1], + # e=player_hitbox_se[0],f=player_hitbox_se[1], + # g=player_hitbox_sw[0],h=player_hitbox_sw[1]) - nw_close_in_x = jnp.logical_and(player_hitbox_nw[0]>=item_x,player_hitbox_nw[0]<=(item_x+item_width)) - nw_close_in_y = jnp.logical_and(player_hitbox_nw[1]>=item_y,player_hitbox_nw[1]<=(item_y+item_height)) + def diff_of_4(val1:int, val2:int) -> bool: + return ((val1 - val2) <= 4) + + nw_close_in_x = jnp.logical_and(diff_of_4(item_x,player_hitbox_nw[0]),diff_of_4(player_hitbox_nw[0],(item_x+item_width))) + nw_close_in_y = jnp.logical_and(diff_of_4(item_y,player_hitbox_nw[1]),diff_of_4(player_hitbox_nw[1],(item_y+item_height))) nw_touches_item = jnp.logical_and(nw_close_in_x,nw_close_in_y) - ne_close_in_x = jnp.logical_and(player_hitbox_ne[0]>=item_x,player_hitbox_ne[0]<=(item_x+item_width)) - ne_close_in_y = jnp.logical_and(player_hitbox_ne[1]>=item_y,player_hitbox_ne[1]<=(item_y+item_height)) + ne_close_in_x = jnp.logical_and(diff_of_4(item_x,player_hitbox_ne[0]),diff_of_4(player_hitbox_ne[0],(item_x+item_width))) + ne_close_in_y = jnp.logical_and(diff_of_4(item_y,player_hitbox_ne[1]),diff_of_4(player_hitbox_ne[1],(item_y+item_height))) ne_touches_item = jnp.logical_and(ne_close_in_x,ne_close_in_y) - se_close_in_x = jnp.logical_and(player_hitbox_se[0]>=item_x,player_hitbox_se[0]<=(item_x+item_width)) - se_close_in_y = jnp.logical_and(player_hitbox_se[1]>=item_y,player_hitbox_se[1]<=(item_y+item_height)) + se_close_in_x = jnp.logical_and(diff_of_4(item_x,player_hitbox_se[0]),diff_of_4(player_hitbox_se[0],(item_x+item_width))) + se_close_in_y = jnp.logical_and(diff_of_4(item_y,player_hitbox_se[1]),diff_of_4(player_hitbox_se[1],(item_y+item_height))) se_touches_item = jnp.logical_and(se_close_in_x,se_close_in_y) - sw_close_in_x = jnp.logical_and(player_hitbox_sw[0]>=item_x,player_hitbox_sw[0]<=(item_x+item_width)) - sw_close_in_y = jnp.logical_and(player_hitbox_sw[1]>=item_y,player_hitbox_sw[1]<=(item_y+item_height)) + sw_close_in_x = jnp.logical_and(diff_of_4(item_x,player_hitbox_sw[0]),diff_of_4(player_hitbox_sw[0],(item_x+item_width))) + sw_close_in_y = jnp.logical_and(diff_of_4(item_y,player_hitbox_sw[1]),diff_of_4(player_hitbox_sw[1],(item_y+item_height))) sw_touches_item = jnp.logical_and(sw_close_in_x,sw_close_in_y) item_touches = jnp.logical_and(on_same_tile, @@ -949,10 +958,18 @@ def check_for_item(self, state: AdventureState, item_ID: int) -> bool: ne_touches_item), jnp.logical_or(se_touches_item, sw_touches_item))) - + #jax.debug.print("Logical values: nw:{a},{b},ne:{c},{d},se:{e},{f},sw:{g},{h}", + # a=nw_close_in_x, + # b=nw_close_in_y, + # c=ne_close_in_x, + # d=ne_close_in_y, + # e=se_close_in_x, + # f=se_close_in_y, + # g=sw_close_in_x, + # h=sw_close_in_y) + #jax.debug.print("Logical values: {a},{b},{c},{d},{e}",a=on_same_tile,b=nw_touches_item,c=sw_touches_item,d=ne_touches_item,e=se_touches_item) return item_touches - #ToDo if the player holds an item skip new_player_inventory = jax.lax.cond( check_for_item(self=self, state=state, item_ID=self.consts.KEY_YELLOW_ID), lambda _: self.consts.KEY_YELLOW_ID, From 1c86d56fae75df15c5500410397284e0eef282b3 Mon Sep 17 00:00:00 2001 From: LucyLMM Date: Sun, 21 Dec 2025 13:00:28 +0100 Subject: [PATCH 042/102] Last Maze Room T-T --- src/jaxatari/games/jax_adventure.py | 100 +++++++++++++++++++++++++++- 1 file changed, 99 insertions(+), 1 deletion(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 611a98aae..5e59833ef 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -732,6 +732,101 @@ def _check_for_wall(self, state: AdventureState, direction: int) -> bool: ) ) + room_11_walls = jnp.logical_or( + jnp.logical_or( + jnp.logical_or( + jnp.logical_and( + player_y >= 199, + jnp.logical_or( + jnp.logical_or( + jnp.logical_and(player_x >= 30, player_x <= 38), + jnp.logical_and(player_x >= 120, player_x <= 126) + ), + jnp.logical_or( + jnp.logical_or( + jnp.logical_and(player_x <= 20, player_x >= 14), + jnp.logical_and(player_x >= 135, player_x <= 142) + ), + jnp.logical_and(player_x>=72, player_x<=84) + ) + ) + ), + jnp.logical_and( + jnp.logical_and(player_y >= 170, player_y <= 199), + jnp.logical_or( + jnp.logical_or( + jnp.logical_or( + jnp.logical_and(player_x >= 30, player_x <= 60), + jnp.logical_and(player_x >= edge_right, player_x <= 126) + ), + jnp.logical_and(player_x>=72, player_x<=84) + ), + jnp.logical_or( + player_x <= 20, + player_x >= 135 + ) + ) + ) + ), + + jnp.logical_or( + jnp.logical_and( + jnp.logical_and(player_y >= 135, player_y <= 170), + jnp.logical_and(player_x>=72, player_x<=84) + ), + jnp.logical_and( + jnp.logical_and(player_y >= 105, player_y <= 135), + jnp.logical_or( + jnp.logical_or( + jnp.logical_and(player_x>=16, player_x<=30), + jnp.logical_and(player_x>=126, player_x<=140) + ), + jnp.logical_and(player_x>=38, player_x<=118) + ) + ) + ), + ), + jnp.logical_or( + jnp.logical_or( + jnp.logical_and( + jnp.logical_and(player_y >= 75, player_y <= 105), + jnp.logical_or( + jnp.logical_or( + jnp.logical_or( + jnp.logical_and(player_x>=16, player_x<=30), + jnp.logical_and(player_x>=104, player_x<=118) + ), + jnp.logical_or( + jnp.logical_and(player_x>=38, player_x<=53), + jnp.logical_and(player_x>=126, player_x<=140) + ), + ), + jnp.logical_and(player_x>=72, player_x<=84) + ) + ), + jnp.logical_and( + jnp.logical_and(player_y >= 40, player_y <= 70), + jnp.logical_or( + jnp.logical_or( + jnp.logical_or( + player_x<=30, + player_x>=126 + ), + jnp.logical_or( + jnp.logical_and(player_x>=38, player_x<=53), + jnp.logical_and(player_x>=104, player_x<=118) + ), + ), + jnp.logical_and(player_x>=edge_left, player_x<=edge_right) + ) + ) + ), + jnp.logical_and( + player_y <= 40, + jnp.logical_and(player_x>=edge_left, player_x<=edge_right) + ) + ) + ) ### end extra maze walls @@ -759,7 +854,10 @@ def _check_for_wall(self, state: AdventureState, direction: int) -> bool: room_10_walls ) - room_11_clear = True + room_11_clear = jnp.logical_or( + jnp.logical_not(room == 10), + room_11_walls + ) room_12_clear = jnp.logical_or( jnp.logical_not(room == 11), #either it is not room 1 or From 7cd6e451d33090595828acf4b353b8168001e0b5 Mon Sep 17 00:00:00 2001 From: DanielCress Date: Sun, 21 Dec 2025 13:32:24 +0100 Subject: [PATCH 043/102] Updated dragons; carfull they eat now --- src/jaxatari/games/jax_adventure.py | 110 ++++++++++++++++++++++------ 1 file changed, 88 insertions(+), 22 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 5e59833ef..18db359fa 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -126,12 +126,13 @@ class AdventureConstants(NamedTuple): BRIDGE_ID: int = 4 MAGNET_ID: int = 5 CHALICE_ID: int = 6 + #dragons (X,Y, Room, state, counter, eat) + DRAGON_YELLOW_SPAWN: Tuple[int, int, int] = (80, 170, 5, 0, 0, 0) + DRAGON_GREEN_SPAWN: Tuple[int, int, int] = (80, 130, 4, 0, 0, 0) #Spawn Locations of all Entities: (X, Y, Room/Tile) YELLOW_GATE_POS: Tuple[int, int, int] = (76, 140, 0) BLACK_GATE_POS: Tuple[int, int, int] = (76, 140, 11) PLAYER_SPAWN: Tuple[int, int, int] = (78, 174, 0) #Changed from (78, 174, 0) - DRAGON_YELLOW_SPAWN: Tuple[int, int, int] = (80, 170, 5, 0) - DRAGON_GREEN_SPAWN: Tuple[int, int, int] = (80, 130, 4, 0) KEY_YELLOW_SPAWN: Tuple[int, int, int] = (31, 110, 0) #Changed from (31, 110, 0) for Testing KEY_BLACK_SPAWN: Tuple[int, int, int] = (31, 100, 4) SWORD_SPAWN: Tuple[int, int, int] = (31,180,1) @@ -1213,33 +1214,97 @@ def _item_drop(self, state: AdventureState, action: chex.Array) -> AdventureStat def _dragon_step(self, state: AdventureState) -> AdventureState: + + #yellow dragon direction_x = jnp.sign(state.player[0] - state.dragon_yellow[0]) direction_y = jnp.sign(state.player[1]- state.dragon_yellow[1]) dragon_yellow_x = state.dragon_yellow[0] dragon_yellow_y = state.dragon_yellow[1] - dragon_yellow_x, dragon_yellow_y = jax.lax.cond( - state.player[2]==state.dragon_yellow[2], - lambda _: ((dragon_yellow_x + direction_x*2, dragon_yellow_y + direction_y*2)), - lambda _: (dragon_yellow_x, dragon_yellow_y), + dragon_yellow_animation = state.dragon_yellow[3] + dragon_yellow_counter = state.dragon_yellow[4] + #dragon_yellow_eat = state.dragon_yellow[5] + # wait after attack + dragon_yellow_counter = jax.lax.cond( + dragon_yellow_animation == 1, + lambda f: f+1, + lambda f:f, + operand = dragon_yellow_counter + ) + dragon_yellow_freeze = dragon_yellow_counter % 15 != 0 + #dragon eats player + dragon_yellow_eat = jax.lax.cond( + jnp.logical_and(jnp.logical_and((state.player[0]-dragon_yellow_x)*direction_x<4,(state.player[1]-dragon_yellow_y)*direction_y<4),jnp.logical_and(dragon_yellow_animation==1,jnp.logical_not(dragon_yellow_freeze))), + lambda:1, + lambda:0 + ) + #move towards player and attack + dragon_yellow_x, dragon_yellow_y, dragon_yellow_animation, dragon_yellow_counter= jax.lax.cond( + jnp.logical_and(state.player[2]==state.dragon_yellow[2],jnp.logical_not(dragon_yellow_freeze)), + lambda _: (dragon_yellow_x + direction_x*2, dragon_yellow_y + direction_y*2, jax.lax.cond( + jnp.logical_and(jnp.logical_and((state.player[0]-dragon_yellow_x)*direction_x<4,(state.player[1]-dragon_yellow_y)*direction_y<4),dragon_yellow_animation!=2), + lambda _:1, + lambda _:0, + operand = None + ),0), + lambda _: (dragon_yellow_x, dragon_yellow_y, jax.lax.cond(jnp.logical_not(dragon_yellow_freeze), lambda _: 0, lambda _: 1, operand = None), dragon_yellow_counter), operand = None ) + # dont ever move again when dead + dragon_yellow_counter = jax.lax.cond( + dragon_yellow_animation == 2, + lambda _: 1, + lambda f:f, + operand=dragon_yellow_counter + ) + + + #green dragon direction_x = jnp.sign(state.player[0] - state.dragon_green[0]) direction_y = jnp.sign(state.player[1]- state.dragon_green[1]) dragon_green_x = state.dragon_green[0] dragon_green_y = state.dragon_green[1] - dragon_green_x, dragon_green_y = jax.lax.cond( - state.player[2]==state.dragon_green[2], - lambda _: ((dragon_green_x + direction_x*2, dragon_green_y + direction_y*2)), - lambda _: (dragon_green_x, dragon_green_y), + dragon_green_animation = state.dragon_green[3] + dragon_green_counter = state.dragon_green[4] + # wait after attack + dragon_green_counter = jax.lax.cond( + dragon_green_animation == 1, + lambda f: f+1, + lambda f:f, + operand = dragon_green_counter + ) + dragon_green_freeze = dragon_green_counter % 15 != 0 + #dragon eats player + dragon_green_eat = jax.lax.cond( + jnp.logical_and(jnp.logical_and((state.player[0]-dragon_green_x)*direction_x<4,(state.player[1]-dragon_green_y)*direction_y<4),jnp.logical_and(dragon_green_animation==1,jnp.logical_not(dragon_green_freeze))), + lambda:1, + lambda:0 + ) + #move towards player and attack + dragon_green_x, dragon_green_y, dragon_green_animation, dragon_green_counter= jax.lax.cond( + jnp.logical_and(state.player[2]==state.dragon_green[2],jnp.logical_not(dragon_green_freeze)), + lambda _: (dragon_green_x + direction_x*2, dragon_green_y + direction_y*2, jax.lax.cond( + jnp.logical_and(jnp.logical_and((state.player[0]-dragon_green_x)*direction_x<4,(state.player[1]-dragon_green_y)*direction_y<4),dragon_green_animation!=2), + lambda _:1, + lambda _:0, + operand = None + ),0), + lambda _: (dragon_green_x, dragon_green_y, jax.lax.cond(jnp.logical_not(dragon_green_freeze), lambda _: 0, lambda _: 1, operand = None), dragon_green_counter), operand = None ) + # dont ever move again when dead + dragon_green_counter = jax.lax.cond( + dragon_green_animation == 2, + lambda _: 1, + lambda f:f, + operand=dragon_green_counter + ) return AdventureState( step_counter = state.step_counter, player = state.player, - dragon_yellow = jnp.array([dragon_yellow_x,dragon_yellow_y,state.dragon_yellow[2]]).astype(jnp.int32), - dragon_green = jnp.array([dragon_green_x,dragon_green_y,state.dragon_green[2]]).astype(jnp.int32), + dragon_yellow = jnp.array([dragon_yellow_x,dragon_yellow_y,state.dragon_yellow[2],dragon_yellow_animation,dragon_yellow_counter,dragon_yellow_eat]).astype(jnp.int32), + dragon_green = jnp.array([dragon_green_x,dragon_green_y,state.dragon_green[2],dragon_green_animation,dragon_green_counter,dragon_green_eat]).astype(jnp.int32), key_yellow=state.key_yellow, key_black=state.key_black, gate_yellow=state.gate_yellow, @@ -1249,12 +1314,6 @@ def _dragon_step(self, state: AdventureState) -> AdventureState: magnet=state.magnet, chalice=state.chalice ) - - #Did Yo delete this Daniel? - @partial(jax.jit, static_argnums=(0,)) - def step(self, state: AdventureState, action: chex.Array) -> Tuple[AdventureObservation, AdventureState, float, bool, AdventureInfo]: - previous_state = state - state = self._player_step(state, action) def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureObservation, AdventureState]: @@ -1270,11 +1329,13 @@ def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureOb dragon_yellow = jnp.array([self.consts.DRAGON_YELLOW_SPAWN[0], self.consts.DRAGON_YELLOW_SPAWN[1], self.consts.DRAGON_YELLOW_SPAWN[2], - self.consts.DRAGON_YELLOW_SPAWN[3]]).astype(jnp.int32), #ToDo + self.consts.DRAGON_YELLOW_SPAWN[3], + self.consts.DRAGON_YELLOW_SPAWN[4]]).astype(jnp.int32), #ToDo dragon_green = jnp.array([self.consts.DRAGON_GREEN_SPAWN[0], self.consts.DRAGON_GREEN_SPAWN[1], self.consts.DRAGON_GREEN_SPAWN[2], - self.consts.DRAGON_GREEN_SPAWN[3]]).astype(jnp.int32), #ToDo + self.consts.DRAGON_GREEN_SPAWN[3], + self.consts.DRAGON_GREEN_SPAWN[4]]).astype(jnp.int32), #ToDo #Keys: x ,y, tile key_yellow = jnp.array([self.consts.KEY_YELLOW_SPAWN[0], self.consts.KEY_YELLOW_SPAWN[1], @@ -1488,11 +1549,16 @@ def _get_info(self, state: AdventureState, ) -> AdventureInfo: @partial(jax.jit, static_argnums=(0,)) def _get_reward(self, previous_state: AdventureState, state: AdventureState): - return 1 + reward = jax.lax.cond( + jnp.logical_or(state.dragon_yellow[5]==1,state.dragon_green[5]==1), + lambda :-1, + lambda :0 + ) + return reward @partial(jax.jit, static_argnums=(0,)) def _get_done(self, state: AdventureState) -> bool: - return 0 + return jnp.logical_or(state.dragon_yellow[5]==1,state.dragon_green[5]==1) class AdventureRenderer(JAXGameRenderer): def __init__(self, consts: AdventureConstants = None): From 7337c57be9c46d7f2a379f2b85e427f3b66fd94c Mon Sep 17 00:00:00 2001 From: LucyLMM Date: Sun, 21 Dec 2025 13:34:57 +0100 Subject: [PATCH 044/102] Bridge Functionality Done --- src/jaxatari/games/jax_adventure.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 18db359fa..21fe0f398 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -939,7 +939,24 @@ def _check_for_wall(self, state: AdventureState, direction: int) -> bool: base_rooms = jnp.logical_and(room_1_to_8, room_9_to_14) - return_bool = jnp.logical_and(base_rooms, castle_collision )# todo + walls_detected = jnp.logical_and(base_rooms, castle_collision ) + + #Check for Bridge negating wall + + bridgeX = state.bridge[0] + bridgeY = state.bridge[1] + bridgeTile =state.bridge[2] + + bridgeOnSameTile = bridgeTile == room + bridgeInRange = jnp.logical_and( + jnp.logical_and(player_x >= bridgeX + 8, player_x <= bridgeX + 24), + jnp.logical_and(player_y >= bridgeY, player_y <= bridgeY + 48) + ) + + bridge_detected = jnp.logical_and(bridgeOnSameTile, bridgeInRange) + + + return_bool = jnp.logical_or(walls_detected, bridge_detected) return return_bool From 95c2090155521f9160f457a753a67c1ca4286248 Mon Sep 17 00:00:00 2001 From: DanielCress Date: Sun, 21 Dec 2025 14:20:00 +0100 Subject: [PATCH 045/102] =?UTF-8?q?Schwert=20t=C3=B6tet?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/jaxatari/games/jax_adventure.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 21fe0f398..649255ee2 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -1231,6 +1231,10 @@ def _item_drop(self, state: AdventureState, action: chex.Array) -> AdventureStat def _dragon_step(self, state: AdventureState) -> AdventureState: + #get sword position to kill dragons + sword_x = state.sword[0] + sword_y = state.sword[1] + sword_room = state.sword[2] #yellow dragon direction_x = jnp.sign(state.player[0] - state.dragon_yellow[0]) @@ -1239,7 +1243,6 @@ def _dragon_step(self, state: AdventureState) -> AdventureState: dragon_yellow_y = state.dragon_yellow[1] dragon_yellow_animation = state.dragon_yellow[3] dragon_yellow_counter = state.dragon_yellow[4] - #dragon_yellow_eat = state.dragon_yellow[5] # wait after attack dragon_yellow_counter = jax.lax.cond( dragon_yellow_animation == 1, @@ -1266,6 +1269,15 @@ def _dragon_step(self, state: AdventureState) -> AdventureState: lambda _: (dragon_yellow_x, dragon_yellow_y, jax.lax.cond(jnp.logical_not(dragon_yellow_freeze), lambda _: 0, lambda _: 1, operand = None), dragon_yellow_counter), operand = None ) + #kill dragon + direction_x = jnp.sign(sword_x - state.dragon_yellow[0]) + direction_y = jnp.sign(sword_y- state.dragon_yellow[1]) + dragon_yellow_animation = jax.lax.cond( + jnp.logical_and(state.dragon_yellow[2]==sword_room, jnp.logical_and((sword_x-dragon_yellow_x)*direction_x<4, (sword_y-dragon_yellow_y)*direction_y<22)), + lambda _:2, + lambda a:a, + operand = dragon_yellow_animation + ) # dont ever move again when dead dragon_yellow_counter = jax.lax.cond( dragon_yellow_animation == 2, @@ -1308,6 +1320,15 @@ def _dragon_step(self, state: AdventureState) -> AdventureState: lambda _: (dragon_green_x, dragon_green_y, jax.lax.cond(jnp.logical_not(dragon_green_freeze), lambda _: 0, lambda _: 1, operand = None), dragon_green_counter), operand = None ) + #kill dragon + direction_x = jnp.sign(sword_x - state.dragon_green[0]) + direction_y = jnp.sign(sword_y- state.dragon_green[1]) + dragon_green_animation = jax.lax.cond( + jnp.logical_and(state.dragon_green[2]==sword_room, jnp.logical_and((sword_x-dragon_green_x)*direction_x<4, (sword_y-dragon_green_y)*direction_y<22)), + lambda _:2, + lambda a:a, + operand = dragon_green_animation + ) # dont ever move again when dead dragon_green_counter = jax.lax.cond( dragon_green_animation == 2, @@ -1331,7 +1352,6 @@ def _dragon_step(self, state: AdventureState) -> AdventureState: magnet=state.magnet, chalice=state.chalice ) - def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureObservation, AdventureState]: From 31048474122cd22728d23d64caa5f64fdb21814c Mon Sep 17 00:00:00 2001 From: DanielCress Date: Sun, 21 Dec 2025 14:31:10 +0100 Subject: [PATCH 046/102] Diagonal Movement --- src/jaxatari/games/jax_adventure.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 649255ee2..24d6d9fef 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -961,10 +961,10 @@ def _check_for_wall(self, state: AdventureState, direction: int) -> bool: return return_bool def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureState: - left = jnp.logical_or(action == Action.LEFT, action == Action.LEFTFIRE) - right = jnp.logical_or(action == Action.RIGHT, action == Action.RIGHTFIRE) - up = jnp.logical_or(action == Action.UP, action == Action.UPFIRE) - down = jnp.logical_or(action == Action.DOWN, action == Action.DOWNFIRE) + left = jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(action== Action.LEFT, action == Action.LEFTFIRE),action== Action.UPLEFT),action == Action.UPLEFTFIRE), action==Action.DOWNLEFT), action==Action.DOWNLEFTFIRE) + right = jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(action== Action.RIGHT, action == Action.RIGHTFIRE),action== Action.UPRIGHT),action == Action.UPRIGHTFIRE), action==Action.DOWNRIGHT), action==Action.DOWNRIGHTFIRE) + up = jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(action== Action.UP, action == Action.UPFIRE),action== Action.UPRIGHT),action == Action.UPRIGHTFIRE), action==Action.UPLEFT), action==Action.UPLEFTFIRE) + down = jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(action== Action.DOWN, action == Action.DOWNFIRE),action== Action.DOWNRIGHT),action == Action.DOWNRIGHTFIRE), action==Action.DOWNLEFT), action==Action.DOWNLEFTFIRE) From c093bf92cdcb9e7a770d8a1b8be31a7dea727684 Mon Sep 17 00:00:00 2001 From: DanielCress Date: Sun, 21 Dec 2025 15:38:30 +0100 Subject: [PATCH 047/102] Update jax_adventure.py --- src/jaxatari/games/jax_adventure.py | 80 +++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 24d6d9fef..84a86d1fd 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -1352,6 +1352,85 @@ def _dragon_step(self, state: AdventureState) -> AdventureState: magnet=state.magnet, chalice=state.chalice ) + + def _magnet_step(self, state: AdventureState) -> AdventureState: + magnet_x = state.magnet[0] + magnet_y = state.magnet[1] + + #try to pull sword + sword_x = state.sword[0] + sword_y = state.sword[1] + direction_x = jnp.sign(magnet_x - sword_x) + direction_y = jnp.sign(magnet_y - sword_y) + sword_x, sword_y = jax.lax.cond( + jnp.logical_and(state.sword[2]==state.magnet[2], state.player[3]!=3), + lambda _: (sword_x+direction_x,sword_y+direction_y), + lambda _: (sword_x,sword_y), + operand = None + ) + + #try to pull yellow key + key_yellow_x = state.key_yellow[0] + key_yellow_y = state.key_yellow[1] + direction_x = jnp.sign(magnet_x - key_yellow_x) + direction_y = jnp.sign(magnet_y - key_yellow_y) + key_yellow_x, key_yellow_y = jax.lax.cond( + jnp.logical_and(state.key_yellow[2]==state.magnet[2], state.player[3]!=1), + lambda _: (key_yellow_x+direction_x,key_yellow_y+direction_y), + lambda _: (key_yellow_x,key_yellow_y), + operand = None + ) + + #try to pull black key + key_black_x = state.key_black[0] + key_black_y = state.key_black[1] + direction_x = jnp.sign(magnet_x - key_black_x) + direction_y = jnp.sign(magnet_y - key_black_y) + key_black_x, key_black_y = jax.lax.cond( + jnp.logical_and(state.key_black[2]==state.magnet[2], state.player[3]!=2), + lambda _: (key_black_x+direction_x,key_black_y+direction_y), + lambda _: (key_black_x,key_black_y), + operand = None + ) + + #try to pull bridge + bridge_x = state.bridge[0] + bridge_y = state.bridge[1] + direction_x = jnp.sign(magnet_x - bridge_x) + direction_y = jnp.sign(magnet_y - bridge_y) + bridge_x, bridge_y = jax.lax.cond( + jnp.logical_and(state.bridge[2]==state.magnet[2], state.player[3]!=4), + lambda _: (bridge_x+direction_x,bridge_y+direction_y), + lambda _: (bridge_x,bridge_y), + operand = None + ) + + #try to pull chalice + chalice_x = state.chalice[0] + chalice_y = state.chalice[1] + direction_x = jnp.sign(magnet_x - chalice_x) + direction_y = jnp.sign(magnet_y - chalice_y) + chalice_x, chalice_y = jax.lax.cond( + jnp.logical_and(state.chalice[2]==state.magnet[2], state.player[3]!=6), + lambda _: (chalice_x+direction_x,chalice_y+direction_y), + lambda _: (chalice_x,chalice_y), + operand = None + ) + + return AdventureState( + step_counter = state.step_counter, + player = state.player, + dragon_yellow = state.dragon_yellow, + dragon_green = state.dragon_green, + key_yellow=jnp.array([key_yellow_x,key_yellow_y,state.key_yellow[2]]).astype(jnp.int32), + key_black=jnp.array([key_black_x,key_black_y,state.key_black[2]]).astype(jnp.int32), + gate_yellow=state.gate_yellow, + gate_black=state.gate_black, + sword=jnp.array([sword_x,sword_y,state.sword[2]]).astype(jnp.int32), + bridge=jnp.array([bridge_x,bridge_y,state.bridge[2]]).astype(jnp.int32), + magnet=state.magnet, + chalice=jnp.array([chalice_x,chalice_y,state.chalice[2],state.chalice[3]]).astype(jnp.int32), + ) def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureObservation, AdventureState]: @@ -1425,6 +1504,7 @@ def step(self, state: AdventureState, action: chex.Array) -> Tuple[AdventureObse state = self._item_pickup(state) state = self._item_drop(state, action) state = self._dragon_step(state) + state = self._magnet_step(state) done = self._get_done(state) env_reward = self._get_reward(previous_state, state) From 6fc80ce285655ee1764f4cf238ed0a15b912fd3d Mon Sep 17 00:00:00 2001 From: LucyLMM Date: Sun, 21 Dec 2025 15:54:19 +0100 Subject: [PATCH 048/102] Added Gate Opening --- src/jaxatari/games/jax_adventure.py | 158 ++++++++++++++++++++++++++-- 1 file changed, 152 insertions(+), 6 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 84a86d1fd..cef35f0f1 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -150,13 +150,13 @@ class AdventureState(NamedTuple): step_counter: chex.Array #position player: x ,y ,tile, inventory player: chex.Array - #positions dragons: x, y ,tile ,state + #positions dragons: x, y ,tile ,state, counter dragon_yellow: chex.Array dragon_green: chex.Array #positions keys: x, y, tile key_yellow: chex.Array key_black: chex.Array - #gates: state + #gates: state, counter gate_yellow: chex.Array gate_black: chex.Array #position sword: x, y, tile @@ -915,12 +915,49 @@ def _check_for_wall(self, state: AdventureState, direction: int) -> bool: castle_towers = jnp.logical_or(player_y >= castle_tower_height, jnp.logical_or(castle_towers_in, castle_towers_out)) castle_base_out = jnp.logical_or(player_x<=castle_base_left, player_x>=castle_base_right) - castle_base_in = jnp.logical_and(player_x>=edge_left, player_x<=edge_right) + castle_base_in_1 = jnp.logical_and(jnp.logical_and(player_y>= castle_tower_height, player_y <= castle_base_height),jnp.logical_and(player_x>=edge_left+8, player_x<=edge_right-10)) + castle_base_in_2 = jnp.logical_and(player_y <= castle_tower_height, jnp.logical_and(player_x>=edge_left, player_x<=edge_right)) + castle_base_in = jnp.logical_or(castle_base_in_1, castle_base_in_2) castle_base = jnp.logical_or(player_y >= castle_base_height, jnp.logical_or(castle_base_in, castle_base_out)) + castle_walls = jnp.logical_and(castle_towers, castle_base) + + ##logic implementation gate border + + gate_yellow_x = self.consts.YELLOW_GATE_POS[0] + gate_yellow_y = self.consts.YELLOW_GATE_POS[1] + gate_yellow_open = state.gate_yellow[0] + + gate_black_x = self.consts.BLACK_GATE_POS[0] + gate_black_y = self.consts.BLACK_GATE_POS[1] + gate_black_open = state.gate_black[0] + + gate_yellow_not_block = jnp.logical_or( + jnp.logical_not(room == 0), + gate_yellow_open > 4 + ) + + gate_black_not_block = jnp.logical_or( + jnp.logical_not(room == 11), + gate_black_open > 4 + ) + + gates_not_blocking = jnp.logical_and(gate_yellow_not_block, gate_black_not_block) + + castle_gate = jnp.logical_or( + gates_not_blocking, + jnp.logical_or( + jnp.logical_or( + player_x >= edge_right, + player_x <= edge_left + ), + player_y >= castle_base_height + ) + ) + castle_collision = jnp.logical_or( jnp.logical_not(jnp.logical_or(room==0, room==11)), #either it is not a castle tile, or - jnp.logical_and(castle_towers, castle_base) + jnp.logical_and(castle_walls, castle_gate) ) room_1_and_2 = jnp.logical_and(room_1_clear, room_2_clear) @@ -1114,6 +1151,114 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt ) ) + def _gate_interaction(self, state: AdventureState) -> AdventureState: + gate_yellow_open = state.gate_yellow[0] + gate_black_open = state.gate_black[0] + gate_yellow_counter = state.gate_yellow[1] + gate_black_counter = state.gate_black[1] + + room = state.player[2] + player_x = state.player[0] + player_y = state.player[1] + + yellow_key_in_inventory = (state.player[3] == 1) + black_key_in_inventory = (state.player[3] == 2) + + player_infront_yellow_gate = jnp.logical_and( + room == 0, + jnp.logical_and( + jnp.logical_and( + player_x >= self.consts.PATH_VERTICAL_LEFT, + player_x <= self.consts.PATH_VERTICAL_RIGHT + ),jnp.logical_and( + player_y >= self.consts.CASTLE_BASE_CORNER_Y, + player_y <= self.consts.CASTLE_BASE_CORNER_Y + 8 + ) + ) + ) + + player_infront_black_gate = jnp.logical_and( + room == 11, + jnp.logical_and( + jnp.logical_and( + player_x >= self.consts.PATH_VERTICAL_LEFT, + player_x <= self.consts.PATH_VERTICAL_RIGHT + ),jnp.logical_and( + player_y >= self.consts.CASTLE_BASE_CORNER_Y, + player_y <= self.consts.CASTLE_BASE_CORNER_Y + 8 + ) + ) + ) + + + yellow_key_in_range = jnp.logical_and(yellow_key_in_inventory, player_infront_yellow_gate) + black_key_in_range = jnp.logical_and(black_key_in_inventory, player_infront_black_gate) + + gate_opening_yellow = jnp.logical_or(jnp.logical_and(gate_yellow_open>0, gate_yellow_open<6), yellow_key_in_range) + gate_opening_black = jnp.logical_or(jnp.logical_and(gate_black_open>0, gate_black_open<6), black_key_in_range) + + gate_render_yellow = False + gate_render_yellow = jax.lax.cond( + jnp.logical_and(gate_opening_yellow, gate_yellow_counter >= gate_yellow_open * 20), + lambda _: True, + lambda _: False, + operand = None + ) + + gate_yellow_counter = jax.lax.cond( + gate_render_yellow, + lambda op: op, + lambda op: op+1, + operand = gate_yellow_counter + ) + + gate_render_black = False + gate_render_black = jax.lax.cond( + jnp.logical_and(gate_opening_black, gate_black_counter >= gate_black_open * 20), + lambda _: True, + lambda _: False, + operand = None + ) + + gate_black_counter = jax.lax.cond( + gate_render_black, + lambda op: op, + lambda op: op+1, + operand = gate_black_counter + ) + + gate_yellow_open = jax.lax.cond( + gate_render_yellow, + lambda op: op + 1, + lambda op: op, + operand = gate_yellow_open + ) + + gate_black_open = jax.lax.cond( + gate_opening_black, + lambda op: op + 1, + lambda op: op, + operand = gate_black_open + ) + + new_gate_yellow = [gate_yellow_open, gate_yellow_counter] + new_gate_black = [gate_black_open, gate_black_counter] + + return AdventureState( + step_counter=state.step_counter, + player = state.player, + dragon_yellow=state.dragon_yellow, + dragon_green=state.dragon_green, + key_yellow=state.key_yellow, + key_black=state.key_black, + gate_yellow=new_gate_yellow, + gate_black=new_gate_black, + sword=state.sword, + bridge=state.bridge, + magnet=state.magnet, + chalice=state.chalice + ) + def _item_pickup(self, state: AdventureState) -> AdventureState: def check_for_item(self:JaxAdventure, state: AdventureState, item_ID: int) -> bool: @@ -1460,8 +1605,8 @@ def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureOb self.consts.KEY_BLACK_SPAWN[1], self.consts.KEY_BLACK_SPAWN[2]]).astype(jnp.int32), #Gate: state - gate_yellow=jnp.array([0]).astype(jnp.int32), - gate_black=jnp.array([0]).astype(jnp.int32), + gate_yellow=jnp.array([0,0]).astype(jnp.int32), + gate_black=jnp.array([0,0]).astype(jnp.int32), #Items: x, y, tile sword = jnp.array([self.consts.SWORD_SPAWN[0], self.consts.SWORD_SPAWN[1], @@ -1504,6 +1649,7 @@ def step(self, state: AdventureState, action: chex.Array) -> Tuple[AdventureObse state = self._item_pickup(state) state = self._item_drop(state, action) state = self._dragon_step(state) + state = self._gate_interaction(state) state = self._magnet_step(state) done = self._get_done(state) From 957d261a34c1094c7acce51465d64b09260d6831 Mon Sep 17 00:00:00 2001 From: LucyLMM Date: Sun, 21 Dec 2025 16:00:53 +0100 Subject: [PATCH 049/102] Fixed Gate Speed --- src/jaxatari/games/jax_adventure.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index cef35f0f1..bd2cd45bf 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -1194,8 +1194,8 @@ def _gate_interaction(self, state: AdventureState) -> AdventureState: yellow_key_in_range = jnp.logical_and(yellow_key_in_inventory, player_infront_yellow_gate) black_key_in_range = jnp.logical_and(black_key_in_inventory, player_infront_black_gate) - gate_opening_yellow = jnp.logical_or(jnp.logical_and(gate_yellow_open>0, gate_yellow_open<6), yellow_key_in_range) - gate_opening_black = jnp.logical_or(jnp.logical_and(gate_black_open>0, gate_black_open<6), black_key_in_range) + gate_opening_yellow = jnp.logical_or(jnp.logical_and(gate_yellow_open>0, gate_yellow_open<5), yellow_key_in_range) + gate_opening_black = jnp.logical_or(jnp.logical_and(gate_black_open>0, gate_black_open<5), black_key_in_range) gate_render_yellow = False gate_render_yellow = jax.lax.cond( From ef03dd1109c15b0a37dfe9a2a4993b87f5ca773e Mon Sep 17 00:00:00 2001 From: Leif Schwass Date: Sun, 21 Dec 2025 16:01:59 +0100 Subject: [PATCH 050/102] Item Pickup --- src/jaxatari/games/jax_adventure.py | 172 +++++++++++++++++++++------- 1 file changed, 129 insertions(+), 43 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 611a98aae..d0e396b9f 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -147,7 +147,7 @@ class AdventureConstants(NamedTuple): class AdventureState(NamedTuple): #step conter for performance indicator? step_counter: chex.Array - #position player: x ,y ,tile, inventory + #position player: x ,y ,tile, inventory, inventory cooldown player: chex.Array #positions dragons: x, y ,tile ,state dragon_yellow: chex.Array @@ -998,14 +998,14 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt ) ) - def _item_pickup(self, state: AdventureState) -> AdventureState: + def _item_pickup(self, state: AdventureState, action: chex.Array) -> AdventureState: def check_for_item(self:JaxAdventure, state: AdventureState, item_ID: int) -> bool: item_x, item_y, tile, item_width, item_height = jax.lax.switch( item_ID, [lambda:(0,0,0,0,0), #this should never occour lambda:(state.key_yellow[0],state.key_yellow[1],state.key_yellow[2],self.consts.KEY_SIZE[0],self.consts.KEY_SIZE[1]), - lambda:(state.key_black[0],state.key_yellow[1],state.key_yellow[2],self.consts.KEY_SIZE[0],self.consts.KEY_SIZE[1]), + lambda:(state.key_black[0],state.key_black[1],state.key_black[2],self.consts.KEY_SIZE[0],self.consts.KEY_SIZE[1]), lambda:(state.sword[0],state.sword[1],state.sword[2],self.consts.SWORD_SIZE[0],self.consts.SWORD_SIZE[1]), lambda:(state.bridge[0],state.bridge[1],state.bridge[2],self.consts.BRIDGE_SIZE[0],self.consts.BRIDGE_SIZE[1]), lambda:(state.magnet[0],state.magnet[1],state.magnet[2],self.consts.MAGNET_SIZE[0],self.consts.MAGNET_SIZE[1]), @@ -1014,41 +1014,107 @@ def check_for_item(self:JaxAdventure, state: AdventureState, item_ID: int) -> bo #jax.debug.print("Hitbox values item:{a},{b},{c},{d},{e}",a=item_x,b=item_y,c=tile,d=item_width,e=item_height) #HARDCODED BAAAAAD, but i dont care right now (performance?)(items smaler then 4 pixels would be buggy) on_same_tile = (tile==state.player[2]) - player_hitbox_nw = (state.player[0]-1,state.player[1]-1) - player_hitbox_ne = (state.player[0]+self.consts.PLAYER_SIZE[0],state.player[1]-1) - player_hitbox_se = (state.player[0]+self.consts.PLAYER_SIZE[0],state.player[1]+self.consts.PLAYER_SIZE[1]) - player_hitbox_sw = (state.player[0]-1,state.player[1]+self.consts.PLAYER_SIZE[1]) + player_hitbox_nw = (state.player[0],state.player[1]) + player_hitbox_ne = (state.player[0]+self.consts.PLAYER_SIZE[0]-1,state.player[1]) + player_hitbox_se = (state.player[0]+self.consts.PLAYER_SIZE[0]-1,state.player[1]+self.consts.PLAYER_SIZE[1]-1) + player_hitbox_sw = (state.player[0],state.player[1]+self.consts.PLAYER_SIZE[1]-1) #jax.debug.print("Hitbox values Player:{a},{b}|{c},{d}|{e},{f}|{g},{h}", # a=player_hitbox_nw[0],b=player_hitbox_nw[1], # c=player_hitbox_ne[0],d=player_hitbox_ne[1], # e=player_hitbox_se[0],f=player_hitbox_se[1], # g=player_hitbox_sw[0],h=player_hitbox_sw[1]) - + + walk_direction = jax.lax.switch( + action, + [lambda:Action.NOOP, #this should never occour + lambda:Action.FIRE, + lambda:Action.UP, + lambda:Action.RIGHT, + lambda:Action.LEFT, + lambda:Action.DOWN, + lambda:Action.UPRIGHT, + lambda:Action.UPLEFT, + lambda:Action.DOWNRIGHT, + lambda:Action.DOWNLEFT, + lambda:Action.UP, #UPFIRE, + lambda:Action.RIGHT, #RIGHTFIRE, + lambda:Action.LEFT, #LEFTFIRE....etc + lambda:Action.DOWN, + lambda:Action.UPRIGHT, + lambda:Action.UPLEFT, + lambda:Action.DOWNRIGHT, + lambda:Action.DOWNLEFT + ] + ) + def diff_of_4(val1:int, val2:int) -> bool: - return ((val1 - val2) <= 4) + return ((val1 - val2) < 4) - nw_close_in_x = jnp.logical_and(diff_of_4(item_x,player_hitbox_nw[0]),diff_of_4(player_hitbox_nw[0],(item_x+item_width))) - nw_close_in_y = jnp.logical_and(diff_of_4(item_y,player_hitbox_nw[1]),diff_of_4(player_hitbox_nw[1],(item_y+item_height))) - nw_touches_item = jnp.logical_and(nw_close_in_x,nw_close_in_y) + nw_close_in_x = jnp.logical_and(diff_of_4(item_x,player_hitbox_nw[0]),diff_of_4(player_hitbox_nw[0],(item_x+item_width-1))) + nw_close_in_y = jnp.logical_and(diff_of_4(item_y,player_hitbox_nw[1]),diff_of_4(player_hitbox_nw[1],(item_y+item_height-1))) + nw_close = jnp.logical_and(nw_close_in_x,nw_close_in_y) - ne_close_in_x = jnp.logical_and(diff_of_4(item_x,player_hitbox_ne[0]),diff_of_4(player_hitbox_ne[0],(item_x+item_width))) - ne_close_in_y = jnp.logical_and(diff_of_4(item_y,player_hitbox_ne[1]),diff_of_4(player_hitbox_ne[1],(item_y+item_height))) - ne_touches_item = jnp.logical_and(ne_close_in_x,ne_close_in_y) - - se_close_in_x = jnp.logical_and(diff_of_4(item_x,player_hitbox_se[0]),diff_of_4(player_hitbox_se[0],(item_x+item_width))) - se_close_in_y = jnp.logical_and(diff_of_4(item_y,player_hitbox_se[1]),diff_of_4(player_hitbox_se[1],(item_y+item_height))) - se_touches_item = jnp.logical_and(se_close_in_x,se_close_in_y) + ne_close_in_x = jnp.logical_and(diff_of_4(item_x,player_hitbox_ne[0]),diff_of_4(player_hitbox_ne[0],(item_x+item_width-1))) + ne_close_in_y = jnp.logical_and(diff_of_4(item_y,player_hitbox_ne[1]),diff_of_4(player_hitbox_ne[1],(item_y+item_height-1))) + ne_close = jnp.logical_and(ne_close_in_x,ne_close_in_y) + + se_close_in_x = jnp.logical_and(diff_of_4(item_x,player_hitbox_se[0]),diff_of_4(player_hitbox_se[0],(item_x+item_width-1))) + se_close_in_y = jnp.logical_and(diff_of_4(item_y,player_hitbox_se[1]),diff_of_4(player_hitbox_se[1],(item_y+item_height-1))) + se_close = jnp.logical_and(se_close_in_x,se_close_in_y) sw_close_in_x = jnp.logical_and(diff_of_4(item_x,player_hitbox_sw[0]),diff_of_4(player_hitbox_sw[0],(item_x+item_width))) sw_close_in_y = jnp.logical_and(diff_of_4(item_y,player_hitbox_sw[1]),diff_of_4(player_hitbox_sw[1],(item_y+item_height))) - sw_touches_item = jnp.logical_and(sw_close_in_x,sw_close_in_y) - + sw_close = jnp.logical_and(sw_close_in_x,sw_close_in_y) + + #player is north to the item + player_north = jnp.logical_and(jnp.logical_or(sw_close,se_close), + jnp.logical_or(nw_close_in_x,ne_close_in_x)) + player_north_walks_south = jnp.logical_and(player_north, + jnp.logical_or(walk_direction==Action.DOWN, + jnp.logical_or(walk_direction==Action.DOWNLEFT, + walk_direction==Action.DOWNRIGHT))) + #player is north-east to the item + + #player is east to the item + player_east = jnp.logical_and(jnp.logical_or(nw_close,sw_close), + jnp.logical_or(ne_close_in_y,se_close_in_y)) + player_east_walks_west = jnp.logical_and(player_east, + jnp.logical_or(walk_direction==Action.LEFT, + jnp.logical_or(walk_direction==Action.DOWNLEFT, + walk_direction==Action.UPLEFT))) + #player is south-east to the item + + #player is south to the item + player_south = jnp.logical_and(jnp.logical_or(nw_close,ne_close), + jnp.logical_or(sw_close_in_x,se_close_in_x)) + player_south_walks_north = jnp.logical_and(player_south, + jnp.logical_or(walk_direction==Action.UP, + jnp.logical_or(walk_direction==Action.UPLEFT, + walk_direction==Action.UPRIGHT))) + #player is south-west to the item + + #player is west to the item + player_west = jnp.logical_and(jnp.logical_or(ne_close,se_close), + jnp.logical_or(nw_close_in_y,sw_close_in_y)) + player_west_walks_east = jnp.logical_and(player_west, + jnp.logical_or(walk_direction==Action.RIGHT, + jnp.logical_or(walk_direction==Action.DOWNRIGHT, + walk_direction==Action.UPRIGHT))) + #player is north-west to the item + + #jax.debug.print("Walking Direction: {a},{b},{c},{d},{e}", + # a=walk_direction, + # b=player_north_walks_south, + # c=player_east_walks_west, + # d=player_south_walks_north, + # e=player_west_walks_east) + #item is on the same tile and is being approached from the correct side item_touches = jnp.logical_and(on_same_tile, - jnp.logical_or(jnp.logical_or(nw_touches_item, - ne_touches_item), - jnp.logical_or(se_touches_item, - sw_touches_item))) + jnp.logical_or(jnp.logical_or(player_north_walks_south, + player_east_walks_west), + jnp.logical_or(player_south_walks_north, + player_west_walks_east))) #jax.debug.print("Logical values: nw:{a},{b},ne:{c},{d},se:{e},{f},sw:{g},{h}", # a=nw_close_in_x, # b=nw_close_in_y, @@ -1061,18 +1127,44 @@ def diff_of_4(val1:int, val2:int) -> bool: #jax.debug.print("Logical values: {a},{b},{c},{d},{e}",a=on_same_tile,b=nw_touches_item,c=sw_touches_item,d=ne_touches_item,e=se_touches_item) return item_touches + #HOLY ASS, this is a sin new_player_inventory = jax.lax.cond( - check_for_item(self=self, state=state, item_ID=self.consts.KEY_YELLOW_ID), - lambda _: self.consts.KEY_YELLOW_ID, + action == Action.NOOP, lambda op: op, + lambda _: jax.lax.cond( + check_for_item(self=self, state=state, item_ID=self.consts.KEY_YELLOW_ID), + lambda _: self.consts.KEY_YELLOW_ID, + lambda _: jax.lax.cond( + check_for_item(self=self, state=state, item_ID=self.consts.KEY_BLACK_ID), + lambda _: self.consts.KEY_BLACK_ID, + lambda _: jax.lax.cond( + check_for_item(self=self, state=state, item_ID=self.consts.SWORD_ID), + lambda _: self.consts.SWORD_ID, + lambda _: jax.lax.cond( + check_for_item(self=self, state=state, item_ID=self.consts.BRIDGE_ID), + lambda _: self.consts.BRIDGE_ID, + lambda _: jax.lax.cond( + check_for_item(self=self, state=state, item_ID=self.consts.MAGNET_ID), + lambda _: self.consts.MAGNET_ID, + lambda _: jax.lax.cond( + check_for_item(self=self, state=state, item_ID=self.consts.CHALICE_ID), + lambda _: self.consts.CHALICE_ID, + lambda op: op, + operand=state.player[3] + ), + operand=state.player[3] + ), + operand=state.player[3] + ), + operand=state.player[3] + ), + operand=state.player[3] + ), + operand=state.player[3] + ), operand=state.player[3] ) - #ToDo check around the player, if there is an item - #if yes pick it up - #check clockwise if an item is near the player - #picking up the FIRST item it sees and according to a certain priority - return AdventureState( step_counter=state.step_counter, @@ -1152,22 +1244,16 @@ def _dragon_step(self, state: AdventureState) -> AdventureState: chalice=state.chalice ) - #Did Yo delete this Daniel? - @partial(jax.jit, static_argnums=(0,)) - def step(self, state: AdventureState, action: chex.Array) -> Tuple[AdventureObservation, AdventureState, float, bool, AdventureInfo]: - previous_state = state - state = self._player_step(state, action) - - def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureObservation, AdventureState]: state = AdventureState( step_counter = jnp.array(0).astype(jnp.int32), - #Player Spawn: x, y, tile, inventory + #Player Spawn: x, y, tile, inventory, inventory cooldown player = jnp.array([self.consts.PLAYER_SPAWN[0], self.consts.PLAYER_SPAWN[1], self.consts.PLAYER_SPAWN[2], - self.consts.EMPTY_HAND_ID]).astype(jnp.int32), + self.consts.EMPTY_HAND_ID, + 0]).astype(jnp.int32), #Dragons: x, y ,tile ,state dragon_yellow = jnp.array([self.consts.DRAGON_YELLOW_SPAWN[0], self.consts.DRAGON_YELLOW_SPAWN[1], @@ -1226,7 +1312,7 @@ def step(self, state: AdventureState, action: chex.Array) -> Tuple[AdventureObse chalice=state.chalice ) state = self._player_step(state, action) - state = self._item_pickup(state) + state = self._item_pickup(state, action) state = self._item_drop(state, action) state = self._dragon_step(state) @@ -1403,7 +1489,7 @@ def __init__(self, consts: AdventureConstants = None): self.config = render_utils.RendererConfig( game_dimensions=(250, 160), channels=3, - #downscale=(200, 128) + #ownscale=(200, 128) ) self.jr = render_utils.JaxRenderingUtils(self.config) From c7a8645c5c51e3dc5c38601c6ee3144ee454326b Mon Sep 17 00:00:00 2001 From: Leif Schwass Date: Sun, 21 Dec 2025 16:10:24 +0100 Subject: [PATCH 051/102] Added some more comments --- src/jaxatari/games/jax_adventure.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 7a317bc66..d51b77331 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -1114,7 +1114,7 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt return AdventureState( step_counter = state.step_counter, - player = jnp.array([new_player_x,new_player_y,new_player_tile,state.player[3]]).astype(jnp.int32), #SEEMS NOT GOOD + player = jnp.array([new_player_x,new_player_y,new_player_tile,state.player[3]]).astype(jnp.int32), dragon_yellow = state.dragon_yellow, dragon_green = state.dragon_green, key_yellow = jax.lax.cond(state.player[3]==self.consts.KEY_YELLOW_ID, @@ -1260,7 +1260,7 @@ def _gate_interaction(self, state: AdventureState) -> AdventureState: ) def _item_pickup(self, state: AdventureState, action: chex.Array) -> AdventureState: - + #Funny comment for Daniel def check_for_item(self:JaxAdventure, state: AdventureState, item_ID: int) -> bool: item_x, item_y, tile, item_width, item_height = jax.lax.switch( item_ID, @@ -1388,7 +1388,7 @@ def diff_of_4(val1:int, val2:int) -> bool: #jax.debug.print("Logical values: {a},{b},{c},{d},{e}",a=on_same_tile,b=nw_touches_item,c=sw_touches_item,d=ne_touches_item,e=se_touches_item) return item_touches - #HOLY ASS, this is a sin + #HOLY ASS, this seems like a sin new_player_inventory = jax.lax.cond( action == Action.NOOP, lambda op: op, From cae82a2483a249447a58ba8dac7c79f4e8974d53 Mon Sep 17 00:00:00 2001 From: DanielCress Date: Sun, 21 Dec 2025 16:16:49 +0100 Subject: [PATCH 052/102] chalice --- src/jaxatari/games/jax_adventure.py | 35 +++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index d51b77331..275fe42f7 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -1114,7 +1114,7 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt return AdventureState( step_counter = state.step_counter, - player = jnp.array([new_player_x,new_player_y,new_player_tile,state.player[3]]).astype(jnp.int32), + player = jnp.array([new_player_x,new_player_y,new_player_tile,state.player[3]]).astype(jnp.int32), #SEEMS NOT GOOD dragon_yellow = state.dragon_yellow, dragon_green = state.dragon_green, key_yellow = jax.lax.cond(state.player[3]==self.consts.KEY_YELLOW_ID, @@ -1260,7 +1260,7 @@ def _gate_interaction(self, state: AdventureState) -> AdventureState: ) def _item_pickup(self, state: AdventureState, action: chex.Array) -> AdventureState: - #Funny comment for Daniel + def check_for_item(self:JaxAdventure, state: AdventureState, item_ID: int) -> bool: item_x, item_y, tile, item_width, item_height = jax.lax.switch( item_ID, @@ -1388,7 +1388,7 @@ def diff_of_4(val1:int, val2:int) -> bool: #jax.debug.print("Logical values: {a},{b},{c},{d},{e}",a=on_same_tile,b=nw_touches_item,c=sw_touches_item,d=ne_touches_item,e=se_touches_item) return item_touches - #HOLY ASS, this seems like a sin + #HOLY ASS, this is a sin new_player_inventory = jax.lax.cond( action == Action.NOOP, lambda op: op, @@ -1669,6 +1669,26 @@ def _magnet_step(self, state: AdventureState) -> AdventureState: chalice=jnp.array([chalice_x,chalice_y,state.chalice[2],state.chalice[3]]).astype(jnp.int32), ) + def _chalice_step(self, state:AdventureState) -> AdventureState: + + chalice_color=state.chalice[3] + chalice_color = (chalice_color +1) % 10 + + return AdventureState( + step_counter=state.step_counter, + player = state.player, + dragon_yellow=state.dragon_yellow, + dragon_green=state.dragon_green, + key_yellow=state.key_yellow, + key_black=state.key_black, + gate_yellow=state.gate_yellow, + gate_black=state.gate_black, + sword=state.sword, + bridge=state.bridge, + magnet=state.magnet, + chalice=jnp.array([state.chalice[0],state.chalice[1],state.chalice[2],chalice_color]).astype(jnp.int32), + ) + def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureObservation, AdventureState]: @@ -1745,6 +1765,7 @@ def step(self, state: AdventureState, action: chex.Array) -> Tuple[AdventureObse state = self._dragon_step(state) state = self._gate_interaction(state) state = self._magnet_step(state) + state = self._chalice_step(state) done = self._get_done(state) env_reward = self._get_reward(previous_state, state) @@ -1911,11 +1932,17 @@ def _get_reward(self, previous_state: AdventureState, state: AdventureState): lambda :-1, lambda :0 ) + reward = jax.lax.cond( + state.chalice[2]==1, + lambda :1, + lambda :0 + ) return reward @partial(jax.jit, static_argnums=(0,)) def _get_done(self, state: AdventureState) -> bool: - return jnp.logical_or(state.dragon_yellow[5]==1,state.dragon_green[5]==1) + return jnp.logical_or(jnp.logical_or(state.dragon_yellow[5]==1,state.dragon_green[5]==1), state.chalice[2]==1) + class AdventureRenderer(JAXGameRenderer): def __init__(self, consts: AdventureConstants = None): From 2c71361f6a6b7792c87ff8b7fe7f16a1f252c524 Mon Sep 17 00:00:00 2001 From: Leif Schwass Date: Sun, 21 Dec 2025 16:52:35 +0100 Subject: [PATCH 053/102] Added a LOT more comments --- src/jaxatari/games/jax_adventure.py | 45 ++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 275fe42f7..99ef9edbc 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -148,7 +148,7 @@ class AdventureConstants(NamedTuple): class AdventureState(NamedTuple): #step conter for performance indicator? step_counter: chex.Array - #position player: x ,y ,tile, inventory, inventory cooldown + #position player: x ,y ,tile, inventory player: chex.Array #positions dragons: x, y ,tile ,state, counter dragon_yellow: chex.Array @@ -1112,6 +1112,7 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt operand = None, ) + #only change the state of the player and the item that is beeing carried return AdventureState( step_counter = state.step_counter, player = jnp.array([new_player_x,new_player_y,new_player_tile,state.player[3]]).astype(jnp.int32), #SEEMS NOT GOOD @@ -1261,6 +1262,11 @@ def _gate_interaction(self, state: AdventureState) -> AdventureState: def _item_pickup(self, state: AdventureState, action: chex.Array) -> AdventureState: + #helper function that chhecks if an item is near the player + #same tile, in range of 4 pixels + #it used the corners of the player and calculates if they are in x and y range to the item corners + #followed by TRYING to integrate that items are only piced p when walked into. NOT woring, tried, gave up + #VERY questionalble performance due to hardcoded checks def check_for_item(self:JaxAdventure, state: AdventureState, item_ID: int) -> bool: item_x, item_y, tile, item_width, item_height = jax.lax.switch( item_ID, @@ -1273,7 +1279,7 @@ def check_for_item(self:JaxAdventure, state: AdventureState, item_ID: int) -> bo lambda:(state.chalice[0],state.chalice[1],state.chalice[2],self.consts.CHALICE_SIZE[0],self.consts.CHALICE_SIZE[1]) ]) #jax.debug.print("Hitbox values item:{a},{b},{c},{d},{e}",a=item_x,b=item_y,c=tile,d=item_width,e=item_height) - #HARDCODED BAAAAAD, but i dont care right now (performance?)(items smaler then 4 pixels would be buggy) + on_same_tile = (tile==state.player[2]) player_hitbox_nw = (state.player[0],state.player[1]) player_hitbox_ne = (state.player[0]+self.consts.PLAYER_SIZE[0]-1,state.player[1]) @@ -1286,6 +1292,8 @@ def check_for_item(self:JaxAdventure, state: AdventureState, item_ID: int) -> bo # e=player_hitbox_se[0],f=player_hitbox_se[1], # g=player_hitbox_sw[0],h=player_hitbox_sw[1]) + + #change the waling and FIRE actions to ony walking actions for simplicity walk_direction = jax.lax.switch( action, [lambda:Action.NOOP, #this should never occour @@ -1389,6 +1397,9 @@ def diff_of_4(val1:int, val2:int) -> bool: return item_touches #HOLY ASS, this is a sin + #check if the player is moving (not action NOOP) + #it checks for every item if it is near the player + #if that is the case it puts it in the Player inventory new_player_inventory = jax.lax.cond( action == Action.NOOP, lambda op: op, @@ -1443,7 +1454,8 @@ def diff_of_4(val1:int, val2:int) -> bool: ) def _item_drop(self, state: AdventureState, action: chex.Array) -> AdventureState: - + #check if the Action Fire is used (ToDo, for all Fire actions?) + #set the player inventory to EMPTY_HAND_ID new_player_inventory = jax.lax.cond( action == Action.FIRE, lambda _: self.consts.EMPTY_HAND_ID, @@ -1669,6 +1681,7 @@ def _magnet_step(self, state: AdventureState) -> AdventureState: chalice=jnp.array([chalice_x,chalice_y,state.chalice[2],state.chalice[3]]).astype(jnp.int32), ) + """This function solely exists for maing the chalice change colors""" def _chalice_step(self, state:AdventureState) -> AdventureState: chalice_color=state.chalice[3] @@ -1689,18 +1702,18 @@ def _chalice_step(self, state:AdventureState) -> AdventureState: chalice=jnp.array([state.chalice[0],state.chalice[1],state.chalice[2],chalice_color]).astype(jnp.int32), ) - + """This function is called when the game starts and when it is reseted + It initializes the Adventure state, for the most part these Values are pulled from the consts""" def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureObservation, AdventureState]: state = AdventureState( step_counter = jnp.array(0).astype(jnp.int32), - #Player Spawn: x, y, tile, inventory, inventory cooldown + #Player Spawn: x, y, tile, inventory player = jnp.array([self.consts.PLAYER_SPAWN[0], self.consts.PLAYER_SPAWN[1], self.consts.PLAYER_SPAWN[2], - self.consts.EMPTY_HAND_ID, - 0]).astype(jnp.int32), - #Dragons: x, y ,tile ,state + self.consts.EMPTY_HAND_ID]).astype(jnp.int32), + #Dragons: x, y ,tile ,state(neutral,dead,atacking), counter( ToDo for?? ) dragon_yellow = jnp.array([self.consts.DRAGON_YELLOW_SPAWN[0], self.consts.DRAGON_YELLOW_SPAWN[1], self.consts.DRAGON_YELLOW_SPAWN[2], @@ -1718,7 +1731,7 @@ def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureOb key_black = jnp.array([self.consts.KEY_BLACK_SPAWN[0], self.consts.KEY_BLACK_SPAWN[1], self.consts.KEY_BLACK_SPAWN[2]]).astype(jnp.int32), - #Gate: state + #Gate: state, counter (ToDo for animation?) gate_yellow=jnp.array([0,0]).astype(jnp.int32), gate_black=jnp.array([0,0]).astype(jnp.int32), #Items: x, y, tile @@ -1731,7 +1744,7 @@ def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureOb magnet= jnp.array([self.consts.MAGNET_SPAWN[0], self.consts.MAGNET_SPAWN[1], self.consts.MAGNET_SPAWN[2]]).astype(jnp.int32), #ToDo - #Chalice: x, y, tile, color + #Chalice: x, y, tile, color (ToDo move color to constants) chalice = jnp.array([self.consts.CHALICE_SPAWN[0], self.consts.CHALICE_SPAWN[1], self.consts.CHALICE_SPAWN[2],7]).astype(jnp.int32), #ToDo @@ -1740,6 +1753,7 @@ def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureOb return initial_obs, state + #this is the ??main loop??, it will go throught all called steps, that change the Adventure state @partial(jax.jit, static_argnums=(0,)) def step(self, state: AdventureState, action: chex.Array) -> Tuple[AdventureObservation, AdventureState, float, bool, AdventureInfo]: # Split step key from state and keep a new key for the next state @@ -1778,6 +1792,7 @@ def step(self, state: AdventureState, action: chex.Array) -> Tuple[AdventureObse def render(self, state: AdventureState) -> jnp.ndarray: return self.renderer.render(state) + #ToDo, done for all movable entities, why, no clue def _get_observation(self, state: AdventureState): player = EntityPosition( x=state.player[0], @@ -1882,6 +1897,7 @@ def _get_observation(self, state: AdventureState): chalice=chalice ) + #ToDo, no clue what this is used for @partial(jax.jit, static_argnums=(0,)) def obs_to_flat_array(self, obs: AdventureObservation) -> jnp.ndarray: return jnp.concatenate([ @@ -1895,6 +1911,7 @@ def obs_to_flat_array(self, obs: AdventureObservation) -> jnp.ndarray: def action_space(self) -> spaces.Discrete: return spaces.Discrete(6) + #ToDo, used for the RL? def observation_space(self) -> spaces: return spaces.Dict({ "player": spaces.Dict({ @@ -1970,7 +1987,13 @@ def __init__(self, consts: AdventureConstants = None): @partial(jax.jit, static_argnums=(0,)) def render(self, state): - #set bg color here + #in general, assets are loaded in based on the Adventure state + #where the state.player[2] is the current room of the player + #dragon_xxx[3] are their state (neutral,attacking, dead) + #gate[0] is the state (open, closing, closed) + #chalice[3] is or the blinking + + #set bg here raster = self.jr.create_object_raster(self.BACKGROUND) room_mask =self.SHAPE_MASKS["room_number"][state.player[2]] raster = self.jr.render_at(raster, 0, 0, room_mask) From 16eb335c632df7f9fa9d4309d104c68c197b44b6 Mon Sep 17 00:00:00 2001 From: Leif Schwass Date: Sun, 21 Dec 2025 16:58:16 +0100 Subject: [PATCH 054/102] Deleted Unused code and added more comments --- src/jaxatari/games/jax_adventure.py | 64 ++++++++++++++--------------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 99ef9edbc..6198a0d5e 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -18,7 +18,7 @@ def _get_default_asset_config() -> tuple: Kept immutable (tuple of dicts) to fit NamedTuple defaults. """ return ( - #all rooms in order ToDo pt overview map into the readme? + #all rooms in order ToDo put overview map into the readme? {'name': 'room_number', 'type': 'group', 'files': ['Room_1.npy', 'Room_2.npy', 'Room_3.npy', @@ -34,7 +34,7 @@ def _get_default_asset_config() -> tuple: 'Room_13.npy', 'Room_14.npy']}, {'name': 'bg', 'type': 'background', 'file': 'Room_1.npy'}, - #Player in all the different colors + #Player in all the different colors, which change depending on the background {'name': 'player_colors', 'type': 'group', 'files': ["Player_Yellow.npy", "Player_Yellow.npy", "Player_Green.npy", @@ -71,7 +71,7 @@ def _get_default_asset_config() -> tuple: {'name': 'sword', 'type': 'single', 'file': 'Sword.npy'}, {'name': 'bridge', 'type': 'single', 'file': 'Bridge.npy'}, {'name': 'magnet', 'type': 'single', 'file': 'Magnet.npy'}, - #Chalice + #Chalice and its diffrent colors {'name': 'chalice', 'type': 'group', 'files': ['Chalice_Black.npy', 'Chalice_DarkBlue.npy', 'Chalice_Gray.npy', @@ -86,31 +86,10 @@ def _get_default_asset_config() -> tuple: class AdventureConstants(NamedTuple): + #Map Size, coordinates are (x,y) and the upper left corner is (0,0) WIDTH: int = 160 HEIGHT: int = 250 - # Wall coordinates the player cannot pass through - LEFT_WALL_X: int = 8 - RIGHT_WALL_X: int = 148 - UPPER_WALL_Y: int = 43 - LOWER_WALL_Y: int = 199 - #special black borders to the left and right - SPECIAL_WALL_LEFT: int = 12 - SPECIAL_WALL_RIGHT: int = 145 - # Path South and North to another Room, X-Coordinates that offer hole in the wall - PATH_VERTICAL_LEFT: int = 64 - PATH_VERTICAL_RIGHT: int = 95 - # Path East and West, Y-Coordinates that offer hole in the wall - PATH_HORIZONTAL_UP: int = 40 - PATH_HORIZONTAL_DOWN: int = 200 - # Castle Edges - CASTLE_TOWER_LEFT_X: int = 35 - CASTLE_TOWER_RIGHT_X: int = 120 - CASTLE_BASE_LEFT_X: int = 45 - CASTLE_BASE_RIGHT_X: int = 113 - CASTLE_TOWER_CORNER_Y: int = 105 - CASTLE_BASE_CORNER_Y: int = 170 - - #upper left corner is 0, 0 + #Entity Sizes PLAYER_SIZE: Tuple[int, int] = (4, 8) KEY_SIZE: Tuple[int, int] = (8, 6) DRAGON_SIZE: Tuple[int, int] = (8, 44) @@ -119,6 +98,7 @@ class AdventureConstants(NamedTuple): BRIDGE_SIZE: Tuple[int, int] = (32, 48) MAGNET_SIZE: Tuple[int, int] = (8, 16) CHALICE_SIZE: Tuple[int, int] = (8, 18) + #Inventory IDs EMPTY_HAND_ID: int = 0 KEY_YELLOW_ID: int = 1 KEY_BLACK_ID: int = 2 @@ -139,12 +119,35 @@ class AdventureConstants(NamedTuple): BRIDGE_SPAWN: Tuple[int, int, int] = (40,130,10) MAGNET_SPAWN: Tuple[int, int, int] = (120,180,12) CHALICE_SPAWN: Tuple[int, int, int] = (35,180,13) + + #Constants that are used for restricting player movement, for easy of fine tuning + # Wall coordinates the player cannot pass through + LEFT_WALL_X: int = 8 + RIGHT_WALL_X: int = 148 + UPPER_WALL_Y: int = 43 + LOWER_WALL_Y: int = 199 + #special black borders to the left and right + SPECIAL_WALL_LEFT: int = 12 + SPECIAL_WALL_RIGHT: int = 145 + # Path South and North to another Room, X-Coordinates that offer hole in the wall + PATH_VERTICAL_LEFT: int = 64 + PATH_VERTICAL_RIGHT: int = 95 + # Path East and West, Y-Coordinates that offer hole in the wall + PATH_HORIZONTAL_UP: int = 40 + PATH_HORIZONTAL_DOWN: int = 200 + # Castle Edges + CASTLE_TOWER_LEFT_X: int = 35 + CASTLE_TOWER_RIGHT_X: int = 120 + CASTLE_BASE_LEFT_X: int = 45 + CASTLE_BASE_RIGHT_X: int = 113 + CASTLE_TOWER_CORNER_Y: int = 105 + CASTLE_BASE_CORNER_Y: int = 170 + # sset config baked into constants (immutable default) for asset overrides ASSET_CONFIG: tuple = _get_default_asset_config() # immutable state container - class AdventureState(NamedTuple): #step conter for performance indicator? step_counter: chex.Array @@ -1010,13 +1013,6 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt right_no_wall = jnp.logical_and(right,self._check_for_wall(state, 1)) up_no_wall = jnp.logical_and(up,self._check_for_wall(state, 2)) down_no_wall = jnp.logical_and(down,self._check_for_wall(state, 3)) - - #chek for item - #has_item = jax.lax.cond( - # pred=state.player[3]==self.consts.EMPTY_HAND_ID, - # true_fun=False, - # false_fun=True - #) new_item_x = jax.lax.switch( state.player[3], From 046198a7fbf859543d549b74626bbf7443f2756d Mon Sep 17 00:00:00 2001 From: DanielCress Date: Sun, 21 Dec 2025 17:11:32 +0100 Subject: [PATCH 055/102] Item transport --- src/jaxatari/games/jax_adventure.py | 70 +++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 19 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 6198a0d5e..f38eb848b 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -1067,48 +1067,80 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt operand = (new_player_y,new_item_y) ) new_player_tile = state.player[2] - new_player_y, new_player_tile = jax.lax.cond( + new_item_tile = jax.lax.switch( + state.player[3], + [lambda:0, + lambda:state.key_yellow[2], + lambda:state.key_black[2], + lambda:state.sword[2], + lambda:state.bridge[2], + lambda:state.magnet[2], + lambda:state.chalice[2] + ] + ) + + #change of rooms + new_player_y, new_player_tile, new_item_tile, new_item_y = jax.lax.cond( new_player_y > 212, lambda _: (27, jax.lax.switch( new_player_tile, [lambda:2,lambda:0,lambda:0, lambda:4, lambda:0, lambda:0, lambda:5, lambda:8, lambda:0, lambda: 6, lambda:7, lambda:10, - lambda:11, lambda:12])), - lambda _: (new_player_y, new_player_tile), + lambda:11, lambda:12]), + jax.lax.switch( new_item_tile, [lambda:2,lambda:0,lambda:0, + lambda:4, lambda:0, lambda:0, + lambda:5, lambda:8, lambda:0, + lambda: 6, lambda:7, lambda:10, + lambda:11, lambda:12]), new_item_y-(new_player_y-27)), + lambda _: (new_player_y, new_player_tile, new_item_tile, new_item_y), operand = None, ) - new_player_y, new_player_tile = jax.lax.cond( + new_player_y, new_player_tile, new_item_tile, new_item_y = jax.lax.cond( new_player_y < 27, lambda _: (212, jax.lax.switch( new_player_tile, [lambda:1,lambda:0,lambda:0, lambda:0, lambda:3, lambda:6, lambda:9, lambda:10, lambda:7, lambda: 0, lambda:11, lambda:12, - lambda:13, lambda:0])), - lambda _: (new_player_y, new_player_tile), + lambda:13, lambda:0]), + jax.lax.switch( new_player_tile, [lambda:1,lambda:0,lambda:0, + lambda:0, lambda:3, lambda:6, + lambda:9, lambda:10, lambda:7, + lambda: 0, lambda:11, lambda:12, + lambda:13, lambda:0]), new_item_y+(212-new_player_y)), + lambda _: (new_player_y, new_player_tile, new_item_tile, new_item_y), operand = None, ) - new_player_x, new_player_tile = jax.lax.cond( + new_player_x, new_player_tile, new_item_tile, new_item_x = jax.lax.cond( new_player_x > 160, lambda _: (0, jax.lax.switch( new_player_tile, [lambda:0,lambda:0,lambda:3, lambda:0, lambda:0, lambda:2, lambda:7, lambda:6, lambda:10, lambda: 8, lambda:9, lambda:0, - lambda:0, lambda:0])), - lambda _: (new_player_x, new_player_tile), + lambda:0, lambda:0]), + jax.lax.switch( new_player_tile, [lambda:0,lambda:0,lambda:3, + lambda:0, lambda:0, lambda:2, + lambda:7, lambda:6, lambda:10, + lambda: 8, lambda:9, lambda:0, + lambda:0, lambda:0]), new_item_x-new_player_x), + lambda _: (new_player_x, new_player_tile, new_item_tile, new_item_x), operand = None, ) - new_player_x, new_player_tile = jax.lax.cond( + new_player_x, new_player_tile, new_item_tile, new_item_x = jax.lax.cond( new_player_x < 0, lambda _: (160, jax.lax.switch( new_player_tile, [lambda:0,lambda:0,lambda:5, lambda:2, lambda:0, lambda:0, lambda:7, lambda:6, lambda:9, lambda: 10, lambda:8, lambda:0, - lambda:0, lambda:0])), - lambda _: (new_player_x, new_player_tile), + lambda:0, lambda:0]), + jax.lax.switch( new_player_tile, [lambda:0,lambda:0,lambda:5, + lambda:2, lambda:0, lambda:0, + lambda:7, lambda:6, lambda:9, + lambda: 10, lambda:8, lambda:0, + lambda:0, lambda:0]), new_item_x+(160-new_player_x)), + lambda _: (new_player_x, new_player_tile, new_item_tile, new_item_x), operand = None, ) - #only change the state of the player and the item that is beeing carried return AdventureState( step_counter = state.step_counter, player = jnp.array([new_player_x,new_player_y,new_player_tile,state.player[3]]).astype(jnp.int32), #SEEMS NOT GOOD @@ -1117,34 +1149,34 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt key_yellow = jax.lax.cond(state.player[3]==self.consts.KEY_YELLOW_ID, lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), lambda op: op[3], - operand=(new_item_x,new_item_y,state.key_yellow[2],state.key_yellow), + operand=(new_item_x,new_item_y,new_item_tile,state.key_yellow), ), key_black= jax.lax.cond(state.player[3]==self.consts.KEY_BLACK_ID, lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), lambda op: op[3], - operand=(new_item_x,new_item_y,state.key_black[2],state.key_black) + operand=(new_item_x,new_item_y,new_item_tile,state.key_black) ), gate_yellow=state.gate_yellow, gate_black=state.gate_black, sword= jax.lax.cond(state.player[3]==self.consts.SWORD_ID, lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), lambda op: op[3], - operand=(new_item_x,new_item_y,state.sword[2],state.sword) + operand=(new_item_x,new_item_y,new_item_tile,state.sword) ), bridge= jax.lax.cond(state.player[3]==self.consts.BRIDGE_ID, lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), lambda op: op[3], - operand=(new_item_x,new_item_y,state.bridge[2],state.bridge) + operand=(new_item_x,new_item_y,new_item_tile,state.bridge) ), magnet= jax.lax.cond(state.player[3]==self.consts.MAGNET_ID, lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), lambda op: op[3], - operand=(new_item_x,new_item_y,state.magnet[2],state.magnet) + operand=(new_item_x,new_item_y,new_item_tile,state.magnet) ), chalice= jax.lax.cond(state.player[3]==self.consts.CHALICE_ID, lambda op: jnp.array([op[0],op[1],op[2],op[3]]).astype(jnp.int32), lambda op: op[4], - operand=(new_item_x,new_item_y,state.chalice[2],state.chalice[3],state.chalice) + operand=(new_item_x,new_item_y,new_item_tile,state.chalice[3],state.chalice) ) ) From d63281fdaeb9e109d6d3dfffd4909eacca4f0253 Mon Sep 17 00:00:00 2001 From: DanielCress Date: Sun, 21 Dec 2025 17:24:22 +0100 Subject: [PATCH 056/102] dragons stay dead --- src/jaxatari/games/jax_adventure.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index f38eb848b..3032232aa 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -1538,12 +1538,12 @@ def _dragon_step(self, state: AdventureState) -> AdventureState: dragon_yellow_x, dragon_yellow_y, dragon_yellow_animation, dragon_yellow_counter= jax.lax.cond( jnp.logical_and(state.player[2]==state.dragon_yellow[2],jnp.logical_not(dragon_yellow_freeze)), lambda _: (dragon_yellow_x + direction_x*2, dragon_yellow_y + direction_y*2, jax.lax.cond( - jnp.logical_and(jnp.logical_and((state.player[0]-dragon_yellow_x)*direction_x<4,(state.player[1]-dragon_yellow_y)*direction_y<4),dragon_yellow_animation!=2), - lambda _:1, - lambda _:0, + jnp.logical_and((state.player[0]-dragon_yellow_x)*direction_x<4,(state.player[1]-dragon_yellow_y)*direction_y<4), + lambda _:jax.lax.cond(dragon_yellow_animation==2, lambda _:2, lambda _:1, operand = None), + lambda _:jax.lax.cond(dragon_yellow_animation==2, lambda _:2, lambda _:0, operand = None), operand = None ),0), - lambda _: (dragon_yellow_x, dragon_yellow_y, jax.lax.cond(jnp.logical_not(dragon_yellow_freeze), lambda _: 0, lambda _: 1, operand = None), dragon_yellow_counter), + lambda _: (dragon_yellow_x, dragon_yellow_y, jax.lax.cond(jnp.logical_not(dragon_yellow_freeze), lambda _: jax.lax.cond(dragon_yellow_animation==2, lambda _:2, lambda _:0, operand = None), lambda _: jax.lax.cond(dragon_yellow_animation==2, lambda _:2, lambda _:1, operand = None), operand = None), dragon_yellow_counter), operand = None ) #kill dragon @@ -1553,7 +1553,7 @@ def _dragon_step(self, state: AdventureState) -> AdventureState: jnp.logical_and(state.dragon_yellow[2]==sword_room, jnp.logical_and((sword_x-dragon_yellow_x)*direction_x<4, (sword_y-dragon_yellow_y)*direction_y<22)), lambda _:2, lambda a:a, - operand = dragon_yellow_animation + operand= dragon_yellow_animation ) # dont ever move again when dead dragon_yellow_counter = jax.lax.cond( @@ -1590,11 +1590,11 @@ def _dragon_step(self, state: AdventureState) -> AdventureState: jnp.logical_and(state.player[2]==state.dragon_green[2],jnp.logical_not(dragon_green_freeze)), lambda _: (dragon_green_x + direction_x*2, dragon_green_y + direction_y*2, jax.lax.cond( jnp.logical_and(jnp.logical_and((state.player[0]-dragon_green_x)*direction_x<4,(state.player[1]-dragon_green_y)*direction_y<4),dragon_green_animation!=2), - lambda _:1, - lambda _:0, + lambda _:lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:1, operand = None), + lambda _:lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:0, operand = None), operand = None ),0), - lambda _: (dragon_green_x, dragon_green_y, jax.lax.cond(jnp.logical_not(dragon_green_freeze), lambda _: 0, lambda _: 1, operand = None), dragon_green_counter), + lambda _: (dragon_green_x, dragon_green_y, jax.lax.cond(jnp.logical_not(dragon_green_freeze), lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:0, operand = None), lambda _: lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:1, operand = None), operand = None), dragon_green_counter), operand = None ) #kill dragon From 8ae392a8e3c55ad938dd630ed91afafae8a8a528 Mon Sep 17 00:00:00 2001 From: DanielCress Date: Sun, 21 Dec 2025 17:52:25 +0100 Subject: [PATCH 057/102] removed error --- src/jaxatari/games/jax_adventure.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 3032232aa..a7f2fc750 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -1590,11 +1590,11 @@ def _dragon_step(self, state: AdventureState) -> AdventureState: jnp.logical_and(state.player[2]==state.dragon_green[2],jnp.logical_not(dragon_green_freeze)), lambda _: (dragon_green_x + direction_x*2, dragon_green_y + direction_y*2, jax.lax.cond( jnp.logical_and(jnp.logical_and((state.player[0]-dragon_green_x)*direction_x<4,(state.player[1]-dragon_green_y)*direction_y<4),dragon_green_animation!=2), - lambda _:lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:1, operand = None), - lambda _:lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:0, operand = None), + lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:1, operand = None), + lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:0, operand = None), operand = None ),0), - lambda _: (dragon_green_x, dragon_green_y, jax.lax.cond(jnp.logical_not(dragon_green_freeze), lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:0, operand = None), lambda _: lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:1, operand = None), operand = None), dragon_green_counter), + lambda _: (dragon_green_x, dragon_green_y, jax.lax.cond(jnp.logical_not(dragon_green_freeze), lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:0, operand = None), lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:1, operand = None), operand = None), dragon_green_counter), operand = None ) #kill dragon From fdd35efa6caf2f66aaf79b85e9b6d634a48ec0f7 Mon Sep 17 00:00:00 2001 From: LucyLMM Date: Sun, 21 Dec 2025 18:03:50 +0100 Subject: [PATCH 058/102] Gate closing added --- src/jaxatari/games/jax_adventure.py | 96 ++++++++++++++++++----------- 1 file changed, 59 insertions(+), 37 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index a7f2fc750..1cf182e90 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -1181,8 +1181,10 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt ) def _gate_interaction(self, state: AdventureState) -> AdventureState: - gate_yellow_open = state.gate_yellow[0] - gate_black_open = state.gate_black[0] + gate_yellow_state = state.gate_yellow[0] + gate_yellow_close = False + gate_black_state = state.gate_black[0] + gate_black_close = False gate_yellow_counter = state.gate_yellow[1] gate_black_counter = state.gate_black[1] @@ -1223,55 +1225,75 @@ def _gate_interaction(self, state: AdventureState) -> AdventureState: yellow_key_in_range = jnp.logical_and(yellow_key_in_inventory, player_infront_yellow_gate) black_key_in_range = jnp.logical_and(black_key_in_inventory, player_infront_black_gate) - gate_opening_yellow = jnp.logical_or(jnp.logical_and(gate_yellow_open>0, gate_yellow_open<5), yellow_key_in_range) - gate_opening_black = jnp.logical_or(jnp.logical_and(gate_black_open>0, gate_black_open<5), black_key_in_range) - - gate_render_yellow = False - gate_render_yellow = jax.lax.cond( - jnp.logical_and(gate_opening_yellow, gate_yellow_counter >= gate_yellow_open * 20), - lambda _: True, - lambda _: False, - operand = None + gate_opening_yellow = jnp.logical_and(jnp.logical_and(jnp.logical_and(gate_yellow_state>=0, gate_yellow_state<6), yellow_key_in_range), gate_yellow_counter == 0) + gate_opening_black = jnp.logical_and(jnp.logical_and(gate_black_state>=0, gate_black_state<6), black_key_in_range) + + gate_yellow_close =jnp.logical_and(jnp.logical_and(gate_yellow_state>0, gate_yellow_counter > 20), yellow_key_in_range) + gate_black_close = jnp.logical_and(jnp.logical_and(gate_black_state>0, gate_black_counter > 20), black_key_in_range) + + gate_opening_yellow = jnp.logical_and(gate_opening_yellow, jnp.logical_not(gate_yellow_close)) + gate_opening_black = jnp.logical_and(gate_opening_black, jnp.logical_not(gate_black_close)) + + gate_yellow_state = jax.lax.cond( + gate_opening_yellow, + lambda op: op + 1, + lambda op: op, + operand = gate_yellow_state ) - gate_yellow_counter = jax.lax.cond( - gate_render_yellow, + gate_yellow_state = jax.lax.cond( + gate_yellow_close, + lambda op: op - 1, + lambda op:op, + operand = gate_yellow_state + ) + + gate_black_state = jax.lax.cond( + gate_opening_black, + lambda op: op + 1, lambda op: op, - lambda op: op+1, + operand = gate_black_state + ) + + gate_black_state = jax.lax.cond( + gate_black_close, + lambda op: op - 1, + lambda op:op, + operand = gate_black_state + ) + + gate_yellow_counter = jax.lax.cond( + jnp.logical_or(gate_yellow_state == 6, jnp.logical_and(gate_yellow_state==0, gate_yellow_counter<30)), + lambda op:op + 1, + lambda op:op, operand = gate_yellow_counter ) - gate_render_black = False - gate_render_black = jax.lax.cond( - jnp.logical_and(gate_opening_black, gate_black_counter >= gate_black_open * 20), - lambda _: True, - lambda _: False, - operand = None + gate_yellow_counter = jax.lax.cond( + jnp.logical_and(gate_yellow_state == 0, gate_yellow_counter>=30), + lambda _: 0, + lambda op:op, + operand = gate_yellow_counter ) + jax.debug.print("Counter yellow: {a}", a = gate_yellow_counter) + gate_black_counter = jax.lax.cond( - gate_render_black, - lambda op: op, - lambda op: op+1, + gate_black_state == 6, + lambda op:op + 1, + lambda op:op, operand = gate_black_counter ) - gate_yellow_open = jax.lax.cond( - gate_render_yellow, - lambda op: op + 1, - lambda op: op, - operand = gate_yellow_open - ) - - gate_black_open = jax.lax.cond( - gate_opening_black, - lambda op: op + 1, - lambda op: op, - operand = gate_black_open + gate_black_counter = jax.lax.cond( + gate_black_state == 0, + lambda _: 0, + lambda op:op, + operand = gate_black_counter ) - new_gate_yellow = [gate_yellow_open, gate_yellow_counter] - new_gate_black = [gate_black_open, gate_black_counter] + new_gate_yellow = [gate_yellow_state, gate_yellow_counter] + new_gate_black = [gate_black_state, gate_black_counter] return AdventureState( step_counter=state.step_counter, From 471a4b97d8e37367a3cc5f781f3f57a34a73a8b7 Mon Sep 17 00:00:00 2001 From: LucyLMM Date: Sun, 21 Dec 2025 18:15:19 +0100 Subject: [PATCH 059/102] Make Bridge usable - The Bridge Access and slotting will have to be reworked in the future, but for the purpose of being testable we have changed the hitbox, so the bridge can be purposefully moved from the left side --- src/jaxatari/games/jax_adventure.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 1cf182e90..abf60d815 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -95,7 +95,7 @@ class AdventureConstants(NamedTuple): DRAGON_SIZE: Tuple[int, int] = (8, 44) GATE_SIZE: Tuple[int, int] = (7, 32) SWORD_SIZE: Tuple[int, int] = (8, 10) - BRIDGE_SIZE: Tuple[int, int] = (32, 48) + BRIDGE_SIZE: Tuple[int, int] = (4, 48) MAGNET_SIZE: Tuple[int, int] = (8, 16) CHALICE_SIZE: Tuple[int, int] = (8, 18) #Inventory IDs @@ -1226,7 +1226,7 @@ def _gate_interaction(self, state: AdventureState) -> AdventureState: black_key_in_range = jnp.logical_and(black_key_in_inventory, player_infront_black_gate) gate_opening_yellow = jnp.logical_and(jnp.logical_and(jnp.logical_and(gate_yellow_state>=0, gate_yellow_state<6), yellow_key_in_range), gate_yellow_counter == 0) - gate_opening_black = jnp.logical_and(jnp.logical_and(gate_black_state>=0, gate_black_state<6), black_key_in_range) + gate_opening_black = jnp.logical_and(jnp.logical_and(jnp.logical_and(gate_black_state>=0, gate_black_state<6), black_key_in_range), gate_black_counter == 0) gate_yellow_close =jnp.logical_and(jnp.logical_and(gate_yellow_state>0, gate_yellow_counter > 20), yellow_key_in_range) gate_black_close = jnp.logical_and(jnp.logical_and(gate_black_state>0, gate_black_counter > 20), black_key_in_range) @@ -1276,17 +1276,15 @@ def _gate_interaction(self, state: AdventureState) -> AdventureState: operand = gate_yellow_counter ) - jax.debug.print("Counter yellow: {a}", a = gate_yellow_counter) - gate_black_counter = jax.lax.cond( - gate_black_state == 6, + jnp.logical_or(gate_black_state == 6, jnp.logical_and(gate_black_state==0, gate_black_counter<30)), lambda op:op + 1, lambda op:op, operand = gate_black_counter ) gate_black_counter = jax.lax.cond( - gate_black_state == 0, + jnp.logical_and(gate_black_state == 0, gate_black_counter>=30), lambda _: 0, lambda op:op, operand = gate_black_counter From fb2fc37438e7e92b56cc2ef6bdfb75218038519f Mon Sep 17 00:00:00 2001 From: Leif Schwass Date: Sun, 21 Dec 2025 18:17:02 +0100 Subject: [PATCH 060/102] Final Score is steps taken --- src/jaxatari/games/jax_adventure.py | 49 ++++++++++++++++------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index a7f2fc750..77298a48e 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -1006,14 +1006,15 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt up = jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(action== Action.UP, action == Action.UPFIRE),action== Action.UPRIGHT),action == Action.UPRIGHTFIRE), action==Action.UPLEFT), action==Action.UPLEFTFIRE) down = jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(action== Action.DOWN, action == Action.DOWNFIRE),action== Action.DOWNRIGHT),action == Action.DOWNRIGHTFIRE), action==Action.DOWNLEFT), action==Action.DOWNLEFTFIRE) - - #check for no wall before walking left_no_wall = jnp.logical_and(left,self._check_for_wall(state, 0)) right_no_wall = jnp.logical_and(right,self._check_for_wall(state, 1)) up_no_wall = jnp.logical_and(up,self._check_for_wall(state, 2)) down_no_wall = jnp.logical_and(down,self._check_for_wall(state, 3)) + new_step_counter = state.step_counter + + #get x cord of the item beeing held new_item_x = jax.lax.switch( state.player[3], [lambda:0, @@ -1027,20 +1028,20 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt ) new_player_x = state.player[0] - new_player_x, new_item_x = jax.lax.cond( + new_player_x, new_item_x, new_step_counter = jax.lax.cond( left_no_wall, - lambda y: (y[0]-4,y[1]-4), + lambda y: (y[0]-4,y[1]-4,y[2]+1), lambda y: y, - operand = (new_player_x,new_item_x), + operand = (new_player_x,new_item_x,new_step_counter), ) - new_player_x, new_item_x = jax.lax.cond( + new_player_x, new_item_x, new_step_counter = jax.lax.cond( right_no_wall, - lambda y: (y[0]+4,y[1]+4), + lambda y: (y[0]+4,y[1]+4,y[2]+1), lambda y: y, - operand = (new_player_x,new_item_x), + operand = (new_player_x,new_item_x,new_step_counter), ) - + #get y cord of the item beeing held new_item_y = jax.lax.switch( state.player[3], [lambda:0, @@ -1054,17 +1055,17 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt ) new_player_y = state.player[1] - new_player_y, new_item_y = jax.lax.cond( + new_player_y, new_item_y, new_step_counter = jax.lax.cond( down_no_wall, - lambda y: (y[0]+8,y[1]+8), + lambda y: (y[0]+8,y[1]+8,y[2]), lambda y: y, - operand = (new_player_y,new_item_y) + operand = (new_player_y,new_item_y,new_step_counter) ) - new_player_y, new_item_y = jax.lax.cond( + new_player_y, new_item_y, new_step_counter = jax.lax.cond( up_no_wall, - lambda y: (y[0]-8,y[1]-8), + lambda y: (y[0]-8,y[1]-8,y[2]), lambda y: y, - operand = (new_player_y,new_item_y) + operand = (new_player_y,new_item_y,new_step_counter) ) new_player_tile = state.player[2] new_item_tile = jax.lax.switch( @@ -1142,7 +1143,7 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt ) return AdventureState( - step_counter = state.step_counter, + step_counter = jnp.array(new_step_counter).astype(jnp.int32), player = jnp.array([new_player_x,new_player_y,new_player_tile,state.player[3]]).astype(jnp.int32), #SEEMS NOT GOOD dragon_yellow = state.dragon_yellow, dragon_green = state.dragon_green, @@ -1975,13 +1976,17 @@ def _get_reward(self, previous_state: AdventureState, state: AdventureState): reward = jax.lax.cond( jnp.logical_or(state.dragon_yellow[5]==1,state.dragon_green[5]==1), lambda :-1, - lambda :0 - ) - reward = jax.lax.cond( - state.chalice[2]==1, - lambda :1, - lambda :0 + lambda : jax.lax.cond( + state.chalice[2]==1, + lambda :state.step_counter, + lambda :0 #this should happen on reset? + ) ) + #reward = jax.lax.cond( + # state.chalice[2]==1, + # lambda :1, + # lambda :0 + #) return reward @partial(jax.jit, static_argnums=(0,)) From 2d0c58db7293c4dac91bba739cba6a07af4e7156 Mon Sep 17 00:00:00 2001 From: LucyLMM Date: Sun, 21 Dec 2025 18:50:34 +0100 Subject: [PATCH 061/102] Removed Screenshots --- Adventure_screenshots/Room_Maze_5.npy | Bin 160128 -> 0 bytes Adventure_screenshots/frame_00001.npy | Bin 120128 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Adventure_screenshots/Room_Maze_5.npy delete mode 100644 Adventure_screenshots/frame_00001.npy diff --git a/Adventure_screenshots/Room_Maze_5.npy b/Adventure_screenshots/Room_Maze_5.npy deleted file mode 100644 index cfe9be99054f59e30fb68ec0207dc20848c650fe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 160128 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 From fb6f6898832db7d5e77fd76669f55e96d4bf21eb Mon Sep 17 00:00:00 2001 From: DanielCress Date: Mon, 23 Mar 2026 12:42:42 +0100 Subject: [PATCH 062/102] dragon looks for player room after first encounter + kleine Bugfixes --- src/jaxatari/games/jax_adventure.py | 107 +++++++++++++++++++--------- 1 file changed, 75 insertions(+), 32 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index f6d607018..35641b4f8 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -3,7 +3,6 @@ from functools import partial from typing import NamedTuple, Tuple import jax -import jax.lax import jax.numpy as jnp import chex @@ -106,9 +105,9 @@ class AdventureConstants(NamedTuple): BRIDGE_ID: int = 4 MAGNET_ID: int = 5 CHALICE_ID: int = 6 - #dragons (X,Y, Room, state, counter, eat) - DRAGON_YELLOW_SPAWN: Tuple[int, int, int] = (80, 170, 5, 0, 0, 0) - DRAGON_GREEN_SPAWN: Tuple[int, int, int] = (80, 130, 4, 0, 0, 0) + #dragons (X,Y, Room, state, counter, eat, activate) + DRAGON_YELLOW_SPAWN: Tuple[int, int, int, int ,int, int, int] = (80, 170, 5, 0, 0, 0, 0) + DRAGON_GREEN_SPAWN: Tuple[int, int, int, int, int, int, int] = (80, 130, 4, 0, 0, 0, 0) #Spawn Locations of all Entities: (X, Y, Room/Tile) YELLOW_GATE_POS: Tuple[int, int, int] = (76, 140, 0) BLACK_GATE_POS: Tuple[int, int, int] = (76, 140, 11) @@ -153,7 +152,7 @@ class AdventureState(NamedTuple): step_counter: chex.Array #position player: x ,y ,tile, inventory player: chex.Array - #positions dragons: x, y ,tile ,state, counter + #positions dragons: x, y ,tile ,state, counter, eat, activate dragon_yellow: chex.Array dragon_green: chex.Array #positions keys: x, y, tile @@ -170,6 +169,8 @@ class AdventureState(NamedTuple): magnet: chex.Array #position chalice: x, y, tile, color chalice: chex.Array + #random key + rndKey: chex.PRNGKey class EntityPosition(NamedTuple): @@ -278,7 +279,7 @@ def _check_for_wall(self, state: AdventureState, direction: int) -> bool: ## Rooms: room_1_clear = jnp.logical_or( - jnp.logical_not(room == 0), #either it is not room 1 or + jnp.logical_not(room == 0), #either it is not room 0 or jnp.logical_and( #walls of the room are not being crossed jnp.logical_and( collision_left_wall, @@ -306,7 +307,7 @@ def _check_for_wall(self, state: AdventureState, direction: int) -> bool: ) room_3_clear = jnp.logical_or( - jnp.logical_not(room == 2), #either it is not room 1 or + jnp.logical_not(room == 2), #either it is not room 2 or jnp.logical_and( #walls of the room are not being crossed jnp.logical_and( collision_left_wall_path, @@ -320,7 +321,7 @@ def _check_for_wall(self, state: AdventureState, direction: int) -> bool: ) room_4_clear = jnp.logical_or( - jnp.logical_not(room == 3), #either it is not room 1 or + jnp.logical_not(room == 3), #either it is not room 3 or jnp.logical_and( #walls of the room are not being crossed jnp.logical_and( collision_left_wall_path, @@ -334,7 +335,7 @@ def _check_for_wall(self, state: AdventureState, direction: int) -> bool: ) room_5_clear = jnp.logical_or( - jnp.logical_not(room == 4), #either it is not room 1 or + jnp.logical_not(room == 4), #either it is not room 4 or jnp.logical_and( #walls of the room are not being crossed jnp.logical_and( collision_left_wall, @@ -348,7 +349,7 @@ def _check_for_wall(self, state: AdventureState, direction: int) -> bool: ) room_6_clear = jnp.logical_or( - jnp.logical_not(room == 5), #either it is not room 1 or + jnp.logical_not(room == 5), #either it is not room 5 or jnp.logical_and( #walls of the room are not being crossed jnp.logical_and( collision_left_special, @@ -864,7 +865,7 @@ def _check_for_wall(self, state: AdventureState, direction: int) -> bool: ) room_12_clear = jnp.logical_or( - jnp.logical_not(room == 11), #either it is not room 1 or + jnp.logical_not(room == 11), #either it is not room 12 or jnp.logical_and( #walls of the room are not being crossed jnp.logical_and( collision_left_wall, @@ -878,7 +879,7 @@ def _check_for_wall(self, state: AdventureState, direction: int) -> bool: ) room_13_clear = jnp.logical_or( - jnp.logical_not(room == 12), #either it is not room 1 or + jnp.logical_not(room == 12), #either it is not room 13 or jnp.logical_and( #walls of the room are not being crossed jnp.logical_and( collision_left_wall, @@ -892,7 +893,7 @@ def _check_for_wall(self, state: AdventureState, direction: int) -> bool: ) room_14_clear = jnp.logical_or( - jnp.logical_not(room == 13), #either it is not room 1 or + jnp.logical_not(room == 13), #either it is not room 14 or jnp.logical_and( #walls of the room are not being crossed jnp.logical_and( collision_left_wall, @@ -927,12 +928,8 @@ def _check_for_wall(self, state: AdventureState, direction: int) -> bool: ##logic implementation gate border - gate_yellow_x = self.consts.YELLOW_GATE_POS[0] - gate_yellow_y = self.consts.YELLOW_GATE_POS[1] gate_yellow_open = state.gate_yellow[0] - gate_black_x = self.consts.BLACK_GATE_POS[0] - gate_black_y = self.consts.BLACK_GATE_POS[1] gate_black_open = state.gate_black[0] gate_yellow_not_block = jnp.logical_or( @@ -1178,7 +1175,8 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt lambda op: jnp.array([op[0],op[1],op[2],op[3]]).astype(jnp.int32), lambda op: op[4], operand=(new_item_x,new_item_y,new_item_tile,state.chalice[3],state.chalice) - ) + ), + rndKey = state.rndKey ) def _gate_interaction(self, state: AdventureState) -> AdventureState: @@ -1306,7 +1304,8 @@ def _gate_interaction(self, state: AdventureState) -> AdventureState: sword=state.sword, bridge=state.bridge, magnet=state.magnet, - chalice=state.chalice + chalice=state.chalice, + rndKey=state.rndKey ) def _item_pickup(self, state: AdventureState, action: chex.Array) -> AdventureState: @@ -1499,7 +1498,8 @@ def diff_of_4(val1:int, val2:int) -> bool: sword=state.sword, bridge=state.bridge, magnet=state.magnet, - chalice=state.chalice + chalice=state.chalice, + rndKey=state.rndKey ) def _item_drop(self, state: AdventureState, action: chex.Array) -> AdventureState: @@ -1524,7 +1524,8 @@ def _item_drop(self, state: AdventureState, action: chex.Array) -> AdventureStat sword=state.sword, bridge=state.bridge, magnet=state.magnet, - chalice=state.chalice + chalice=state.chalice, + rndKey=state.rndKey ) @@ -1539,8 +1540,11 @@ def _dragon_step(self, state: AdventureState) -> AdventureState: direction_y = jnp.sign(state.player[1]- state.dragon_yellow[1]) dragon_yellow_x = state.dragon_yellow[0] dragon_yellow_y = state.dragon_yellow[1] + dragon_yellow_tile = state.dragon_yellow[2] dragon_yellow_animation = state.dragon_yellow[3] dragon_yellow_counter = state.dragon_yellow[4] + dragon_yellow_activate = state.dragon_yellow[6] + # wait after attack dragon_yellow_counter = jax.lax.cond( dragon_yellow_animation == 1, @@ -1549,15 +1553,28 @@ def _dragon_step(self, state: AdventureState) -> AdventureState: operand = dragon_yellow_counter ) dragon_yellow_freeze = dragon_yellow_counter % 15 != 0 + + #dragon starts looking for plyer room after first encounter + dragon_yellow_activate = jax.lax.cond(state.player[2] == dragon_yellow_tile, lambda:1, lambda: dragon_yellow_activate) + rndKey, subkey = jax.random.split(state.rndKey) + dragon_yellow_x, dragon_yellow_y, dragon_yellow_tile = jax.lax.cond( + jnp.logical_and(jnp.logical_and(dragon_yellow_tile != state.player[2], jnp.logical_not(dragon_yellow_freeze)),dragon_yellow_activate==1), + lambda: (jax.lax.cond(dragon_yellow_x>156, lambda:4, lambda:dragon_yellow_x +2), + jax.lax.cond(dragon_yellow_y>208, lambda:4, lambda:dragon_yellow_y+2), + jax.lax.cond(jnp.logical_or(dragon_yellow_x>156,dragon_yellow_y>208), lambda:jax.random.randint(subkey, (), 0, 13) , lambda:dragon_yellow_tile)), + lambda:(dragon_yellow_x, dragon_yellow_y, dragon_yellow_tile) + ) + #dragon eats player dragon_yellow_eat = jax.lax.cond( jnp.logical_and(jnp.logical_and((state.player[0]-dragon_yellow_x)*direction_x<4,(state.player[1]-dragon_yellow_y)*direction_y<4),jnp.logical_and(dragon_yellow_animation==1,jnp.logical_not(dragon_yellow_freeze))), lambda:1, lambda:0 ) + #move towards player and attack dragon_yellow_x, dragon_yellow_y, dragon_yellow_animation, dragon_yellow_counter= jax.lax.cond( - jnp.logical_and(state.player[2]==state.dragon_yellow[2],jnp.logical_not(dragon_yellow_freeze)), + jnp.logical_and(state.player[2]==dragon_yellow_tile,jnp.logical_not(dragon_yellow_freeze)), lambda _: (dragon_yellow_x + direction_x*2, dragon_yellow_y + direction_y*2, jax.lax.cond( jnp.logical_and((state.player[0]-dragon_yellow_x)*direction_x<4,(state.player[1]-dragon_yellow_y)*direction_y<4), lambda _:jax.lax.cond(dragon_yellow_animation==2, lambda _:2, lambda _:1, operand = None), @@ -1567,15 +1584,17 @@ def _dragon_step(self, state: AdventureState) -> AdventureState: lambda _: (dragon_yellow_x, dragon_yellow_y, jax.lax.cond(jnp.logical_not(dragon_yellow_freeze), lambda _: jax.lax.cond(dragon_yellow_animation==2, lambda _:2, lambda _:0, operand = None), lambda _: jax.lax.cond(dragon_yellow_animation==2, lambda _:2, lambda _:1, operand = None), operand = None), dragon_yellow_counter), operand = None ) + #kill dragon direction_x = jnp.sign(sword_x - state.dragon_yellow[0]) direction_y = jnp.sign(sword_y- state.dragon_yellow[1]) dragon_yellow_animation = jax.lax.cond( - jnp.logical_and(state.dragon_yellow[2]==sword_room, jnp.logical_and((sword_x-dragon_yellow_x)*direction_x<4, (sword_y-dragon_yellow_y)*direction_y<22)), + jnp.logical_and(dragon_yellow_tile==sword_room, jnp.logical_and((sword_x-dragon_yellow_x)*direction_x<4, (sword_y-dragon_yellow_y)*direction_y<22)), lambda _:2, lambda a:a, operand= dragon_yellow_animation ) + # dont ever move again when dead dragon_yellow_counter = jax.lax.cond( dragon_yellow_animation == 2, @@ -1590,8 +1609,11 @@ def _dragon_step(self, state: AdventureState) -> AdventureState: direction_y = jnp.sign(state.player[1]- state.dragon_green[1]) dragon_green_x = state.dragon_green[0] dragon_green_y = state.dragon_green[1] + dragon_green_tile = state.dragon_green[2] dragon_green_animation = state.dragon_green[3] dragon_green_counter = state.dragon_green[4] + dragon_green_activate = state.dragon_green[6] + # wait after attack dragon_green_counter = jax.lax.cond( dragon_green_animation == 1, @@ -1600,15 +1622,28 @@ def _dragon_step(self, state: AdventureState) -> AdventureState: operand = dragon_green_counter ) dragon_green_freeze = dragon_green_counter % 15 != 0 + + #dragon starts looking for plyer room after first encounter + dragon_green_activate = jax.lax.cond(state.player[2] == dragon_green_tile, lambda:1, lambda: dragon_green_activate) + rndKey, subkey = jax.random.split(rndKey) + dragon_green_x, dragon_green_y, dragon_green_tile = jax.lax.cond( + jnp.logical_and(jnp.logical_and(dragon_green_tile != state.player[2], jnp.logical_not(dragon_green_freeze)),dragon_green_activate==1), + lambda: (jax.lax.cond(dragon_green_x>156, lambda:4, lambda:dragon_green_x +2), + jax.lax.cond(dragon_green_y>208, lambda:4, lambda:dragon_green_y+2), + jax.lax.cond(jnp.logical_or(dragon_green_x>156,dragon_green_y>208), lambda:jax.random.randint(subkey, (), 0, 13) , lambda:dragon_green_tile)), + lambda:(dragon_green_x, dragon_green_y, dragon_green_tile) + ) + #dragon eats player dragon_green_eat = jax.lax.cond( jnp.logical_and(jnp.logical_and((state.player[0]-dragon_green_x)*direction_x<4,(state.player[1]-dragon_green_y)*direction_y<4),jnp.logical_and(dragon_green_animation==1,jnp.logical_not(dragon_green_freeze))), lambda:1, lambda:0 ) + #move towards player and attack dragon_green_x, dragon_green_y, dragon_green_animation, dragon_green_counter= jax.lax.cond( - jnp.logical_and(state.player[2]==state.dragon_green[2],jnp.logical_not(dragon_green_freeze)), + jnp.logical_and(state.player[2]==dragon_green_tile,jnp.logical_not(dragon_green_freeze)), lambda _: (dragon_green_x + direction_x*2, dragon_green_y + direction_y*2, jax.lax.cond( jnp.logical_and(jnp.logical_and((state.player[0]-dragon_green_x)*direction_x<4,(state.player[1]-dragon_green_y)*direction_y<4),dragon_green_animation!=2), lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:1, operand = None), @@ -1618,15 +1653,17 @@ def _dragon_step(self, state: AdventureState) -> AdventureState: lambda _: (dragon_green_x, dragon_green_y, jax.lax.cond(jnp.logical_not(dragon_green_freeze), lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:0, operand = None), lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:1, operand = None), operand = None), dragon_green_counter), operand = None ) + #kill dragon direction_x = jnp.sign(sword_x - state.dragon_green[0]) direction_y = jnp.sign(sword_y- state.dragon_green[1]) dragon_green_animation = jax.lax.cond( - jnp.logical_and(state.dragon_green[2]==sword_room, jnp.logical_and((sword_x-dragon_green_x)*direction_x<4, (sword_y-dragon_green_y)*direction_y<22)), + jnp.logical_and(dragon_green_tile==sword_room, jnp.logical_and((sword_x-dragon_green_x)*direction_x<4, (sword_y-dragon_green_y)*direction_y<22)), lambda _:2, lambda a:a, operand = dragon_green_animation ) + # dont ever move again when dead dragon_green_counter = jax.lax.cond( dragon_green_animation == 2, @@ -1639,8 +1676,8 @@ def _dragon_step(self, state: AdventureState) -> AdventureState: return AdventureState( step_counter = state.step_counter, player = state.player, - dragon_yellow = jnp.array([dragon_yellow_x,dragon_yellow_y,state.dragon_yellow[2],dragon_yellow_animation,dragon_yellow_counter,dragon_yellow_eat]).astype(jnp.int32), - dragon_green = jnp.array([dragon_green_x,dragon_green_y,state.dragon_green[2],dragon_green_animation,dragon_green_counter,dragon_green_eat]).astype(jnp.int32), + dragon_yellow = jnp.array([dragon_yellow_x,dragon_yellow_y,dragon_yellow_tile,dragon_yellow_animation,dragon_yellow_counter,dragon_yellow_eat, dragon_yellow_activate]).astype(jnp.int32), + dragon_green = jnp.array([dragon_green_x,dragon_green_y,dragon_green_tile,dragon_green_animation,dragon_green_counter,dragon_green_eat, dragon_green_activate]).astype(jnp.int32), key_yellow=state.key_yellow, key_black=state.key_black, gate_yellow=state.gate_yellow, @@ -1648,7 +1685,8 @@ def _dragon_step(self, state: AdventureState) -> AdventureState: sword=state.sword, bridge=state.bridge, magnet=state.magnet, - chalice=state.chalice + chalice=state.chalice, + rndKey=rndKey ) def _magnet_step(self, state: AdventureState) -> AdventureState: @@ -1728,6 +1766,7 @@ def _magnet_step(self, state: AdventureState) -> AdventureState: bridge=jnp.array([bridge_x,bridge_y,state.bridge[2]]).astype(jnp.int32), magnet=state.magnet, chalice=jnp.array([chalice_x,chalice_y,state.chalice[2],state.chalice[3]]).astype(jnp.int32), + rndKey=state.rndKey ) """This function solely exists for maing the chalice change colors""" @@ -1749,12 +1788,13 @@ def _chalice_step(self, state:AdventureState) -> AdventureState: bridge=state.bridge, magnet=state.magnet, chalice=jnp.array([state.chalice[0],state.chalice[1],state.chalice[2],chalice_color]).astype(jnp.int32), + rndKey=state.rndKey ) """This function is called when the game starts and when it is reseted It initializes the Adventure state, for the most part these Values are pulled from the consts""" def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureObservation, AdventureState]: - + state_key, _step_key = jax.random.split(key) state = AdventureState( step_counter = jnp.array(0).astype(jnp.int32), #Player Spawn: x, y, tile, inventory @@ -1797,6 +1837,8 @@ def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureOb chalice = jnp.array([self.consts.CHALICE_SPAWN[0], self.consts.CHALICE_SPAWN[1], self.consts.CHALICE_SPAWN[2],7]).astype(jnp.int32), #ToDo + #random key + rndKey = state_key ) initial_obs = self._get_observation(state) @@ -1820,7 +1862,8 @@ def step(self, state: AdventureState, action: chex.Array) -> Tuple[AdventureObse sword=state.sword, bridge=state.bridge, magnet=state.magnet, - chalice=state.chalice + chalice=state.chalice, + rndKey=state.rndKey ) state = self._player_step(state, action) state = self._item_pickup(state, action) @@ -1994,10 +2037,10 @@ def _get_info(self, state: AdventureState, ) -> AdventureInfo: @partial(jax.jit, static_argnums=(0,)) def _get_reward(self, previous_state: AdventureState, state: AdventureState): reward = jax.lax.cond( - jnp.logical_or(state.dragon_yellow[5]==1,state.dragon_green[5]==1), + jnp.logical_or(state.dragon_yellow[5]==1,state.dragon_green[5]==1), #lose when eaten by dragon lambda :-1, lambda : jax.lax.cond( - state.chalice[2]==1, + state.chalice[2]==1, #win when chalice in yellow castle lambda :state.step_counter, lambda :0 #this should happen on reset? ) From de26c1d2f4bc02bc94da7388dcb55ad05fd28ace Mon Sep 17 00:00:00 2001 From: DanielCress Date: Mon, 23 Mar 2026 13:32:39 +0100 Subject: [PATCH 063/102] Castle entrance fix --- src/jaxatari/games/jax_adventure.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 35641b4f8..7a80c30c0 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -1076,6 +1076,34 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt lambda:state.chalice[2] ] ) + + #enter yellow castle + new_player_y, new_player_tile, new_item_tile, new_item_y = jax.lax.cond( + jnp.logical_and(new_player_tile == 0, jnp.logical_and(new_player_y <145,jnp.logical_and(new_player_x<110, new_player_x>50))), + lambda: (212, 1, 1,new_item_y+(212-new_player_y)), + lambda: (new_player_y, new_player_tile, new_item_tile, new_item_y) + ) + + #leave yellow castle + new_player_x, new_player_y, new_player_tile, new_item_tile, new_item_y, new_item_x = jax.lax.cond( + jnp.logical_and(new_player_tile == 1, new_player_y >212), + lambda: (77, 145, 0, 0, new_item_y-(new_player_y-145),new_item_x+(77-new_player_x)), + lambda: (new_player_x, new_player_y, new_player_tile, new_item_tile, new_item_y, new_item_x) + ) + + #enter black castle + new_player_y, new_player_tile, new_item_tile, new_item_y = jax.lax.cond( + jnp.logical_and(new_player_tile == 11, jnp.logical_and(new_player_y <145,jnp.logical_and(new_player_x<110, new_player_x>50))), + lambda: (212, 12, 12,new_item_y+(212-new_player_y)), + lambda: (new_player_y, new_player_tile, new_item_tile, new_item_y) + ) + + #leave black castle + new_player_x, new_player_y, new_player_tile, new_item_tile, new_item_y, new_item_x = jax.lax.cond( + jnp.logical_and(new_player_tile == 12, new_player_y >212), + lambda: (77, 145, 11, 11, new_item_y-(new_player_y-145),new_item_x+(77-new_player_x)), + lambda: (new_player_x, new_player_y, new_player_tile, new_item_tile, new_item_y, new_item_x) + ) #change of rooms new_player_y, new_player_tile, new_item_tile, new_item_y = jax.lax.cond( From 597ab22811d4bba321122d4bb91b75f624d29593 Mon Sep 17 00:00:00 2001 From: DanielCress Date: Sun, 29 Mar 2026 16:05:57 +0200 Subject: [PATCH 064/102] Update jax_adventure.py --- src/jaxatari/games/jax_adventure.py | 133 ++++++++-------------------- 1 file changed, 35 insertions(+), 98 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 7a80c30c0..b3c492461 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -5,6 +5,7 @@ import jax import jax.numpy as jnp import chex +from flax import struct import jaxatari.spaces as spaces from jaxatari.renderers import JAXGameRenderer @@ -84,7 +85,7 @@ def _get_default_asset_config() -> tuple: ) -class AdventureConstants(NamedTuple): +class AdventureConstants(struct.PyTreeNode): #Map Size, coordinates are (x,y) and the upper left corner is (0,0) WIDTH: int = 160 HEIGHT: int = 250 @@ -145,9 +146,13 @@ class AdventureConstants(NamedTuple): # sset config baked into constants (immutable default) for asset overrides ASSET_CONFIG: tuple = _get_default_asset_config() + #Dragon constants + DRAGON_SPEED: int = 2 + DRAGON_BITE_TIMER: int = 15 + # immutable state container -class AdventureState(NamedTuple): +class AdventureState(struct.PyTreeNode): #step conter for performance indicator? step_counter: chex.Array #position player: x ,y ,tile, inventory @@ -173,7 +178,7 @@ class AdventureState(NamedTuple): rndKey: chex.PRNGKey -class EntityPosition(NamedTuple): +class EntityPosition(struct.PyTreeNode): x: jnp.ndarray y: jnp.ndarray tile: jnp.ndarray @@ -182,7 +187,7 @@ class EntityPosition(NamedTuple): state: jnp.ndarray -class AdventureObservation(NamedTuple): +class AdventureObservation(struct.PyTreeNode): player: EntityPosition dragon_yellow: EntityPosition dragon_green: EntityPosition @@ -196,7 +201,7 @@ class AdventureObservation(NamedTuple): chalice: EntityPosition -class AdventureInfo(NamedTuple): +class AdventureInfo(struct.PyTreeNode): time: jnp.ndarray @@ -1076,7 +1081,7 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt lambda:state.chalice[2] ] ) - + #enter yellow castle new_player_y, new_player_tile, new_item_tile, new_item_y = jax.lax.cond( jnp.logical_and(new_player_tile == 0, jnp.logical_and(new_player_y <145,jnp.logical_and(new_player_x<110, new_player_x>50))), @@ -1104,7 +1109,7 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt lambda: (77, 145, 11, 11, new_item_y-(new_player_y-145),new_item_x+(77-new_player_x)), lambda: (new_player_x, new_player_y, new_player_tile, new_item_tile, new_item_y, new_item_x) ) - + #change of rooms new_player_y, new_player_tile, new_item_tile, new_item_y = jax.lax.cond( new_player_y > 212, @@ -1167,11 +1172,9 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt operand = None, ) - return AdventureState( + return state.replace( step_counter = jnp.array(new_step_counter).astype(jnp.int32), player = jnp.array([new_player_x,new_player_y,new_player_tile,state.player[3]]).astype(jnp.int32), #SEEMS NOT GOOD - dragon_yellow = state.dragon_yellow, - dragon_green = state.dragon_green, key_yellow = jax.lax.cond(state.player[3]==self.consts.KEY_YELLOW_ID, lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), lambda op: op[3], @@ -1182,8 +1185,6 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt lambda op: op[3], operand=(new_item_x,new_item_y,new_item_tile,state.key_black) ), - gate_yellow=state.gate_yellow, - gate_black=state.gate_black, sword= jax.lax.cond(state.player[3]==self.consts.SWORD_ID, lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), lambda op: op[3], @@ -1203,8 +1204,7 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt lambda op: jnp.array([op[0],op[1],op[2],op[3]]).astype(jnp.int32), lambda op: op[4], operand=(new_item_x,new_item_y,new_item_tile,state.chalice[3],state.chalice) - ), - rndKey = state.rndKey + ) ) def _gate_interaction(self, state: AdventureState) -> AdventureState: @@ -1320,24 +1320,13 @@ def _gate_interaction(self, state: AdventureState) -> AdventureState: new_gate_yellow = [gate_yellow_state, gate_yellow_counter] new_gate_black = [gate_black_state, gate_black_counter] - return AdventureState( - step_counter=state.step_counter, - player = state.player, - dragon_yellow=state.dragon_yellow, - dragon_green=state.dragon_green, - key_yellow=state.key_yellow, - key_black=state.key_black, + return state.replace( gate_yellow=new_gate_yellow, - gate_black=new_gate_black, - sword=state.sword, - bridge=state.bridge, - magnet=state.magnet, - chalice=state.chalice, - rndKey=state.rndKey + gate_black=new_gate_black ) def _item_pickup(self, state: AdventureState, action: chex.Array) -> AdventureState: - + #helper function that chhecks if an item is near the player #same tile, in range of 4 pixels #it used the corners of the player and calculates if they are in x and y range to the item corners @@ -1358,9 +1347,9 @@ def check_for_item(self:JaxAdventure, state: AdventureState, item_ID: int) -> bo on_same_tile = (tile==state.player[2]) player_hitbox_nw = (state.player[0],state.player[1]) - player_hitbox_ne = (state.player[0]+self.consts.PLAYER_SIZE[0]-1,state.player[1]) - player_hitbox_se = (state.player[0]+self.consts.PLAYER_SIZE[0]-1,state.player[1]+self.consts.PLAYER_SIZE[1]-1) - player_hitbox_sw = (state.player[0],state.player[1]+self.consts.PLAYER_SIZE[1]-1) + player_hitbox_ne = (state.player[0]+self.consts.PLAYER_SIZE[0],state.player[1]) + player_hitbox_se = (state.player[0]+self.consts.PLAYER_SIZE[0],state.player[1]+self.consts.PLAYER_SIZE[1]) + player_hitbox_sw = (state.player[0],state.player[1]+self.consts.PLAYER_SIZE[1]) #jax.debug.print("Hitbox values Player:{a},{b}|{c},{d}|{e},{f}|{g},{h}", # a=player_hitbox_nw[0],b=player_hitbox_nw[1], @@ -1514,20 +1503,8 @@ def diff_of_4(val1:int, val2:int) -> bool: ) - return AdventureState( - step_counter=state.step_counter, - player = jnp.array([state.player[0],state.player[1],state.player[2],new_player_inventory]).astype(jnp.int32), - dragon_yellow=state.dragon_yellow, - dragon_green=state.dragon_green, - key_yellow=state.key_yellow, - key_black=state.key_black, - gate_yellow=state.gate_yellow, - gate_black=state.gate_black, - sword=state.sword, - bridge=state.bridge, - magnet=state.magnet, - chalice=state.chalice, - rndKey=state.rndKey + return state.replace( + player = jnp.array([state.player[0],state.player[1],state.player[2],new_player_inventory]).astype(jnp.int32) ) def _item_drop(self, state: AdventureState, action: chex.Array) -> AdventureState: @@ -1540,24 +1517,14 @@ def _item_drop(self, state: AdventureState, action: chex.Array) -> AdventureStat operand=state.player[3] ) - return AdventureState( - step_counter=state.step_counter, - player = jnp.array([state.player[0],state.player[1],state.player[2],new_player_inventory]).astype(jnp.int32), - dragon_yellow=state.dragon_yellow, - dragon_green=state.dragon_green, - key_yellow=state.key_yellow, - key_black=state.key_black, - gate_yellow=state.gate_yellow, - gate_black=state.gate_black, - sword=state.sword, - bridge=state.bridge, - magnet=state.magnet, - chalice=state.chalice, - rndKey=state.rndKey + return state.replace( + player = jnp.array([state.player[0],state.player[1],state.player[2],new_player_inventory]).astype(jnp.int32) ) def _dragon_step(self, state: AdventureState) -> AdventureState: + speed = self.consts.DRAGON_SPEED + #get sword position to kill dragons sword_x = state.sword[0] sword_y = state.sword[1] @@ -1580,7 +1547,7 @@ def _dragon_step(self, state: AdventureState) -> AdventureState: lambda f:f, operand = dragon_yellow_counter ) - dragon_yellow_freeze = dragon_yellow_counter % 15 != 0 + dragon_yellow_freeze = dragon_yellow_counter % self.consts.DRAGON_BITE_TIMER != 0 #dragon starts looking for plyer room after first encounter dragon_yellow_activate = jax.lax.cond(state.player[2] == dragon_yellow_tile, lambda:1, lambda: dragon_yellow_activate) @@ -1603,7 +1570,7 @@ def _dragon_step(self, state: AdventureState) -> AdventureState: #move towards player and attack dragon_yellow_x, dragon_yellow_y, dragon_yellow_animation, dragon_yellow_counter= jax.lax.cond( jnp.logical_and(state.player[2]==dragon_yellow_tile,jnp.logical_not(dragon_yellow_freeze)), - lambda _: (dragon_yellow_x + direction_x*2, dragon_yellow_y + direction_y*2, jax.lax.cond( + lambda _: (dragon_yellow_x + direction_x*speed, dragon_yellow_y + direction_y*speed, jax.lax.cond( jnp.logical_and((state.player[0]-dragon_yellow_x)*direction_x<4,(state.player[1]-dragon_yellow_y)*direction_y<4), lambda _:jax.lax.cond(dragon_yellow_animation==2, lambda _:2, lambda _:1, operand = None), lambda _:jax.lax.cond(dragon_yellow_animation==2, lambda _:2, lambda _:0, operand = None), @@ -1649,7 +1616,7 @@ def _dragon_step(self, state: AdventureState) -> AdventureState: lambda f:f, operand = dragon_green_counter ) - dragon_green_freeze = dragon_green_counter % 15 != 0 + dragon_green_freeze = dragon_green_counter % self.consts.DRAGON_BITE_TIMER != 0 #dragon starts looking for plyer room after first encounter dragon_green_activate = jax.lax.cond(state.player[2] == dragon_green_tile, lambda:1, lambda: dragon_green_activate) @@ -1672,7 +1639,7 @@ def _dragon_step(self, state: AdventureState) -> AdventureState: #move towards player and attack dragon_green_x, dragon_green_y, dragon_green_animation, dragon_green_counter= jax.lax.cond( jnp.logical_and(state.player[2]==dragon_green_tile,jnp.logical_not(dragon_green_freeze)), - lambda _: (dragon_green_x + direction_x*2, dragon_green_y + direction_y*2, jax.lax.cond( + lambda _: (dragon_green_x + direction_x*speed, dragon_green_y + direction_y*speed, jax.lax.cond( jnp.logical_and(jnp.logical_and((state.player[0]-dragon_green_x)*direction_x<4,(state.player[1]-dragon_green_y)*direction_y<4),dragon_green_animation!=2), lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:1, operand = None), lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:0, operand = None), @@ -1701,19 +1668,9 @@ def _dragon_step(self, state: AdventureState) -> AdventureState: ) - return AdventureState( - step_counter = state.step_counter, - player = state.player, + return state.replace( dragon_yellow = jnp.array([dragon_yellow_x,dragon_yellow_y,dragon_yellow_tile,dragon_yellow_animation,dragon_yellow_counter,dragon_yellow_eat, dragon_yellow_activate]).astype(jnp.int32), dragon_green = jnp.array([dragon_green_x,dragon_green_y,dragon_green_tile,dragon_green_animation,dragon_green_counter,dragon_green_eat, dragon_green_activate]).astype(jnp.int32), - key_yellow=state.key_yellow, - key_black=state.key_black, - gate_yellow=state.gate_yellow, - gate_black=state.gate_black, - sword=state.sword, - bridge=state.bridge, - magnet=state.magnet, - chalice=state.chalice, rndKey=rndKey ) @@ -1781,20 +1738,12 @@ def _magnet_step(self, state: AdventureState) -> AdventureState: operand = None ) - return AdventureState( - step_counter = state.step_counter, - player = state.player, - dragon_yellow = state.dragon_yellow, - dragon_green = state.dragon_green, + return state.replace( key_yellow=jnp.array([key_yellow_x,key_yellow_y,state.key_yellow[2]]).astype(jnp.int32), key_black=jnp.array([key_black_x,key_black_y,state.key_black[2]]).astype(jnp.int32), - gate_yellow=state.gate_yellow, - gate_black=state.gate_black, sword=jnp.array([sword_x,sword_y,state.sword[2]]).astype(jnp.int32), bridge=jnp.array([bridge_x,bridge_y,state.bridge[2]]).astype(jnp.int32), - magnet=state.magnet, - chalice=jnp.array([chalice_x,chalice_y,state.chalice[2],state.chalice[3]]).astype(jnp.int32), - rndKey=state.rndKey + chalice=jnp.array([chalice_x,chalice_y,state.chalice[2],state.chalice[3]]).astype(jnp.int32) ) """This function solely exists for maing the chalice change colors""" @@ -1803,20 +1752,8 @@ def _chalice_step(self, state:AdventureState) -> AdventureState: chalice_color=state.chalice[3] chalice_color = (chalice_color +1) % 10 - return AdventureState( - step_counter=state.step_counter, - player = state.player, - dragon_yellow=state.dragon_yellow, - dragon_green=state.dragon_green, - key_yellow=state.key_yellow, - key_black=state.key_black, - gate_yellow=state.gate_yellow, - gate_black=state.gate_black, - sword=state.sword, - bridge=state.bridge, - magnet=state.magnet, - chalice=jnp.array([state.chalice[0],state.chalice[1],state.chalice[2],chalice_color]).astype(jnp.int32), - rndKey=state.rndKey + return state.replace( + chalice=jnp.array([state.chalice[0],state.chalice[1],state.chalice[2],chalice_color]).astype(jnp.int32) ) """This function is called when the game starts and when it is reseted From 8c292a089cc74cf5984babc3fd885d453e59706d Mon Sep 17 00:00:00 2001 From: DanielCress Date: Sun, 29 Mar 2026 18:00:06 +0200 Subject: [PATCH 065/102] add adventure_mods.py --- src/jaxatari/games/mods/adventure_mods.py | 31 +++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/jaxatari/games/mods/adventure_mods.py diff --git a/src/jaxatari/games/mods/adventure_mods.py b/src/jaxatari/games/mods/adventure_mods.py new file mode 100644 index 000000000..d17369422 --- /dev/null +++ b/src/jaxatari/games/mods/adventure_mods.py @@ -0,0 +1,31 @@ +import os +from jaxatari.modification import JaxAtariModController +from jaxatari.games.mods.adventure.adventure_mod_plugins import FasterDragonsMod, FasterBiteMod, FleaingDragonMod, DragonReviveMod, RandomPlayerSpawnMod +class AdventureEnvMod(JaxAtariModController): + """ + Game-specific Mod Controller for Adventure. + It simply inherits all logic from JaxAtariModController and defines the ADVENTURE_MOD_REGISTRY. + """ + + REGISTRY = { + "faster_dragon": FasterDragonsMod, + "faster_bite": FasterBiteMod, + "fleaing_dragon": FleaingDragonMod, + "dragon_revive": DragonReviveMod, + "random_player_spawn": RandomPlayerSpawnMod + } + + _mod_sprite_dir = os.path.join(os.path.dirname(__file__), "adventure", "sprites") + + def __init__(self, + env, + mods_config: list = [], + allow_conflicts: bool = False + ): + + super().__init__( + env=env, + mods_config=mods_config, + allow_conflicts=allow_conflicts, + registry=self.REGISTRY + ) From d4edcec2b35ea87daec12ef9813e03ecc3ee2b1c Mon Sep 17 00:00:00 2001 From: DanielCress Date: Sun, 29 Mar 2026 18:04:21 +0200 Subject: [PATCH 066/102] add adventure_mod_plugins.py --- .../mods/adventure/adventure_mod_plugins.py | 363 ++++++++++++++++++ 1 file changed, 363 insertions(+) create mode 100644 src/jaxatari/games/mods/adventure/adventure_mod_plugins.py diff --git a/src/jaxatari/games/mods/adventure/adventure_mod_plugins.py b/src/jaxatari/games/mods/adventure/adventure_mod_plugins.py new file mode 100644 index 000000000..96eb095c9 --- /dev/null +++ b/src/jaxatari/games/mods/adventure/adventure_mod_plugins.py @@ -0,0 +1,363 @@ +import jax +import jax.numpy as jnp +from functools import partial +from jaxatari.games.jax_adventure import AdventureState +from jaxatari.modification import JaxAtariInternalModPlugin, JaxAtariPostStepModPlugin +import chex +from jaxatari.environment import JAXAtariAction as Action +import random + +# --- 1. Individual Mod Plugins --- +class FasterDragonsMod(JaxAtariInternalModPlugin): + constants_overrides = { + "DRAGON_SPEED": 4, + } + +class FasterBiteMod(JaxAtariInternalModPlugin): + constants_overrides = { + "DRAGON_BITE_TIMER": 0, + } + +class FleaingDragonMod(JaxAtariInternalModPlugin): + + conflicts_with = ["dragon_revive"] + + @partial(jax.jit, static_argnums=(0,)) + def _dragon_step(self, state: AdventureState) -> AdventureState: + speed = self._env.consts.DRAGON_SPEED + + #get sword position to kill dragons + sword_x = state.sword[0] + sword_y = state.sword[1] + sword_room = state.sword[2] + + #yellow dragon + direction_x = jnp.sign(state.player[0] - state.dragon_yellow[0]) + direction_y = jnp.sign(state.player[1]- state.dragon_yellow[1]) + move_direction_x, move_direction_y = jax.lax.cond( + state.player[3]==self._env.consts.SWORD_ID, + lambda: (-direction_x, -direction_y), + lambda: (direction_x, direction_y) + ) + dragon_yellow_x = state.dragon_yellow[0] + dragon_yellow_y = state.dragon_yellow[1] + dragon_yellow_tile = state.dragon_yellow[2] + dragon_yellow_animation = state.dragon_yellow[3] + dragon_yellow_counter = state.dragon_yellow[4] + dragon_yellow_activate = state.dragon_yellow[6] + + # wait after attack + dragon_yellow_counter = jax.lax.cond( + dragon_yellow_animation == 1, + lambda f: f+1, + lambda f:f, + operand = dragon_yellow_counter + ) + dragon_yellow_freeze = dragon_yellow_counter % self._env.consts.DRAGON_BITE_TIMER != 0 + + #dragon starts looking for plyer room after first encounter + dragon_yellow_activate = jax.lax.cond(state.player[2] == dragon_yellow_tile, lambda:1, lambda: dragon_yellow_activate) + rndKey, subkey = jax.random.split(state.rndKey) + dragon_yellow_x, dragon_yellow_y, dragon_yellow_tile = jax.lax.cond( + jnp.logical_and(jnp.logical_and(dragon_yellow_tile != state.player[2], jnp.logical_not(dragon_yellow_freeze)),dragon_yellow_activate==1), + lambda: (jax.lax.cond(dragon_yellow_x>156, lambda:4, lambda:dragon_yellow_x +2), + jax.lax.cond(dragon_yellow_y>208, lambda:4, lambda:dragon_yellow_y+2), + jax.lax.cond(jnp.logical_or(dragon_yellow_x>156,dragon_yellow_y>208), lambda:jax.random.randint(subkey, (), 0, 13) , lambda:dragon_yellow_tile)), + lambda:(dragon_yellow_x, dragon_yellow_y, dragon_yellow_tile) + ) + + #dragon eats player + dragon_yellow_eat = jax.lax.cond( + jnp.logical_and(jnp.logical_and((state.player[0]-dragon_yellow_x)*direction_x<4,(state.player[1]-dragon_yellow_y)*direction_y<4),jnp.logical_and(dragon_yellow_animation==1,jnp.logical_not(dragon_yellow_freeze))), + lambda:1, + lambda:0 + ) + + #move towards player and attack + dragon_yellow_x, dragon_yellow_y, dragon_yellow_animation, dragon_yellow_counter= jax.lax.cond( + jnp.logical_and(state.player[2]==dragon_yellow_tile,jnp.logical_not(dragon_yellow_freeze)), + lambda _: (dragon_yellow_x + move_direction_x*speed, dragon_yellow_y + move_direction_y*speed, jax.lax.cond( + jnp.logical_and((state.player[0]-dragon_yellow_x)*direction_x<4,(state.player[1]-dragon_yellow_y)*direction_y<4), + lambda _:jax.lax.cond(dragon_yellow_animation==2, lambda _:2, lambda _:1, operand = None), + lambda _:jax.lax.cond(dragon_yellow_animation==2, lambda _:2, lambda _:0, operand = None), + operand = None + ),0), + lambda _: (dragon_yellow_x, dragon_yellow_y, jax.lax.cond(jnp.logical_not(dragon_yellow_freeze), lambda _: jax.lax.cond(dragon_yellow_animation==2, lambda _:2, lambda _:0, operand = None), lambda _: jax.lax.cond(dragon_yellow_animation==2, lambda _:2, lambda _:1, operand = None), operand = None), dragon_yellow_counter), + operand = None + ) + + #kill dragon + direction_x = jnp.sign(sword_x - state.dragon_yellow[0]) + direction_y = jnp.sign(sword_y- state.dragon_yellow[1]) + dragon_yellow_animation = jax.lax.cond( + jnp.logical_and(dragon_yellow_tile==sword_room, jnp.logical_and((sword_x-dragon_yellow_x)*direction_x<4, (sword_y-dragon_yellow_y)*direction_y<22)), + lambda _:2, + lambda a:a, + operand= dragon_yellow_animation + ) + + # dont ever move again when dead + dragon_yellow_counter = jax.lax.cond( + dragon_yellow_animation == 2, + lambda _: 1, + lambda f:f, + operand=dragon_yellow_counter + ) + + + #green dragon + direction_x = jnp.sign(state.player[0] - state.dragon_green[0]) + direction_y = jnp.sign(state.player[1]- state.dragon_green[1]) + move_direction_x, move_direction_y = jax.lax.cond( + state.player[3]==self._env.consts.SWORD_ID, + lambda: (-direction_x, -direction_y), + lambda: (direction_x, direction_y) + ) + dragon_green_x = state.dragon_green[0] + dragon_green_y = state.dragon_green[1] + dragon_green_tile = state.dragon_green[2] + dragon_green_animation = state.dragon_green[3] + dragon_green_counter = state.dragon_green[4] + dragon_green_activate = state.dragon_green[6] + + # wait after attack + dragon_green_counter = jax.lax.cond( + dragon_green_animation == 1, + lambda f: f+1, + lambda f:f, + operand = dragon_green_counter + ) + dragon_green_freeze = dragon_green_counter % self._env.consts.DRAGON_BITE_TIMER != 0 + + #dragon starts looking for plyer room after first encounter + dragon_green_activate = jax.lax.cond(state.player[2] == dragon_green_tile, lambda:1, lambda: dragon_green_activate) + rndKey, subkey = jax.random.split(rndKey) + dragon_green_x, dragon_green_y, dragon_green_tile = jax.lax.cond( + jnp.logical_and(jnp.logical_and(dragon_green_tile != state.player[2], jnp.logical_not(dragon_green_freeze)),dragon_green_activate==1), + lambda: (jax.lax.cond(dragon_green_x>156, lambda:4, lambda:dragon_green_x +2), + jax.lax.cond(dragon_green_y>208, lambda:4, lambda:dragon_green_y+2), + jax.lax.cond(jnp.logical_or(dragon_green_x>156,dragon_green_y>208), lambda:jax.random.randint(subkey, (), 0, 13) , lambda:dragon_green_tile)), + lambda:(dragon_green_x, dragon_green_y, dragon_green_tile) + ) + + #dragon eats player + dragon_green_eat = jax.lax.cond( + jnp.logical_and(jnp.logical_and((state.player[0]-dragon_green_x)*direction_x<4,(state.player[1]-dragon_green_y)*direction_y<4),jnp.logical_and(dragon_green_animation==1,jnp.logical_not(dragon_green_freeze))), + lambda:1, + lambda:0 + ) + + #move towards player and attack + dragon_green_x, dragon_green_y, dragon_green_animation, dragon_green_counter= jax.lax.cond( + jnp.logical_and(state.player[2]==dragon_green_tile,jnp.logical_not(dragon_green_freeze)), + lambda _: (dragon_green_x + move_direction_x*speed, dragon_green_y + move_direction_y*speed, jax.lax.cond( + jnp.logical_and(jnp.logical_and((state.player[0]-dragon_green_x)*direction_x<4,(state.player[1]-dragon_green_y)*direction_y<4),dragon_green_animation!=2), + lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:1, operand = None), + lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:0, operand = None), + operand = None + ),0), + lambda _: (dragon_green_x, dragon_green_y, jax.lax.cond(jnp.logical_not(dragon_green_freeze), lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:0, operand = None), lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:1, operand = None), operand = None), dragon_green_counter), + operand = None + ) + + #kill dragon + direction_x = jnp.sign(sword_x - state.dragon_green[0]) + direction_y = jnp.sign(sword_y- state.dragon_green[1]) + dragon_green_animation = jax.lax.cond( + jnp.logical_and(dragon_green_tile==sword_room, jnp.logical_and((sword_x-dragon_green_x)*direction_x<4, (sword_y-dragon_green_y)*direction_y<22)), + lambda _:2, + lambda a:a, + operand = dragon_green_animation + ) + + # dont ever move again when dead + dragon_green_counter = jax.lax.cond( + dragon_green_animation == 2, + lambda _: 1, + lambda f:f, + operand=dragon_green_counter + ) + + + return state.replace( + dragon_yellow = jnp.array([dragon_yellow_x,dragon_yellow_y,dragon_yellow_tile,dragon_yellow_animation,dragon_yellow_counter,dragon_yellow_eat, dragon_yellow_activate]).astype(jnp.int32), + dragon_green = jnp.array([dragon_green_x,dragon_green_y,dragon_green_tile,dragon_green_animation,dragon_green_counter,dragon_green_eat, dragon_green_activate]).astype(jnp.int32), + rndKey=rndKey + ) + +class DragonReviveMod(JaxAtariInternalModPlugin): + + conflicts_with = ["fleaing_dragon"] + + @partial(jax.jit, static_argnums=(0,)) + def _dragon_step(self, state: AdventureState) -> AdventureState: + speed = self._env.consts.DRAGON_SPEED + + #get sword position to kill dragons + sword_x = state.sword[0] + sword_y = state.sword[1] + sword_room = state.sword[2] + + #yellow dragon + direction_x = jnp.sign(state.player[0] - state.dragon_yellow[0]) + direction_y = jnp.sign(state.player[1]- state.dragon_yellow[1]) + dragon_yellow_x = state.dragon_yellow[0] + dragon_yellow_y = state.dragon_yellow[1] + dragon_yellow_tile = state.dragon_yellow[2] + dragon_yellow_animation = state.dragon_yellow[3] + dragon_yellow_counter = state.dragon_yellow[4] + dragon_yellow_activate = state.dragon_yellow[6] + + # wait after attack + dragon_yellow_counter = jax.lax.cond( + jnp.logical_and(dragon_yellow_animation == 1, dragon_yellow_counter >=0), + lambda f: f+1, + lambda f:f, + operand = dragon_yellow_counter + ) + dragon_yellow_freeze = dragon_yellow_counter % self._env.consts.DRAGON_BITE_TIMER != 0 + + #dragon starts looking for plyer room after first encounter + dragon_yellow_activate = jax.lax.cond(state.player[2] == dragon_yellow_tile, lambda:1, lambda: dragon_yellow_activate) + rndKey, subkey = jax.random.split(state.rndKey) + dragon_yellow_x, dragon_yellow_y, dragon_yellow_tile = jax.lax.cond( + jnp.logical_and(jnp.logical_and(dragon_yellow_tile != state.player[2], jnp.logical_not(dragon_yellow_freeze)),dragon_yellow_activate==1), + lambda: (jax.lax.cond(dragon_yellow_x>156, lambda:4, lambda:dragon_yellow_x +2), + jax.lax.cond(dragon_yellow_y>208, lambda:4, lambda:dragon_yellow_y+2), + jax.lax.cond(jnp.logical_or(dragon_yellow_x>156,dragon_yellow_y>208), lambda:jax.random.randint(subkey, (), 0, 13) , lambda:dragon_yellow_tile)), + lambda:(dragon_yellow_x, dragon_yellow_y, dragon_yellow_tile) + ) + + #dragon eats player + dragon_yellow_eat = jax.lax.cond( + jnp.logical_and(jnp.logical_and((state.player[0]-dragon_yellow_x)*direction_x<4,(state.player[1]-dragon_yellow_y)*direction_y<4),jnp.logical_and(dragon_yellow_animation==1,jnp.logical_not(dragon_yellow_freeze))), + lambda:1, + lambda:0 + ) + + #move towards player and attack + dragon_yellow_x, dragon_yellow_y, dragon_yellow_animation, dragon_yellow_counter= jax.lax.cond( + jnp.logical_and(state.player[2]==dragon_yellow_tile,jnp.logical_and(jnp.logical_not(dragon_yellow_freeze),dragon_yellow_counter>=0)), + lambda _: (dragon_yellow_x + direction_x*speed, dragon_yellow_y + direction_y*speed, jax.lax.cond( + jnp.logical_and((state.player[0]-dragon_yellow_x)*direction_x<4,(state.player[1]-dragon_yellow_y)*direction_y<4), + lambda _:jax.lax.cond(dragon_yellow_animation==2, lambda _:2, lambda _:1, operand = None), + lambda _:jax.lax.cond(dragon_yellow_animation==2, lambda _:2, lambda _:0, operand = None), + operand = None + ),0), + lambda _: (dragon_yellow_x, dragon_yellow_y, jax.lax.cond(jnp.logical_not(dragon_yellow_freeze), lambda _: jax.lax.cond(dragon_yellow_animation==2, lambda _:2, lambda _:0, operand = None), lambda _: jax.lax.cond(dragon_yellow_animation==2, lambda _:2, lambda _:1, operand = None), operand = None), dragon_yellow_counter), + operand = None + ) + + #kill dragon + direction_x = jnp.sign(sword_x - state.dragon_yellow[0]) + direction_y = jnp.sign(sword_y- state.dragon_yellow[1]) + dragon_yellow_animation = jax.lax.cond( + jnp.logical_and(dragon_yellow_tile==sword_room, jnp.logical_and((sword_x-dragon_yellow_x)*direction_x<4, (sword_y-dragon_yellow_y)*direction_y<22)), + lambda _:2, + lambda a:a, + operand= dragon_yellow_animation + ) + + # dont ever move again when dead + dragon_yellow_counter = jax.lax.cond( + jnp.logical_and(dragon_yellow_animation == 2, dragon_yellow_counter >=0), + lambda _: -1, + lambda f:f, + operand=dragon_yellow_counter + ) + + #revive after delay + dragon_yellow_counter, dragon_yellow_animation = jax.lax.cond( + dragon_yellow_counter <0 , + lambda: jax.lax.cond( + dragon_yellow_counter == -150, + lambda: (0, 0), + lambda: (dragon_yellow_counter - 1, dragon_yellow_animation) + ), + lambda: (dragon_yellow_counter, dragon_yellow_animation) + ) + + + #green dragon + direction_x = jnp.sign(state.player[0] - state.dragon_green[0]) + direction_y = jnp.sign(state.player[1]- state.dragon_green[1]) + dragon_green_x = state.dragon_green[0] + dragon_green_y = state.dragon_green[1] + dragon_green_tile = state.dragon_green[2] + dragon_green_animation = state.dragon_green[3] + dragon_green_counter = state.dragon_green[4] + dragon_green_activate = state.dragon_green[6] + + # wait after attack + dragon_green_counter = jax.lax.cond( + dragon_green_animation == 1, + lambda f: f+1, + lambda f:f, + operand = dragon_green_counter + ) + dragon_green_freeze = dragon_green_counter % self._env.consts.DRAGON_BITE_TIMER != 0 + + #dragon starts looking for plyer room after first encounter + dragon_green_activate = jax.lax.cond(state.player[2] == dragon_green_tile, lambda:1, lambda: dragon_green_activate) + rndKey, subkey = jax.random.split(rndKey) + dragon_green_x, dragon_green_y, dragon_green_tile = jax.lax.cond( + jnp.logical_and(jnp.logical_and(dragon_green_tile != state.player[2], jnp.logical_not(dragon_green_freeze)),dragon_green_activate==1), + lambda: (jax.lax.cond(dragon_green_x>156, lambda:4, lambda:dragon_green_x +2), + jax.lax.cond(dragon_green_y>208, lambda:4, lambda:dragon_green_y+2), + jax.lax.cond(jnp.logical_or(dragon_green_x>156,dragon_green_y>208), lambda:jax.random.randint(subkey, (), 0, 13) , lambda:dragon_green_tile)), + lambda:(dragon_green_x, dragon_green_y, dragon_green_tile) + ) + + #dragon eats player + dragon_green_eat = jax.lax.cond( + jnp.logical_and(jnp.logical_and((state.player[0]-dragon_green_x)*direction_x<4,(state.player[1]-dragon_green_y)*direction_y<4),jnp.logical_and(dragon_green_animation==1,jnp.logical_not(dragon_green_freeze))), + lambda:1, + lambda:0 + ) + + #move towards player and attack + dragon_green_x, dragon_green_y, dragon_green_animation, dragon_green_counter= jax.lax.cond( + jnp.logical_and(state.player[2]==dragon_green_tile,jnp.logical_not(dragon_green_freeze)), + lambda _: (dragon_green_x + direction_x*speed, dragon_green_y + direction_y*speed, jax.lax.cond( + jnp.logical_and(jnp.logical_and((state.player[0]-dragon_green_x)*direction_x<4,(state.player[1]-dragon_green_y)*direction_y<4),dragon_green_animation!=2), + lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:1, operand = None), + lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:0, operand = None), + operand = None + ),0), + lambda _: (dragon_green_x, dragon_green_y, jax.lax.cond(jnp.logical_not(dragon_green_freeze), lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:0, operand = None), lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:1, operand = None), operand = None), dragon_green_counter), + operand = None + ) + + #kill dragon + direction_x = jnp.sign(sword_x - state.dragon_green[0]) + direction_y = jnp.sign(sword_y- state.dragon_green[1]) + dragon_green_animation = jax.lax.cond( + jnp.logical_and(dragon_green_tile==sword_room, jnp.logical_and((sword_x-dragon_green_x)*direction_x<4, (sword_y-dragon_green_y)*direction_y<22)), + lambda _:2, + lambda a:a, + operand = dragon_green_animation + ) + + # dont ever move again when dead + dragon_green_counter = jax.lax.cond( + dragon_green_animation == 2, + lambda _: 1, + lambda f:f, + operand=dragon_green_counter + ) + + + return state.replace( + dragon_yellow = jnp.array([dragon_yellow_x,dragon_yellow_y,dragon_yellow_tile,dragon_yellow_animation,dragon_yellow_counter,dragon_yellow_eat, dragon_yellow_activate]).astype(jnp.int32), + dragon_green = jnp.array([dragon_green_x,dragon_green_y,dragon_green_tile,dragon_green_animation,dragon_green_counter,dragon_green_eat, dragon_green_activate]).astype(jnp.int32), + rndKey=rndKey + ) + +class RandomPlayerSpawnMod(JaxAtariInternalModPlugin): + spawnlocations = [(78,174,0),(78,174,2),(78,174,3),(78,70,4),(78,100,5),(78,174,6),(78,174,7),(78,174,8),(78,60,9),(78,174,10),(78,174,11)] + + rnd = random.randint(0, 10) + + constants_overrides = { + "PLAYER_SPAWN": spawnlocations[rnd], + } From 126b28dae6ff677540e45b79fcb68ceb0e157317 Mon Sep 17 00:00:00 2001 From: LucyLMM Date: Sun, 29 Mar 2026 18:33:41 +0200 Subject: [PATCH 067/102] Updated Room Assets for Mods --- src/jaxatari/games/mods/adventure/Room_15.npy | Bin 0 -> 160128 bytes src/jaxatari/games/mods/adventure/Room_16.npy | Bin 0 -> 160128 bytes src/jaxatari/games/mods/adventure/Room_17.npy | Bin 0 -> 160128 bytes src/jaxatari/games/mods/adventure/Room_18.npy | Bin 0 -> 160128 bytes src/jaxatari/games/mods/adventure/Room_20.npy | Bin 0 -> 160128 bytes src/jaxatari/games/mods/adventure/Room_21.npy | Bin 0 -> 160128 bytes src/jaxatari/games/mods/adventure/Room_22.npy | Bin 0 -> 160128 bytes src/jaxatari/games/mods/adventure/Room_23.npy | Bin 0 -> 160128 bytes src/jaxatari/games/mods/adventure/Room_24.npy | Bin 0 -> 160128 bytes src/jaxatari/games/mods/adventure/Room_25.npy | Bin 0 -> 160128 bytes src/jaxatari/games/mods/adventure/Room_26.npy | Bin 0 -> 160128 bytes src/jaxatari/games/mods/adventure/Room_27.npy | Bin 0 -> 160128 bytes src/jaxatari/games/mods/adventure/Room_28.npy | Bin 0 -> 160128 bytes src/jaxatari/games/mods/adventure/Room_29.npy | Bin 0 -> 160128 bytes src/jaxatari/games/mods/adventure/Room_30.npy | Bin 0 -> 160128 bytes .../games/sprites/adventure/Room_1.npy | Bin 160128 -> 160128 bytes .../games/sprites/adventure/Room_8.npy | Bin 160128 -> 160128 bytes 17 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/jaxatari/games/mods/adventure/Room_15.npy create mode 100644 src/jaxatari/games/mods/adventure/Room_16.npy create mode 100644 src/jaxatari/games/mods/adventure/Room_17.npy create mode 100644 src/jaxatari/games/mods/adventure/Room_18.npy create mode 100644 src/jaxatari/games/mods/adventure/Room_20.npy create mode 100644 src/jaxatari/games/mods/adventure/Room_21.npy create mode 100644 src/jaxatari/games/mods/adventure/Room_22.npy create mode 100644 src/jaxatari/games/mods/adventure/Room_23.npy create mode 100644 src/jaxatari/games/mods/adventure/Room_24.npy create mode 100644 src/jaxatari/games/mods/adventure/Room_25.npy create mode 100644 src/jaxatari/games/mods/adventure/Room_26.npy create mode 100644 src/jaxatari/games/mods/adventure/Room_27.npy create mode 100644 src/jaxatari/games/mods/adventure/Room_28.npy create mode 100644 src/jaxatari/games/mods/adventure/Room_29.npy create mode 100644 src/jaxatari/games/mods/adventure/Room_30.npy diff --git a/src/jaxatari/games/mods/adventure/Room_15.npy b/src/jaxatari/games/mods/adventure/Room_15.npy new file mode 100644 index 0000000000000000000000000000000000000000..fccc6198a90ee91f42d8c45eaaabf1c575d3f203 GIT binary patch literal 160128 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 literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/mods/adventure/Room_17.npy b/src/jaxatari/games/mods/adventure/Room_17.npy new file mode 100644 index 0000000000000000000000000000000000000000..0957db2009253439c21544b8bb727a68d1e7c257 GIT binary patch literal 160128 zcmeI4F>W1H6huEMS%o`;l!73jU;%U>8VV|85hDsjA{%IcRZw^ltPz=H18;;z=Dgf@ zA~{lgHJ*EC&dcxo*H_HSQHSQ!G#q6wEolknSNi}KdqnM&-D9fep>(O{Y<~F z?Vr|9?`QgbG(WBX^nRw_*Y;2Ar}uOEed+$)=k)t%{ddpT{no!fwC$hP+wZ#H-SeUO zY5jN4*ZtP-qwSy8+wZ#H-SeUOY5jN4*ZtP-qwSy8+wZ#H-SeUOY5jN4*ZtP-qwSy8 z+wZ#H-SeUOY5jN4*ZtP-qwSy8+wZ#H-SeUOY5jN4*ZtP-qwSy8+wZ#H-SeUOY5jN4 z*ZtP-qwSy8+wZ#H-SeUOY5jN4*ZtP-qwSy8+wZ#H-SeUOY5jN4*ZtP-qwSy8+wZ#H z-SeUOY5jN4*ZtP-qwSy8+wZ#H-SeUOY5jN4*ZtP-qwSy8+wZ#H-SeUOY5jN4*ZtP- zqwSy8+wZ#H-SeUOY5jN4*ZtP-qwSy8+wZ#H-SeUOY5jN4*ZtP-qwSy8+wZ#H-SeUO zY5jN4*ZtP-qwSy8+wZ#H-SeUOY5jN4*ZtP-qwSy8Pw$t`SN~^^W?%*~AOkWW12P~3 zG9UvoAOkWW12P~3G9UvoAOkWW12P~3G9UvoAOkWW12P~3G9UvoAOkWW12P~3G9Uvo zAOkWW12P~3G9UvoAOkWW12P~3G9UvoAOkWW12P~3G9UvoAOkWW12P~3G9UvoAOkWm zpMmuI4O<4%&v(B5{h4$=bpNzJo&V|nbpN#f>HX99)BV%_bpEIN)BV%_r}t0aPxnvz z)A^t7PxnvzpWZ)xKixm=Pv?KSKixm=e|rD){dE7dKb`;S{&fGe|LOhH_tX8;{&fDQ z`_ui?{-^g(-%s~X`_uWK?oanm`=8!FeLvkl?N8@_xHc*8 zwEyY-)A!T;)Bbe+r~A|W)BdOTPv1}XPy5sPpYBihPy3(VKYc&lKkZNFf4V>2Kka{d z|MdNI|Fl1y|LOj8|Fr+<{nPi;{nP$*{-^uX{nP%Z_fOwX_fPxN`Je7j_fPwu-amam z-9PP5=YP8YQ}^Hg{G?C)CB5^f{T-Ck`HTT{luw$|`_uj@pERfUr~OktX-@A? z`=@-;oZg@IPx+)dy+7@r@=0@gf7(CgljijPw13Jc&FTGV|CCRf)BDr@DW5c__ow|+ zK50(xPy45Q(wyF(_D}hwIlVvapYlm_dVktK<&)<0{V&GrIZs~{s literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/mods/adventure/Room_18.npy b/src/jaxatari/games/mods/adventure/Room_18.npy new file mode 100644 index 0000000000000000000000000000000000000000..08049ba663eb01fc32b5ef04aeadb2611520057b GIT binary patch literal 160128 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 literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/mods/adventure/Room_22.npy b/src/jaxatari/games/mods/adventure/Room_22.npy new file mode 100644 index 0000000000000000000000000000000000000000..b1d994d077992449fb107fc199df2da3436a2f3b GIT binary patch literal 160128 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 F;J;?`3s(RD literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/mods/adventure/Room_23.npy b/src/jaxatari/games/mods/adventure/Room_23.npy new file mode 100644 index 0000000000000000000000000000000000000000..8ea8e40559c7e835ce13ecfff0ef6dc3fb67884f GIT binary patch literal 160128 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 KXa~Np4*U;0r4=gx literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/mods/adventure/Room_27.npy b/src/jaxatari/games/mods/adventure/Room_27.npy new file mode 100644 index 0000000000000000000000000000000000000000..de4318bfe25b1a2fa1cde99f2a04e7c272e95691 GIT binary patch literal 160128 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 Y8IS=PkO3Kx0U3}18IS=P_^%lF8@#R|MgRZ+ literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/mods/adventure/Room_29.npy b/src/jaxatari/games/mods/adventure/Room_29.npy new file mode 100644 index 0000000000000000000000000000000000000000..af5bc5b8bb3696d6e541e612914485cb17676c25 GIT binary patch literal 160128 zcmeI)F^*l;5{2PQ$|yQ(5DqW`0tP?^A|W6`7B(V47`1@}h!_Ha2TRcSOrZXaN{d}= z{wMiKkM-)F+N-{R$bWwR+V&tF{s{L^ROzk2cJpTGL<*^e*Y{O@-@_~`v7cTYcl^Ispn`{eHTyMO+lw{N%G zqkrr`0~*kP1~i}n4QN0E8qk0SG@t(`I|u>%cg zKm!`kfCe<60S#zC0~*kP1~i}n4QN0E8qk0SG@t=XiWqQ(IrdPeL^{T(Mp7fOINq?DM z^}5!p{?>ZZQ>G{VWqQ@?TCe(B>q$?Up7fXLRj+Hk>Tj(lJ!N{*U#3^RuJx+FwVw2p z=}CW?UiG@xtNzw{(o?1<{bhR9>sqh+TkAl`zebv6GpXv9Vz902#Ui+MW-|745tM*0xOuz5+{it8_+UNB9PTx;owJ+*t z`hBPGNBx@DKBwPz`hNPVeNjKt?>l`z>esyXIsLxV_tRJHi~5;<-|72Nzvi{i>Gz$! zpT25e)X(($PT!CEHLrb6zwh+@^i}(!ex~1d`hL`}dF^xheW&lIui6*&GyT5P_oIHz zYoF8aJAFTW)xM~o>Gz$!AN6Zq`<#B?>HF!c_C@_nzwh+@s9*Ei=k)td-!JWp-akF3 zerSK1Pv_nJXx=>g_iK_5>YwJ*d3QgWH`iZfn0!>TS4Q*Z`l}3)k7`zbSzC0QEAQTi z=F>U7k-ks!=2@fN`_OzkCm-~Enm5;9Wr%!KvsXs*=K8A)k&kLte_2~}n=9|$hvw5c zy^+38^X6Hj-TTmdIwv3WeVRAdUuB4VRI^t`^XB@i43Up&R)1Mrbek*h-iPMXIlYm- zPxIzkquu+^d^#r|^nIE)*I#9bd{nbnM)T(Ss|=BkYF2+)TXdT%@7{;z(>cA7zEAV! zS)<+i(0n>4AM|~iH`iZfhU7k-ks!=2@fN z`_OzkCm-~Enm5;9Wr%!KvsXs*=K8A)k&kLte_2~}n=9|$hvw5cy^+38^X6Hj-TTmd zIwv3WeVRAdUuB4VRI^t`^XB@i43Up&R)1Mrbek*h-iPMXIlYm-PxIzkquu+^d^#r| z^nIE)*I#9bd{nbnM)T(Ss|=BkYF2;z?_bm(<>~u$zdwCHdS5rE_owsj{xnbf@1CE& zANAAC>HX=vyFbm-{=4U=???S~b9#R|@9t0YwEyn;>HASX-JIT^&b#~5Jng@Ge)@jY zPdBIcr}OUqG*A2Qo}a!S_0!Gi{pq~BKh4wryXU9xNBwkjdVf0a?oacy|L*ze`%ypL zoZg?#yZh5T?Z10|`hL_;H>dZf^X~pMPy6qlpS~aU)6MDq>Abr?&C~w7=cn&S{d9AB ze>(5(PxG|@?)mBaQ9s?B-k;99`_nw_zk7cAe$-Dlr}wAx?*24S`|qBgz903|&FTH= zyt_Zm)Bd~Xr|(DobaQ%tI`8gJ^R)l&`RV&nKi!<(pU%7c(>(3Jdw%+U)K533_owsj z{xnbf@1CE&ANAAC>HX=vyFbm-{=4U=???S~b9#R|@9t0YwEyn;>HASX-JIT^&b#~5 zJng@Ge)@jYPdBIcr}OUqG*A2Qo}a!S_0!Gi{pq~BKh4wryXU9xNBwkjdVf0a?oacy z|L*ze`%ypLoZg?#yZh5T?Z10|`hL_;H>dZf^X~pMPy6qlpS~aU)6MDq>Abr?&C~w7 z=cn&S{d9ABe>(5(PxG|@?)mBaQ9s?B-k;99`_nw_zk7cAe$-Dlr}wAx?*24S`|qBg zz903|&FTH=yt_Zm)Bd~Xr|(DobaQ%tI`8gJ^R)l&`RV&nKi!<(pU!E2`hItwexLI6 z_tU?he&6o>Pk&#!-}LXFexK9dm-dnV{nPJr`uoy8(!YQDeNKO0+DH2LPruLU?@Rkg z|NiOsIsJWUAL-ve{XVC^FYP1!`={UM^!KHGq<{bP`<(v1w2$=fpMIay-F-PXNdNxn_c{H2X&>p|Km9(Zzc1}0{rms*``m7~ zNB`J?1~i}n4QN0E8qk0SG@tE0iApaVLf13I7sI-mnOpaVLf13I7sI-mnOpaVLf13I7sI-mnOpaVLf13I7sI-mnO zpaVLf13I7sI-mnOpaVLf13I7sI-mnOpaVLf13I7sI-mnOpaVLf13I7sI-mnO@UA*= zcXxMBe*XRY!Tszf^`5b#mUvQ6Z@-QA(;FoJ7M8wG`7IgAXJ|gkS7smCNdLj^Ip5oO zfA9Qh|1=-vQ@&X}y*=tPeoHOAv84z341J&SB>NVY=A-ooA=z$(|nXaH}A`zPj8R<%b&mG-_skH^gM^5?^FJqte1S2 z=A-;2nO`vJ?NNX6*-QVK-ng{yR*t?;`K>uG{T$6l`Ac&TF1wC{OaIw@01yA8dMq_D?*0 zpYkamt5~I@?*x1TH>wi-^`)p$Bfm#TDQ_|MxEX#@zwP- zV|qXF)@vQ5_ep$pJ^7K|PrP;gn>m#Hn6aalcHWl8*T0!V$&VR3YKgb5e=~=YA2U|}YTZh=8FhM}#8=nTjOqQv zTd#GL-Y4-slyDETpC^{>{gbemD9_ep$pJ>ape#}_?t92{gX4L6@5?@_UGp6?wZ@t!0 zdY{Bs*OMRV{lr_>znMeHj~P2^iMOtQGl!BNGgkj<-AcC^b$Xw~SJ%^w>3zzl{_lF7 z?w9h_`=|LRUp-&<{&c^TuihWcNBQdcy7#C1rF`}NXg<_eb+lzIwjy z{po%wU%fw?kMh;?b?;C2OZn>k(R`Gzp09g)xO4m-5y7qxmRbJzw|!bib6Z-XG0J`Re()_ow@%eD(flKFU|m*S$a8FXgNENApp> zdcN-c>3%6+y+4|d^40To?@#wj`Re`Ae3Y-AuX}&GU&>eSkLII%^?cp?)BRGudVe$@ z<*VoG-kiN3&r~9RR_5Nr+%2&_Vy+7SA<*WBc z^HIKfzV7|$ekotQKbnv7)$?`lPxnjt>iyAtl&_wzdw;rL%2)4?=A(S|eBJxg{ZhVq ze>5NEtLN+9pYE6P)%&CQC|^Ba_x^Ohl&{_&%}4p_`MUR~`=xyK{%AhRSI^hIKix0o ztM^CqQNDV@A=dFbUw|uf89ekM4)^G=DWu=c9b}e0%q&`=R{a^QZUe ze3Vc5y4UG`D8Kst=zNr4eLplG-4Eqy{%W4iNBQdc_U=#jL;1buPw&(DD4+6muhacd ze)av)`6$2oerP_rAIj7G)jXY#^40V0-JkA<@_Wyp-ly|XKIQ9Pr~9G&>ieVfQGWIP z(0p`1l&ATtc{(5EtLNLhKiv=I_ntq!Pv@h2%GbS4_e1&B_ebZW{ObFm`RINqPxDvv zbUw;g&$oAfx*y8#J%4(i&PVx_uX~;Dhw`iMkIqN=)%Qd5(fv@K=C9`Ie3Y-AZ}0we zKa}5l{`5YbkMb#B_d4AVx*C{O24@2_5` z^LOW0zt7S0b@zwnKl*)FpO4)$eokeBJ$_`Hz0z z)#s!4>&~x!pQGpN?hnm>^!u(pAH839e)antJzsZ!X#S($clG(`{krq3-{i0Q%zV80e{71j<>hsb2b>~;V&(ZUB z_lM>``h8cQkKV64zxsWSp0B$yZU_ee%<-i?{oBg-Tk5YkAC0P=cD)Q&aZx- zqvz}H56yq{`>sA8yUw40K{-fV__4(-iy7Q~w=ji#m`$O{|{l2TuNAK62 zU;REu&)3}_n*ZqcU41@!zwZ3%_c?mL?*7pH-S121mw#~Y4%~qb=ztFBfDY(@4(Nam z=ztFBfDY(@4(Nam=ztFBfDY(@4(Nam=ztFBfDY(@4(Nam=ztFBfDY(@4(Nam=ztFB zfDY(@4(Nam=ztFBfDY(@4(Nam=ztFBfDY(@4(Nam=ztFBfDY(@4(Nam=ztFBKysk_ zpI=Dxr~OpdX@2>;`_4P4_AB-8ygRdV_mdyhb#KUT*m;N5ex?4McV~9~-AR5_*S#UX zVdouI`<424-ksU`cPIH#UH69khMjj#-<{+~b=@2C8+P7dwO^@!=iQl| ze|M4})pc*kZ`gT<)qbV^op)z;{@qD_RM)*BzhUPcR{NFucix@Z`FAJzQC;_j{Dz%( zSnXHp-+6a$Bm3!ey7$K&=ztFBfDY(@4(Nam=ztFBfDY(@4(Nam=ztFBfDY(@4(Nam z=ztFBfDY(@4(Nam=ztFBfDY(@4(Nam=ztFBfDY(@4(Nam=ztFBfDY(@4(Nam=ztFB cfDY(@4(Nam=ztFBfDY(@4(Nam{9g|I2h|_#3;+NC literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/sprites/adventure/Room_1.npy b/src/jaxatari/games/sprites/adventure/Room_1.npy index 4582bdb6617ec1a1f828806ad3413e25f036c377..118d506dbfee823f5fcc63016b085a839568a867 100644 GIT binary patch delta 22 ccmZp8%-H}$EsR^38q~H=QDb`JHF1In0BuSM7ytkO delta 23 dcmZp8%-H}$EsR^38q_8WxQJ|TP-A-I1psh32+9Be diff --git a/src/jaxatari/games/sprites/adventure/Room_8.npy b/src/jaxatari/games/sprites/adventure/Room_8.npy index 51a55a9bcd3572c6748a449d40eb350173cbfe8f..cc601c8abfb2cfddfd1eba0697443b232fcbee44 100644 GIT binary patch delta 22 ccmZp8%-H}$EsR^38q~H=QDb`JHF1In0BuSM7ytkO delta 23 dcmZp8%-H}$EsR^38q_8WxQJ|TP-A-I1psh32+9Be From cb88834d7dae2c253850f0a653d00cccbd8055d8 Mon Sep 17 00:00:00 2001 From: lschwass Date: Sun, 29 Mar 2026 20:05:09 +0200 Subject: [PATCH 068/102] Wall checking now donw via background npy sprites. Fine Tuning still required, broke some cross tile movement??? --- src/jaxatari/games/jax_adventure.py | 78 ++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index b3c492461..a17edca1a 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -205,6 +205,10 @@ class AdventureInfo(struct.PyTreeNode): time: jnp.ndarray +def _load_background_map(path: str) -> jnp.ndarray: + background_map = jnp.load(path) + return background_map + class JaxAdventure(JaxEnvironment[AdventureState, AdventureObservation, AdventureInfo, AdventureConstants]): def __init__(self, consts: AdventureConstants = None): consts = consts or AdventureConstants() @@ -219,6 +223,28 @@ def __init__(self, consts: AdventureConstants = None): Action.DOWN, ] + #jax.debug.print("base dir:{a}", a=render_utils.get_base_sprite_dir()) + #jax.debug.print("path:{a}", a=os.path.join(render_utils.get_base_sprite_dir(), "adventure", "Room_2.npy")) + #jax.debug.print("sprite path: {a}", a=f"{os.path.dirname(os.path.abspath(__file__))}/sprites/adventure") + #background_assets_names = _get_default_asset_config()[0]["files"] + + sprite_path = f"{os.path.dirname(os.path.abspath(__file__))}/sprites/adventure" + + self.BackgroundRoom1 = _load_background_map(os.path.join(sprite_path, "Room_1.npy")) + self.BackgroundRoom2 = _load_background_map(os.path.join(sprite_path, "Room_2.npy")) + self.BackgroundRoom3 = _load_background_map(os.path.join(sprite_path, "Room_3.npy")) + self.BackgroundRoom4 = _load_background_map(os.path.join(sprite_path, "Room_4.npy")) + self.BackgroundRoom5 = _load_background_map(os.path.join(sprite_path, "Room_5.npy")) + self.BackgroundRoom6 = _load_background_map(os.path.join(sprite_path, "Room_6.npy")) + self.BackgroundRoom7 = _load_background_map(os.path.join(sprite_path, "Room_7.npy")) + self.BackgroundRoom8 = _load_background_map(os.path.join(sprite_path, "Room_8.npy")) + self.BackgroundRoom9 = _load_background_map(os.path.join(sprite_path, "Room_9.npy")) + self.BackgroundRoom10 = _load_background_map(os.path.join(sprite_path, "Room_10.npy")) + self.BackgroundRoom11 = _load_background_map(os.path.join(sprite_path, "Room_11.npy")) + self.BackgroundRoom12 = _load_background_map(os.path.join(sprite_path, "Room_12.npy")) + self.BackgroundRoom13 = _load_background_map(os.path.join(sprite_path, "Room_13.npy")) + self.BackgroundRoom14 = _load_background_map(os.path.join(sprite_path, "Room_14.npy")) + def _check_for_wall(self, state: AdventureState, direction: int) -> bool: room = state.player[2] @@ -251,6 +277,55 @@ def _check_for_wall(self, state: AdventureState, direction: int) -> bool: operand = player_y, ) + #jax.debug.print("step") + #test load background of Rooms + def is_tile_walkable(tileset: jnp.ndarray, Pos_x: int, Pos_y: int) -> bool: + #determin if we should be allowed to walk, based on the background only + #tileset data at a given x and y position is [r, g, b, 255] + #[151, 151, 151, 255] = Grey (allowed player movement) + #anything else are walls (inversed in certain maze tileset) or top or bottom border. + is_walkable_1 = (tileset[Pos_y+2,Pos_x][0] == jnp.uint8(151)) + is_walkable_2 = (tileset[Pos_y+2,Pos_x][1] == jnp.uint8(151)) + is_walkable_3 = (tileset[Pos_y+2,Pos_x][2] == jnp.uint8(151)) + is_walkable = jnp.logical_and(is_walkable_1, jnp.logical_and(is_walkable_2,is_walkable_3)) + #jax.debug.print("Tile: {a} is walkable {b}",a=tileset[Pos_y,Pos_x][0:3], b=is_walkable) + return is_walkable + + #jax.debug.print("Room: {a} is equal to 0 {b}, is walkable {c}",a=room, b=(room == 0),c=is_tile_walkable(self.BackgroundRoom1, player_x, player_y)) + in_Room_1_and_walkable = jnp.logical_and(jnp.equal(room, 0), is_tile_walkable(self.BackgroundRoom1, player_x, player_y)) + in_Room_2_and_walkable = jnp.logical_and(jnp.equal(room, 1), is_tile_walkable(self.BackgroundRoom2, player_x, player_y)) + in_Room_3_and_walkable = jnp.logical_and(jnp.equal(room, 2), is_tile_walkable(self.BackgroundRoom3, player_x, player_y)) + in_Room_4_and_walkable = jnp.logical_and(jnp.equal(room, 3), is_tile_walkable(self.BackgroundRoom4, player_x, player_y)) + in_Room_5_and_walkable = jnp.logical_and(jnp.equal(room, 4), is_tile_walkable(self.BackgroundRoom5, player_x, player_y)) + in_Room_6_and_walkable = jnp.logical_and(jnp.equal(room, 5), is_tile_walkable(self.BackgroundRoom6, player_x, player_y)) + in_Room_7_and_walkable = jnp.logical_and(jnp.equal(room, 6), is_tile_walkable(self.BackgroundRoom7, player_x, player_y)) + in_Room_8_and_walkable = jnp.logical_and(jnp.equal(room, 7), is_tile_walkable(self.BackgroundRoom8, player_x, player_y)) + in_Room_9_and_walkable = jnp.logical_and(jnp.equal(room, 8), is_tile_walkable(self.BackgroundRoom9, player_x, player_y)) + in_Room_10_and_walkable = jnp.logical_and(jnp.equal(room, 9), is_tile_walkable(self.BackgroundRoom10, player_x, player_y)) + in_Room_11_and_walkable = jnp.logical_and(jnp.equal(room, 10), is_tile_walkable(self.BackgroundRoom11, player_x, player_y)) + in_Room_12_and_walkable = jnp.logical_and(jnp.equal(room, 11), is_tile_walkable(self.BackgroundRoom12, player_x, player_y)) + in_Room_13_and_walkable = jnp.logical_and(jnp.equal(room, 12), is_tile_walkable(self.BackgroundRoom13, player_x, player_y)) + in_Room_14_and_walkable = jnp.logical_and(jnp.equal(room, 13), is_tile_walkable(self.BackgroundRoom14, player_x, player_y)) + + Room_1_or_2_and_walkable = jnp.logical_or(in_Room_1_and_walkable, in_Room_2_and_walkable) + Room_3_or_4_and_walkable = jnp.logical_or(in_Room_3_and_walkable, in_Room_4_and_walkable) + Room_5_or_6_and_walkable = jnp.logical_or(in_Room_5_and_walkable, in_Room_6_and_walkable) + Room_7_or_8_and_walkable = jnp.logical_or(in_Room_7_and_walkable, in_Room_8_and_walkable) + Room_9_or_10_and_walkable = jnp.logical_or(in_Room_9_and_walkable, in_Room_10_and_walkable) + Room_11_or_12_and_walkable = jnp.logical_or(in_Room_11_and_walkable, in_Room_12_and_walkable) + Room_13_or_14_and_walkable = jnp.logical_or(in_Room_13_and_walkable, in_Room_14_and_walkable) + + Room_1_or_2_or_3_or_4_and_walkable = jnp.logical_or(Room_1_or_2_and_walkable, Room_3_or_4_and_walkable) + Room_5_or_6_or_7_or_8_and_walkable = jnp.logical_or(Room_5_or_6_and_walkable, Room_7_or_8_and_walkable) + Room_9_or_10_or_11_or_12_and_walkable = jnp.logical_or(Room_9_or_10_and_walkable, Room_11_or_12_and_walkable) + + Room_1_or_2_or_3_or_4_or_5_or_6_or_7_or_8_and_walkable = jnp.logical_or(Room_1_or_2_or_3_or_4_and_walkable, Room_5_or_6_or_7_or_8_and_walkable) + Room_9_or_10_or_11_or_12_or_13_or_14_and_walkable = jnp.logical_or(Room_9_or_10_or_11_or_12_and_walkable, Room_13_or_14_and_walkable) + + current_Room_is_walkable = jnp.logical_or(Room_1_or_2_or_3_or_4_or_5_or_6_or_7_or_8_and_walkable,Room_9_or_10_or_11_or_12_or_13_or_14_and_walkable) + #jax.debug.print("is walkable {a}", a= current_Room_is_walkable) + #return current_Room_is_walkable + ### Left Wall with and without Path left_wall = self.consts.LEFT_WALL_X upper_edge = self.consts.PATH_HORIZONTAL_UP @@ -981,7 +1056,8 @@ def _check_for_wall(self, state: AdventureState, direction: int) -> bool: base_rooms = jnp.logical_and(room_1_to_8, room_9_to_14) - walls_detected = jnp.logical_and(base_rooms, castle_collision ) + #walls_detected = jnp.logical_and(base_rooms, castle_collision ) + walls_detected = jnp.logical_and(current_Room_is_walkable, castle_collision ) #Check for Bridge negating wall From ea75460097e19dadfdfc987a15090890069d5854 Mon Sep 17 00:00:00 2001 From: lschwass Date: Sun, 29 Mar 2026 20:14:18 +0200 Subject: [PATCH 069/102] Fixed Tile Transition. (partially, some borders are blac an need a special check wall condition) --- src/jaxatari/games/jax_adventure.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index a17edca1a..f98bbb853 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -283,13 +283,18 @@ def is_tile_walkable(tileset: jnp.ndarray, Pos_x: int, Pos_y: int) -> bool: #determin if we should be allowed to walk, based on the background only #tileset data at a given x and y position is [r, g, b, 255] #[151, 151, 151, 255] = Grey (allowed player movement) - #anything else are walls (inversed in certain maze tileset) or top or bottom border. + #[0, 0, 0, 255] are top or bottom border allow movement for tilechange + #anything else are walls (inversed in certain maze tileset) . is_walkable_1 = (tileset[Pos_y+2,Pos_x][0] == jnp.uint8(151)) is_walkable_2 = (tileset[Pos_y+2,Pos_x][1] == jnp.uint8(151)) is_walkable_3 = (tileset[Pos_y+2,Pos_x][2] == jnp.uint8(151)) is_walkable = jnp.logical_and(is_walkable_1, jnp.logical_and(is_walkable_2,is_walkable_3)) + is_border_1 = (tileset[Pos_y+2,Pos_x][0] == jnp.uint8(0)) + is_border_2 = (tileset[Pos_y+2,Pos_x][1] == jnp.uint8(0)) + is_border_3 = (tileset[Pos_y+2,Pos_x][2] == jnp.uint8(0)) + is_border = jnp.logical_and(is_border_1, jnp.logical_and(is_border_2,is_border_3)) #jax.debug.print("Tile: {a} is walkable {b}",a=tileset[Pos_y,Pos_x][0:3], b=is_walkable) - return is_walkable + return jnp.logical_or(is_walkable,is_border) #jax.debug.print("Room: {a} is equal to 0 {b}, is walkable {c}",a=room, b=(room == 0),c=is_tile_walkable(self.BackgroundRoom1, player_x, player_y)) in_Room_1_and_walkable = jnp.logical_and(jnp.equal(room, 0), is_tile_walkable(self.BackgroundRoom1, player_x, player_y)) From b5eb49b71665c8c9675198b36e4e7901b2e89664 Mon Sep 17 00:00:00 2001 From: lschwass Date: Sun, 29 Mar 2026 20:48:40 +0200 Subject: [PATCH 070/102] removed complex wall detection logic --- src/jaxatari/core.py | 2 + src/jaxatari/games/jax_adventure.py | 674 +--------------------------- 2 files changed, 4 insertions(+), 672 deletions(-) diff --git a/src/jaxatari/core.py b/src/jaxatari/core.py index d76f64ea1..6cad5699e 100644 --- a/src/jaxatari/core.py +++ b/src/jaxatari/core.py @@ -26,6 +26,7 @@ def _warn_deprecated_obs_to_flat_array(env: JaxEnvironment) -> None: # Map of game names to their module paths GAME_MODULES = { + "adventure": "jaxatari.games.jax_adventure", "amidar": "jaxatari.games.jax_amidar", "airraid": "jaxatari.games.jax_airraid", "alien": "jaxatari.games.jax_alien", @@ -77,6 +78,7 @@ def _warn_deprecated_obs_to_flat_array(env: JaxEnvironment) -> None: # Mod modules registry: for each game, provide the Controller class path MOD_MODULES = { + "adventure": "jaxatari.games.mods.adventure_mods.AdventureEnvMod", "pong": "jaxatari.games.mods.pong_mods.PongEnvMod", "kangaroo": "jaxatari.games.mods.kangaroo_mods.KangarooEnvMod", "freeway": "jaxatari.games.mods.freeway_mods.FreewayEnvMod", diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index f98bbb853..94478e3d8 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -329,667 +329,13 @@ def is_tile_walkable(tileset: jnp.ndarray, Pos_x: int, Pos_y: int) -> bool: current_Room_is_walkable = jnp.logical_or(Room_1_or_2_or_3_or_4_or_5_or_6_or_7_or_8_and_walkable,Room_9_or_10_or_11_or_12_or_13_or_14_and_walkable) #jax.debug.print("is walkable {a}", a= current_Room_is_walkable) - #return current_Room_is_walkable - - ### Left Wall with and without Path - left_wall = self.consts.LEFT_WALL_X - upper_edge = self.consts.PATH_HORIZONTAL_UP - lower_edge = self.consts.PATH_HORIZONTAL_DOWN - collision_left_wall = player_x >= left_wall - collision_left_wall_path = jnp.logical_or(collision_left_wall, jnp.logical_and(player_y>=upper_edge, player_y<=lower_edge)) - collision_left_special = player_x >= self.consts.SPECIAL_WALL_LEFT - - ### Right Wall with and without Path - right_wall = self.consts.RIGHT_WALL_X - upper_edge = self.consts.PATH_HORIZONTAL_UP - lower_edge = self.consts.PATH_HORIZONTAL_DOWN - collision_right_wall = player_x <= right_wall - collision_right_wall_path = jnp.logical_or(collision_right_wall, jnp.logical_and(player_y>=upper_edge, player_y<=lower_edge)) - collision_right_special = player_x <= self.consts.SPECIAL_WALL_RIGHT - - ### Upper Wall with and without Path - upper_wall = self.consts.UPPER_WALL_Y + + edge_left = self.consts.PATH_VERTICAL_LEFT edge_right = self.consts.PATH_VERTICAL_RIGHT - collision_upper_wall = player_y >= upper_wall - collision_upper_wall_path = jnp.logical_or(collision_upper_wall, jnp.logical_and(player_x>=edge_left, player_x<=edge_right)) - ### Lower Wall with and without Path - lower_wall = self.consts.LOWER_WALL_Y edge_left = self.consts.PATH_VERTICAL_LEFT edge_right = self.consts.PATH_VERTICAL_RIGHT - collision_lower_wall = player_y <= lower_wall - collision_lower_wall_path = jnp.logical_or(collision_lower_wall, jnp.logical_and(player_x>=edge_left, player_x<=edge_right)) - - - ## Rooms: - room_1_clear = jnp.logical_or( - jnp.logical_not(room == 0), #either it is not room 0 or - jnp.logical_and( #walls of the room are not being crossed - jnp.logical_and( - collision_left_wall, - collision_right_wall - ), - jnp.logical_and( - collision_upper_wall_path, - collision_lower_wall_path - ) - ) - ) - - room_2_clear = jnp.logical_or( - jnp.logical_not(room == 1), #either it is not room 1 or - jnp.logical_and( #walls of the room are not being crossed - jnp.logical_and( - collision_left_wall, - collision_right_wall - ), - jnp.logical_and( - collision_upper_wall, - collision_lower_wall_path - ) - ) - ) - - room_3_clear = jnp.logical_or( - jnp.logical_not(room == 2), #either it is not room 2 or - jnp.logical_and( #walls of the room are not being crossed - jnp.logical_and( - collision_left_wall_path, - collision_right_wall_path - ), - jnp.logical_and( - collision_upper_wall_path, - collision_lower_wall - ) - ) - ) - - room_4_clear = jnp.logical_or( - jnp.logical_not(room == 3), #either it is not room 3 or - jnp.logical_and( #walls of the room are not being crossed - jnp.logical_and( - collision_left_wall_path, - collision_right_special - ), - jnp.logical_and( - collision_upper_wall, - collision_lower_wall_path - ) - ) - ) - - room_5_clear = jnp.logical_or( - jnp.logical_not(room == 4), #either it is not room 4 or - jnp.logical_and( #walls of the room are not being crossed - jnp.logical_and( - collision_left_wall, - collision_right_wall - ), - jnp.logical_and( - collision_upper_wall_path, - collision_lower_wall - ) - ) - ) - - room_6_clear = jnp.logical_or( - jnp.logical_not(room == 5), #either it is not room 5 or - jnp.logical_and( #walls of the room are not being crossed - jnp.logical_and( - collision_left_special, - collision_right_wall_path - ), - jnp.logical_and( - collision_upper_wall_path, - collision_lower_wall - ) - ) - ) - - ### extra maze walls - - room_7_walls = jnp.logical_or( - player_y >= 170, # either below lowest thick wall or - jnp.logical_or( - jnp.logical_or( # the two corridors up - jnp.logical_and(player_x>=30, player_x <= 38), #left corridor - jnp.logical_and(player_x>=120, player_x <= 126) #right corridor - ), - jnp.logical_or( - jnp.logical_or( - jnp.logical_and( - jnp.logical_and(player_y <= 135, player_y >= 105), - jnp.logical_or( - jnp.logical_or( - jnp.logical_and(player_x >=45, player_x <= 110), - player_x <= 20 - ), - player_x >=135 - ) - ), - jnp.logical_and( - jnp.logical_and(player_y <= 105, player_y >= 75), - jnp.logical_or( - jnp.logical_or( - jnp.logical_and(player_x >= 45, player_x <=53), - jnp.logical_and(player_x >= 15, player_x <= 20) - ), - jnp.logical_or( - jnp.logical_and(player_x >= 102, player_x <= 110), - jnp.logical_and(player_x >= 135, player_x <= 143) - ) - ) - ) - ), - jnp.logical_or( - jnp.logical_and( - jnp.logical_and(player_y <= 70, player_y >= 40), - jnp.logical_or( - jnp.logical_or( - jnp.logical_and(player_x >= 62, player_x <= 94), - jnp.logical_or(player_x <= 20, player_x >=135) - ), - jnp.logical_or( - jnp.logical_and(player_x >= 102, player_x <= 110), - jnp.logical_and(player_x >= 45, player_x <= 53) - ) - ) - ), - jnp.logical_and( - player_y <= 40, - jnp.logical_or( - jnp.logical_or( - jnp.logical_and(player_x >= 62, player_x <= 70), - jnp.logical_and(player_x >= 86, player_x <= 94) - ), - jnp.logical_or( - jnp.logical_and(player_x >= 102, player_x <= 110), - jnp.logical_and(player_x >= 45, player_x <= 53) - ) - ) - ) - ) - ) - ) - ) - - room_8_walls = jnp.logical_or( - jnp.logical_or( - jnp.logical_or( - jnp.logical_and( - player_y >= 199, - jnp.logical_or( - jnp.logical_or( - jnp.logical_and(player_x >= 30, player_x <= 38), - jnp.logical_and(player_x >= 120, player_x <= 126) - ), - jnp.logical_or( - jnp.logical_or( - jnp.logical_and(player_x >= 102, player_x <= 110), - jnp.logical_and(player_x >= 45, player_x <= 53) - ), - jnp.logical_and(player_x>=edge_left, player_x<=edge_right) - ) - ) - ), - jnp.logical_and( - jnp.logical_and(player_y >= 170, player_y <= 199), - jnp.logical_or( - jnp.logical_or( - jnp.logical_or( - jnp.logical_and(player_x >= 30, player_x <= 38), - jnp.logical_and(player_x >= 120, player_x <= 126) - ), - jnp.logical_or( - jnp.logical_or( - jnp.logical_and(player_x >= 102, player_x <= 110), - jnp.logical_and(player_x >= 45, player_x <= 53) - ), - jnp.logical_and(player_x>=edge_left, player_x<=edge_right) - ) - ), - jnp.logical_or( - player_x <= 20, - player_x >= 135 - ) - ) - ) - ), - - jnp.logical_or( - jnp.logical_and( - jnp.logical_and(player_y >= 135, player_y <= 170), - jnp.logical_or( - jnp.logical_or( - jnp.logical_or( - jnp.logical_and(player_x >= 30, player_x <= 38), - jnp.logical_and(player_x >= 120, player_x <= 126) - ), - jnp.logical_or( - jnp.logical_or( - jnp.logical_and(player_x >= 102, player_x <= 110), - jnp.logical_and(player_x >= 45, player_x <= 53) - ), - jnp.logical_and(player_x>=72, player_x<=84) - ) - ), - jnp.logical_or( - jnp.logical_and(player_x <= 20, player_x >= 14), - jnp.logical_and(player_x >= 135, player_x <= 142) - ) - ) - ), - jnp.logical_and( - jnp.logical_and(player_y >= 105, player_y <= 135), - jnp.logical_or( - jnp.logical_or( - player_x <= 38, - player_x >= 120 - ), - jnp.logical_or( - jnp.logical_or( - jnp.logical_and(player_x >= 102, player_x <= 110), - jnp.logical_and(player_x >= 45, player_x <= 53) - ), - jnp.logical_and(player_x>=72, player_x<=84) - ) - ) - ) - ), - ), - jnp.logical_or( - jnp.logical_or( - jnp.logical_and( - jnp.logical_and(player_y >= 75, player_y <= 105), - jnp.logical_or( - jnp.logical_or( - jnp.logical_and(player_x >= 102, player_x <= 110), - jnp.logical_and(player_x >= 45, player_x <= 53) - ), - jnp.logical_and(player_x>=72, player_x<=84) - ), - ), - jnp.logical_and( - jnp.logical_and(player_y >= 40, player_y <= 70), - jnp.logical_or( - jnp.logical_or( - jnp.logical_or( - jnp.logical_and(player_x >= 30, player_x <= 53), - jnp.logical_and(player_x >= 102, player_x <= 126) - ), - jnp.logical_and(player_x>=72, player_x<=84) - ), - jnp.logical_or( - player_x <= 20, - player_x >= 135 - ) - ) - ) - ), - jnp.logical_and( - player_y <= 40, - jnp.logical_or( - jnp.logical_or( - jnp.logical_and(player_x >= 30, player_x <= 38), - jnp.logical_and(player_x >= 120, player_x <= 126) - ), - jnp.logical_or( - jnp.logical_or( - jnp.logical_and(player_x <= 20, player_x >= 14), - jnp.logical_and(player_x >= 135, player_x <= 142) - ), - jnp.logical_and(player_x>=72, player_x<=84) - ) - ) - ) - ) - ) - - room_9_walls = jnp.logical_or( - jnp.logical_or( - jnp.logical_or( - jnp.logical_and( - player_y >= 199, - False - ), - jnp.logical_and( - jnp.logical_and(player_y >= 170, player_y <= 199), - jnp.logical_or( - - jnp.logical_and( - player_x >= 30, - player_x <= 126 - ), - - jnp.logical_or( - player_x <= 20, - player_x >= 135 - ) - ) - ) - ), - - jnp.logical_or( - jnp.logical_and( - jnp.logical_and(player_y >= 135, player_y <= 170), - jnp.logical_and( - player_x >= 30, - player_x <= 126 - ) - ), - jnp.logical_and( - jnp.logical_and(player_y >= 105, player_y <= 135), - jnp.logical_and( - player_x >= 14, - player_x <= 142 - ) - ) - ), - ), - jnp.logical_or( - jnp.logical_or( - jnp.logical_and( - jnp.logical_and(player_y >= 75, player_y <= 105), - jnp.logical_or( - jnp.logical_or( - jnp.logical_and(player_x <= 20, player_x >= 14), - jnp.logical_and(player_x >= 135, player_x <= 142) - ), - jnp.logical_and(player_x>=edge_left, player_x<=edge_right) - ), - ), - jnp.logical_and( - jnp.logical_and(player_y >= 40, player_y <= 70), - jnp.logical_or( - jnp.logical_or( - jnp.logical_or( - jnp.logical_and(player_x >= 30, player_x <= 53), - jnp.logical_and(player_x >= 102, player_x <= 126) - ), - jnp.logical_and(player_x>=edge_left, player_x<=edge_right) - ), - jnp.logical_or( - player_x <= 20, - player_x >= 135 - ) - ) - ) - ), - jnp.logical_and( - player_y <= 40, - jnp.logical_or( - jnp.logical_or( - jnp.logical_and(player_x >= 30, player_x <= 38), - jnp.logical_and(player_x >= 120, player_x <= 126) - ), - jnp.logical_or( - jnp.logical_or( - jnp.logical_and(player_x >= 102, player_x <= 110), - jnp.logical_and(player_x >= 45, player_x <= 53) - ), - jnp.logical_and(player_x>=edge_left, player_x<=edge_right) - ) - ) - ) - ) - ) - - room_10_walls = jnp.logical_or( - jnp.logical_or( - jnp.logical_or( - jnp.logical_and( - player_y >= 199, - jnp.logical_or( - jnp.logical_or( - jnp.logical_or( - jnp.logical_and(player_x >= 62, player_x <= 70), - jnp.logical_and(player_x >= 86, player_x <= 94) - ), - jnp.logical_or( - jnp.logical_and(player_x >= 102, player_x <= 110), - jnp.logical_and(player_x >= 45, player_x <= 53) - ) - ), - jnp.logical_or( # the two corridors up - jnp.logical_and(player_x>=30, player_x <= 38), #left corridor - jnp.logical_and(player_x>=120, player_x <= 126) #right corridor - ) - ) - ), - jnp.logical_and( - jnp.logical_and(player_y >= 170, player_y <= 199), - jnp.logical_or( - jnp.logical_or( - jnp.logical_or( - jnp.logical_and(player_x >= 30, player_x <= 53), - jnp.logical_and(player_x >= 102, player_x <= 126) - ), - jnp.logical_or( - jnp.logical_and(player_x >= 62, player_x <= 70), - jnp.logical_and(player_x >= 86, player_x <= 94) - ) - ), - jnp.logical_or( - player_x <= 20, - player_x >= 135 - ) - ) - ) - ), - - jnp.logical_or( - jnp.logical_and( - jnp.logical_and(player_y >= 135, player_y <= 170), - jnp.logical_or( - jnp.logical_or( - jnp.logical_and(player_x >= 62, player_x <= 70), - jnp.logical_and(player_x >= 86, player_x <= 94) - ), - jnp.logical_or( - jnp.logical_and(player_x <= 20, player_x >= 14), - jnp.logical_and(player_x >= 135, player_x <= 142) - ) - ) - ), - jnp.logical_and( - jnp.logical_and(player_y >= 105, player_y <= 135), - jnp.logical_or( - jnp.logical_and(player_x >=14, player_x <= 70), - jnp.logical_and(player_x >= 86, player_x <= 142) - ) - ) - ), - ), - jnp.logical_or( - jnp.logical_or( - jnp.logical_and( - jnp.logical_and(player_y >= 75, player_y <= 105), - jnp.logical_or( - jnp.logical_and(player_x >= 38, player_x <= 44), - jnp.logical_and(player_x >= 112, player_x <= 118) - ), - ), - jnp.logical_and( - player_y >= 40, - player_y <= 70 - ) - ), - jnp.logical_and( - player_y <= 40, - False - ) - ) - ) - - room_11_walls = jnp.logical_or( - jnp.logical_or( - jnp.logical_or( - jnp.logical_and( - player_y >= 199, - jnp.logical_or( - jnp.logical_or( - jnp.logical_and(player_x >= 30, player_x <= 38), - jnp.logical_and(player_x >= 120, player_x <= 126) - ), - jnp.logical_or( - jnp.logical_or( - jnp.logical_and(player_x <= 20, player_x >= 14), - jnp.logical_and(player_x >= 135, player_x <= 142) - ), - jnp.logical_and(player_x>=72, player_x<=84) - ) - ) - ), - jnp.logical_and( - jnp.logical_and(player_y >= 170, player_y <= 199), - jnp.logical_or( - jnp.logical_or( - jnp.logical_or( - jnp.logical_and(player_x >= 30, player_x <= 60), - jnp.logical_and(player_x >= edge_right, player_x <= 126) - ), - jnp.logical_and(player_x>=72, player_x<=84) - ), - jnp.logical_or( - player_x <= 20, - player_x >= 135 - ) - ) - ) - ), - - jnp.logical_or( - jnp.logical_and( - jnp.logical_and(player_y >= 135, player_y <= 170), - jnp.logical_and(player_x>=72, player_x<=84) - ), - jnp.logical_and( - jnp.logical_and(player_y >= 105, player_y <= 135), - jnp.logical_or( - jnp.logical_or( - jnp.logical_and(player_x>=16, player_x<=30), - jnp.logical_and(player_x>=126, player_x<=140) - ), - jnp.logical_and(player_x>=38, player_x<=118) - ) - ) - ), - ), - jnp.logical_or( - jnp.logical_or( - jnp.logical_and( - jnp.logical_and(player_y >= 75, player_y <= 105), - jnp.logical_or( - jnp.logical_or( - jnp.logical_or( - jnp.logical_and(player_x>=16, player_x<=30), - jnp.logical_and(player_x>=104, player_x<=118) - ), - jnp.logical_or( - jnp.logical_and(player_x>=38, player_x<=53), - jnp.logical_and(player_x>=126, player_x<=140) - ), - ), - jnp.logical_and(player_x>=72, player_x<=84) - ) - ), - jnp.logical_and( - jnp.logical_and(player_y >= 40, player_y <= 70), - jnp.logical_or( - jnp.logical_or( - jnp.logical_or( - player_x<=30, - player_x>=126 - ), - jnp.logical_or( - jnp.logical_and(player_x>=38, player_x<=53), - jnp.logical_and(player_x>=104, player_x<=118) - ), - ), - jnp.logical_and(player_x>=edge_left, player_x<=edge_right) - ) - ) - ), - jnp.logical_and( - player_y <= 40, - jnp.logical_and(player_x>=edge_left, player_x<=edge_right) - ) - ) - ) - - - ### end extra maze walls - - room_7_clear = jnp.logical_or( - jnp.logical_not(room == 6), - jnp.logical_and( - collision_lower_wall_path, - room_7_walls - ) - ) - - room_8_clear = jnp.logical_or( - jnp.logical_not(room == 7), - room_8_walls - ) - - room_9_clear = jnp.logical_or( - jnp.logical_not(room == 8), - room_9_walls - ) - - room_10_clear = jnp.logical_or( - jnp.logical_not(room == 9), - room_10_walls - ) - - room_11_clear = jnp.logical_or( - jnp.logical_not(room == 10), - room_11_walls - ) - - room_12_clear = jnp.logical_or( - jnp.logical_not(room == 11), #either it is not room 12 or - jnp.logical_and( #walls of the room are not being crossed - jnp.logical_and( - collision_left_wall, - collision_right_wall - ), - jnp.logical_and( - collision_upper_wall_path, - collision_lower_wall_path - ) - ) - ) - - room_13_clear = jnp.logical_or( - jnp.logical_not(room == 12), #either it is not room 13 or - jnp.logical_and( #walls of the room are not being crossed - jnp.logical_and( - collision_left_wall, - collision_right_wall - ), - jnp.logical_and( - collision_upper_wall_path, - collision_lower_wall_path - ) - ) - ) - - room_14_clear = jnp.logical_or( - jnp.logical_not(room == 13), #either it is not room 14 or - jnp.logical_and( #walls of the room are not being crossed - jnp.logical_and( - collision_left_wall, - collision_right_wall - ), - jnp.logical_and( - collision_upper_wall, - collision_lower_wall_path - ) - ) - ) #Castle Collisions castle_tower_left = self.consts.CASTLE_TOWER_LEFT_X @@ -1045,23 +391,7 @@ def is_tile_walkable(tileset: jnp.ndarray, Pos_x: int, Pos_y: int) -> bool: jnp.logical_and(castle_walls, castle_gate) ) - room_1_and_2 = jnp.logical_and(room_1_clear, room_2_clear) - room_3_and_4 = jnp.logical_and(room_3_clear, room_4_clear) - room_1_to_4 = jnp.logical_and(room_1_and_2, room_3_and_4) - room_5_and_6 = jnp.logical_and(room_5_clear, room_6_clear) - room_7_and_8 = jnp.logical_and(room_7_clear, room_8_clear) - room_5_to_8 = jnp.logical_and(room_5_and_6, room_7_and_8) - room_9_and_10 = jnp.logical_and(room_9_clear, room_10_clear) - room_11_and_12= jnp.logical_and(room_11_clear, room_12_clear) - room_9_to_12 = jnp.logical_and(room_9_and_10, room_11_and_12) - room_13_and_14 = jnp.logical_and(room_13_clear, room_14_clear) - - room_1_to_8 = jnp.logical_and(room_1_to_4,room_5_to_8) - room_9_to_14 = jnp.logical_and(room_9_to_12, room_13_and_14) - - base_rooms = jnp.logical_and(room_1_to_8, room_9_to_14) - #walls_detected = jnp.logical_and(base_rooms, castle_collision ) walls_detected = jnp.logical_and(current_Room_is_walkable, castle_collision ) #Check for Bridge negating wall From d62c486cdac76b3bd847b3666c3043ffc4960904 Mon Sep 17 00:00:00 2001 From: LucyLMM Date: Sun, 29 Mar 2026 21:09:12 +0200 Subject: [PATCH 071/102] All Mod Assets created and sorted --- .../adventure/sprites/Dragon_red_attack.npy | Bin 0 -> 1536 bytes .../adventure/sprites/Dragon_red_dead.npy | Bin 0 -> 1352 bytes .../adventure/sprites/Dragon_red_neutral.npy | Bin 0 -> 1408 bytes .../mods/adventure/sprites/Key_white.npy | Bin 0 -> 320 bytes .../adventure/sprites/Player_BabyBlue.npy | Bin 0 -> 256 bytes .../adventure/sprites/Player_LightBlue.npy | Bin 0 -> 256 bytes .../mods/adventure/sprites/Player_Orange.npy | Bin 0 -> 256 bytes .../adventure/sprites/Player_Turquoise.npy | Bin 0 -> 256 bytes .../mods/adventure/sprites/Player_White.npy | Bin 0 -> 256 bytes .../adventure/sprites/Player_inverted.npy | Bin 0 -> 256 bytes .../mods/adventure/{ => sprites}/Room_15.npy | Bin .../mods/adventure/{ => sprites}/Room_16.npy | Bin .../mods/adventure/{ => sprites}/Room_17.npy | Bin .../mods/adventure/{ => sprites}/Room_18.npy | Bin .../mods/adventure/{ => sprites}/Room_20.npy | Bin .../mods/adventure/{ => sprites}/Room_21.npy | Bin .../mods/adventure/{ => sprites}/Room_22.npy | Bin .../mods/adventure/{ => sprites}/Room_23.npy | Bin .../mods/adventure/{ => sprites}/Room_24.npy | Bin .../mods/adventure/{ => sprites}/Room_25.npy | Bin .../mods/adventure/{ => sprites}/Room_26.npy | Bin .../mods/adventure/{ => sprites}/Room_27.npy | Bin 160128 -> 160128 bytes .../mods/adventure/{ => sprites}/Room_28.npy | Bin 160128 -> 160128 bytes .../mods/adventure/{ => sprites}/Room_29.npy | Bin 160128 -> 160128 bytes .../mods/adventure/{ => sprites}/Room_30.npy | Bin 160128 -> 160128 bytes .../games/mods/adventure/sprites/Room_31.npy | Bin 0 -> 160128 bytes .../games/mods/adventure/sprites/bat_1.npy | Bin 0 -> 512 bytes .../games/mods/adventure/sprites/bat_2.npy | Bin 0 -> 512 bytes 28 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/jaxatari/games/mods/adventure/sprites/Dragon_red_attack.npy create mode 100644 src/jaxatari/games/mods/adventure/sprites/Dragon_red_dead.npy create mode 100644 src/jaxatari/games/mods/adventure/sprites/Dragon_red_neutral.npy create mode 100644 src/jaxatari/games/mods/adventure/sprites/Key_white.npy create mode 100644 src/jaxatari/games/mods/adventure/sprites/Player_BabyBlue.npy create mode 100644 src/jaxatari/games/mods/adventure/sprites/Player_LightBlue.npy create mode 100644 src/jaxatari/games/mods/adventure/sprites/Player_Orange.npy create mode 100644 src/jaxatari/games/mods/adventure/sprites/Player_Turquoise.npy create mode 100644 src/jaxatari/games/mods/adventure/sprites/Player_White.npy create mode 100644 src/jaxatari/games/mods/adventure/sprites/Player_inverted.npy rename src/jaxatari/games/mods/adventure/{ => sprites}/Room_15.npy (100%) rename src/jaxatari/games/mods/adventure/{ => sprites}/Room_16.npy (100%) rename src/jaxatari/games/mods/adventure/{ => sprites}/Room_17.npy (100%) rename src/jaxatari/games/mods/adventure/{ => sprites}/Room_18.npy (100%) rename src/jaxatari/games/mods/adventure/{ => sprites}/Room_20.npy (100%) rename src/jaxatari/games/mods/adventure/{ => sprites}/Room_21.npy (100%) rename src/jaxatari/games/mods/adventure/{ => sprites}/Room_22.npy (100%) rename src/jaxatari/games/mods/adventure/{ => sprites}/Room_23.npy (100%) rename src/jaxatari/games/mods/adventure/{ => sprites}/Room_24.npy (100%) rename src/jaxatari/games/mods/adventure/{ => sprites}/Room_25.npy (100%) rename src/jaxatari/games/mods/adventure/{ => sprites}/Room_26.npy (100%) rename src/jaxatari/games/mods/adventure/{ => sprites}/Room_27.npy (82%) rename src/jaxatari/games/mods/adventure/{ => sprites}/Room_28.npy (94%) rename src/jaxatari/games/mods/adventure/{ => sprites}/Room_29.npy (99%) rename src/jaxatari/games/mods/adventure/{ => sprites}/Room_30.npy (89%) create mode 100644 src/jaxatari/games/mods/adventure/sprites/Room_31.npy create mode 100644 src/jaxatari/games/mods/adventure/sprites/bat_1.npy create mode 100644 src/jaxatari/games/mods/adventure/sprites/bat_2.npy diff --git a/src/jaxatari/games/mods/adventure/sprites/Dragon_red_attack.npy b/src/jaxatari/games/mods/adventure/sprites/Dragon_red_attack.npy new file mode 100644 index 0000000000000000000000000000000000000000..46cb8dee251d642ffc3aa55a84b0fb0032ef5042 GIT binary patch literal 1536 zcmdszF%H5o5Cl!jE8H2RG)O5B51<3lP*91NhFt`nD7w=c>|nVq&pnS1f)*|GAqUmdcuulrG&CU%sw_iE0))}im>nSbC-|A4n^!}SdBLhE;f e&sAo)*IIMVgytQ1Ts7xjYuVEt_f5H&iSaL7Fj2w) literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/mods/adventure/sprites/Dragon_red_dead.npy b/src/jaxatari/games/mods/adventure/sprites/Dragon_red_dead.npy new file mode 100644 index 0000000000000000000000000000000000000000..759958ad114b836ac396c9f4e67049b00fa65901 GIT binary patch literal 1352 zcmdUrF%H5o3`N7rDY6BmEQl^}05%W{0~4xf5CftpEiAw(I31^fdia%PxfE3_M5?~? z|BIdUu~^NQ>z=uotII;Mjc#h)?L2bcx?LX2m>xHI%mVqd^iYJ#FZSsvRQtg=@pj^E zGW7OtJFUJ^*3+05eM(eY|IB=P8{XB#Ag3R}>-xtCUozNh%6n=#d7Qya&Pq@2n|grb zioV>_YH(6HD>LlBVTc8XbDI8|p?=yNexI%k?#flp;u){ye4e3hV=#+&)bb4cHU=}H SS|4Okjln#w;7Pg9Ys%g+Y9p!u literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/mods/adventure/sprites/Dragon_red_neutral.npy b/src/jaxatari/games/mods/adventure/sprites/Dragon_red_neutral.npy new file mode 100644 index 0000000000000000000000000000000000000000..6c82fbca5e5468556305cb7fe1652c02980c12dd GIT binary patch literal 1408 zcmc(aF$%&!5JlJ4Q*5^iTPUOu4`8R*SXfCgD;8oTQ5*FXp3c)~M))uc<1PfnK=||j z`F z*7x>iTRmN)JP%`@^eX5b#W)yL?m+%Y(QnK7ceIOpIpZv@yu)+MDNa4=ps(q#IKP{A zMvO}akNd+*B`!1WQ(Sgq=YeTEIr}%~|Ad*}57{>qd*v?V&=luA%$m|3o@+jKmSo)X Qy)<)1v&NChE_{l=0BDa~&Hw-a literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/mods/adventure/sprites/Key_white.npy b/src/jaxatari/games/mods/adventure/sprites/Key_white.npy new file mode 100644 index 0000000000000000000000000000000000000000..354e7a2af293873007f2e2dd5b88dbc6c71d9d12 GIT binary patch literal 320 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1JQ);NLqoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I$dItms#3MQI53bhL40WJnC;6D<;BF%s#jgtw|hf@+Lfh-SWgJ=*y*9Q{= IOQOjG0FL34X#fBK literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/mods/adventure/sprites/Player_BabyBlue.npy b/src/jaxatari/games/mods/adventure/sprites/Player_BabyBlue.npy new file mode 100644 index 0000000000000000000000000000000000000000..8d06b6bba46d8e280ba59932bd4db3ee4ee7ce0e GIT binary patch literal 256 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1JQ);NLqoAIaUsO_*m=~X4l#&V(cT3DEP6dh= fXCxM+0{I#iItnI0q^YA&t3V#$N=o|we;_dcgxqu= literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/mods/adventure/sprites/Player_LightBlue.npy b/src/jaxatari/games/mods/adventure/sprites/Player_LightBlue.npy new file mode 100644 index 0000000000000000000000000000000000000000..dcb96d542fd678312144bf72eb5f24ef6f7bad9d GIT binary patch literal 256 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1JQ);NLqoAIaUsO_*m=~X4l#&V(cT3DEP6dh= fXCxM+0{I#iItnI0q^YA&t3V#$lDqWq|3G2@@!WOa literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/mods/adventure/sprites/Player_Orange.npy b/src/jaxatari/games/mods/adventure/sprites/Player_Orange.npy new file mode 100644 index 0000000000000000000000000000000000000000..1909708f6c85edbaea845304e5c7bbf6c8f40772 GIT binary patch literal 256 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1JQ);NLqoAIaUsO_*m=~X4l#&V(cT3DEP6dh= fXCxM+0{I#iItnI0q^YA&t3V#$`rWMke;_dc-z{+8 literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/mods/adventure/sprites/Player_Turquoise.npy b/src/jaxatari/games/mods/adventure/sprites/Player_Turquoise.npy new file mode 100644 index 0000000000000000000000000000000000000000..aac3ec21e5e2d391de89066ee0a79124d11a36f1 GIT binary patch literal 256 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1JQ);NLqoAIaUsO_*m=~X4l#&V(cT3DEP6dh= fXCxM+0{I#iItnI0q^YA&t3V#$V*0!9|3G2@P&{*A literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/mods/adventure/sprites/Player_White.npy b/src/jaxatari/games/mods/adventure/sprites/Player_White.npy new file mode 100644 index 0000000000000000000000000000000000000000..840391301b9b64b3a2e8295ac812a35017a53dce GIT binary patch literal 256 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1JQ);NLqoAIaUsO_*m=~X4l#&V(cT3DEP6dh= cXCxM+0{I#iItnI0q^YA&t3V#$`ai$`0FY9fUjP6A literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/mods/adventure/sprites/Player_inverted.npy b/src/jaxatari/games/mods/adventure/sprites/Player_inverted.npy new file mode 100644 index 0000000000000000000000000000000000000000..5cbc9b86812aaf6024dc755b4e2b4f19d697b6fd GIT binary patch literal 256 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1JQ);NLqoAIaUsO_*m=~X4l#&V(cT3DEP6dh= fXCxM+0{I#iItnI0q^YA&t3V#$nm&E{|AE8+sJwJv literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/mods/adventure/Room_15.npy b/src/jaxatari/games/mods/adventure/sprites/Room_15.npy similarity index 100% rename from src/jaxatari/games/mods/adventure/Room_15.npy rename to src/jaxatari/games/mods/adventure/sprites/Room_15.npy diff --git a/src/jaxatari/games/mods/adventure/Room_16.npy b/src/jaxatari/games/mods/adventure/sprites/Room_16.npy similarity index 100% rename from src/jaxatari/games/mods/adventure/Room_16.npy rename to src/jaxatari/games/mods/adventure/sprites/Room_16.npy diff --git a/src/jaxatari/games/mods/adventure/Room_17.npy b/src/jaxatari/games/mods/adventure/sprites/Room_17.npy similarity index 100% rename from src/jaxatari/games/mods/adventure/Room_17.npy rename to src/jaxatari/games/mods/adventure/sprites/Room_17.npy diff --git a/src/jaxatari/games/mods/adventure/Room_18.npy b/src/jaxatari/games/mods/adventure/sprites/Room_18.npy similarity index 100% rename from src/jaxatari/games/mods/adventure/Room_18.npy rename to src/jaxatari/games/mods/adventure/sprites/Room_18.npy diff --git a/src/jaxatari/games/mods/adventure/Room_20.npy b/src/jaxatari/games/mods/adventure/sprites/Room_20.npy similarity index 100% rename from src/jaxatari/games/mods/adventure/Room_20.npy rename to src/jaxatari/games/mods/adventure/sprites/Room_20.npy diff --git a/src/jaxatari/games/mods/adventure/Room_21.npy b/src/jaxatari/games/mods/adventure/sprites/Room_21.npy similarity index 100% rename from src/jaxatari/games/mods/adventure/Room_21.npy rename to src/jaxatari/games/mods/adventure/sprites/Room_21.npy diff --git a/src/jaxatari/games/mods/adventure/Room_22.npy b/src/jaxatari/games/mods/adventure/sprites/Room_22.npy similarity index 100% rename from src/jaxatari/games/mods/adventure/Room_22.npy rename to src/jaxatari/games/mods/adventure/sprites/Room_22.npy diff --git a/src/jaxatari/games/mods/adventure/Room_23.npy b/src/jaxatari/games/mods/adventure/sprites/Room_23.npy similarity index 100% rename from src/jaxatari/games/mods/adventure/Room_23.npy rename to src/jaxatari/games/mods/adventure/sprites/Room_23.npy diff --git a/src/jaxatari/games/mods/adventure/Room_24.npy b/src/jaxatari/games/mods/adventure/sprites/Room_24.npy similarity index 100% rename from src/jaxatari/games/mods/adventure/Room_24.npy rename to src/jaxatari/games/mods/adventure/sprites/Room_24.npy diff --git a/src/jaxatari/games/mods/adventure/Room_25.npy b/src/jaxatari/games/mods/adventure/sprites/Room_25.npy similarity index 100% rename from src/jaxatari/games/mods/adventure/Room_25.npy rename to src/jaxatari/games/mods/adventure/sprites/Room_25.npy diff --git a/src/jaxatari/games/mods/adventure/Room_26.npy b/src/jaxatari/games/mods/adventure/sprites/Room_26.npy similarity index 100% rename from src/jaxatari/games/mods/adventure/Room_26.npy rename to src/jaxatari/games/mods/adventure/sprites/Room_26.npy diff --git a/src/jaxatari/games/mods/adventure/Room_27.npy b/src/jaxatari/games/mods/adventure/sprites/Room_27.npy similarity index 82% rename from src/jaxatari/games/mods/adventure/Room_27.npy rename to src/jaxatari/games/mods/adventure/sprites/Room_27.npy index de4318bfe25b1a2fa1cde99f2a04e7c272e95691..ca16aff50dd71d7455317a233627c98ef550e88e 100644 GIT binary patch literal 160128 zcmeI5F^*kT5JW#ItC(y+c7PEOumCa;2>}tZ@E`(&tr;KzB9=hl#S#pD8|VWn)w|!< z2WgO?RJXgj&YK9CzrXtC%dfwE@ABK__uChD58vP4etvWN$FI+BpWfX5@bdnb`{zG@ z_wxS5-SO|gc>dGF-J5^^@ZZ|9|{;T&( z=aav!?|xs(m+I6{`ab#7`Q&fw?R@k;>6D-RZGH8A>3s6Hb?S%alRwp0&!_!Y@0ZRe ze_P-EzLYQ3sh{+H@~893-`3mt=zY>DKl$7G>iyFB)HFkQ=aav!xAW2aq*H$KxAoQgrSr+()~O$wPySS2J)ibpyr z`%=DCr+(7+$)C}m(C}DTc>_#KKWC9^?cf&_FJuA`~KIyAN5E3 zw{_ZYwNClnZ~pJs={|Jdwod!4)+xXH$zPKJ`OEmCZs@*ko%UO;Q-1f$_@w)`_0|2+ ze9BM$wtnsVQGVLLtr~Ovzl;8a_KIy(~eRY2{pYoHxtzY|ol%Mu*>$Kl$o$|Y% zzyF#H$X~`6bwl@6pa1{bbl1zNy}$c?%{PBv#7A4VpShpi@6+as-rxPc z=9|AS;-jtG&)m=M_i6J*@9%zJ^UdEE@zK`pXYObB`?UF@_jkXq`R4D7_-O0)GxxLm zecF7{`@7%QeDn83e6)4@nfuxOK5f3}{oU_tzWMtiKH9qd%>C?spEh6g{_giR-~4?M zA8p-!=6-g+Pn$1#fA{;EZ~nfBkG5_ob z-~GPko4+sOqpjP|+|Ta!Y4b(z?|xtN&EFUC(bnx}?q~P=wE3dXkqFOBqW1@+W@@KdD## zHx!cXdzKlw`;O8oLCe+fUS zSN`NLWhn8>pZq2Kq+a=xzm%cGFMslv@RNGwPyQx`h!4`Iw+}7#)BEZf-)TSOZ|l@Q z%_qNl#uwc$?T7qry`7KVSI_t)KIp#WZ|muPjb-tIOZSDDg3Q z4~_il@;5O=d`w>X>#{}N9D3Rh`P({Wr1|7m?=qV9L;ki-e9(OItIOZS5b-g24~_il z@;5O=d`w>X>#{}N9D3Rh`P({Wr1|7m?=qV9L;ki-e9(OItIOZS5b-g24~_il@;5O= zd`w>X>#{}N9D3Rh`P({Wr1|7m?=qV9L;ki-e9(OItIOZS5b-g24~_il@;5O=d`w>X z>#{}N9D3Rh`P({Wr1|7m?=qV9L;ki-e9(OItIOZS5b-g24~_il@;5O=d`w>X>#{}N z9D3Rh`P({Wr1|7m?=qV9L;ki-e9(OItIOZS5b-g24~_il@;5O=d`w>X>#{}N9D3Rh z`P({Wr1|7m?=qV9L;ki-e9(OItIOZS5b-g24~_il@;5O=d`w>X>#{}N9D3Rh`P({W zr1|7m?=qV9Lw?fR{jQ$h&iA&zzk5Hs=aawg@8|Ts@@GFOLy2GhJ8mp}PS_({F;Cx0nJiC_NYFX1Qk%AfqD z3?+W~lfQ(Y)GL4Tmok+2kP)G z8TK>xv-^D}HqOv?zpwe`@9PZ4rWy7#_p|$bCN|E{cE7Lr=I`qa#-kP)G8Si>Om&@hRA8#N7G9UvoAOkWW z12P~3G9UvoAOkWW12P~3G9UvoAOkWW12P~3G9UvoAOkWW12P~3G9UvoAOkWW12P~3 zG9UvoAOkWW12P~3G9UvoAOkWW12P~3G9UvoAOkWW12P~3G9UvoAOkWW12S+H1OEak C<2BU) literal 160128 zcmeI5F>Ym55JW#It8iuz6EFw}SO6J_gn$T*7$XA2AR9=4h$Rqsu>@w`2Ksd-(Pf{ zlAnM6`rv8$N#6c1-f8xs(HrD%>*;>vPj$+lzMuM6@0ZRee_N;f(|q!$`s(?#|LXnH z`Q&fwyWf}cr8@PKzEA#iKKa{vJ0HDII^`#STVK6jI-mS)o%*5qL-1l{ONr1xAk^DdY^R4PyV*PdcSl&`P(}6L-Wa>>Z|9|{;T&(=aav! z?|xs(m+I6{`ab#7`Q&fw?R@k;>6D-RZGH8A>3s6Hb?S%alRwp0&!_!Y@0ZRee_P-E zzLYQ3sh{+H@~893-`3mt=zY>DKl$7G>iyFB)HFkQ=aav!xAW2aq*H$KxAoQgrSr+()~O$wPySS2J)icc{Z{MOzW=rFNBzr~Ovzl;8a_KIy(~eRY2{ zpYoHxtzY|ol%Mu*>$Kl$o$|Y%zyF#H$X~`6bwl@U>$Kl$o$|Y1#wXpkt*`En=2L$1 zxAkk^kMh(0ZJqX8ty6yY^Y>qq0r|`LqHgHEZJqX8ty6yY%lM@Gw)NHh(R|8J{oa~zx(<7ugQS?WqeULbloa~zx!o;(tX?d>i%dx+gr~Kq^>({;?<){7II_N-Ozp2=l{Pp-M6jV&)m=M_i6J*@9%zJ^UdEE@zK`pXYObB`?UF@_jkXq z`R4D7_-O0)GxxLmecF7{`@7%QeDn83e6)4@nfuxOK5f3}{oU_tzWMtiKH9qd%>C?s zpEh6g{_giR-~4?MA8p-!=6-g+Pn$1#fA{;EZ~nfBkG5_ob-~GPko4+sOqpjP|+|Ta!Y4b(z?|xtN&EFUC(bnx}?q~P=wE3d< zcfYUs=I@L6XzTVf_p|$b+I-RbyWiJ*^Y=x3v~~NL``P_IZNBLJ-S2C@`THV1+PeMB z{p^09HedAq?)Np{{CyE0ZQXw6es;f4n=g8Q_xqY}{=SHhwr)RjKfB+j%@@7D`+dzf ze_zB$TeqLNpWW}%=8N9n{l1is?vv`P=coJc?%%zi-SfTaeD2=Q?)l`e`{(Hx!cXdz zKlw`;O8oLCe+fUSSN`NLWhn8>pZq2Kq+a=xzm%cGFMslv@RNGwPySMd62JV(U&2r7 zl|T7Q8A|-}Cw~b)saO8wFJ&n4%b)xu{G?v_lfQ`};)C?*?L$lb^uBt=ciIp6+dB16 z^U1HC@kRGb`yqc@Z|9@;)iXYc54tb;+j_bm`PDPN=zhdU>ZkWpJ>8G|>hd=+N_hd=+M0`x%LnFVs z{7noIACp)9x@=K5ho1IB{hd=+M0`x%LnFVs{7noI zACp)9x@=K5ho1IB{hd=+M0`x%LnFVs{7noIACp)9 zx@=K5ho1IB{hd=+M0`x%LnFVs{7noIACp)9x@=K5 zho1IB{hd=+M0`x%LnFVs{7noIACp)9x@=K5ho1IB z{hd=+M0`x%LnFVs{7noIACp)9x@=K5ho1IB{+P~w+A`Ahgoz49l2DMN{0 z{^T#=C-uso{G|*fe)*HXgrC$afAW_yl=$UO{t|vtul&hh%248$Klw}eNxkwXeJ8mp}PS_({F;Cx0nJ ziC_NYFX1Qk%AfqD3?+W~lfQ(Y)GL4Tmok+2@+W^O zLy2Gh=AymS8XoXrGH(ML#zO z$w<8V-F>U-1VsMx^DjU9;;XlAe!2Pe?&Lzxw{-yC*;1zxwZYKKSVUN4JkZe)X>p-+grZ`|ZE~=k1%Dn+N}x zfegri49I{C$bbyUfDFih49I{C$bbyUfDFih49I{C$bbyUfDFih49I{C$bbyUfDFih z49I{C$bbyUfDFih49I{C$bbyUfDFih49I{C$bbyUfDFih49I{C$bbyU!2gwjzy5gd z!9Qjo12P~3G9UvoAOkWW12P~3G9UvoAOkWW12P~3G9UvoAOkWW12P~3G9UvoAOkWW z12P~3G9UvoAOkXR%D~H)FCY9jZ%%31Y0v#ql= z8_uTU>h!xAbH-*=XLQP0^*ghzvo#yersC@KyBTxFW>jZ%%31Y0v#ql=8_uTU>h!xA zbH-*=XLQP0^*ghzvo#yersC@KyBTxFW>jZ%%31Y0v#ql=8_uTU>h!xAbH-*=XLQP0 z^*ghzvo#yersC@KyBTxFW>jZ%%31Y0v#ql=8_uTU>h!xAbH-*=XLQP0^*ghzvo#ye zrsC@KyBTxFW>jZ%%31Y0v#ql=8_uTU>h!xAbH-*=XLQP0^*ghzvo#yersC@KyBTxF zW>jZ%%31Y0v#ql=8_uTU>h!xAbH-*=XLQP0^*ghzvo#yersC@KyBTxFW>jZ%%31Y0 zv#ql=8_uTU>h!xAbH-*=XLQP0^*ghzvo#yersC@KyBTxFW>jZ%%31Y0v#ql=8_uTU z>h!xAzdqyB9Jl_C_~`mh@9)0P`PsiKG|fkPzx>Sd)6GB4M|ywPzw@*Fruj(km!DaF zy7{O1Nbm3ZcYc=NG#}~x@-xd%H~%yr>HS^*&d>6j<|DmderEaU=AY&xy}#?<`B{F` ze5Ciw&n!RP{L_4-_jmm}Kg(~LkMw@|ndPUOf0~c<{;q%LXZcO@k=`#qv;1`PPxF!9 z-}UeOEWc?!();CSmY;6^X+F~XyZ)V@E@s2BfY=t-}za7 z(|n}&%g-!7-Tc#hr1y9IJ3q^Bnve8;`I+UXn}3>*^!~1Y=V$p%^O4>!KePOF^H1}U z-rx1_{4Bp|KGOT&bbctGH(jTG$REv<-rZ00>aYL%EvNHI^O4>^ouBu6e5d(H@3;S6 z|I_)U`AF}d&d>Wj{?mM<_uGH3|LOeFe5ChJ=jZ(%|7kwb`|ZEi|8#z7KGOTA^Yea> z|1=-z{r2DMe>%T3AL;$m`FX#`f0~cEikM#cO{Jh`eKg~yazy0_6pUyAM zM|%Hse%|l#pXMXI-~N03Pv@8BBfWn*KkxVWPxF!9Z~wjir}Inmk={R@pZ9zGr};?l zxBp)M)A^HN}sr1wwf=lvf4X+F~X?Z4Ombbe_*()*|L z^L~&2G#}~x_TTG&I=?g@>HX9BdB4Yhnve8;`|tHXonM-d^#1Amyx-$L%}08_{rCEx z&M(bJdjE8O-tY0B<|Dn|{(JpT=a=Rqy?;8t^nJ>Ybb4QUp7#IW_3iy^_xGmryS<<7 z{^alV|Nk|ekNnO4{nga}_I|eeqkgZhZ|`TjzpL{_@7vzbc7N3G)%ETDZ1;C{zUY11 z``PY~`n|foy`Sy=uFe;|Z+k!6{ZYSH*SGhx-QU&uqW5j@XS+Y@_v-rgezyC&I$!j@ z?fq=`NBv%1-`>x5e^=*=-nYGkNUm3zP+FA{;tj! zy>ELz+x=0$SJ$`qv)$j-`J(r2?`OL|>i6pU_I|eeyEN_ecF+UEki%v_HDP zT_^s@e|nzwclBw1bbq@}{gMClJnir5)BfoGcAfeo|LJ+!-_@u6(f#c@^+*2G^R&OK zPy3_$+jZ)X{HNz>e^;OONB6hu)F1gz&(r>{KJAb0Z`Y|m@}Hik{at<9AKl-sQ-9eK${{&t=EBme1n+TYcu{n7pH zI`v2X)AO{yt55r*``dNukNl_SX@6Ir_DA=(>(n3lPtVi-u0HLL?r+zrKk}cRr~O@h z+8^EDu2X;HKRr+TyZW?0y1!kg{>XoNp7wY3X@7KoyH5R)|MWcV@9NY3=>B${`Xm48 zdD`FAr~T3W?K<^G{?qfczpGFCqx;)+>W}=V=V^aepY})hx9ij&`A^T&{;odlkM3{R zsXy|co~Qj?ecB)0->y@C3Q1U)u;W@{p~vSNB-0Ew7;uQ`=k5Yb?T4&r{`&ZSD*Gr_qXfRANfzu z)BdhL?T_wn*Qr19pPr}vU47ag-QTWLf8;+sPy4(2v_HDPU8nxYe|nzwclEBn>HGBl zv`+r%KFxRa>HGBl>GyT-(|lUro-g_9>eNqnKh1aV(|lS_`=kA&lYg2|>(lS+-lzGr zPW{k*n(yk<_v!u9@9W;D`Lw=0U-H-0sh{qCn(yAH`Lv$)NBc=9|1_W0r{CATPxEP= z`l0(Y-_@t@)BC62*S$~kX?=UXX$ zL-%REt54sj_fNmCd!Odh`u2RuUstDoy8CIqd!OdhdfFfDC!PG$d|ID=U-v%Er*-Ow z?$dl%pT1A;pMGEWKFz1~?fH_wu1@`Q_tSj$KFz1~v_INUI{Byhv_Ad5?tPk1>(me3 zr}?g)zJGIb^WYydkO3Kx0U3}18IS=PkO3Kx0U3}18IS=PkO3Kx0U3}18IS=PkO3Kx z0U3}18IS=PkO3Kx0U3}18IS=PkO3Kx0U3}18IS=PkO3Kx0U3}18IS=PkO3Kx0U3}1 Y8IS=PkO3Kx0U3}18IS=P_^%lF8_Xs>w*UYD literal 160128 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 Y8IS=PkO3Kx0U3}18IS=P_^%lF8@#R|MgRZ+ diff --git a/src/jaxatari/games/mods/adventure/Room_29.npy b/src/jaxatari/games/mods/adventure/sprites/Room_29.npy similarity index 99% rename from src/jaxatari/games/mods/adventure/Room_29.npy rename to src/jaxatari/games/mods/adventure/sprites/Room_29.npy index af5bc5b8bb3696d6e541e612914485cb17676c25..5f41093c0bdbedab508fccd70364db6baa038889 100644 GIT binary patch delta 1970 zcmeH{u?fRK3`LO}<5V8uAf2Z$7rLAnsCJ zBfft5{+F;eSexu81at$IYHIzdvk~_L07rLAnsCJ zBfft5{+F;eSexu81at$IYHIzdvk~_L0p{xPKe=sUY-2j>7ePHp1AB>X^v>zB{ z(jXkR0~2im<75Fya(*z%9bTcaU~@y91LNckKN>b4xURqmBoaWxD2vE2n4I8oV7h`C z;{#w2KG;;U02GuXjs^$7_6bZ(9~eg(Ir)O`1YqI#VDf>)1)Bx(3mB&h0E1yuNdu_J UY#4l^i%J+bHZ(YIoY24y0FEQ`nE(I) delta 2218 zcmZp8%-QgmbAijGe23`?`iy%fFK}0xRN^o>p{xPKe=sUY-2j>7ePHp1AB>X^v>zB{ z(jXkR0~2im<75Fya(*z%9bTcaU~@y91LNckKN>b4xURqmBoaWxD2vE2n4I8oV7h`C z;{#w2KG;;U02GuXjs^$7_6bZ(9~eg(Ir)O`1YqI#VDf>)1)Bx(3mB&h0E1yuNdu_J UY#4l^i%J+bHZ(YIoY24y0FEQ`nE(I) diff --git a/src/jaxatari/games/mods/adventure/sprites/Room_31.npy b/src/jaxatari/games/mods/adventure/sprites/Room_31.npy new file mode 100644 index 0000000000000000000000000000000000000000..673d889ab009bd076c0e47ff5a914195fbb76e8c GIT binary patch literal 160128 zcmeI*yN=#O6ae6#mZ#WmK}taoP*5Y321G+ag(9+u0ui(U8sI4?(xuL8@MKG-IAS!i z*B;yR`}Reej6FVc@yzG5TSUq~Uw`}6H{ZQ?`Q!5E?TfotKiuDbeslZR?@w=^+}!^7 z^8UB`=f8aa^8UqLYX9>2&#&&@wZHo5`LB2H?mzhW(~q9qJpJt5U!Q#VUzPSARke8wOn&PR8;Y6woIn1C?C^JPBQ0~pkiGPrKmJ-7 z9P6*^_rE1vwt6q)?&F&o%Ke} z?NRsjf2`dZw?E@8@9|?c;#psw>uZmGW9lvMjkUG^HpUp4li!BMcgF3{c*}b{g8?nx~{TXk0kHf)Zb@CM@kBc_`&TVLp@7z=0 zb@+<9jO%MJvsVo4%fL|nbDsM;&%K>j{CtgiZ|k?-eSaT${$p_8XL-bLkx3?7yJn2B*2enA z&wu{*#c1cVr2+Ymua>@s#^#T|AtNoH^T%IHUvtK0lg&APhWaL7QHEkYXK`r*k>8?T zdVJ$C`hQ^M(7xhrQ=e#ayK>p)tNl#0UB`@;1w5gi$_~Wm}%hIv@@wc?8e7w?Ed7sC+ zW^ri);jOHfp2v9Xb{Qz$#eG+-Hiniq5Z=mq>3NLDZkK`Nt}I<~+W1++K;*?W<~HZ? z&F8t#c_070w|2&n-=f~y`mE>J-$b7O7(Dh_@9|q^lF62C`Qodkuc5K?pT9$~p0m2N zfxi5gyX=cudM(B~pYJ|fd3%1%$oY({apuWfUe;KHIgf9>FSkW|)GQp|!Ww7Xm*aAG z`SluWH0N>cvvu6F-NSd==P$KK*~5ES7m>#~kxeG7fQ zBKP$@=ipcl);dqlI9khInm6)W)cIPv+VbbF*_~@3j76P~*VUFkcg2E$#{YplVX=e3{bKL*e1U{5)KQ%*~-Q%y|i zH>FRxUiZf`Jk><%7iFx8sdJ4TU)=s|PBjtzq8@YhHL+vH6SF^W<(W-25&fbr$L+dL zu~E97Yumr4+A|CfHI8cM5Pv>b*EsW9v#fJix}0NTioY~}ZNGBO?vLX*EJR&%wzYjy ze3Y7b#2&|6d6wa!)>1jnnEPwYF=icNw&QuKi79TU^kHQ?R$83JR1@Jg>K1D==CSR~ zIp4W%=gh6|aa>N#U)S!(+;Pn1XE`U2Mc;h9q3fw`hsO1MpFYDw)Mr1(+I`65({+@5 zAM==K?`n%@XR2c#qON)O+CC{hO3ggijIDX6c$er?*0JtrkNZ@2wdK!U59jmRJ&gFM z*V^MWf0S55+{fC=`xMvLRx`$9u`x%)blvCA#ylSr6YpG(J=Awfzp~HJp5|-n>O1H8 zoc9~*o3E?9j`xTM&gJKUDV1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ c1{h#~0R|XgfB^;=V1NMz7+`<_23i>S57vhSTL1t6 literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/mods/adventure/sprites/bat_1.npy b/src/jaxatari/games/mods/adventure/sprites/bat_1.npy new file mode 100644 index 0000000000000000000000000000000000000000..537386231667e0d0a67103fa88bbc5542624e61d GIT binary patch literal 512 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1JQ);NLqoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I$-Mmh=>ItnJ5ItsN4WC1P)%E5m;Mu6mqk;kS6rWZz|TLTj(M1%B!)PMj? TEsPBoL=%U}!Suk?(1Zp6IYu|q literal 0 HcmV?d00001 diff --git a/src/jaxatari/games/mods/adventure/sprites/bat_2.npy b/src/jaxatari/games/mods/adventure/sprites/bat_2.npy new file mode 100644 index 0000000000000000000000000000000000000000..b6a2686d0a9493050914c3295f003877c307493e GIT binary patch literal 512 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1JQ);NLqoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I$-Mmh=>ItnJ5ItsN4WC1P)%D{i1b`T~PkfI-^7Dgl633CIo983(P4p|(X Yk1hu@7bcEu4onV4!_>g|=rloj0N_eB)Bpeg literal 0 HcmV?d00001 From d933990cc1d15c9effd7caeea302802481a7cf45 Mon Sep 17 00:00:00 2001 From: LucyLMM Date: Sun, 29 Mar 2026 21:19:40 +0200 Subject: [PATCH 072/102] Adjusted Black Walls for automatic border detection --- .../games/mods/adventure/sprites/Room_23.npy | Bin 160128 -> 160128 bytes .../games/mods/adventure/sprites/Room_24.npy | Bin 160128 -> 160128 bytes .../games/sprites/adventure/Room_12.npy | Bin 160128 -> 160128 bytes .../games/sprites/adventure/Room_4.npy | Bin 160128 -> 160128 bytes .../games/sprites/adventure/Room_6.npy | Bin 160128 -> 160128 bytes 5 files changed, 0 insertions(+), 0 deletions(-) diff --git a/src/jaxatari/games/mods/adventure/sprites/Room_23.npy b/src/jaxatari/games/mods/adventure/sprites/Room_23.npy index 8ea8e40559c7e835ce13ecfff0ef6dc3fb67884f..3b781ce4e253a6d706a30c9d8cafde110d8fa6d1 100644 GIT binary patch literal 160128 zcmeI&v5H+~7)If-NaIyZHwr0?sD&3`r`T9nNydy=h>?lfs8?Z;%RMGVYTpfeIWRtf z6G(Vj!};>?SNZ#^Z@&Ec+xM=1zxw0m#oep#?{7Z8zWMXFXE#r;Z+>`r|LgtppTB!~ z|KjfL-+%G^r&o7x{{GdE&wsgl^XCsf{`8}#*UvtC^V=sMKE3|y`uMN+udc2xK5oDO z0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdb zFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^4Fm3_N-AQ4_x5L3-|L~e{2hDG`8#&6e{;>>v3v4&>|XqxdoTXZy{Gr@*gg3> zb}#SWx%cAl+{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;I zt86V@{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;It86V@ z{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy* zR2%;It86V@{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;I zt86V@{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;It86V@ z{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy* zR2%;It86V@{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;I zt86V@{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;It86V@ z{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy* zR2%;It86V@{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;I zt86V@{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;It86V@ z{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy* zR2%;It86V@{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;I zt86V@{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;It86V@ z{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy* zR2%;It86V@{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;I zt86V@{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;It86V@ z{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy*R2%;It86V@{`gy* zR2%;It86V@{`gy*R2%;It86V@{`gy*RGXvzZf`G_|MRE%cUZfR?e_2dJ+|*veV^4y zwX43@Lv{H(_MTU+*6u?&seUeh{8hG=E`R(jPO1%m{8hG=E`R(jPO1%m{8hG=E`R(j zPO1%m{8hG=E`R(jPO1%m{8hG=E`R(jPO1%m{8hG=E`R(jPO1%m{8hG=?ooeNS63Gw zH(-DP1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg vfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|ZOuMGSHZ{?Gz literal 160128 zcmeI&v1*=m9ERbzdKB5B(7}p2cmQsSi-VIiHsT;wQgu;}!l8%z*$$a~UU+W;=~YNe z%flVMU$6eB{`<{$Uw`}k2UmYy{dM#5?)8uNH(y@g{QbxCn`hTIKfSvD{r<(TKfJns zdH3$mzk2b@>$|sq{`%(^zumq4{YRgE{>iiJ=U=@2>9dcYUH@}^{Ktn^S63HbZomKo z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFz~(_xV^nx-si73Z{A!U^XsYI{^8%zQ~O-i z=Xp$f@4k2SxgM*_-?8_czhn3MKiB*nyC;9g?#17^_u}u|dwTzl-IKp#_wxRodoTXZ zy{Gr@*gg3>b}#SWx%cAl+iomS=4^fY z_^Z{I%k}Q@%g?K?>)p?fo<4tavN(OQ`}XYd$>R57|F4I`Fl-&}0Rs#$zyJdbFu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs# zzyJdbFu(u<3^2d|0}RZ?!13|%_V$>|^}5c(e{CJzTyMu7_x{G7KZoKfpS~_^lxf^`~3g?-rqjI zGef}6I4V2sZ z$3A}ylm^Oe{bQd$21*0vw*Ilt9|NUmU34F;E&PxAl*G{un3?l-v5pK7S092Fh*yW1l|;N(1G#{;|&=1Eqm-TmRVSkAc!a zxvhWf^T$AGpxo9!_W5I=G*E8qAN%|Gef}6I4V2sZ$3A}ylm^Oe{bQd$21*0vw*Ilt9|NUmU34F;E&PxAl*G{un3?l-v5pK7S092Fh*y zW1l|;N(1G#{;|&=1Eqm-TmRVSkAc!axvhWf^T$AGpxo9!_W5I=G*E8qAN%|be`Vk=u9h-2 literal 160128 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 literal 160128 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 literal 160128 zcmeIyv1(*x0EXe%dKKxSkir$U@B-`<8w+7Uf*Y|ASF&oOR(lB+xvagU7>o4hh3~Mi z`wW~JX83rA^YhI7`^|S>fBXFh7k^&-b@k%*)sJ^qUtV7Q{l~Mb>&vU3Uf%tFck}BH zFYjL5{{Q(`H^02Pef<2@&o{r_KED6x)6YM-zI^t@snR^_zTQ@szxID#temlZ zTTagUUjFzy%hr)DfBYSBa@K}F{?4*>q{|uJU9bq zzyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3^2d| s0}L?000Rs#zyJdbFu(u<3^2d|0}L?000Rs#zyJdbFu(u<3~UYj2kS8ZKL7v# diff --git a/src/jaxatari/games/sprites/adventure/Room_6.npy b/src/jaxatari/games/sprites/adventure/Room_6.npy index 01bd23b80aa4e9ea756ab4ae82dcda31b9456bf3..28613a44850c222f6eacbdfbaa2bcbd622177870 100644 GIT binary patch literal 160128 zcmeI%F=|v{7>3cYNaHG|8-)}`)WQYWDK-{DK!S-_h>?lfsH?C@o3&(PV}hjq@4#H2 z1dnh9!<9FDIX(vR`_-G5uixHVd|&)n9iN=NU$34oS3kcUtoE0y52x#|>!Z)_PS?jL z*B^gz^y%#6>f>i0kG`B-{rSP;r;qlR2hXm4d-8C9`D?lTultL|V&icG1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`>b|JA_7<>6-Pv$wamxqha;e;3|6KR@4;&t16DZTTGe z+r8D>^0mDSp9g>Zl}`ENkH6{PuTHsD`Muxu_LR@jJAc3C`lo;8zXksIGef}6I4V2sZ$3A}ylm^Oe{bQd$21*0vw*Ilt9|NUmU34F;E&PxAl*G{un3?l-v5pK7S092Fh*y zW1l|;N(1G#{;|&=1Eqm-TmRVSkAc!axvhWf^T$AGpxo9!_W5I=G*E8qAN%|Gef}6I4V2sZ$3A}y zlm^Oe{bQd$21*0vw*Ilt9|NUmU34 zF;E&PxAl*G{un3?l-v5pK7S092Fh*yW1l|;N(1G#{;|&=1Eqm-TmRVSkAc!axvhWf z^T$AGpxo9!_W5I=G*E8qAN%|3bn>nf%jg%n2A!UfnVHWoraf*G+8BNMezS7DJhOOb5ErHl!Z`k&xj zo&=9@1;dp$d^tV_^7F;3=PzI1nZ8cnmPf0Tx9jE8#q#@?{pH?b`R;iAd42ft&GGtZ zb@}mUhaXN>7au=)fB0#2@#lLFA3xYz>_55q?a}?c#gE1Hf8Cv?Y2$GN1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`>b|JA_R`N3w}=l8GU&E>Q0`?uk})6>&U`P_yZ-IULf zzujBCDPP;$@OkjZU+I)T{`lMe`_*l3RetYxxxLNj=$*e`bN$o5^4|h~{PE}i-_k(2 zt$+H*pZ=8w%5DAAKmPQuG*E8qpZ@Wuf2DzPTmSTrKm98Wl-v5Jf4lZ~ou9v7`Mb{F z@$T-;{;xOXkEPN+fBf;sKxv@d)<5?7W1uupZtEZW{4r1(D7W>Gef}6I4V2sZ$3A}y zlm^Oe{bQd$21*0vw*Ilt9|NUmU34 zF;E&PxAl*G{un3?l-v5pK7S092Fh*yW1l|;N(1G#{;|&=1Eqm-TmRVSkAc!axvhWf z^T$AGpxo9!_W5I=G*E8qAN%|Gef}6I4V2sZ$3A}ylm^Oe{bQd$21*0vw*Ilt9|NUmU34F;E&PxAl*G{un3?l-v5pK7S092Fh*yW1l|; zN(1G#{;|&=1Eqm-TmRVSkAc!axvhWf^T$AGpxo9!_W5I=G*E8qAN%|Gef}6I4V2sZ$3A}ylm^Oe z{bQd$21*0vw*Ilt9|NUmU34F;E&P zxAl*G{un3?l-v5pK7S092Fh*yW1l|;N(1G#{;|&=1EqmoZ=anXY_@%_`nT=--rN4R zZZ*CYf8!f*G~bQ*oA0*Vj&IA~_(mMfcO(AhyDhil+wwQQ5l8dgh`;%6%kB8K{EctK z(R?@JZ@$}dJH9P{;~Q}_-;Ma2@3!2IZ_D5KMjXv|BmU;QEw|&_@;AN_NAul?zxi&< z?fAC*jc>%!zu#z@rj5r97+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ J0S4wU@CO``Kehk> From bd645d1d8fb581e4a012e6b21022ec20782c5734 Mon Sep 17 00:00:00 2001 From: DanielCress Date: Mon, 30 Mar 2026 17:44:45 +0200 Subject: [PATCH 073/102] Update jax_adventure.py --- src/jaxatari/games/jax_adventure.py | 218 +++++++++++++++++++++++++--- 1 file changed, 198 insertions(+), 20 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 94478e3d8..f7f3a07b9 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -54,11 +54,15 @@ def _get_default_asset_config() -> tuple: 'Dragon_yellow_attack.npy', 'Dragon_yellow_dead.npy']}, {'name': 'dragon_green', 'type': 'group', 'files': ['Dragon_green_neutral.npy', + 'Dragon_green_attack.npy', + 'Dragon_green_dead.npy']}, + {'name': 'dragon_red', 'type': 'group', 'files': ['Dragon_green_neutral.npy', 'Dragon_green_attack.npy', 'Dragon_green_dead.npy']}, #Keys {'name': 'key_yellow', 'type': 'single', 'file': 'Key_yellow.npy'}, {'name': 'key_black', 'type': 'single', 'file': 'Key_black.npy'}, + {'name': 'key_white', 'type': 'single', 'file': 'Key_black.npy'}, #Gate and its animation {'name': 'gate_state', 'type': 'group', 'files': ['Gate_closed.npy', 'Gate_opening_0.npy', @@ -82,6 +86,9 @@ def _get_default_asset_config() -> tuple: 'Chalice_Red.npy', 'Chalice_Turquoise.npy', 'Chalice_Yellow.npy']}, + {'name': 'bat', 'type': 'group', 'files': ['Dragon_green_neutral.npy', + 'Dragon_green_attack.npy']}, + {'name': 'dot', 'type': 'single', 'file': 'Key_black.npy'} ) @@ -98,6 +105,7 @@ class AdventureConstants(struct.PyTreeNode): BRIDGE_SIZE: Tuple[int, int] = (4, 48) MAGNET_SIZE: Tuple[int, int] = (8, 16) CHALICE_SIZE: Tuple[int, int] = (8, 18) + DOT_SIZE: Tuple[int, int] = (1,1) #Inventory IDs EMPTY_HAND_ID: int = 0 KEY_YELLOW_ID: int = 1 @@ -106,19 +114,26 @@ class AdventureConstants(struct.PyTreeNode): BRIDGE_ID: int = 4 MAGNET_ID: int = 5 CHALICE_ID: int = 6 + KEY_WHITE_ID: int = 7 + DOT_ID: int = 8 #dragons (X,Y, Room, state, counter, eat, activate) DRAGON_YELLOW_SPAWN: Tuple[int, int, int, int ,int, int, int] = (80, 170, 5, 0, 0, 0, 0) DRAGON_GREEN_SPAWN: Tuple[int, int, int, int, int, int, int] = (80, 130, 4, 0, 0, 0, 0) + DRAGON_RED_SPAWN: Tuple[int, int, int, int, int, int, int] = (80, 130, 19, 0, 0, 0, 0) #Spawn Locations of all Entities: (X, Y, Room/Tile) YELLOW_GATE_POS: Tuple[int, int, int] = (76, 140, 0) BLACK_GATE_POS: Tuple[int, int, int] = (76, 140, 11) + WHITE_GATE_POS: Tuple[int, int, int] = (76, 140, 24) PLAYER_SPAWN: Tuple[int, int, int] = (78, 174, 0) #Changed from (78, 174, 0) KEY_YELLOW_SPAWN: Tuple[int, int, int] = (31, 110, 0) #Changed from (31, 110, 0) for Testing KEY_BLACK_SPAWN: Tuple[int, int, int] = (31, 100, 4) + KEY_WHITE_SPAWN: Tuple[int, int, int] = (31, 110, 19) SWORD_SPAWN: Tuple[int, int, int] = (31,180,1) BRIDGE_SPAWN: Tuple[int, int, int] = (40,130,10) MAGNET_SPAWN: Tuple[int, int, int] = (120,180,12) CHALICE_SPAWN: Tuple[int, int, int] = (35,180,13) + BAT_SPAWN: Tuple[int, int, int, int] = (76, 140, 19, 0) + DOT_SPAWN: Tuple[int, int, int] = (76, 140, 29) #Constants that are used for restricting player movement, for easy of fine tuning # Wall coordinates the player cannot pass through @@ -160,12 +175,15 @@ class AdventureState(struct.PyTreeNode): #positions dragons: x, y ,tile ,state, counter, eat, activate dragon_yellow: chex.Array dragon_green: chex.Array + dragon_red: chex.Array #positions keys: x, y, tile key_yellow: chex.Array key_black: chex.Array + key_white: chex.Array #gates: state, counter gate_yellow: chex.Array gate_black: chex.Array + gate_white: chex.Array #position sword: x, y, tile sword: chex.Array #position bridge: x, y, tile @@ -176,6 +194,10 @@ class AdventureState(struct.PyTreeNode): chalice: chex.Array #random key rndKey: chex.PRNGKey + #bat: x, y, tile, state + bat: chex.Array + #dot: x, y, tile + dot: chex.Array class EntityPosition(struct.PyTreeNode): @@ -229,7 +251,7 @@ def __init__(self, consts: AdventureConstants = None): #background_assets_names = _get_default_asset_config()[0]["files"] sprite_path = f"{os.path.dirname(os.path.abspath(__file__))}/sprites/adventure" - +# self.BackgroundRoom1 = _load_background_map(os.path.join(sprite_path, "Room_1.npy")) self.BackgroundRoom2 = _load_background_map(os.path.join(sprite_path, "Room_2.npy")) self.BackgroundRoom3 = _load_background_map(os.path.join(sprite_path, "Room_3.npy")) @@ -361,6 +383,8 @@ def is_tile_walkable(tileset: jnp.ndarray, Pos_x: int, Pos_y: int) -> bool: gate_yellow_open = state.gate_yellow[0] + gate_white_open = state.gate_white[0] + gate_black_open = state.gate_black[0] gate_yellow_not_block = jnp.logical_or( @@ -368,12 +392,17 @@ def is_tile_walkable(tileset: jnp.ndarray, Pos_x: int, Pos_y: int) -> bool: gate_yellow_open > 4 ) + gate_white_not_block = jnp.logical_or( + jnp.logical_not(room == 24), + gate_white_open > 4 + ) + gate_black_not_block = jnp.logical_or( jnp.logical_not(room == 11), gate_black_open > 4 ) - gates_not_blocking = jnp.logical_and(gate_yellow_not_block, gate_black_not_block) + gates_not_blocking = jnp.logical_and(jnp.logical_and(gate_yellow_not_block, gate_black_not_block),gate_white_not_block) castle_gate = jnp.logical_or( gates_not_blocking, @@ -387,7 +416,7 @@ def is_tile_walkable(tileset: jnp.ndarray, Pos_x: int, Pos_y: int) -> bool: ) castle_collision = jnp.logical_or( - jnp.logical_not(jnp.logical_or(room==0, room==11)), #either it is not a castle tile, or + jnp.logical_not(jnp.logical_or(jnp.logical_or(room==0, room==11),room==24)), #either it is not a castle tile, or jnp.logical_and(castle_walls, castle_gate) ) @@ -436,7 +465,9 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt lambda:state.sword[0], lambda:state.bridge[0], lambda:state.magnet[0], - lambda:state.chalice[0] + lambda:state.chalice[0], + lambda:state.key_white[0], + lambda:state.dot[0] ] ) @@ -463,7 +494,9 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt lambda:state.sword[1], lambda:state.bridge[1], lambda:state.magnet[1], - lambda:state.chalice[1] + lambda:state.chalice[1], + lambda:state.key_white[1], + lambda:state.dot[1] ] ) @@ -489,13 +522,15 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt lambda:state.sword[2], lambda:state.bridge[2], lambda:state.magnet[2], - lambda:state.chalice[2] + lambda:state.chalice[2], + lambda:state.key_white[2], + lambda:state.dot[2] ] ) #enter yellow castle new_player_y, new_player_tile, new_item_tile, new_item_y = jax.lax.cond( - jnp.logical_and(new_player_tile == 0, jnp.logical_and(new_player_y <145,jnp.logical_and(new_player_x<110, new_player_x>50))), + jnp.logical_and(new_player_tile == 0, jnp.logical_and(new_player_y <148,jnp.logical_and(new_player_x<110, new_player_x>50))), lambda: (212, 1, 1,new_item_y+(212-new_player_y)), lambda: (new_player_y, new_player_tile, new_item_tile, new_item_y) ) @@ -503,13 +538,13 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt #leave yellow castle new_player_x, new_player_y, new_player_tile, new_item_tile, new_item_y, new_item_x = jax.lax.cond( jnp.logical_and(new_player_tile == 1, new_player_y >212), - lambda: (77, 145, 0, 0, new_item_y-(new_player_y-145),new_item_x+(77-new_player_x)), + lambda: (77, 148, 0, 0, new_item_y-(new_player_y-148),new_item_x+(77-new_player_x)), lambda: (new_player_x, new_player_y, new_player_tile, new_item_tile, new_item_y, new_item_x) ) #enter black castle new_player_y, new_player_tile, new_item_tile, new_item_y = jax.lax.cond( - jnp.logical_and(new_player_tile == 11, jnp.logical_and(new_player_y <145,jnp.logical_and(new_player_x<110, new_player_x>50))), + jnp.logical_and(new_player_tile == 11, jnp.logical_and(new_player_y <148,jnp.logical_and(new_player_x<110, new_player_x>50))), lambda: (212, 12, 12,new_item_y+(212-new_player_y)), lambda: (new_player_y, new_player_tile, new_item_tile, new_item_y) ) @@ -517,7 +552,7 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt #leave black castle new_player_x, new_player_y, new_player_tile, new_item_tile, new_item_y, new_item_x = jax.lax.cond( jnp.logical_and(new_player_tile == 12, new_player_y >212), - lambda: (77, 145, 11, 11, new_item_y-(new_player_y-145),new_item_x+(77-new_player_x)), + lambda: (77, 148, 11, 11, new_item_y-(new_player_y-148),new_item_x+(77-new_player_x)), lambda: (new_player_x, new_player_y, new_player_tile, new_item_tile, new_item_y, new_item_x) ) @@ -596,13 +631,18 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt lambda op: op[3], operand=(new_item_x,new_item_y,new_item_tile,state.key_black) ), + key_white= jax.lax.cond(state.player[3]==self.consts.KEY_WHITE_ID, + lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: op[3], + operand=(new_item_x,new_item_y,new_item_tile,state.key_white) + ), sword= jax.lax.cond(state.player[3]==self.consts.SWORD_ID, lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), lambda op: op[3], operand=(new_item_x,new_item_y,new_item_tile,state.sword) ), bridge= jax.lax.cond(state.player[3]==self.consts.BRIDGE_ID, - lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), lambda op: op[3], operand=(new_item_x,new_item_y,new_item_tile,state.bridge) ), @@ -615,15 +655,23 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt lambda op: jnp.array([op[0],op[1],op[2],op[3]]).astype(jnp.int32), lambda op: op[4], operand=(new_item_x,new_item_y,new_item_tile,state.chalice[3],state.chalice) - ) + ), + dot= jax.lax.cond(state.player[3]==self.consts.DOT_ID, + lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: op[3], + operand=(new_item_x,new_item_y,new_item_tile,state.dot) + ), ) def _gate_interaction(self, state: AdventureState) -> AdventureState: gate_yellow_state = state.gate_yellow[0] gate_yellow_close = False + gate_white_state = state.gate_white[0] + gate_white_close = False gate_black_state = state.gate_black[0] gate_black_close = False gate_yellow_counter = state.gate_yellow[1] + gate_white_counter = state.gate_white[1] gate_black_counter = state.gate_black[1] room = state.player[2] @@ -632,6 +680,7 @@ def _gate_interaction(self, state: AdventureState) -> AdventureState: yellow_key_in_inventory = (state.player[3] == 1) black_key_in_inventory = (state.player[3] == 2) + white_key_in_inventory = (state.player[3] == 7) player_infront_yellow_gate = jnp.logical_and( room == 0, @@ -659,18 +708,35 @@ def _gate_interaction(self, state: AdventureState) -> AdventureState: ) ) + player_infront_white_gate = jnp.logical_and( + room == 24, + jnp.logical_and( + jnp.logical_and( + player_x >= self.consts.PATH_VERTICAL_LEFT, + player_x <= self.consts.PATH_VERTICAL_RIGHT + ),jnp.logical_and( + player_y >= self.consts.CASTLE_BASE_CORNER_Y, + player_y <= self.consts.CASTLE_BASE_CORNER_Y + 8 + ) + ) + ) + yellow_key_in_range = jnp.logical_and(yellow_key_in_inventory, player_infront_yellow_gate) black_key_in_range = jnp.logical_and(black_key_in_inventory, player_infront_black_gate) + white_key_in_range = jnp.logical_and(white_key_in_inventory, player_infront_white_gate) gate_opening_yellow = jnp.logical_and(jnp.logical_and(jnp.logical_and(gate_yellow_state>=0, gate_yellow_state<6), yellow_key_in_range), gate_yellow_counter == 0) gate_opening_black = jnp.logical_and(jnp.logical_and(jnp.logical_and(gate_black_state>=0, gate_black_state<6), black_key_in_range), gate_black_counter == 0) + gate_opening_white = jnp.logical_and(jnp.logical_and(jnp.logical_and(gate_white_state>=0, gate_white_state<6), white_key_in_range), gate_white_counter == 0) gate_yellow_close =jnp.logical_and(jnp.logical_and(gate_yellow_state>0, gate_yellow_counter > 20), yellow_key_in_range) gate_black_close = jnp.logical_and(jnp.logical_and(gate_black_state>0, gate_black_counter > 20), black_key_in_range) + gate_white_close =jnp.logical_and(jnp.logical_and(gate_white_state>0, gate_white_counter > 20), white_key_in_range) gate_opening_yellow = jnp.logical_and(gate_opening_yellow, jnp.logical_not(gate_yellow_close)) gate_opening_black = jnp.logical_and(gate_opening_black, jnp.logical_not(gate_black_close)) + gate_opening_white = jnp.logical_and(gate_opening_white, jnp.logical_not(gate_white_close)) gate_yellow_state = jax.lax.cond( gate_opening_yellow, @@ -700,6 +766,20 @@ def _gate_interaction(self, state: AdventureState) -> AdventureState: operand = gate_black_state ) + gate_white_state = jax.lax.cond( + gate_opening_white, + lambda op: op + 1, + lambda op: op, + operand = gate_white_state + ) + + gate_white_state = jax.lax.cond( + gate_white_close, + lambda op: op - 1, + lambda op:op, + operand = gate_white_state + ) + gate_yellow_counter = jax.lax.cond( jnp.logical_or(gate_yellow_state == 6, jnp.logical_and(gate_yellow_state==0, gate_yellow_counter<30)), lambda op:op + 1, @@ -728,12 +808,28 @@ def _gate_interaction(self, state: AdventureState) -> AdventureState: operand = gate_black_counter ) + gate_white_counter = jax.lax.cond( + jnp.logical_or(gate_white_state == 6, jnp.logical_and(gate_white_state==0, gate_white_counter<30)), + lambda op:op + 1, + lambda op:op, + operand = gate_white_counter + ) + + gate_white_counter = jax.lax.cond( + jnp.logical_and(gate_white_state == 0, gate_white_counter>=30), + lambda _: 0, + lambda op:op, + operand = gate_white_counter + ) + new_gate_yellow = [gate_yellow_state, gate_yellow_counter] new_gate_black = [gate_black_state, gate_black_counter] + new_gate_white = [gate_white_state, gate_white_counter] return state.replace( gate_yellow=new_gate_yellow, - gate_black=new_gate_black + gate_black=new_gate_black, + gate_white=new_gate_white, ) def _item_pickup(self, state: AdventureState, action: chex.Array) -> AdventureState: @@ -752,7 +848,9 @@ def check_for_item(self:JaxAdventure, state: AdventureState, item_ID: int) -> bo lambda:(state.sword[0],state.sword[1],state.sword[2],self.consts.SWORD_SIZE[0],self.consts.SWORD_SIZE[1]), lambda:(state.bridge[0],state.bridge[1],state.bridge[2],self.consts.BRIDGE_SIZE[0],self.consts.BRIDGE_SIZE[1]), lambda:(state.magnet[0],state.magnet[1],state.magnet[2],self.consts.MAGNET_SIZE[0],self.consts.MAGNET_SIZE[1]), - lambda:(state.chalice[0],state.chalice[1],state.chalice[2],self.consts.CHALICE_SIZE[0],self.consts.CHALICE_SIZE[1]) + lambda:(state.chalice[0],state.chalice[1],state.chalice[2],self.consts.CHALICE_SIZE[0],self.consts.CHALICE_SIZE[1]), + lambda:(state.key_white[0],state.key_white[1],state.key_white[2],self.consts.KEY_SIZE[0],self.consts.KEY_SIZE[1]), + lambda:(state.dot[0],state.dot[1],state.dot[2],self.consts.DOT_SIZE[0],self.consts.DOT_SIZE[1]) ]) #jax.debug.print("Hitbox values item:{a},{b},{c},{d},{e}",a=item_x,b=item_y,c=tile,d=item_width,e=item_height) @@ -897,7 +995,17 @@ def diff_of_4(val1:int, val2:int) -> bool: lambda _: jax.lax.cond( check_for_item(self=self, state=state, item_ID=self.consts.CHALICE_ID), lambda _: self.consts.CHALICE_ID, - lambda op: op, + lambda _: jax.lax.cond( + check_for_item(self=self, state=state, item_ID=self.consts.KEY_WHITE_ID), + lambda _: self.consts.KEY_WHITE_ID, + lambda _: jax.lax.cond( + check_for_item(self=self, state=state, item_ID=self.consts.DOT_ID), + lambda _: self.consts.DOT_ID, + lambda op: op, + operand=state.player[3] + ), + operand=state.player[3] + ), operand=state.player[3] ), operand=state.player[3] @@ -1125,6 +1233,18 @@ def _magnet_step(self, state: AdventureState) -> AdventureState: operand = None ) + #try to pull white key + key_white_x = state.key_white[0] + key_white_y = state.key_white[1] + direction_x = jnp.sign(magnet_x - key_white_x) + direction_y = jnp.sign(magnet_y - key_white_y) + key_white_x, key_white_y = jax.lax.cond( + jnp.logical_and(state.key_white[2]==state.magnet[2], state.player[3]!=7), + lambda _: (key_white_x+direction_x,key_white_y+direction_y), + lambda _: (key_white_x,key_white_y), + operand = None + ) + #try to pull bridge bridge_x = state.bridge[0] bridge_y = state.bridge[1] @@ -1152,6 +1272,7 @@ def _magnet_step(self, state: AdventureState) -> AdventureState: return state.replace( key_yellow=jnp.array([key_yellow_x,key_yellow_y,state.key_yellow[2]]).astype(jnp.int32), key_black=jnp.array([key_black_x,key_black_y,state.key_black[2]]).astype(jnp.int32), + key_white=jnp.array([key_white_x,key_white_y,state.key_white[2]]).astype(jnp.int32), sword=jnp.array([sword_x,sword_y,state.sword[2]]).astype(jnp.int32), bridge=jnp.array([bridge_x,bridge_y,state.bridge[2]]).astype(jnp.int32), chalice=jnp.array([chalice_x,chalice_y,state.chalice[2],state.chalice[3]]).astype(jnp.int32) @@ -1188,7 +1309,12 @@ def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureOb self.consts.DRAGON_GREEN_SPAWN[1], self.consts.DRAGON_GREEN_SPAWN[2], self.consts.DRAGON_GREEN_SPAWN[3], - self.consts.DRAGON_GREEN_SPAWN[4]]).astype(jnp.int32), #ToDo + self.consts.DRAGON_GREEN_SPAWN[4]]).astype(jnp.int32), + dragon_red = jnp.array([self.consts.DRAGON_RED_SPAWN[0], + self.consts.DRAGON_RED_SPAWN[1], + self.consts.DRAGON_RED_SPAWN[2], + self.consts.DRAGON_RED_SPAWN[3], + self.consts.DRAGON_RED_SPAWN[4]]).astype(jnp.int32), #ToDo #Keys: x ,y, tile key_yellow = jnp.array([self.consts.KEY_YELLOW_SPAWN[0], self.consts.KEY_YELLOW_SPAWN[1], @@ -1196,9 +1322,13 @@ def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureOb key_black = jnp.array([self.consts.KEY_BLACK_SPAWN[0], self.consts.KEY_BLACK_SPAWN[1], self.consts.KEY_BLACK_SPAWN[2]]).astype(jnp.int32), + key_white = jnp.array([self.consts.KEY_WHITE_SPAWN[0], + self.consts.KEY_WHITE_SPAWN[1], + self.consts.KEY_WHITE_SPAWN[2]]).astype(jnp.int32), #Gate: state, counter (ToDo for animation?) gate_yellow=jnp.array([0,0]).astype(jnp.int32), gate_black=jnp.array([0,0]).astype(jnp.int32), + gate_white=jnp.array([0,0]).astype(jnp.int32), #Items: x, y, tile sword = jnp.array([self.consts.SWORD_SPAWN[0], self.consts.SWORD_SPAWN[1], @@ -1214,7 +1344,14 @@ def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureOb self.consts.CHALICE_SPAWN[1], self.consts.CHALICE_SPAWN[2],7]).astype(jnp.int32), #ToDo #random key - rndKey = state_key + rndKey = state_key, + bat = jnp.array([self.consts.BAT_SPAWN[0], + self.consts.BAT_SPAWN[1], + self.consts.BAT_SPAWN[2], + self.consts.BAT_SPAWN[3]]).astype(jnp.int32), + dot = jnp.array([self.consts.DOT_SPAWN[0], + self.consts.DOT_SPAWN[1], + self.consts.DOT_SPAWN[2]]).astype(jnp.int32) ) initial_obs = self._get_observation(state) @@ -1231,15 +1368,20 @@ def step(self, state: AdventureState, action: chex.Array) -> Tuple[AdventureObse player=state.player, dragon_yellow=state.dragon_yellow, dragon_green=state.dragon_green, + dragon_red=state.dragon_red, key_yellow=state.key_yellow, key_black=state.key_black, + key_white=state.key_white, gate_yellow=state.gate_yellow, gate_black=state.gate_black, + gate_white=state.gate_white, sword=state.sword, bridge=state.bridge, magnet=state.magnet, chalice=state.chalice, - rndKey=state.rndKey + rndKey=state.rndKey, + bat=state.bat, + dot=state.dot ) state = self._player_step(state, action) state = self._item_pickup(state, action) @@ -1413,7 +1555,7 @@ def _get_info(self, state: AdventureState, ) -> AdventureInfo: @partial(jax.jit, static_argnums=(0,)) def _get_reward(self, previous_state: AdventureState, state: AdventureState): reward = jax.lax.cond( - jnp.logical_or(state.dragon_yellow[5]==1,state.dragon_green[5]==1), #lose when eaten by dragon + jnp.logical_or(jnp.logical_or(state.dragon_yellow[5]==1,state.dragon_green[5]==1),state.dragon_red[5]==1), #lose when eaten by dragon lambda :-1, lambda : jax.lax.cond( state.chalice[2]==1, #win when chalice in yellow castle @@ -1430,7 +1572,7 @@ def _get_reward(self, previous_state: AdventureState, state: AdventureState): @partial(jax.jit, static_argnums=(0,)) def _get_done(self, state: AdventureState) -> bool: - return jnp.logical_or(jnp.logical_or(state.dragon_yellow[5]==1,state.dragon_green[5]==1), state.chalice[2]==1) + return jnp.logical_or(jnp.logical_or(jnp.logical_or(state.dragon_yellow[5]==1,state.dragon_green[5]==1),state.dragon_red[5]==1), state.chalice[2]==1) class AdventureRenderer(JAXGameRenderer): @@ -1489,6 +1631,13 @@ def render(self, state): lambda r : r, operand = raster, ) + dragon_red_mask = self.SHAPE_MASKS["dragon_red"][state.dragon_green[3]] + raster = jax.lax.cond( + state.dragon_red[2]==state.player[2], + lambda r : self.jr.render_at(raster, state.dragon_red[0], state.dragon_red[1], dragon_red_mask), + lambda r : r, + operand = raster, + ) #keys key_yellow_mask = self.SHAPE_MASKS["key_yellow"] @@ -1505,6 +1654,13 @@ def render(self, state): lambda r : r, operand = raster, ) + key_white_mask = self.SHAPE_MASKS["key_white"] + raster = jax.lax.cond( + state.key_white[2]==state.player[2], + lambda r : self.jr.render_at(raster, state.key_white[0], state.key_white[1], key_white_mask), + lambda r : r, + operand = raster, + ) #Gates gate_yellow_mask = self.SHAPE_MASKS["gate_state"][state.gate_yellow[0]] @@ -1522,6 +1678,13 @@ def render(self, state): lambda r : r, operand = raster, ) + gate_white_mask = self.SHAPE_MASKS["gate_state"][state.gate_white[0]] + raster = jax.lax.cond( + self.consts.WHITE_GATE_POS[2]==state.player[2], + lambda r : self.jr.render_at(raster, self.consts.WHITE_GATE_POS[0], self.consts.WHITE_GATE_POS[1], gate_white_mask),#ToDO + lambda r : r, + operand = raster, + ) #items @@ -1556,4 +1719,19 @@ def render(self, state): operand = raster, ) + bat_mask = self.SHAPE_MASKS["bat"][state.bat[3]] + raster = jax.lax.cond( + state.bat[2]==state.player[2], + lambda r : self.jr.render_at(raster, self.consts.BAT_SPAWN[0], self.consts.BAT_SPAWN[1], bat_mask),#ToDO + lambda r : r, + operand = raster, + ) + dot_mask = self.SHAPE_MASKS["dot"] + raster = jax.lax.cond( + state.dot[2]==state.player[2], + lambda r : self.jr.render_at(raster, state.dot[0], state.dot[1], dot_mask), + lambda r : r, + operand = raster, + ) + return self.jr.render_from_palette(raster, self.PALETTE) From 9c0956f2567322933783b243e0990d41c26c5370 Mon Sep 17 00:00:00 2001 From: DanielCress Date: Mon, 30 Mar 2026 17:45:18 +0200 Subject: [PATCH 074/102] add complex mods --- .../mods/adventure/adventure_mod_plugins.py | 2373 +++++++++++++++++ 1 file changed, 2373 insertions(+) diff --git a/src/jaxatari/games/mods/adventure/adventure_mod_plugins.py b/src/jaxatari/games/mods/adventure/adventure_mod_plugins.py index 96eb095c9..4c05abbea 100644 --- a/src/jaxatari/games/mods/adventure/adventure_mod_plugins.py +++ b/src/jaxatari/games/mods/adventure/adventure_mod_plugins.py @@ -1,9 +1,11 @@ import jax import jax.numpy as jnp from functools import partial +from typing import Tuple from jaxatari.games.jax_adventure import AdventureState from jaxatari.modification import JaxAtariInternalModPlugin, JaxAtariPostStepModPlugin import chex +import os from jaxatari.environment import JAXAtariAction as Action import random @@ -361,3 +363,2374 @@ class RandomPlayerSpawnMod(JaxAtariInternalModPlugin): constants_overrides = { "PLAYER_SPAWN": spawnlocations[rnd], } + +class LevelTwoMod(JaxAtariInternalModPlugin): + asset_overrides = { + #all rooms in order + 'room_number': {'name': 'room_number', 'type': 'group', 'files': ['Room_1.npy', + 'Room_2.npy', + 'Room_3.npy', + 'Room_4.npy', + 'Room_5.npy', + 'Room_6.npy', + 'Room_7.npy', + 'Room_8.npy', + 'Room_9.npy', + 'Room_10.npy', + 'Room_11.npy', + 'Room_12.npy', + 'Room_13.npy', + 'Room_14.npy', + 'Room_15.npy', + 'Room_16.npy', + 'Room_17.npy', + 'Room_18.npy', + 'Room_20.npy', + 'Room_21.npy', + 'Room_22.npy', + 'Room_23.npy', + 'Room_24.npy', + 'Room_25.npy', + 'Room_26.npy', + 'Room_27.npy', + 'Room_28.npy', + 'Room_29.npy', + 'Room_30.npy' + ]}, + #Player in all the different colors, which change depending on the background + "player_colors": {'name': 'player_colors', 'type': 'group', 'files': ["Player_Yellow.npy", + "Player_Yellow.npy", + "Player_Green.npy", + "Player_Purple.npy", + "Player_Pink.npy", + "Player_Green_yellow.npy", + "Player_Blue.npy", + "Player_Blue.npy", + "Player_Blue.npy", + "Player_Blue.npy", + "Player_Blue.npy", + "Player_Black.npy", + "Player_Pink.npy", + "Player_Magenta.npy", + "Player_inverted.npy", + "Player_inverted.npy", + "Player_inverted.npy", + "Player_inverted.npy", + "Player_inverted.npy", + "Player_inverted.npy", + "Player_inverted.npy", + "Player_BabyBlue.npy", + "Player_Turquoise.npy", + "Player_LightBlue.npy", + "Player_White.npy", + "Player_Orange.npy", + "Player_Orange.npy", + "Player_Orange.npy", + "Player_Orange.npy"]}, + #Red Dragon + "dragon_red": {'name': 'dragon_red', 'type': 'group', 'files': ['Dragon_red_neutral.npy', + 'Dragon_red_attack.npy', + 'Dragon_red_dead.npy']}, + #white Key + "key_white": {'name': 'key_white', 'type': 'single', 'file': 'Key_white.npy'}, + + #bat + "bat": {'name': 'bat', 'type': 'group', 'files': ['bat_1.npy', + 'bat_2.npy']} + } + + constants_overrides ={ + "DRAGON_YELLOW_SPAWN": (80, 170, 25, 0, 0, 0, 0), + "DRAGON_GREEN_SPAWN": (80, 130, 5, 0, 0, 0, 0), + "DRAGON_RED_SPAWN": (80, 130, 15, 0, 0, 0, 0), + "KEY_YELLOW_SPAWN": (31, 170, 19), + "KEY_BLACK_SPAWN": (31, 100, 28), + "KEY_WHITE_SPAWN": (31, 110, 8), + "SWORD_SPAWN": (31,180,0), + "BRIDGE_SPAWN": (65,130,20), + "MAGNET_SPAWN": (120,180,23), + "CHALICE_SPAWN": (50,170,15), + "BAT_SPAWN": (76, 140, 11, 0) + } + + @partial(jax.jit, static_argnums=(0,)) + def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureState: + def _check_walls_new_rooms(state: AdventureState, direction: int) -> bool: + room = state.player[2] + + # direction 0: left, 1: right, 2: up, 3: down + player_x = state.player[0] + player_x = jax.lax.cond( + direction == 0, + lambda x: x-4, + lambda x: x, + operand = player_x, + ) + player_x = jax.lax.cond( + direction == 1, + lambda x: x+4, + lambda x: x, + operand = player_x, + ) + + player_y = state.player[1] + player_y = jax.lax.cond( + direction == 2, + lambda y: y-8, + lambda y: y, + operand = player_y, + ) + player_y = jax.lax.cond( + direction == 3, + lambda y: y+8, + lambda y: y, + operand = player_y, + ) + + #jax.debug.print("step") + #test load background of Rooms + def is_tile_walkable(tileset: jnp.ndarray, Pos_x: int, Pos_y: int) -> bool: + #determin if we should be allowed to walk, based on the background only + #tileset data at a given x and y position is [r, g, b, 255] + #[151, 151, 151, 255] = Grey (allowed player movement) + #[0, 0, 0, 255] are top or bottom border allow movement for tilechange + #anything else are walls (inversed in certain maze tileset) . + is_walkable_1 = (tileset[Pos_y+2,Pos_x][0] == jnp.uint8(151)) + is_walkable_2 = (tileset[Pos_y+2,Pos_x][1] == jnp.uint8(151)) + is_walkable_3 = (tileset[Pos_y+2,Pos_x][2] == jnp.uint8(151)) + is_walkable = jnp.logical_and(is_walkable_1, jnp.logical_and(is_walkable_2,is_walkable_3)) + is_border_1 = (tileset[Pos_y+2,Pos_x][0] == jnp.uint8(0)) + is_border_2 = (tileset[Pos_y+2,Pos_x][1] == jnp.uint8(0)) + is_border_3 = (tileset[Pos_y+2,Pos_x][2] == jnp.uint8(0)) + is_border = jnp.logical_and(is_border_1, jnp.logical_and(is_border_2,is_border_3)) + #jax.debug.print("Tile: {a} is walkable {b}",a=tileset[Pos_y,Pos_x][0:3], b=is_walkable) + return jnp.logical_or(is_walkable,is_border) + + def is_inverted_walkable(tileset: jnp.ndarray, Pos_x: int, Pos_y: int) -> bool: + #determin if we should be allowed to walk, based on the background only + #tileset data at a given x and y position is [r, g, b, 255] + #[151, 151, 151, 255] = Grey (allowed player movement) + #[0, 0, 0, 255] are top or bottom border allow movement for tilechange + #anything else are walls (inversed in certain maze tileset) . + is_walkable_1 = (tileset[Pos_y+2,Pos_x][0] == jnp.uint8(151)) + is_walkable_2 = (tileset[Pos_y+2,Pos_x][1] == jnp.uint8(151)) + is_walkable_3 = (tileset[Pos_y+2,Pos_x][2] == jnp.uint8(151)) + is_walkable = jnp.logical_and(is_walkable_1, jnp.logical_and(is_walkable_2,is_walkable_3)) + #jax.debug.print("Tile: {a} is walkable {b}",a=tileset[Pos_y,Pos_x][0:3], b=is_walkable) + return is_walkable + + def _load_background_map(path: str) -> jnp.ndarray: + background_map = jnp.load(path) + return background_map + + + sprite_path = f"{os.path.dirname(os.path.abspath(__file__))}/sprites" + + #jax.debug.print("Room: {a} is equal to 0 {b}, is walkable {c}",a=room, b=(room == 0),c=is_tile_walkable(self.BackgroundRoom1, player_x, player_y)) + in_Room_15_and_walkable = jnp.logical_and(jnp.equal(room, 14), jnp.logical_not(is_inverted_walkable(_load_background_map(os.path.join(sprite_path, "Room_15.npy")), player_x, player_y))) + in_Room_16_and_walkable = jnp.logical_and(jnp.equal(room, 15), jnp.logical_not(is_inverted_walkable(_load_background_map(os.path.join(sprite_path, "Room_16.npy")), player_x, player_y))) + in_Room_17_and_walkable = jnp.logical_and(jnp.equal(room, 16), jnp.logical_not(is_inverted_walkable(_load_background_map(os.path.join(sprite_path, "Room_17.npy")), player_x, player_y))) + in_Room_18_and_walkable = jnp.logical_and(jnp.equal(room, 17), jnp.logical_not(is_inverted_walkable(_load_background_map(os.path.join(sprite_path, "Room_18.npy")), player_x, player_y))) + in_Room_20_and_walkable = jnp.logical_and(jnp.equal(room, 18), jnp.logical_not(is_inverted_walkable(_load_background_map(os.path.join(sprite_path, "Room_20.npy")), player_x, player_y))) + in_Room_21_and_walkable = jnp.logical_and(jnp.equal(room, 19), jnp.logical_not(is_inverted_walkable(_load_background_map(os.path.join(sprite_path, "Room_21.npy")), player_x, player_y))) + in_Room_22_and_walkable = jnp.logical_and(jnp.equal(room, 20), jnp.logical_not(is_inverted_walkable(_load_background_map(os.path.join(sprite_path, "Room_22.npy")), player_x, player_y))) + in_Room_23_and_walkable = jnp.logical_and(jnp.equal(room, 21), is_tile_walkable(_load_background_map(os.path.join(sprite_path, "Room_23.npy")), player_x, player_y)) + in_Room_24_and_walkable = jnp.logical_and(jnp.equal(room, 22), is_tile_walkable(_load_background_map(os.path.join(sprite_path, "Room_24.npy")), player_x, player_y)) + in_Room_25_and_walkable = jnp.logical_and(jnp.equal(room, 23), is_tile_walkable(_load_background_map(os.path.join(sprite_path, "Room_25.npy")), player_x, player_y)) + in_Room_26_and_walkable = jnp.logical_and(jnp.equal(room, 24), is_tile_walkable(_load_background_map(os.path.join(sprite_path, "Room_26.npy")), player_x, player_y)) + in_Room_27_and_walkable = jnp.logical_and(jnp.equal(room, 25), is_tile_walkable(_load_background_map(os.path.join(sprite_path, "Room_27.npy")), player_x, player_y)) + in_Room_28_and_walkable = jnp.logical_and(jnp.equal(room, 26), is_tile_walkable(_load_background_map(os.path.join(sprite_path, "Room_28.npy")), player_x, player_y)) + in_Room_29_and_walkable = jnp.logical_and(jnp.equal(room, 27), is_tile_walkable(_load_background_map(os.path.join(sprite_path, "Room_29.npy")), player_x, player_y)) + in_Room_30_and_walkable = jnp.logical_and(jnp.equal(room, 28), is_tile_walkable(_load_background_map(os.path.join(sprite_path, "Room_30.npy")), player_x, player_y)) + + Room_15_or_16_and_walkable = jnp.logical_or(in_Room_15_and_walkable, in_Room_16_and_walkable) + Room_17_or_18_and_walkable = jnp.logical_or(in_Room_17_and_walkable, in_Room_18_and_walkable) + Room_20_or_21_and_walkable = jnp.logical_or(in_Room_20_and_walkable, in_Room_21_and_walkable) + Room_22_or_23_and_walkable = jnp.logical_or(in_Room_22_and_walkable, in_Room_23_and_walkable) + Room_24_or_25_and_walkable = jnp.logical_or(in_Room_24_and_walkable, in_Room_25_and_walkable) + Room_26_or_27_and_walkable = jnp.logical_or(in_Room_26_and_walkable, in_Room_27_and_walkable) + Room_28_or_29_and_walkable = jnp.logical_or(in_Room_28_and_walkable, in_Room_29_and_walkable) + + Room_15_or_16_or_17_or_18_and_walkable = jnp.logical_or(Room_15_or_16_and_walkable, Room_17_or_18_and_walkable) + Room_20_or_21_or_22_or_23_and_walkable = jnp.logical_or(Room_20_or_21_and_walkable, Room_22_or_23_and_walkable) + Room_24_or_25_or_26_or_27_and_walkable = jnp.logical_or(Room_24_or_25_and_walkable, Room_26_or_27_and_walkable) + + Room_15_or_16_or_17_or_18_or_20_or_21_or_22_or_23_and_walkable = jnp.logical_or(Room_15_or_16_or_17_or_18_and_walkable, Room_20_or_21_or_22_or_23_and_walkable) + Room_24_or_25_or_26_or_27_or_28_or_29_or_30_and_walkable = jnp.logical_or(jnp.logical_or(Room_24_or_25_or_26_or_27_and_walkable, Room_28_or_29_and_walkable),in_Room_30_and_walkable) + + current_Room_is_walkable = jnp.logical_or(jnp.logical_or(Room_15_or_16_or_17_or_18_or_20_or_21_or_22_or_23_and_walkable, Room_24_or_25_or_26_or_27_or_28_or_29_or_30_and_walkable), self._env._check_for_wall(state, direction)) + #jax.debug.print("is walkable {a}", a= current_Room_is_walkable) + + + edge_left = self._env.consts.PATH_VERTICAL_LEFT + edge_right = self._env.consts.PATH_VERTICAL_RIGHT + + edge_left = self._env.consts.PATH_VERTICAL_LEFT + edge_right = self._env.consts.PATH_VERTICAL_RIGHT + + #Castle Collisions + castle_tower_left = self._env.consts.CASTLE_TOWER_LEFT_X + castle_tower_right = self._env.consts.CASTLE_TOWER_RIGHT_X + castle_tower_height = self._env.consts.CASTLE_TOWER_CORNER_Y + castle_base_left = self._env.consts.CASTLE_BASE_LEFT_X + castle_base_right = self._env.consts.CASTLE_BASE_RIGHT_X + castle_base_height = self._env.consts.CASTLE_BASE_CORNER_Y + + castle_towers_out = jnp.logical_or(player_x<=castle_tower_left, player_x>=castle_tower_right) + castle_towers_in = jnp.logical_and(player_x>=edge_left, player_x<=edge_right) + castle_towers = jnp.logical_or(player_y >= castle_tower_height, jnp.logical_or(castle_towers_in, castle_towers_out)) + + castle_base_out = jnp.logical_or(player_x<=castle_base_left, player_x>=castle_base_right) + castle_base_in_1 = jnp.logical_and(jnp.logical_and(player_y>= castle_tower_height, player_y <= castle_base_height),jnp.logical_and(player_x>=edge_left+8, player_x<=edge_right-10)) + castle_base_in_2 = jnp.logical_and(player_y <= castle_tower_height, jnp.logical_and(player_x>=edge_left, player_x<=edge_right)) + castle_base_in = jnp.logical_or(castle_base_in_1, castle_base_in_2) + castle_base = jnp.logical_or(player_y >= castle_base_height, jnp.logical_or(castle_base_in, castle_base_out)) + + castle_walls = jnp.logical_and(castle_towers, castle_base) + + ##logic implementation gate border + + gate_yellow_open = state.gate_yellow[0] + + gate_black_open = state.gate_black[0] + + gate_white_open =state.gate_white[0] + + gate_yellow_not_block = jnp.logical_or( + jnp.logical_not(room == 0), + gate_yellow_open > 4 + ) + + gate_black_not_block = jnp.logical_or( + jnp.logical_not(room == 11), + gate_black_open > 4 + ) + + gate_white_not_block = jnp.logical_or( + jnp.logical_not(room == 24), + gate_white_open > 4 + ) + + gates_not_blocking = jnp.logical_and(jnp.logical_and(gate_yellow_not_block, gate_black_not_block),gate_white_not_block) + + castle_gate = jnp.logical_or( + gates_not_blocking, + jnp.logical_or( + jnp.logical_or( + player_x >= edge_right, + player_x <= edge_left + ), + player_y >= castle_base_height + ) + ) + + castle_collision = jnp.logical_or( + jnp.logical_not(jnp.logical_or(jnp.logical_or(room==0, room==11), room==24)), #either it is not a castle tile, or + jnp.logical_and(castle_walls, castle_gate) + ) + + + walls_detected = jnp.logical_and(current_Room_is_walkable, castle_collision ) + + #Check for Bridge negating wall + + bridgeX = state.bridge[0] + bridgeY = state.bridge[1] + bridgeTile =state.bridge[2] + + bridgeOnSameTile = bridgeTile == room + bridgeInRange = jnp.logical_and( + jnp.logical_and(player_x >= bridgeX + 8, player_x <= bridgeX + 24), + jnp.logical_and(player_y >= bridgeY, player_y <= bridgeY + 48) + ) + + bridge_detected = jnp.logical_and(bridgeOnSameTile, bridgeInRange) + + + return_bool = jnp.logical_or(walls_detected, bridge_detected) + + return return_bool + + left = jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(action== Action.LEFT, action == Action.LEFTFIRE),action== Action.UPLEFT),action == Action.UPLEFTFIRE), action==Action.DOWNLEFT), action==Action.DOWNLEFTFIRE) + right = jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(action== Action.RIGHT, action == Action.RIGHTFIRE),action== Action.UPRIGHT),action == Action.UPRIGHTFIRE), action==Action.DOWNRIGHT), action==Action.DOWNRIGHTFIRE) + up = jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(action== Action.UP, action == Action.UPFIRE),action== Action.UPRIGHT),action == Action.UPRIGHTFIRE), action==Action.UPLEFT), action==Action.UPLEFTFIRE) + down = jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(action== Action.DOWN, action == Action.DOWNFIRE),action== Action.DOWNRIGHT),action == Action.DOWNRIGHTFIRE), action==Action.DOWNLEFT), action==Action.DOWNLEFTFIRE) + + #check for no wall before walking + left_no_wall = jnp.logical_and(left,_check_walls_new_rooms(state, 0)) + right_no_wall = jnp.logical_and(right,_check_walls_new_rooms(state, 1)) + up_no_wall = jnp.logical_and(up,_check_walls_new_rooms(state, 2)) + down_no_wall = jnp.logical_and(down,_check_walls_new_rooms(state, 3)) + + new_step_counter = state.step_counter + + #get x cord of the item beeing held + new_item_x = jax.lax.switch( + state.player[3], + [lambda:0, + lambda:state.key_yellow[0], + lambda:state.key_black[0], + lambda:state.sword[0], + lambda:state.bridge[0], + lambda:state.magnet[0], + lambda:state.chalice[0], + lambda:state.key_white[0] + ] + ) + + new_player_x = state.player[0] + new_player_x, new_item_x, new_step_counter = jax.lax.cond( + left_no_wall, + lambda y: (y[0]-4,y[1]-4,y[2]+1), + lambda y: y, + operand = (new_player_x,new_item_x,new_step_counter), + ) + new_player_x, new_item_x, new_step_counter = jax.lax.cond( + right_no_wall, + lambda y: (y[0]+4,y[1]+4,y[2]+1), + lambda y: y, + operand = (new_player_x,new_item_x,new_step_counter), + ) + + #get y cord of the item beeing held + new_item_y = jax.lax.switch( + state.player[3], + [lambda:0, + lambda:state.key_yellow[1], + lambda:state.key_black[1], + lambda:state.sword[1], + lambda:state.bridge[1], + lambda:state.magnet[1], + lambda:state.chalice[1], + lambda:state.key_white[1] + ] + ) + + new_player_y = state.player[1] + new_player_y, new_item_y, new_step_counter = jax.lax.cond( + down_no_wall, + lambda y: (y[0]+8,y[1]+8,y[2]), + lambda y: y, + operand = (new_player_y,new_item_y,new_step_counter) + ) + new_player_y, new_item_y, new_step_counter = jax.lax.cond( + up_no_wall, + lambda y: (y[0]-8,y[1]-8,y[2]), + lambda y: y, + operand = (new_player_y,new_item_y,new_step_counter) + ) + new_player_tile = state.player[2] + new_item_tile = jax.lax.switch( + state.player[3], + [lambda:0, + lambda:state.key_yellow[2], + lambda:state.key_black[2], + lambda:state.sword[2], + lambda:state.bridge[2], + lambda:state.magnet[2], + lambda:state.chalice[2], + lambda:state.key_white[2] + ] + ) + + #enter yellow castle + new_player_y, new_player_tile, new_item_tile, new_item_y = jax.lax.cond( + jnp.logical_and(new_player_tile == 0, jnp.logical_and(new_player_y <148,jnp.logical_and(new_player_x<110, new_player_x>50))), + lambda: (212, 1, 1,new_item_y+(212-new_player_y)), + lambda: (new_player_y, new_player_tile, new_item_tile, new_item_y) + ) + + #leave yellow castle + new_player_x, new_player_y, new_player_tile, new_item_tile, new_item_y, new_item_x = jax.lax.cond( + jnp.logical_and(new_player_tile == 1, new_player_y >212), + lambda: (77, 148, 0, 0, new_item_y-(new_player_y-145),new_item_x+(77-new_player_x)), + lambda: (new_player_x, new_player_y, new_player_tile, new_item_tile, new_item_y, new_item_x) + ) + + #enter black castle + new_player_y, new_player_tile, new_item_tile, new_item_y = jax.lax.cond( + jnp.logical_and(new_player_tile == 11, jnp.logical_and(new_player_y <148,jnp.logical_and(new_player_x<110, new_player_x>50))), + lambda: (212, 12, 12,new_item_y+(212-new_player_y)), + lambda: (new_player_y, new_player_tile, new_item_tile, new_item_y) + ) + + #leave black castle + new_player_x, new_player_y, new_player_tile, new_item_tile, new_item_y, new_item_x = jax.lax.cond( + jnp.logical_and(new_player_tile == 12, new_player_y >212), + lambda: (77, 148, 11, 11, new_item_y-(new_player_y-148),new_item_x+(77-new_player_x)), + lambda: (new_player_x, new_player_y, new_player_tile, new_item_tile, new_item_y, new_item_x) + ) + + #enter white castle + new_player_y, new_player_tile, new_item_tile, new_item_y = jax.lax.cond( + jnp.logical_and(new_player_tile == 24, jnp.logical_and(new_player_y <148,jnp.logical_and(new_player_x<110, new_player_x>50))), + lambda: (212, 25, 25,new_item_y+(212-new_player_y)), + lambda: (new_player_y, new_player_tile, new_item_tile, new_item_y) + ) + + #leave white castle + new_player_x, new_player_y, new_player_tile, new_item_tile, new_item_y, new_item_x = jax.lax.cond( + jnp.logical_and(new_player_tile == 25, new_player_y >212), + lambda: (77, 148, 24, 24, new_item_y-(new_player_y-148),new_item_x+(77-new_player_x)), + lambda: (new_player_x, new_player_y, new_player_tile, new_item_tile, new_item_y, new_item_x) + ) + + #change of rooms + new_player_y, new_player_tile, new_item_tile, new_item_y = jax.lax.cond( + new_player_y > 212, + lambda _: (27, jax.lax.switch( new_player_tile, [lambda:2,lambda:0,lambda:0, + lambda:18, lambda:0, lambda:0, + lambda:5, lambda:8, lambda:0, + lambda: 6, lambda:7, lambda:10, + lambda:11, lambda:21, lambda:12, + lambda:14, lambda:17, lambda:16, + lambda:19, lambda:20, lambda:0, + lambda:4, lambda:23, lambda:0, + lambda:22, lambda:24, lambda:25, + lambda:28, lambda:24]), + jax.lax.switch( new_item_tile, [lambda:2,lambda:0,lambda:0, + lambda:18, lambda:0, lambda:0, + lambda:5, lambda:8, lambda:0, + lambda: 6, lambda:7, lambda:10, + lambda:11, lambda:21, lambda:12, + lambda:14, lambda:17, lambda:16, + lambda:19, lambda:20, lambda:0, + lambda:4, lambda:23, lambda:0, + lambda:22, lambda:24, lambda:25, + lambda:28, lambda:24]), new_item_y-(new_player_y-27)), + lambda _: (new_player_y, new_player_tile, new_item_tile, new_item_y), + operand = None, + ) + new_player_y, new_player_tile, new_item_tile, new_item_y = jax.lax.cond( + new_player_y < 27, + lambda _: (212, jax.lax.switch( new_player_tile, [lambda:1,lambda:0,lambda:0, + lambda:0, lambda:21, lambda:6, + lambda:9, lambda:10, lambda:7, + lambda: 0, lambda:11, lambda:12, + lambda:14, lambda:0, lambda:15, + lambda:0, lambda:17, lambda:16, + lambda:3, lambda:18, lambda:19, + lambda:13, lambda:24, lambda:22, + lambda:25, lambda:26, lambda:0, + lambda:0, lambda:27]), + jax.lax.switch( new_player_tile, [lambda:1,lambda:0,lambda:0, + lambda:0, lambda:21, lambda:6, + lambda:9, lambda:10, lambda:7, + lambda: 0, lambda:11, lambda:12, + lambda:14, lambda:0, lambda:15, + lambda:0, lambda:17, lambda:16, + lambda:3, lambda:18, lambda:19, + lambda:13, lambda:24, lambda:22, + lambda:25, lambda:26, lambda:0, + lambda:0, lambda:27]), new_item_y+(212-new_player_y)), + lambda _: (new_player_y, new_player_tile, new_item_tile, new_item_y), + operand = None, + ) + new_player_x, new_player_tile, new_item_tile, new_item_x = jax.lax.cond( + new_player_x > 160, + lambda _: (0, jax.lax.switch( new_player_tile, [lambda:0,lambda:0,lambda:3, + lambda:0, lambda:0, lambda:2, + lambda:7, lambda:6, lambda:10, + lambda: 8, lambda:9, lambda:0, + lambda:0, lambda:0, lambda:16, + lambda:17, lambda:15, lambda:14, + lambda:19, lambda:18, lambda:21, + lambda:0, lambda:20, lambda:0, + lambda:0, lambda:28, lambda:27, + lambda:26, lambda:25]), + jax.lax.switch( new_player_tile, [lambda:0,lambda:0,lambda:3, + lambda:0, lambda:0, lambda:2, + lambda:7, lambda:6, lambda:10, + lambda: 8, lambda:9, lambda:0, + lambda:0, lambda:0, lambda:16, + lambda:17, lambda:15, lambda:14, + lambda:19, lambda:18, lambda:21, + lambda:0, lambda:20, lambda:0, + lambda:0, lambda:28, lambda:27, + lambda:26, lambda:25]), new_item_x-new_player_x), + lambda _: (new_player_x, new_player_tile, new_item_tile, new_item_x), + operand = None, + ) + new_player_x, new_player_tile, new_item_tile, new_item_x = jax.lax.cond( + new_player_x < 0, + lambda _: (160, jax.lax.switch( new_player_tile, [lambda:0,lambda:0,lambda:5, + lambda:2, lambda:0, lambda:0, + lambda:7, lambda:6, lambda:9, + lambda: 10, lambda:8, lambda:0, + lambda:0, lambda:0, lambda:17, + lambda:16, lambda:14, lambda:15, + lambda:19, lambda:18, lambda:22, + lambda:20, lambda:0, lambda:20, + lambda:0, lambda:28, lambda:27, + lambda:26, lambda:25]), + jax.lax.switch( new_player_tile, [lambda:0,lambda:0,lambda:5, + lambda:2, lambda:0, lambda:0, + lambda:7, lambda:6, lambda:9, + lambda: 10, lambda:8, lambda:0, + lambda:0, lambda:0, lambda:17, + lambda:16, lambda:14, lambda:15, + lambda:19, lambda:18, lambda:22, + lambda:20, lambda:0, lambda:20, + lambda:0, lambda:28, lambda:27, + lambda:26, lambda:25]), new_item_x+(160-new_player_x)), + lambda _: (new_player_x, new_player_tile, new_item_tile, new_item_x), + operand = None, + ) + + return state.replace( + step_counter = jnp.array(new_step_counter).astype(jnp.int32), + player = jnp.array([new_player_x,new_player_y,new_player_tile,state.player[3]]).astype(jnp.int32), #SEEMS NOT GOOD + key_yellow = jax.lax.cond(state.player[3]==self._env.consts.KEY_YELLOW_ID, + lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: op[3], + operand=(new_item_x,new_item_y,new_item_tile,state.key_yellow), + ), + key_black= jax.lax.cond(state.player[3]==self._env.consts.KEY_BLACK_ID, + lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: op[3], + operand=(new_item_x,new_item_y,new_item_tile,state.key_black) + ), + key_white = jax.lax.cond(state.player[3]==self._env.consts.KEY_WHITE_ID, + lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: op[3], + operand=(new_item_x,new_item_y,new_item_tile,state.key_white), + ), + sword= jax.lax.cond(state.player[3]==self._env.consts.SWORD_ID, + lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: op[3], + operand=(new_item_x,new_item_y,new_item_tile,state.sword) + ), + bridge= jax.lax.cond(state.player[3]==self._env.consts.BRIDGE_ID, + lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: op[3], + operand=(new_item_x,new_item_y,new_item_tile,state.bridge) + ), + magnet= jax.lax.cond(state.player[3]==self._env.consts.MAGNET_ID, + lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: op[3], + operand=(new_item_x,new_item_y,new_item_tile,state.magnet) + ), + chalice= jax.lax.cond(state.player[3]==self._env.consts.CHALICE_ID, + lambda op: jnp.array([op[0],op[1],op[2],op[3]]).astype(jnp.int32), + lambda op: op[4], + operand=(new_item_x,new_item_y,new_item_tile,state.chalice[3],state.chalice) + ) + ) + + #dragons with bat + @partial(jax.jit, static_argnums=(0,)) + def _dragon_step(self, state: AdventureState) -> AdventureState: + speed = self._env.consts.DRAGON_SPEED + + #get sword position to kill dragons + sword_x = state.sword[0] + sword_y = state.sword[1] + sword_room = state.sword[2] + + #yellow dragon + direction_x = jnp.sign(state.player[0] - state.dragon_yellow[0]) + direction_y = jnp.sign(state.player[1]- state.dragon_yellow[1]) + dragon_yellow_x = state.dragon_yellow[0] + dragon_yellow_y = state.dragon_yellow[1] + dragon_yellow_tile = state.dragon_yellow[2] + dragon_yellow_animation = state.dragon_yellow[3] + dragon_yellow_counter = state.dragon_yellow[4] + dragon_yellow_activate = state.dragon_yellow[6] + + # wait after attack + dragon_yellow_counter = jax.lax.cond( + dragon_yellow_animation == 1, + lambda f: f+1, + lambda f:f, + operand = dragon_yellow_counter + ) + dragon_yellow_freeze = dragon_yellow_counter % self._env.consts.DRAGON_BITE_TIMER != 0 + + #dragon starts looking for plyer room after first encounter + dragon_yellow_activate = jax.lax.cond(state.player[2] == dragon_yellow_tile, lambda:1, lambda: dragon_yellow_activate) + rndKey, subkey = jax.random.split(state.rndKey) + dragon_yellow_x, dragon_yellow_y, dragon_yellow_tile = jax.lax.cond( + jnp.logical_and(jnp.logical_and(dragon_yellow_tile != state.player[2], jnp.logical_not(dragon_yellow_freeze)),dragon_yellow_activate==1), + lambda: (jax.lax.cond(dragon_yellow_x>156, lambda:4, lambda:dragon_yellow_x +2), + jax.lax.cond(dragon_yellow_y>208, lambda:4, lambda:dragon_yellow_y+2), + jax.lax.cond(jnp.logical_or(dragon_yellow_x>156,dragon_yellow_y>208), lambda:jax.random.randint(subkey, (), 0, 28) , lambda:dragon_yellow_tile)), + lambda:(dragon_yellow_x, dragon_yellow_y, dragon_yellow_tile) + ) + + #dragon eats player + dragon_yellow_eat = jax.lax.cond( + jnp.logical_and(jnp.logical_and((state.player[0]-dragon_yellow_x)*direction_x<4,(state.player[1]-dragon_yellow_y)*direction_y<4),jnp.logical_and(dragon_yellow_animation==1,jnp.logical_not(dragon_yellow_freeze))), + lambda:1, + lambda:0 + ) + + #move towards player and attack + dragon_yellow_x, dragon_yellow_y, dragon_yellow_animation, dragon_yellow_counter= jax.lax.cond( + jnp.logical_and(state.player[2]==dragon_yellow_tile,jnp.logical_not(dragon_yellow_freeze)), + lambda _: (dragon_yellow_x + direction_x*speed, dragon_yellow_y + direction_y*speed, jax.lax.cond( + jnp.logical_and((state.player[0]-dragon_yellow_x)*direction_x<4,(state.player[1]-dragon_yellow_y)*direction_y<4), + lambda _:jax.lax.cond(dragon_yellow_animation==2, lambda _:2, lambda _:1, operand = None), + lambda _:jax.lax.cond(dragon_yellow_animation==2, lambda _:2, lambda _:0, operand = None), + operand = None + ),0), + lambda _: (dragon_yellow_x, dragon_yellow_y, jax.lax.cond(jnp.logical_not(dragon_yellow_freeze), lambda _: jax.lax.cond(dragon_yellow_animation==2, lambda _:2, lambda _:0, operand = None), lambda _: jax.lax.cond(dragon_yellow_animation==2, lambda _:2, lambda _:1, operand = None), operand = None), dragon_yellow_counter), + operand = None + ) + + #kill dragon + direction_x = jnp.sign(sword_x - state.dragon_yellow[0]) + direction_y = jnp.sign(sword_y- state.dragon_yellow[1]) + dragon_yellow_animation = jax.lax.cond( + jnp.logical_and(dragon_yellow_tile==sword_room, jnp.logical_and((sword_x-dragon_yellow_x)*direction_x<4, (sword_y-dragon_yellow_y)*direction_y<22)), + lambda _:2, + lambda a:a, + operand= dragon_yellow_animation + ) + + # dont ever move again when dead + dragon_yellow_counter = jax.lax.cond( + dragon_yellow_animation == 2, + lambda _: 1, + lambda f:f, + operand=dragon_yellow_counter + ) + + + #green dragon + direction_x = jnp.sign(state.player[0] - state.dragon_green[0]) + direction_y = jnp.sign(state.player[1]- state.dragon_green[1]) + dragon_green_x = state.dragon_green[0] + dragon_green_y = state.dragon_green[1] + dragon_green_tile = state.dragon_green[2] + dragon_green_animation = state.dragon_green[3] + dragon_green_counter = state.dragon_green[4] + dragon_green_activate = state.dragon_green[6] + + # wait after attack + dragon_green_counter = jax.lax.cond( + dragon_green_animation == 1, + lambda f: f+1, + lambda f:f, + operand = dragon_green_counter + ) + dragon_green_freeze = dragon_green_counter % self._env.consts.DRAGON_BITE_TIMER != 0 + + #dragon starts looking for plyer room after first encounter + dragon_green_activate = jax.lax.cond(state.player[2] == dragon_green_tile, lambda:1, lambda: dragon_green_activate) + rndKey, subkey = jax.random.split(rndKey) + dragon_green_x, dragon_green_y, dragon_green_tile = jax.lax.cond( + jnp.logical_and(jnp.logical_and(dragon_green_tile != state.player[2], jnp.logical_not(dragon_green_freeze)),dragon_green_activate==1), + lambda: (jax.lax.cond(dragon_green_x>156, lambda:4, lambda:dragon_green_x +2), + jax.lax.cond(dragon_green_y>208, lambda:4, lambda:dragon_green_y+2), + jax.lax.cond(jnp.logical_or(dragon_green_x>156,dragon_green_y>208), lambda:jax.random.randint(subkey, (), 0, 28) , lambda:dragon_green_tile)), + lambda:(dragon_green_x, dragon_green_y, dragon_green_tile) + ) + + #dragon eats player + dragon_green_eat = jax.lax.cond( + jnp.logical_and(jnp.logical_and((state.player[0]-dragon_green_x)*direction_x<4,(state.player[1]-dragon_green_y)*direction_y<4),jnp.logical_and(dragon_green_animation==1,jnp.logical_not(dragon_green_freeze))), + lambda:1, + lambda:0 + ) + + #move towards player and attack + dragon_green_x, dragon_green_y, dragon_green_animation, dragon_green_counter= jax.lax.cond( + jnp.logical_and(state.player[2]==dragon_green_tile,jnp.logical_not(dragon_green_freeze)), + lambda _: (dragon_green_x + direction_x*speed, dragon_green_y + direction_y*speed, jax.lax.cond( + jnp.logical_and(jnp.logical_and((state.player[0]-dragon_green_x)*direction_x<4,(state.player[1]-dragon_green_y)*direction_y<4),dragon_green_animation!=2), + lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:1, operand = None), + lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:0, operand = None), + operand = None + ),0), + lambda _: (dragon_green_x, dragon_green_y, jax.lax.cond(jnp.logical_not(dragon_green_freeze), lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:0, operand = None), lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:1, operand = None), operand = None), dragon_green_counter), + operand = None + ) + + #kill dragon + direction_x = jnp.sign(sword_x - state.dragon_green[0]) + direction_y = jnp.sign(sword_y- state.dragon_green[1]) + dragon_green_animation = jax.lax.cond( + jnp.logical_and(dragon_green_tile==sword_room, jnp.logical_and((sword_x-dragon_green_x)*direction_x<4, (sword_y-dragon_green_y)*direction_y<22)), + lambda _:2, + lambda a:a, + operand = dragon_green_animation + ) + + # dont ever move again when dead + dragon_green_counter = jax.lax.cond( + dragon_green_animation == 2, + lambda _: 1, + lambda f:f, + operand=dragon_green_counter + ) + + #red dragon + direction_x = jnp.sign(state.player[0] - state.dragon_red[0]) + direction_y = jnp.sign(state.player[1]- state.dragon_red[1]) + dragon_red_x = state.dragon_red[0] + dragon_red_y = state.dragon_red[1] + dragon_red_tile = state.dragon_red[2] + dragon_red_animation = state.dragon_red[3] + dragon_red_counter = state.dragon_red[4] + dragon_red_activate = state.dragon_red[6] + + # wait after attack + dragon_red_counter = jax.lax.cond( + dragon_red_animation == 1, + lambda f: f+1, + lambda f:f, + operand = dragon_red_counter + ) + dragon_red_freeze = dragon_red_counter % self._env.consts.DRAGON_BITE_TIMER != 0 + + #dragon starts looking for plyer room after first encounter + dragon_red_activate = jax.lax.cond(state.player[2] == dragon_red_tile, lambda:1, lambda: dragon_red_activate) + rndKey, subkey = jax.random.split(state.rndKey) + dragon_red_x, dragon_red_y, dragon_red_tile = jax.lax.cond( + jnp.logical_and(jnp.logical_and(dragon_red_tile != state.player[2], jnp.logical_not(dragon_red_freeze)),dragon_red_activate==1), + lambda: (jax.lax.cond(dragon_red_x>156, lambda:4, lambda:dragon_red_x +2), + jax.lax.cond(dragon_red_y>208, lambda:4, lambda:dragon_red_y+2), + jax.lax.cond(jnp.logical_or(dragon_red_x>156,dragon_red_y>208), lambda:jax.random.randint(subkey, (), 0, 28) , lambda:dragon_red_tile)), + lambda:(dragon_red_x, dragon_red_y, dragon_red_tile) + ) + + #dragon eats player + dragon_red_eat = jax.lax.cond( + jnp.logical_and(jnp.logical_and((state.player[0]-dragon_red_x)*direction_x<4,(state.player[1]-dragon_red_y)*direction_y<4),jnp.logical_and(dragon_red_animation==1,jnp.logical_not(dragon_red_freeze))), + lambda:1, + lambda:0 + ) + + #move towards player and attack + dragon_red_x, dragon_red_y, dragon_red_animation, dragon_red_counter= jax.lax.cond( + jnp.logical_and(state.player[2]==dragon_red_tile,jnp.logical_not(dragon_red_freeze)), + lambda _: (dragon_red_x + direction_x*speed, dragon_red_y + direction_y*speed, jax.lax.cond( + jnp.logical_and((state.player[0]-dragon_red_x)*direction_x<4,(state.player[1]-dragon_red_y)*direction_y<4), + lambda _:jax.lax.cond(dragon_red_animation==2, lambda _:2, lambda _:1, operand = None), + lambda _:jax.lax.cond(dragon_red_animation==2, lambda _:2, lambda _:0, operand = None), + operand = None + ),0), + lambda _: (dragon_red_x, dragon_red_y, jax.lax.cond(jnp.logical_not(dragon_red_freeze), lambda _: jax.lax.cond(dragon_red_animation==2, lambda _:2, lambda _:0, operand = None), lambda _: jax.lax.cond(dragon_red_animation==2, lambda _:2, lambda _:1, operand = None), operand = None), dragon_red_counter), + operand = None + ) + + #kill dragon + direction_x = jnp.sign(sword_x - state.dragon_red[0]) + direction_y = jnp.sign(sword_y- state.dragon_red[1]) + dragon_red_animation = jax.lax.cond( + jnp.logical_and(dragon_red_tile==sword_room, jnp.logical_and((sword_x-dragon_red_x)*direction_x<4, (sword_y-dragon_red_y)*direction_y<22)), + lambda _:2, + lambda a:a, + operand= dragon_red_animation + ) + + # dont ever move again when dead + dragon_red_counter = jax.lax.cond( + dragon_red_animation == 2, + lambda _: 1, + lambda f:f, + operand=dragon_red_counter + ) + + + return state.replace( + dragon_yellow = jnp.array([dragon_yellow_x,dragon_yellow_y,dragon_yellow_tile,dragon_yellow_animation,dragon_yellow_counter,dragon_yellow_eat, dragon_yellow_activate]).astype(jnp.int32), + dragon_green = jnp.array([dragon_green_x,dragon_green_y,dragon_green_tile,dragon_green_animation,dragon_green_counter,dragon_green_eat, dragon_green_activate]).astype(jnp.int32), + dragon_red = jnp.array([dragon_red_x,dragon_red_y,dragon_red_tile,dragon_red_animation,dragon_red_counter,dragon_red_eat, dragon_red_activate]).astype(jnp.int32), + rndKey=rndKey + ) + +class LevelThreeMod(JaxAtariInternalModPlugin): + asset_overrides = { + #all rooms in order + 'room_number': {'name': 'room_number', 'type': 'group', 'files': ['Room_1.npy', + 'Room_2.npy', + 'Room_3.npy', + 'Room_4.npy', + 'Room_5.npy', + 'Room_6.npy', + 'Room_7.npy', + 'Room_8.npy', + 'Room_9.npy', + 'Room_10.npy', + 'Room_11.npy', + 'Room_12.npy', + 'Room_13.npy', + 'Room_14.npy', + 'Room_15.npy', + 'Room_16.npy', + 'Room_17.npy', + 'Room_18.npy', + 'Room_20.npy', + 'Room_21.npy', + 'Room_22.npy', + 'Room_23.npy', + 'Room_24.npy', + 'Room_25.npy', + 'Room_26.npy', + 'Room_27.npy', + 'Room_28.npy', + 'Room_29.npy', + 'Room_30.npy' + ]}, + #Player in all the different colors, which change depending on the background + "player_colors": {'name': 'player_colors', 'type': 'group', 'files': ["Player_Yellow.npy", + "Player_Yellow.npy", + "Player_Green.npy", + "Player_Purple.npy", + "Player_Pink.npy", + "Player_Green_yellow.npy", + "Player_Blue.npy", + "Player_Blue.npy", + "Player_Blue.npy", + "Player_Blue.npy", + "Player_Blue.npy", + "Player_Black.npy", + "Player_Pink.npy", + "Player_Magenta.npy", + "Player_inverted.npy", + "Player_inverted.npy", + "Player_inverted.npy", + "Player_inverted.npy", + "Player_inverted.npy", + "Player_inverted.npy", + "Player_inverted.npy", + "Player_BabyBlue.npy", + "Player_Turquoise.npy", + "Player_LightBlue.npy", + "Player_White.npy", + "Player_Orange.npy", + "Player_Orange.npy", + "Player_Orange.npy", + "Player_Orange.npy"]}, + #Red Dragon + "dragon_red": {'name': 'dragon_red', 'type': 'group', 'files': ['Dragon_red_neutral.npy', + 'Dragon_red_attack.npy', + 'Dragon_red_dead.npy']}, + #white Key + "key_white": {'name': 'key_white', 'type': 'single', 'file': 'Key_white.npy'}, + + #bat + "bat": {'name': 'bat', 'type': 'group', 'files': ['bat_1.npy', + 'bat_2.npy']} + } + + rndSpawnLocations = [(31,170,19),(31,100,28),(31,110,8),(31,180,0),(65,130,20),(120,180,23),(50,170,15)] + random.shuffle(rndSpawnLocations) + constants_overrides ={ + + + "DRAGON_YELLOW_SPAWN": (80, 170, 25, 0, 0, 0, 0), + "DRAGON_GREEN_SPAWN": (80, 130, 5, 0, 0, 0, 0), + "DRAGON_RED_SPAWN": (80, 130, 15, 0, 0, 0, 0), + "KEY_YELLOW_SPAWN": rndSpawnLocations[0], + "KEY_BLACK_SPAWN": rndSpawnLocations[1], + "KEY_WHITE_SPAWN": rndSpawnLocations[2], + "SWORD_SPAWN": rndSpawnLocations[3], + "BRIDGE_SPAWN": rndSpawnLocations[4], + "MAGNET_SPAWN": rndSpawnLocations[5], + "CHALICE_SPAWN": rndSpawnLocations[6], + "BAT_SPAWN": (76, 140, 11, 0) + } + + @partial(jax.jit, static_argnums=(0,)) + def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureState: + def _check_walls_new_rooms(state: AdventureState, direction: int) -> bool: + room = state.player[2] + + # direction 0: left, 1: right, 2: up, 3: down + player_x = state.player[0] + player_x = jax.lax.cond( + direction == 0, + lambda x: x-4, + lambda x: x, + operand = player_x, + ) + player_x = jax.lax.cond( + direction == 1, + lambda x: x+4, + lambda x: x, + operand = player_x, + ) + + player_y = state.player[1] + player_y = jax.lax.cond( + direction == 2, + lambda y: y-8, + lambda y: y, + operand = player_y, + ) + player_y = jax.lax.cond( + direction == 3, + lambda y: y+8, + lambda y: y, + operand = player_y, + ) + + #jax.debug.print("step") + #test load background of Rooms + def is_tile_walkable(tileset: jnp.ndarray, Pos_x: int, Pos_y: int) -> bool: + #determin if we should be allowed to walk, based on the background only + #tileset data at a given x and y position is [r, g, b, 255] + #[151, 151, 151, 255] = Grey (allowed player movement) + #[0, 0, 0, 255] are top or bottom border allow movement for tilechange + #anything else are walls (inversed in certain maze tileset) . + is_walkable_1 = (tileset[Pos_y+2,Pos_x][0] == jnp.uint8(151)) + is_walkable_2 = (tileset[Pos_y+2,Pos_x][1] == jnp.uint8(151)) + is_walkable_3 = (tileset[Pos_y+2,Pos_x][2] == jnp.uint8(151)) + is_walkable = jnp.logical_and(is_walkable_1, jnp.logical_and(is_walkable_2,is_walkable_3)) + is_border_1 = (tileset[Pos_y+2,Pos_x][0] == jnp.uint8(0)) + is_border_2 = (tileset[Pos_y+2,Pos_x][1] == jnp.uint8(0)) + is_border_3 = (tileset[Pos_y+2,Pos_x][2] == jnp.uint8(0)) + is_border = jnp.logical_and(is_border_1, jnp.logical_and(is_border_2,is_border_3)) + #jax.debug.print("Tile: {a} is walkable {b}",a=tileset[Pos_y,Pos_x][0:3], b=is_walkable) + return jnp.logical_or(is_walkable,is_border) + + def is_inverted_walkable(tileset: jnp.ndarray, Pos_x: int, Pos_y: int) -> bool: + #determin if we should be allowed to walk, based on the background only + #tileset data at a given x and y position is [r, g, b, 255] + #[151, 151, 151, 255] = Grey (allowed player movement) + #[0, 0, 0, 255] are top or bottom border allow movement for tilechange + #anything else are walls (inversed in certain maze tileset) . + is_walkable_1 = (tileset[Pos_y+2,Pos_x][0] == jnp.uint8(151)) + is_walkable_2 = (tileset[Pos_y+2,Pos_x][1] == jnp.uint8(151)) + is_walkable_3 = (tileset[Pos_y+2,Pos_x][2] == jnp.uint8(151)) + is_walkable = jnp.logical_and(is_walkable_1, jnp.logical_and(is_walkable_2,is_walkable_3)) + #jax.debug.print("Tile: {a} is walkable {b}",a=tileset[Pos_y,Pos_x][0:3], b=is_walkable) + return is_walkable + + def _load_background_map(path: str) -> jnp.ndarray: + background_map = jnp.load(path) + return background_map + + + sprite_path = f"{os.path.dirname(os.path.abspath(__file__))}/sprites" + + #jax.debug.print("Room: {a} is equal to 0 {b}, is walkable {c}",a=room, b=(room == 0),c=is_tile_walkable(self.BackgroundRoom1, player_x, player_y)) + in_Room_15_and_walkable = jnp.logical_and(jnp.equal(room, 14), jnp.logical_not(is_inverted_walkable(_load_background_map(os.path.join(sprite_path, "Room_15.npy")), player_x, player_y))) + in_Room_16_and_walkable = jnp.logical_and(jnp.equal(room, 15), jnp.logical_not(is_inverted_walkable(_load_background_map(os.path.join(sprite_path, "Room_16.npy")), player_x, player_y))) + in_Room_17_and_walkable = jnp.logical_and(jnp.equal(room, 16), jnp.logical_not(is_inverted_walkable(_load_background_map(os.path.join(sprite_path, "Room_17.npy")), player_x, player_y))) + in_Room_18_and_walkable = jnp.logical_and(jnp.equal(room, 17), jnp.logical_not(is_inverted_walkable(_load_background_map(os.path.join(sprite_path, "Room_18.npy")), player_x, player_y))) + in_Room_20_and_walkable = jnp.logical_and(jnp.equal(room, 18), jnp.logical_not(is_inverted_walkable(_load_background_map(os.path.join(sprite_path, "Room_20.npy")), player_x, player_y))) + in_Room_21_and_walkable = jnp.logical_and(jnp.equal(room, 19), jnp.logical_not(is_inverted_walkable(_load_background_map(os.path.join(sprite_path, "Room_21.npy")), player_x, player_y))) + in_Room_22_and_walkable = jnp.logical_and(jnp.equal(room, 20), jnp.logical_not(is_inverted_walkable(_load_background_map(os.path.join(sprite_path, "Room_22.npy")), player_x, player_y))) + in_Room_23_and_walkable = jnp.logical_and(jnp.equal(room, 21), is_tile_walkable(_load_background_map(os.path.join(sprite_path, "Room_23.npy")), player_x, player_y)) + in_Room_24_and_walkable = jnp.logical_and(jnp.equal(room, 22), is_tile_walkable(_load_background_map(os.path.join(sprite_path, "Room_24.npy")), player_x, player_y)) + in_Room_25_and_walkable = jnp.logical_and(jnp.equal(room, 23), is_tile_walkable(_load_background_map(os.path.join(sprite_path, "Room_25.npy")), player_x, player_y)) + in_Room_26_and_walkable = jnp.logical_and(jnp.equal(room, 24), is_tile_walkable(_load_background_map(os.path.join(sprite_path, "Room_26.npy")), player_x, player_y)) + in_Room_27_and_walkable = jnp.logical_and(jnp.equal(room, 25), is_tile_walkable(_load_background_map(os.path.join(sprite_path, "Room_27.npy")), player_x, player_y)) + in_Room_28_and_walkable = jnp.logical_and(jnp.equal(room, 26), is_tile_walkable(_load_background_map(os.path.join(sprite_path, "Room_28.npy")), player_x, player_y)) + in_Room_29_and_walkable = jnp.logical_and(jnp.equal(room, 27), is_tile_walkable(_load_background_map(os.path.join(sprite_path, "Room_29.npy")), player_x, player_y)) + in_Room_30_and_walkable = jnp.logical_and(jnp.equal(room, 28), is_tile_walkable(_load_background_map(os.path.join(sprite_path, "Room_30.npy")), player_x, player_y)) + + Room_15_or_16_and_walkable = jnp.logical_or(in_Room_15_and_walkable, in_Room_16_and_walkable) + Room_17_or_18_and_walkable = jnp.logical_or(in_Room_17_and_walkable, in_Room_18_and_walkable) + Room_20_or_21_and_walkable = jnp.logical_or(in_Room_20_and_walkable, in_Room_21_and_walkable) + Room_22_or_23_and_walkable = jnp.logical_or(in_Room_22_and_walkable, in_Room_23_and_walkable) + Room_24_or_25_and_walkable = jnp.logical_or(in_Room_24_and_walkable, in_Room_25_and_walkable) + Room_26_or_27_and_walkable = jnp.logical_or(in_Room_26_and_walkable, in_Room_27_and_walkable) + Room_28_or_29_and_walkable = jnp.logical_or(in_Room_28_and_walkable, in_Room_29_and_walkable) + + Room_15_or_16_or_17_or_18_and_walkable = jnp.logical_or(Room_15_or_16_and_walkable, Room_17_or_18_and_walkable) + Room_20_or_21_or_22_or_23_and_walkable = jnp.logical_or(Room_20_or_21_and_walkable, Room_22_or_23_and_walkable) + Room_24_or_25_or_26_or_27_and_walkable = jnp.logical_or(Room_24_or_25_and_walkable, Room_26_or_27_and_walkable) + + Room_15_or_16_or_17_or_18_or_20_or_21_or_22_or_23_and_walkable = jnp.logical_or(Room_15_or_16_or_17_or_18_and_walkable, Room_20_or_21_or_22_or_23_and_walkable) + Room_24_or_25_or_26_or_27_or_28_or_29_or_30_and_walkable = jnp.logical_or(jnp.logical_or(Room_24_or_25_or_26_or_27_and_walkable, Room_28_or_29_and_walkable),in_Room_30_and_walkable) + + current_Room_is_walkable = jnp.logical_or(jnp.logical_or(Room_15_or_16_or_17_or_18_or_20_or_21_or_22_or_23_and_walkable, Room_24_or_25_or_26_or_27_or_28_or_29_or_30_and_walkable), self._env._check_for_wall(state, direction)) + #jax.debug.print("is walkable {a}", a= current_Room_is_walkable) + + + edge_left = self._env.consts.PATH_VERTICAL_LEFT + edge_right = self._env.consts.PATH_VERTICAL_RIGHT + + edge_left = self._env.consts.PATH_VERTICAL_LEFT + edge_right = self._env.consts.PATH_VERTICAL_RIGHT + + #Castle Collisions + castle_tower_left = self._env.consts.CASTLE_TOWER_LEFT_X + castle_tower_right = self._env.consts.CASTLE_TOWER_RIGHT_X + castle_tower_height = self._env.consts.CASTLE_TOWER_CORNER_Y + castle_base_left = self._env.consts.CASTLE_BASE_LEFT_X + castle_base_right = self._env.consts.CASTLE_BASE_RIGHT_X + castle_base_height = self._env.consts.CASTLE_BASE_CORNER_Y + + castle_towers_out = jnp.logical_or(player_x<=castle_tower_left, player_x>=castle_tower_right) + castle_towers_in = jnp.logical_and(player_x>=edge_left, player_x<=edge_right) + castle_towers = jnp.logical_or(player_y >= castle_tower_height, jnp.logical_or(castle_towers_in, castle_towers_out)) + + castle_base_out = jnp.logical_or(player_x<=castle_base_left, player_x>=castle_base_right) + castle_base_in_1 = jnp.logical_and(jnp.logical_and(player_y>= castle_tower_height, player_y <= castle_base_height),jnp.logical_and(player_x>=edge_left+8, player_x<=edge_right-10)) + castle_base_in_2 = jnp.logical_and(player_y <= castle_tower_height, jnp.logical_and(player_x>=edge_left, player_x<=edge_right)) + castle_base_in = jnp.logical_or(castle_base_in_1, castle_base_in_2) + castle_base = jnp.logical_or(player_y >= castle_base_height, jnp.logical_or(castle_base_in, castle_base_out)) + + castle_walls = jnp.logical_and(castle_towers, castle_base) + + ##logic implementation gate border + + gate_yellow_open = state.gate_yellow[0] + + gate_black_open = state.gate_black[0] + + gate_white_open =state.gate_white[0] + + gate_yellow_not_block = jnp.logical_or( + jnp.logical_not(room == 0), + gate_yellow_open > 4 + ) + + gate_black_not_block = jnp.logical_or( + jnp.logical_not(room == 11), + gate_black_open > 4 + ) + + gate_white_not_block = jnp.logical_or( + jnp.logical_not(room == 24), + gate_white_open > 4 + ) + + gates_not_blocking = jnp.logical_and(jnp.logical_and(gate_yellow_not_block, gate_black_not_block),gate_white_not_block) + + castle_gate = jnp.logical_or( + gates_not_blocking, + jnp.logical_or( + jnp.logical_or( + player_x >= edge_right, + player_x <= edge_left + ), + player_y >= castle_base_height + ) + ) + + castle_collision = jnp.logical_or( + jnp.logical_not(jnp.logical_or(jnp.logical_or(room==0, room==11), room==24)), #either it is not a castle tile, or + jnp.logical_and(castle_walls, castle_gate) + ) + + + walls_detected = jnp.logical_and(current_Room_is_walkable, castle_collision ) + + #Check for Bridge negating wall + + bridgeX = state.bridge[0] + bridgeY = state.bridge[1] + bridgeTile =state.bridge[2] + + bridgeOnSameTile = bridgeTile == room + bridgeInRange = jnp.logical_and( + jnp.logical_and(player_x >= bridgeX + 8, player_x <= bridgeX + 24), + jnp.logical_and(player_y >= bridgeY, player_y <= bridgeY + 48) + ) + + bridge_detected = jnp.logical_and(bridgeOnSameTile, bridgeInRange) + + + return_bool = jnp.logical_or(walls_detected, bridge_detected) + + return return_bool + + left = jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(action== Action.LEFT, action == Action.LEFTFIRE),action== Action.UPLEFT),action == Action.UPLEFTFIRE), action==Action.DOWNLEFT), action==Action.DOWNLEFTFIRE) + right = jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(action== Action.RIGHT, action == Action.RIGHTFIRE),action== Action.UPRIGHT),action == Action.UPRIGHTFIRE), action==Action.DOWNRIGHT), action==Action.DOWNRIGHTFIRE) + up = jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(action== Action.UP, action == Action.UPFIRE),action== Action.UPRIGHT),action == Action.UPRIGHTFIRE), action==Action.UPLEFT), action==Action.UPLEFTFIRE) + down = jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(action== Action.DOWN, action == Action.DOWNFIRE),action== Action.DOWNRIGHT),action == Action.DOWNRIGHTFIRE), action==Action.DOWNLEFT), action==Action.DOWNLEFTFIRE) + + #check for no wall before walking + left_no_wall = jnp.logical_and(left,_check_walls_new_rooms(state, 0)) + right_no_wall = jnp.logical_and(right,_check_walls_new_rooms(state, 1)) + up_no_wall = jnp.logical_and(up,_check_walls_new_rooms(state, 2)) + down_no_wall = jnp.logical_and(down,_check_walls_new_rooms(state, 3)) + + new_step_counter = state.step_counter + + #get x cord of the item beeing held + new_item_x = jax.lax.switch( + state.player[3], + [lambda:0, + lambda:state.key_yellow[0], + lambda:state.key_black[0], + lambda:state.sword[0], + lambda:state.bridge[0], + lambda:state.magnet[0], + lambda:state.chalice[0], + lambda:state.key_white[0] + ] + ) + + new_player_x = state.player[0] + new_player_x, new_item_x, new_step_counter = jax.lax.cond( + left_no_wall, + lambda y: (y[0]-4,y[1]-4,y[2]+1), + lambda y: y, + operand = (new_player_x,new_item_x,new_step_counter), + ) + new_player_x, new_item_x, new_step_counter = jax.lax.cond( + right_no_wall, + lambda y: (y[0]+4,y[1]+4,y[2]+1), + lambda y: y, + operand = (new_player_x,new_item_x,new_step_counter), + ) + + #get y cord of the item beeing held + new_item_y = jax.lax.switch( + state.player[3], + [lambda:0, + lambda:state.key_yellow[1], + lambda:state.key_black[1], + lambda:state.sword[1], + lambda:state.bridge[1], + lambda:state.magnet[1], + lambda:state.chalice[1], + lambda:state.key_white[1] + ] + ) + + new_player_y = state.player[1] + new_player_y, new_item_y, new_step_counter = jax.lax.cond( + down_no_wall, + lambda y: (y[0]+8,y[1]+8,y[2]), + lambda y: y, + operand = (new_player_y,new_item_y,new_step_counter) + ) + new_player_y, new_item_y, new_step_counter = jax.lax.cond( + up_no_wall, + lambda y: (y[0]-8,y[1]-8,y[2]), + lambda y: y, + operand = (new_player_y,new_item_y,new_step_counter) + ) + new_player_tile = state.player[2] + new_item_tile = jax.lax.switch( + state.player[3], + [lambda:0, + lambda:state.key_yellow[2], + lambda:state.key_black[2], + lambda:state.sword[2], + lambda:state.bridge[2], + lambda:state.magnet[2], + lambda:state.chalice[2], + lambda:state.key_white[2] + ] + ) + + #enter yellow castle + new_player_y, new_player_tile, new_item_tile, new_item_y = jax.lax.cond( + jnp.logical_and(new_player_tile == 0, jnp.logical_and(new_player_y <148,jnp.logical_and(new_player_x<110, new_player_x>50))), + lambda: (212, 1, 1,new_item_y+(212-new_player_y)), + lambda: (new_player_y, new_player_tile, new_item_tile, new_item_y) + ) + + #leave yellow castle + new_player_x, new_player_y, new_player_tile, new_item_tile, new_item_y, new_item_x = jax.lax.cond( + jnp.logical_and(new_player_tile == 1, new_player_y >212), + lambda: (77, 148, 0, 0, new_item_y-(new_player_y-145),new_item_x+(77-new_player_x)), + lambda: (new_player_x, new_player_y, new_player_tile, new_item_tile, new_item_y, new_item_x) + ) + + #enter black castle + new_player_y, new_player_tile, new_item_tile, new_item_y = jax.lax.cond( + jnp.logical_and(new_player_tile == 11, jnp.logical_and(new_player_y <148,jnp.logical_and(new_player_x<110, new_player_x>50))), + lambda: (212, 12, 12,new_item_y+(212-new_player_y)), + lambda: (new_player_y, new_player_tile, new_item_tile, new_item_y) + ) + + #leave black castle + new_player_x, new_player_y, new_player_tile, new_item_tile, new_item_y, new_item_x = jax.lax.cond( + jnp.logical_and(new_player_tile == 12, new_player_y >212), + lambda: (77, 148, 11, 11, new_item_y-(new_player_y-148),new_item_x+(77-new_player_x)), + lambda: (new_player_x, new_player_y, new_player_tile, new_item_tile, new_item_y, new_item_x) + ) + + #enter white castle + new_player_y, new_player_tile, new_item_tile, new_item_y = jax.lax.cond( + jnp.logical_and(new_player_tile == 24, jnp.logical_and(new_player_y <148,jnp.logical_and(new_player_x<110, new_player_x>50))), + lambda: (212, 25, 25,new_item_y+(212-new_player_y)), + lambda: (new_player_y, new_player_tile, new_item_tile, new_item_y) + ) + + #leave white castle + new_player_x, new_player_y, new_player_tile, new_item_tile, new_item_y, new_item_x = jax.lax.cond( + jnp.logical_and(new_player_tile == 25, new_player_y >212), + lambda: (77, 148, 24, 24, new_item_y-(new_player_y-148),new_item_x+(77-new_player_x)), + lambda: (new_player_x, new_player_y, new_player_tile, new_item_tile, new_item_y, new_item_x) + ) + + #change of rooms + new_player_y, new_player_tile, new_item_tile, new_item_y = jax.lax.cond( + new_player_y > 212, + lambda _: (27, jax.lax.switch( new_player_tile, [lambda:2,lambda:0,lambda:0, + lambda:18, lambda:0, lambda:0, + lambda:5, lambda:8, lambda:0, + lambda: 6, lambda:7, lambda:10, + lambda:11, lambda:21, lambda:12, + lambda:14, lambda:17, lambda:16, + lambda:19, lambda:20, lambda:0, + lambda:4, lambda:23, lambda:0, + lambda:22, lambda:24, lambda:25, + lambda:28, lambda:24]), + jax.lax.switch( new_item_tile, [lambda:2,lambda:0,lambda:0, + lambda:18, lambda:0, lambda:0, + lambda:5, lambda:8, lambda:0, + lambda: 6, lambda:7, lambda:10, + lambda:11, lambda:21, lambda:12, + lambda:14, lambda:17, lambda:16, + lambda:19, lambda:20, lambda:0, + lambda:4, lambda:23, lambda:0, + lambda:22, lambda:24, lambda:25, + lambda:28, lambda:24]), new_item_y-(new_player_y-27)), + lambda _: (new_player_y, new_player_tile, new_item_tile, new_item_y), + operand = None, + ) + new_player_y, new_player_tile, new_item_tile, new_item_y = jax.lax.cond( + new_player_y < 27, + lambda _: (212, jax.lax.switch( new_player_tile, [lambda:1,lambda:0,lambda:0, + lambda:0, lambda:21, lambda:6, + lambda:9, lambda:10, lambda:7, + lambda: 0, lambda:11, lambda:12, + lambda:14, lambda:0, lambda:15, + lambda:0, lambda:17, lambda:16, + lambda:3, lambda:18, lambda:19, + lambda:13, lambda:24, lambda:22, + lambda:25, lambda:26, lambda:0, + lambda:0, lambda:27]), + jax.lax.switch( new_player_tile, [lambda:1,lambda:0,lambda:0, + lambda:0, lambda:21, lambda:6, + lambda:9, lambda:10, lambda:7, + lambda: 0, lambda:11, lambda:12, + lambda:14, lambda:0, lambda:15, + lambda:0, lambda:17, lambda:16, + lambda:3, lambda:18, lambda:19, + lambda:13, lambda:24, lambda:22, + lambda:25, lambda:26, lambda:0, + lambda:0, lambda:27]), new_item_y+(212-new_player_y)), + lambda _: (new_player_y, new_player_tile, new_item_tile, new_item_y), + operand = None, + ) + new_player_x, new_player_tile, new_item_tile, new_item_x = jax.lax.cond( + new_player_x > 160, + lambda _: (0, jax.lax.switch( new_player_tile, [lambda:0,lambda:0,lambda:3, + lambda:0, lambda:0, lambda:2, + lambda:7, lambda:6, lambda:10, + lambda: 8, lambda:9, lambda:0, + lambda:0, lambda:0, lambda:16, + lambda:17, lambda:15, lambda:14, + lambda:19, lambda:18, lambda:21, + lambda:0, lambda:20, lambda:0, + lambda:0, lambda:28, lambda:27, + lambda:26, lambda:25]), + jax.lax.switch( new_player_tile, [lambda:0,lambda:0,lambda:3, + lambda:0, lambda:0, lambda:2, + lambda:7, lambda:6, lambda:10, + lambda: 8, lambda:9, lambda:0, + lambda:0, lambda:0, lambda:16, + lambda:17, lambda:15, lambda:14, + lambda:19, lambda:18, lambda:21, + lambda:0, lambda:20, lambda:0, + lambda:0, lambda:28, lambda:27, + lambda:26, lambda:25]), new_item_x-new_player_x), + lambda _: (new_player_x, new_player_tile, new_item_tile, new_item_x), + operand = None, + ) + new_player_x, new_player_tile, new_item_tile, new_item_x = jax.lax.cond( + new_player_x < 0, + lambda _: (160, jax.lax.switch( new_player_tile, [lambda:0,lambda:0,lambda:5, + lambda:2, lambda:0, lambda:0, + lambda:7, lambda:6, lambda:9, + lambda: 10, lambda:8, lambda:0, + lambda:0, lambda:0, lambda:17, + lambda:16, lambda:14, lambda:15, + lambda:19, lambda:18, lambda:22, + lambda:20, lambda:0, lambda:20, + lambda:0, lambda:28, lambda:27, + lambda:26, lambda:25]), + jax.lax.switch( new_player_tile, [lambda:0,lambda:0,lambda:5, + lambda:2, lambda:0, lambda:0, + lambda:7, lambda:6, lambda:9, + lambda: 10, lambda:8, lambda:0, + lambda:0, lambda:0, lambda:17, + lambda:16, lambda:14, lambda:15, + lambda:19, lambda:18, lambda:22, + lambda:20, lambda:0, lambda:20, + lambda:0, lambda:28, lambda:27, + lambda:26, lambda:25]), new_item_x+(160-new_player_x)), + lambda _: (new_player_x, new_player_tile, new_item_tile, new_item_x), + operand = None, + ) + + return state.replace( + step_counter = jnp.array(new_step_counter).astype(jnp.int32), + player = jnp.array([new_player_x,new_player_y,new_player_tile,state.player[3]]).astype(jnp.int32), #SEEMS NOT GOOD + key_yellow = jax.lax.cond(state.player[3]==self._env.consts.KEY_YELLOW_ID, + lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: op[3], + operand=(new_item_x,new_item_y,new_item_tile,state.key_yellow), + ), + key_black= jax.lax.cond(state.player[3]==self._env.consts.KEY_BLACK_ID, + lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: op[3], + operand=(new_item_x,new_item_y,new_item_tile,state.key_black) + ), + key_white = jax.lax.cond(state.player[3]==self._env.consts.KEY_WHITE_ID, + lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: op[3], + operand=(new_item_x,new_item_y,new_item_tile,state.key_white), + ), + sword= jax.lax.cond(state.player[3]==self._env.consts.SWORD_ID, + lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: op[3], + operand=(new_item_x,new_item_y,new_item_tile,state.sword) + ), + bridge= jax.lax.cond(state.player[3]==self._env.consts.BRIDGE_ID, + lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: op[3], + operand=(new_item_x,new_item_y,new_item_tile,state.bridge) + ), + magnet= jax.lax.cond(state.player[3]==self._env.consts.MAGNET_ID, + lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: op[3], + operand=(new_item_x,new_item_y,new_item_tile,state.magnet) + ), + chalice= jax.lax.cond(state.player[3]==self._env.consts.CHALICE_ID, + lambda op: jnp.array([op[0],op[1],op[2],op[3]]).astype(jnp.int32), + lambda op: op[4], + operand=(new_item_x,new_item_y,new_item_tile,state.chalice[3],state.chalice) + ) + ) + + #dragons with bat + @partial(jax.jit, static_argnums=(0,)) + def _dragon_step(self, state: AdventureState) -> AdventureState: + speed = self._env.consts.DRAGON_SPEED + + #get sword position to kill dragons + sword_x = state.sword[0] + sword_y = state.sword[1] + sword_room = state.sword[2] + + #yellow dragon + direction_x = jnp.sign(state.player[0] - state.dragon_yellow[0]) + direction_y = jnp.sign(state.player[1]- state.dragon_yellow[1]) + dragon_yellow_x = state.dragon_yellow[0] + dragon_yellow_y = state.dragon_yellow[1] + dragon_yellow_tile = state.dragon_yellow[2] + dragon_yellow_animation = state.dragon_yellow[3] + dragon_yellow_counter = state.dragon_yellow[4] + dragon_yellow_activate = state.dragon_yellow[6] + + # wait after attack + dragon_yellow_counter = jax.lax.cond( + dragon_yellow_animation == 1, + lambda f: f+1, + lambda f:f, + operand = dragon_yellow_counter + ) + dragon_yellow_freeze = dragon_yellow_counter % self._env.consts.DRAGON_BITE_TIMER != 0 + + #dragon starts looking for plyer room after first encounter + dragon_yellow_activate = jax.lax.cond(state.player[2] == dragon_yellow_tile, lambda:1, lambda: dragon_yellow_activate) + rndKey, subkey = jax.random.split(state.rndKey) + dragon_yellow_x, dragon_yellow_y, dragon_yellow_tile = jax.lax.cond( + jnp.logical_and(jnp.logical_and(dragon_yellow_tile != state.player[2], jnp.logical_not(dragon_yellow_freeze)),dragon_yellow_activate==1), + lambda: (jax.lax.cond(dragon_yellow_x>156, lambda:4, lambda:dragon_yellow_x +2), + jax.lax.cond(dragon_yellow_y>208, lambda:4, lambda:dragon_yellow_y+2), + jax.lax.cond(jnp.logical_or(dragon_yellow_x>156,dragon_yellow_y>208), lambda:jax.random.randint(subkey, (), 0, 28) , lambda:dragon_yellow_tile)), + lambda:(dragon_yellow_x, dragon_yellow_y, dragon_yellow_tile) + ) + + #dragon eats player + dragon_yellow_eat = jax.lax.cond( + jnp.logical_and(jnp.logical_and((state.player[0]-dragon_yellow_x)*direction_x<4,(state.player[1]-dragon_yellow_y)*direction_y<4),jnp.logical_and(dragon_yellow_animation==1,jnp.logical_not(dragon_yellow_freeze))), + lambda:1, + lambda:0 + ) + + #move towards player and attack + dragon_yellow_x, dragon_yellow_y, dragon_yellow_animation, dragon_yellow_counter= jax.lax.cond( + jnp.logical_and(state.player[2]==dragon_yellow_tile,jnp.logical_not(dragon_yellow_freeze)), + lambda _: (dragon_yellow_x + direction_x*speed, dragon_yellow_y + direction_y*speed, jax.lax.cond( + jnp.logical_and((state.player[0]-dragon_yellow_x)*direction_x<4,(state.player[1]-dragon_yellow_y)*direction_y<4), + lambda _:jax.lax.cond(dragon_yellow_animation==2, lambda _:2, lambda _:1, operand = None), + lambda _:jax.lax.cond(dragon_yellow_animation==2, lambda _:2, lambda _:0, operand = None), + operand = None + ),0), + lambda _: (dragon_yellow_x, dragon_yellow_y, jax.lax.cond(jnp.logical_not(dragon_yellow_freeze), lambda _: jax.lax.cond(dragon_yellow_animation==2, lambda _:2, lambda _:0, operand = None), lambda _: jax.lax.cond(dragon_yellow_animation==2, lambda _:2, lambda _:1, operand = None), operand = None), dragon_yellow_counter), + operand = None + ) + + #kill dragon + direction_x = jnp.sign(sword_x - state.dragon_yellow[0]) + direction_y = jnp.sign(sword_y- state.dragon_yellow[1]) + dragon_yellow_animation = jax.lax.cond( + jnp.logical_and(dragon_yellow_tile==sword_room, jnp.logical_and((sword_x-dragon_yellow_x)*direction_x<4, (sword_y-dragon_yellow_y)*direction_y<22)), + lambda _:2, + lambda a:a, + operand= dragon_yellow_animation + ) + + # dont ever move again when dead + dragon_yellow_counter = jax.lax.cond( + dragon_yellow_animation == 2, + lambda _: 1, + lambda f:f, + operand=dragon_yellow_counter + ) + + + #green dragon + direction_x = jnp.sign(state.player[0] - state.dragon_green[0]) + direction_y = jnp.sign(state.player[1]- state.dragon_green[1]) + dragon_green_x = state.dragon_green[0] + dragon_green_y = state.dragon_green[1] + dragon_green_tile = state.dragon_green[2] + dragon_green_animation = state.dragon_green[3] + dragon_green_counter = state.dragon_green[4] + dragon_green_activate = state.dragon_green[6] + + # wait after attack + dragon_green_counter = jax.lax.cond( + dragon_green_animation == 1, + lambda f: f+1, + lambda f:f, + operand = dragon_green_counter + ) + dragon_green_freeze = dragon_green_counter % self._env.consts.DRAGON_BITE_TIMER != 0 + + #dragon starts looking for plyer room after first encounter + dragon_green_activate = jax.lax.cond(state.player[2] == dragon_green_tile, lambda:1, lambda: dragon_green_activate) + rndKey, subkey = jax.random.split(rndKey) + dragon_green_x, dragon_green_y, dragon_green_tile = jax.lax.cond( + jnp.logical_and(jnp.logical_and(dragon_green_tile != state.player[2], jnp.logical_not(dragon_green_freeze)),dragon_green_activate==1), + lambda: (jax.lax.cond(dragon_green_x>156, lambda:4, lambda:dragon_green_x +2), + jax.lax.cond(dragon_green_y>208, lambda:4, lambda:dragon_green_y+2), + jax.lax.cond(jnp.logical_or(dragon_green_x>156,dragon_green_y>208), lambda:jax.random.randint(subkey, (), 0, 28) , lambda:dragon_green_tile)), + lambda:(dragon_green_x, dragon_green_y, dragon_green_tile) + ) + + #dragon eats player + dragon_green_eat = jax.lax.cond( + jnp.logical_and(jnp.logical_and((state.player[0]-dragon_green_x)*direction_x<4,(state.player[1]-dragon_green_y)*direction_y<4),jnp.logical_and(dragon_green_animation==1,jnp.logical_not(dragon_green_freeze))), + lambda:1, + lambda:0 + ) + + #move towards player and attack + dragon_green_x, dragon_green_y, dragon_green_animation, dragon_green_counter= jax.lax.cond( + jnp.logical_and(state.player[2]==dragon_green_tile,jnp.logical_not(dragon_green_freeze)), + lambda _: (dragon_green_x + direction_x*speed, dragon_green_y + direction_y*speed, jax.lax.cond( + jnp.logical_and(jnp.logical_and((state.player[0]-dragon_green_x)*direction_x<4,(state.player[1]-dragon_green_y)*direction_y<4),dragon_green_animation!=2), + lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:1, operand = None), + lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:0, operand = None), + operand = None + ),0), + lambda _: (dragon_green_x, dragon_green_y, jax.lax.cond(jnp.logical_not(dragon_green_freeze), lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:0, operand = None), lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:1, operand = None), operand = None), dragon_green_counter), + operand = None + ) + + #kill dragon + direction_x = jnp.sign(sword_x - state.dragon_green[0]) + direction_y = jnp.sign(sword_y- state.dragon_green[1]) + dragon_green_animation = jax.lax.cond( + jnp.logical_and(dragon_green_tile==sword_room, jnp.logical_and((sword_x-dragon_green_x)*direction_x<4, (sword_y-dragon_green_y)*direction_y<22)), + lambda _:2, + lambda a:a, + operand = dragon_green_animation + ) + + # dont ever move again when dead + dragon_green_counter = jax.lax.cond( + dragon_green_animation == 2, + lambda _: 1, + lambda f:f, + operand=dragon_green_counter + ) + + #red dragon + direction_x = jnp.sign(state.player[0] - state.dragon_red[0]) + direction_y = jnp.sign(state.player[1]- state.dragon_red[1]) + dragon_red_x = state.dragon_red[0] + dragon_red_y = state.dragon_red[1] + dragon_red_tile = state.dragon_red[2] + dragon_red_animation = state.dragon_red[3] + dragon_red_counter = state.dragon_red[4] + dragon_red_activate = state.dragon_red[6] + + # wait after attack + dragon_red_counter = jax.lax.cond( + dragon_red_animation == 1, + lambda f: f+1, + lambda f:f, + operand = dragon_red_counter + ) + dragon_red_freeze = dragon_red_counter % self._env.consts.DRAGON_BITE_TIMER != 0 + + #dragon starts looking for plyer room after first encounter + dragon_red_activate = jax.lax.cond(state.player[2] == dragon_red_tile, lambda:1, lambda: dragon_red_activate) + rndKey, subkey = jax.random.split(state.rndKey) + dragon_red_x, dragon_red_y, dragon_red_tile = jax.lax.cond( + jnp.logical_and(jnp.logical_and(dragon_red_tile != state.player[2], jnp.logical_not(dragon_red_freeze)),dragon_red_activate==1), + lambda: (jax.lax.cond(dragon_red_x>156, lambda:4, lambda:dragon_red_x +2), + jax.lax.cond(dragon_red_y>208, lambda:4, lambda:dragon_red_y+2), + jax.lax.cond(jnp.logical_or(dragon_red_x>156,dragon_red_y>208), lambda:jax.random.randint(subkey, (), 0, 28) , lambda:dragon_red_tile)), + lambda:(dragon_red_x, dragon_red_y, dragon_red_tile) + ) + + #dragon eats player + dragon_red_eat = jax.lax.cond( + jnp.logical_and(jnp.logical_and((state.player[0]-dragon_red_x)*direction_x<4,(state.player[1]-dragon_red_y)*direction_y<4),jnp.logical_and(dragon_red_animation==1,jnp.logical_not(dragon_red_freeze))), + lambda:1, + lambda:0 + ) + + #move towards player and attack + dragon_red_x, dragon_red_y, dragon_red_animation, dragon_red_counter= jax.lax.cond( + jnp.logical_and(state.player[2]==dragon_red_tile,jnp.logical_not(dragon_red_freeze)), + lambda _: (dragon_red_x + direction_x*speed, dragon_red_y + direction_y*speed, jax.lax.cond( + jnp.logical_and((state.player[0]-dragon_red_x)*direction_x<4,(state.player[1]-dragon_red_y)*direction_y<4), + lambda _:jax.lax.cond(dragon_red_animation==2, lambda _:2, lambda _:1, operand = None), + lambda _:jax.lax.cond(dragon_red_animation==2, lambda _:2, lambda _:0, operand = None), + operand = None + ),0), + lambda _: (dragon_red_x, dragon_red_y, jax.lax.cond(jnp.logical_not(dragon_red_freeze), lambda _: jax.lax.cond(dragon_red_animation==2, lambda _:2, lambda _:0, operand = None), lambda _: jax.lax.cond(dragon_red_animation==2, lambda _:2, lambda _:1, operand = None), operand = None), dragon_red_counter), + operand = None + ) + + #kill dragon + direction_x = jnp.sign(sword_x - state.dragon_red[0]) + direction_y = jnp.sign(sword_y- state.dragon_red[1]) + dragon_red_animation = jax.lax.cond( + jnp.logical_and(dragon_red_tile==sword_room, jnp.logical_and((sword_x-dragon_red_x)*direction_x<4, (sword_y-dragon_red_y)*direction_y<22)), + lambda _:2, + lambda a:a, + operand= dragon_red_animation + ) + + # dont ever move again when dead + dragon_red_counter = jax.lax.cond( + dragon_red_animation == 2, + lambda _: 1, + lambda f:f, + operand=dragon_red_counter + ) + + + return state.replace( + dragon_yellow = jnp.array([dragon_yellow_x,dragon_yellow_y,dragon_yellow_tile,dragon_yellow_animation,dragon_yellow_counter,dragon_yellow_eat, dragon_yellow_activate]).astype(jnp.int32), + dragon_green = jnp.array([dragon_green_x,dragon_green_y,dragon_green_tile,dragon_green_animation,dragon_green_counter,dragon_green_eat, dragon_green_activate]).astype(jnp.int32), + dragon_red = jnp.array([dragon_red_x,dragon_red_y,dragon_red_tile,dragon_red_animation,dragon_red_counter,dragon_red_eat, dragon_red_activate]).astype(jnp.int32), + rndKey=rndKey + ) + +class EasterEggMod(JaxAtariInternalModPlugin): + asset_overrides = { + #all rooms in order + 'room_number': {'name': 'room_number', 'type': 'group', 'files': ['Room_1.npy', + 'Room_2.npy', + 'Room_3.npy', + 'Room_4.npy', + 'Room_5.npy', + 'Room_6.npy', + 'Room_7.npy', + 'Room_8.npy', + 'Room_9.npy', + 'Room_10.npy', + 'Room_11.npy', + 'Room_12.npy', + 'Room_13.npy', + 'Room_14.npy', + 'Room_15.npy', + 'Room_16.npy', + 'Room_17.npy', + 'Room_18.npy', + 'Room_20.npy', + 'Room_21.npy', + 'Room_22.npy', + 'Room_23.npy', + 'Room_24.npy', + 'Room_25.npy', + 'Room_26.npy', + 'Room_27.npy', + 'Room_28.npy', + 'Room_29.npy', + 'Room_30.npy', + 'Room_31.npy' + ]}, + #Player in all the different colors, which change depending on the background + "player_colors": {'name': 'player_colors', 'type': 'group', 'files': ["Player_Yellow.npy", + "Player_Yellow.npy", + "Player_Green.npy", + "Player_Purple.npy", + "Player_Pink.npy", + "Player_Green_yellow.npy", + "Player_Blue.npy", + "Player_Blue.npy", + "Player_Blue.npy", + "Player_Blue.npy", + "Player_Blue.npy", + "Player_Black.npy", + "Player_Pink.npy", + "Player_Magenta.npy", + "Player_inverted.npy", + "Player_inverted.npy", + "Player_inverted.npy", + "Player_inverted.npy", + "Player_inverted.npy", + "Player_inverted.npy", + "Player_inverted.npy", + "Player_BabyBlue.npy", + "Player_Turquoise.npy", + "Player_LightBlue.npy", + "Player_White.npy", + "Player_Orange.npy", + "Player_Orange.npy", + "Player_Orange.npy", + "Player_Orange.npy"]}, + #Red Dragon + "dragon_red": {'name': 'dragon_red', 'type': 'group', 'files': ['Dragon_red_neutral.npy', + 'Dragon_red_attack.npy', + 'Dragon_red_dead.npy']}, + #white Key + "key_white": {'name': 'key_white', 'type': 'single', 'file': 'Key_white.npy'}, + + #bat + "bat": {'name': 'bat', 'type': 'group', 'files': ['bat_1.npy', + 'bat_2.npy']}, + #dot + "dot": {'name': 'dot', 'type': 'single', 'file': 'Player_BabyBlue.npy'} #TODO change File + } + + rndSpawnLocations = [(31,170,19),(31,100,28),(31,110,8),(31,180,0),(65,130,20),(120,180,23),(50,170,15)] + random.shuffle(rndSpawnLocations) + constants_overrides ={ + + + "DRAGON_YELLOW_SPAWN": (80, 170, 25, 0, 0, 0, 0), + "DRAGON_GREEN_SPAWN": (80, 130, 5, 0, 0, 0, 0), + "DRAGON_RED_SPAWN": (80, 130, 15, 0, 0, 0, 0), + "KEY_YELLOW_SPAWN": rndSpawnLocations[0], + "KEY_BLACK_SPAWN": rndSpawnLocations[1], + "KEY_WHITE_SPAWN": rndSpawnLocations[2], + "SWORD_SPAWN": rndSpawnLocations[3], + "BRIDGE_SPAWN": rndSpawnLocations[4], + "MAGNET_SPAWN": rndSpawnLocations[5], + "CHALICE_SPAWN": rndSpawnLocations[6], + "BAT_SPAWN": (76, 140, 11, 0), + "DOT_SPAWN": (50, 130, 15) + } + + @partial(jax.jit, static_argnums=(0,)) + def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureState: + def _check_walls_new_rooms(state: AdventureState, direction: int) -> bool: + room = state.player[2] + + # direction 0: left, 1: right, 2: up, 3: down + player_x = state.player[0] + player_x = jax.lax.cond( + direction == 0, + lambda x: x-4, + lambda x: x, + operand = player_x, + ) + player_x = jax.lax.cond( + direction == 1, + lambda x: x+4, + lambda x: x, + operand = player_x, + ) + + player_y = state.player[1] + player_y = jax.lax.cond( + direction == 2, + lambda y: y-8, + lambda y: y, + operand = player_y, + ) + player_y = jax.lax.cond( + direction == 3, + lambda y: y+8, + lambda y: y, + operand = player_y, + ) + + #jax.debug.print("step") + #test load background of Rooms + def is_tile_walkable(tileset: jnp.ndarray, Pos_x: int, Pos_y: int) -> bool: + #determin if we should be allowed to walk, based on the background only + #tileset data at a given x and y position is [r, g, b, 255] + #[151, 151, 151, 255] = Grey (allowed player movement) + #[0, 0, 0, 255] are top or bottom border allow movement for tilechange + #anything else are walls (inversed in certain maze tileset) . + is_walkable_1 = (tileset[Pos_y+2,Pos_x][0] == jnp.uint8(151)) + is_walkable_2 = (tileset[Pos_y+2,Pos_x][1] == jnp.uint8(151)) + is_walkable_3 = (tileset[Pos_y+2,Pos_x][2] == jnp.uint8(151)) + is_walkable = jnp.logical_and(is_walkable_1, jnp.logical_and(is_walkable_2,is_walkable_3)) + is_border_1 = (tileset[Pos_y+2,Pos_x][0] == jnp.uint8(0)) + is_border_2 = (tileset[Pos_y+2,Pos_x][1] == jnp.uint8(0)) + is_border_3 = (tileset[Pos_y+2,Pos_x][2] == jnp.uint8(0)) + is_border = jnp.logical_and(is_border_1, jnp.logical_and(is_border_2,is_border_3)) + #jax.debug.print("Tile: {a} is walkable {b}",a=tileset[Pos_y,Pos_x][0:3], b=is_walkable) + return jnp.logical_or(is_walkable,is_border) + + def is_inverted_walkable(tileset: jnp.ndarray, Pos_x: int, Pos_y: int) -> bool: + #determin if we should be allowed to walk, based on the background only + #tileset data at a given x and y position is [r, g, b, 255] + #[151, 151, 151, 255] = Grey (allowed player movement) + #[0, 0, 0, 255] are top or bottom border allow movement for tilechange + #anything else are walls (inversed in certain maze tileset) . + is_walkable_1 = (tileset[Pos_y+2,Pos_x][0] == jnp.uint8(151)) + is_walkable_2 = (tileset[Pos_y+2,Pos_x][1] == jnp.uint8(151)) + is_walkable_3 = (tileset[Pos_y+2,Pos_x][2] == jnp.uint8(151)) + is_walkable = jnp.logical_and(is_walkable_1, jnp.logical_and(is_walkable_2,is_walkable_3)) + #jax.debug.print("Tile: {a} is walkable {b}",a=tileset[Pos_y,Pos_x][0:3], b=is_walkable) + return is_walkable + + def _load_background_map(path: str) -> jnp.ndarray: + background_map = jnp.load(path) + return background_map + + + sprite_path = f"{os.path.dirname(os.path.abspath(__file__))}/sprites" + + #jax.debug.print("Room: {a} is equal to 0 {b}, is walkable {c}",a=room, b=(room == 0),c=is_tile_walkable(self.BackgroundRoom1, player_x, player_y)) + in_Room_15_and_walkable = jnp.logical_and(jnp.equal(room, 14), jnp.logical_not(is_inverted_walkable(_load_background_map(os.path.join(sprite_path, "Room_15.npy")), player_x, player_y))) + in_Room_16_and_walkable = jnp.logical_and(jnp.equal(room, 15), jnp.logical_not(is_inverted_walkable(_load_background_map(os.path.join(sprite_path, "Room_16.npy")), player_x, player_y))) + in_Room_17_and_walkable = jnp.logical_and(jnp.equal(room, 16), jnp.logical_not(is_inverted_walkable(_load_background_map(os.path.join(sprite_path, "Room_17.npy")), player_x, player_y))) + in_Room_18_and_walkable = jnp.logical_and(jnp.equal(room, 17), jnp.logical_not(is_inverted_walkable(_load_background_map(os.path.join(sprite_path, "Room_18.npy")), player_x, player_y))) + in_Room_20_and_walkable = jnp.logical_and(jnp.equal(room, 18), jnp.logical_not(is_inverted_walkable(_load_background_map(os.path.join(sprite_path, "Room_20.npy")), player_x, player_y))) + in_Room_21_and_walkable = jnp.logical_and(jnp.equal(room, 19), jnp.logical_not(is_inverted_walkable(_load_background_map(os.path.join(sprite_path, "Room_21.npy")), player_x, player_y))) + in_Room_22_and_walkable = jnp.logical_and(jnp.equal(room, 20), jnp.logical_not(is_inverted_walkable(_load_background_map(os.path.join(sprite_path, "Room_22.npy")), player_x, player_y))) + in_Room_23_and_walkable = jnp.logical_and(jnp.equal(room, 21), is_tile_walkable(_load_background_map(os.path.join(sprite_path, "Room_23.npy")), player_x, player_y)) + in_Room_24_and_walkable = jnp.logical_and(jnp.equal(room, 22), is_tile_walkable(_load_background_map(os.path.join(sprite_path, "Room_24.npy")), player_x, player_y)) + in_Room_25_and_walkable = jnp.logical_and(jnp.equal(room, 23), is_tile_walkable(_load_background_map(os.path.join(sprite_path, "Room_25.npy")), player_x, player_y)) + in_Room_26_and_walkable = jnp.logical_and(jnp.equal(room, 24), is_tile_walkable(_load_background_map(os.path.join(sprite_path, "Room_26.npy")), player_x, player_y)) + in_Room_27_and_walkable = jnp.logical_and(jnp.equal(room, 25), is_tile_walkable(_load_background_map(os.path.join(sprite_path, "Room_27.npy")), player_x, player_y)) + in_Room_28_and_walkable = jnp.logical_and(jnp.equal(room, 26), is_tile_walkable(_load_background_map(os.path.join(sprite_path, "Room_28.npy")), player_x, player_y)) + in_Room_29_and_walkable = jnp.logical_and(jnp.equal(room, 27), is_tile_walkable(_load_background_map(os.path.join(sprite_path, "Room_29.npy")), player_x, player_y)) + in_Room_30_and_walkable = jnp.logical_and(jnp.equal(room, 28), is_tile_walkable(_load_background_map(os.path.join(sprite_path, "Room_30.npy")), player_x, player_y)) + + Room_15_or_16_and_walkable = jnp.logical_or(in_Room_15_and_walkable, in_Room_16_and_walkable) + Room_17_or_18_and_walkable = jnp.logical_or(in_Room_17_and_walkable, in_Room_18_and_walkable) + Room_20_or_21_and_walkable = jnp.logical_or(in_Room_20_and_walkable, in_Room_21_and_walkable) + Room_22_or_23_and_walkable = jnp.logical_or(in_Room_22_and_walkable, in_Room_23_and_walkable) + Room_24_or_25_and_walkable = jnp.logical_or(in_Room_24_and_walkable, in_Room_25_and_walkable) + Room_26_or_27_and_walkable = jnp.logical_or(in_Room_26_and_walkable, in_Room_27_and_walkable) + Room_28_or_29_and_walkable = jnp.logical_or(in_Room_28_and_walkable, in_Room_29_and_walkable) + + Room_15_or_16_or_17_or_18_and_walkable = jnp.logical_or(Room_15_or_16_and_walkable, Room_17_or_18_and_walkable) + Room_20_or_21_or_22_or_23_and_walkable = jnp.logical_or(Room_20_or_21_and_walkable, Room_22_or_23_and_walkable) + Room_24_or_25_or_26_or_27_and_walkable = jnp.logical_or(Room_24_or_25_and_walkable, Room_26_or_27_and_walkable) + + Room_15_or_16_or_17_or_18_or_20_or_21_or_22_or_23_and_walkable = jnp.logical_or(Room_15_or_16_or_17_or_18_and_walkable, Room_20_or_21_or_22_or_23_and_walkable) + Room_24_or_25_or_26_or_27_or_28_or_29_or_30_and_walkable = jnp.logical_or(jnp.logical_or(Room_24_or_25_or_26_or_27_and_walkable, Room_28_or_29_and_walkable),in_Room_30_and_walkable) + + current_Room_is_walkable = jnp.logical_or(jnp.logical_or(Room_15_or_16_or_17_or_18_or_20_or_21_or_22_or_23_and_walkable, Room_24_or_25_or_26_or_27_or_28_or_29_or_30_and_walkable), self._env._check_for_wall(state, direction)) + #jax.debug.print("is walkable {a}", a= current_Room_is_walkable) + + + edge_left = self._env.consts.PATH_VERTICAL_LEFT + edge_right = self._env.consts.PATH_VERTICAL_RIGHT + + edge_left = self._env.consts.PATH_VERTICAL_LEFT + edge_right = self._env.consts.PATH_VERTICAL_RIGHT + + #Castle Collisions + castle_tower_left = self._env.consts.CASTLE_TOWER_LEFT_X + castle_tower_right = self._env.consts.CASTLE_TOWER_RIGHT_X + castle_tower_height = self._env.consts.CASTLE_TOWER_CORNER_Y + castle_base_left = self._env.consts.CASTLE_BASE_LEFT_X + castle_base_right = self._env.consts.CASTLE_BASE_RIGHT_X + castle_base_height = self._env.consts.CASTLE_BASE_CORNER_Y + + castle_towers_out = jnp.logical_or(player_x<=castle_tower_left, player_x>=castle_tower_right) + castle_towers_in = jnp.logical_and(player_x>=edge_left, player_x<=edge_right) + castle_towers = jnp.logical_or(player_y >= castle_tower_height, jnp.logical_or(castle_towers_in, castle_towers_out)) + + castle_base_out = jnp.logical_or(player_x<=castle_base_left, player_x>=castle_base_right) + castle_base_in_1 = jnp.logical_and(jnp.logical_and(player_y>= castle_tower_height, player_y <= castle_base_height),jnp.logical_and(player_x>=edge_left+8, player_x<=edge_right-10)) + castle_base_in_2 = jnp.logical_and(player_y <= castle_tower_height, jnp.logical_and(player_x>=edge_left, player_x<=edge_right)) + castle_base_in = jnp.logical_or(castle_base_in_1, castle_base_in_2) + castle_base = jnp.logical_or(player_y >= castle_base_height, jnp.logical_or(castle_base_in, castle_base_out)) + + castle_walls = jnp.logical_and(castle_towers, castle_base) + + ##logic implementation gate border + + gate_yellow_open = state.gate_yellow[0] + + gate_black_open = state.gate_black[0] + + gate_white_open =state.gate_white[0] + + gate_yellow_not_block = jnp.logical_or( + jnp.logical_not(room == 0), + gate_yellow_open > 4 + ) + + gate_black_not_block = jnp.logical_or( + jnp.logical_not(room == 11), + gate_black_open > 4 + ) + + gate_white_not_block = jnp.logical_or( + jnp.logical_not(room == 24), + gate_white_open > 4 + ) + + gates_not_blocking = jnp.logical_and(jnp.logical_and(gate_yellow_not_block, gate_black_not_block),gate_white_not_block) + + castle_gate = jnp.logical_or( + gates_not_blocking, + jnp.logical_or( + jnp.logical_or( + player_x >= edge_right, + player_x <= edge_left + ), + player_y >= castle_base_height + ) + ) + + castle_collision = jnp.logical_or( + jnp.logical_not(jnp.logical_or(jnp.logical_or(room==0, room==11), room==24)), #either it is not a castle tile, or + jnp.logical_and(castle_walls, castle_gate) + ) + + + walls_detected = jnp.logical_and(current_Room_is_walkable, castle_collision ) + + #Check for Bridge negating wall + + bridgeX = state.bridge[0] + bridgeY = state.bridge[1] + bridgeTile =state.bridge[2] + + bridgeOnSameTile = bridgeTile == room + bridgeInRange = jnp.logical_and( + jnp.logical_and(player_x >= bridgeX + 8, player_x <= bridgeX + 24), + jnp.logical_and(player_y >= bridgeY, player_y <= bridgeY + 48) + ) + + bridge_detected = jnp.logical_and(bridgeOnSameTile, bridgeInRange) + + + return_bool = jnp.logical_or(walls_detected, bridge_detected) + + return return_bool + + left = jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(action== Action.LEFT, action == Action.LEFTFIRE),action== Action.UPLEFT),action == Action.UPLEFTFIRE), action==Action.DOWNLEFT), action==Action.DOWNLEFTFIRE) + right = jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(action== Action.RIGHT, action == Action.RIGHTFIRE),action== Action.UPRIGHT),action == Action.UPRIGHTFIRE), action==Action.DOWNRIGHT), action==Action.DOWNRIGHTFIRE) + up = jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(action== Action.UP, action == Action.UPFIRE),action== Action.UPRIGHT),action == Action.UPRIGHTFIRE), action==Action.UPLEFT), action==Action.UPLEFTFIRE) + down = jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(jnp.logical_or(action== Action.DOWN, action == Action.DOWNFIRE),action== Action.DOWNRIGHT),action == Action.DOWNRIGHTFIRE), action==Action.DOWNLEFT), action==Action.DOWNLEFTFIRE) + + #check for no wall before walking + left_no_wall = jnp.logical_and(left,_check_walls_new_rooms(state, 0)) + right_no_wall = jnp.logical_and(right,_check_walls_new_rooms(state, 1)) + up_no_wall = jnp.logical_and(up,_check_walls_new_rooms(state, 2)) + down_no_wall = jnp.logical_and(down,_check_walls_new_rooms(state, 3)) + + new_step_counter = state.step_counter + + #get x cord of the item beeing held + new_item_x = jax.lax.switch( + state.player[3], + [lambda:0, + lambda:state.key_yellow[0], + lambda:state.key_black[0], + lambda:state.sword[0], + lambda:state.bridge[0], + lambda:state.magnet[0], + lambda:state.chalice[0], + lambda:state.key_white[0], + lambda:state.dot[0] + ] + ) + + new_player_x = state.player[0] + new_player_x, new_item_x, new_step_counter = jax.lax.cond( + left_no_wall, + lambda y: (y[0]-4,y[1]-4,y[2]+1), + lambda y: y, + operand = (new_player_x,new_item_x,new_step_counter), + ) + new_player_x, new_item_x, new_step_counter = jax.lax.cond( + right_no_wall, + lambda y: (y[0]+4,y[1]+4,y[2]+1), + lambda y: y, + operand = (new_player_x,new_item_x,new_step_counter), + ) + + #get y cord of the item beeing held + new_item_y = jax.lax.switch( + state.player[3], + [lambda:0, + lambda:state.key_yellow[1], + lambda:state.key_black[1], + lambda:state.sword[1], + lambda:state.bridge[1], + lambda:state.magnet[1], + lambda:state.chalice[1], + lambda:state.key_white[1], + lambda:state.dot[1] + ] + ) + + new_player_y = state.player[1] + new_player_y, new_item_y, new_step_counter = jax.lax.cond( + down_no_wall, + lambda y: (y[0]+8,y[1]+8,y[2]), + lambda y: y, + operand = (new_player_y,new_item_y,new_step_counter) + ) + new_player_y, new_item_y, new_step_counter = jax.lax.cond( + up_no_wall, + lambda y: (y[0]-8,y[1]-8,y[2]), + lambda y: y, + operand = (new_player_y,new_item_y,new_step_counter) + ) + new_player_tile = state.player[2] + new_item_tile = jax.lax.switch( + state.player[3], + [lambda:0, + lambda:state.key_yellow[2], + lambda:state.key_black[2], + lambda:state.sword[2], + lambda:state.bridge[2], + lambda:state.magnet[2], + lambda:state.chalice[2], + lambda:state.key_white[2], + lambda:state.dot[2] + ] + ) + + #enter yellow castle + new_player_y, new_player_tile, new_item_tile, new_item_y = jax.lax.cond( + jnp.logical_and(new_player_tile == 0, jnp.logical_and(new_player_y <148,jnp.logical_and(new_player_x<110, new_player_x>50))), + lambda: (212, 1, 1,new_item_y+(212-new_player_y)), + lambda: (new_player_y, new_player_tile, new_item_tile, new_item_y) + ) + + #leave yellow castle + new_player_x, new_player_y, new_player_tile, new_item_tile, new_item_y, new_item_x = jax.lax.cond( + jnp.logical_and(new_player_tile == 1, new_player_y >212), + lambda: (77, 148, 0, 0, new_item_y-(new_player_y-145),new_item_x+(77-new_player_x)), + lambda: (new_player_x, new_player_y, new_player_tile, new_item_tile, new_item_y, new_item_x) + ) + + #enter black castle + new_player_y, new_player_tile, new_item_tile, new_item_y = jax.lax.cond( + jnp.logical_and(new_player_tile == 11, jnp.logical_and(new_player_y <148,jnp.logical_and(new_player_x<110, new_player_x>50))), + lambda: (212, 12, 12,new_item_y+(212-new_player_y)), + lambda: (new_player_y, new_player_tile, new_item_tile, new_item_y) + ) + + #leave black castle + new_player_x, new_player_y, new_player_tile, new_item_tile, new_item_y, new_item_x = jax.lax.cond( + jnp.logical_and(new_player_tile == 12, new_player_y >212), + lambda: (77, 148, 11, 11, new_item_y-(new_player_y-148),new_item_x+(77-new_player_x)), + lambda: (new_player_x, new_player_y, new_player_tile, new_item_tile, new_item_y, new_item_x) + ) + + #enter white castle + new_player_y, new_player_tile, new_item_tile, new_item_y = jax.lax.cond( + jnp.logical_and(new_player_tile == 24, jnp.logical_and(new_player_y <148,jnp.logical_and(new_player_x<110, new_player_x>50))), + lambda: (212, 25, 25,new_item_y+(212-new_player_y)), + lambda: (new_player_y, new_player_tile, new_item_tile, new_item_y) + ) + + #leave white castle + new_player_x, new_player_y, new_player_tile, new_item_tile, new_item_y, new_item_x = jax.lax.cond( + jnp.logical_and(new_player_tile == 25, new_player_y >212), + lambda: (77, 148, 24, 24, new_item_y-(new_player_y-148),new_item_x+(77-new_player_x)), + lambda: (new_player_x, new_player_y, new_player_tile, new_item_tile, new_item_y, new_item_x) + ) + + #change of rooms + new_player_y, new_player_tile, new_item_tile, new_item_y = jax.lax.cond( + new_player_y > 212, + lambda _: (27, jax.lax.switch( new_player_tile, [lambda:2,lambda:0,lambda:0, + lambda:18, lambda:0, lambda:0, + lambda:5, lambda:8, lambda:0, + lambda: 6, lambda:7, lambda:10, + lambda:11, lambda:21, lambda:12, + lambda:14, lambda:17, lambda:16, + lambda:19, lambda:20, lambda:0, + lambda:4, lambda:23, lambda:0, + lambda:22, lambda:24, lambda:25, + lambda:28, lambda:24]), + jax.lax.switch( new_item_tile, [lambda:2,lambda:0,lambda:0, + lambda:18, lambda:0, lambda:0, + lambda:5, lambda:8, lambda:0, + lambda: 6, lambda:7, lambda:10, + lambda:11, lambda:21, lambda:12, + lambda:14, lambda:17, lambda:16, + lambda:19, lambda:20, lambda:0, + lambda:4, lambda:23, lambda:0, + lambda:22, lambda:24, lambda:25, + lambda:28, lambda:24]), new_item_y-(new_player_y-27)), + lambda _: (new_player_y, new_player_tile, new_item_tile, new_item_y), + operand = None, + ) + new_player_y, new_player_tile, new_item_tile, new_item_y = jax.lax.cond( + new_player_y < 27, + lambda _: (212, jax.lax.switch( new_player_tile, [lambda:1,lambda:0,lambda:0, + lambda:0, lambda:21, lambda:6, + lambda:9, lambda:10, lambda:7, + lambda: 0, lambda:11, lambda:12, + lambda:14, lambda:0, lambda:15, + lambda:0, lambda:17, lambda:16, + lambda:3, lambda:18, lambda:19, + lambda:13, lambda:24, lambda:22, + lambda:25, lambda:26, lambda:0, + lambda:0, lambda:27]), + jax.lax.switch( new_player_tile, [lambda:1,lambda:0,lambda:0, + lambda:0, lambda:21, lambda:6, + lambda:9, lambda:10, lambda:7, + lambda: 0, lambda:11, lambda:12, + lambda:14, lambda:0, lambda:15, + lambda:0, lambda:17, lambda:16, + lambda:3, lambda:18, lambda:19, + lambda:13, lambda:24, lambda:22, + lambda:25, lambda:26, lambda:0, + lambda:0, lambda:27]), new_item_y+(212-new_player_y)), + lambda _: (new_player_y, new_player_tile, new_item_tile, new_item_y), + operand = None, + ) + new_player_x, new_player_tile, new_item_tile, new_item_x = jax.lax.cond( + new_player_x > 160, + lambda _: (0, jax.lax.switch( new_player_tile, [lambda:0,lambda:0,lambda:3, + lambda:0, lambda:0, lambda:2, + lambda:7, lambda:6, lambda:10, + lambda: 8, lambda:9, lambda:0, + lambda:0, lambda:0, lambda:16, + lambda:17, lambda:15, lambda:14, + lambda:19, lambda:18, lambda:21, + lambda:0, lambda:20, lambda:0, + lambda:0, lambda:28, lambda:27, + lambda:26, lambda:25]), + jax.lax.switch( new_player_tile, [lambda:0,lambda:0,lambda:3, + lambda:0, lambda:0, lambda:2, + lambda:7, lambda:6, lambda:10, + lambda: 8, lambda:9, lambda:0, + lambda:0, lambda:0, lambda:16, + lambda:17, lambda:15, lambda:14, + lambda:19, lambda:18, lambda:21, + lambda:0, lambda:20, lambda:0, + lambda:0, lambda:28, lambda:27, + lambda:26, lambda:25]), new_item_x-new_player_x), + lambda _: (new_player_x, new_player_tile, new_item_tile, new_item_x), + operand = None, + ) + new_player_x, new_player_tile, new_item_tile, new_item_x = jax.lax.cond( + new_player_x < 0, + lambda _: (160, jax.lax.switch( new_player_tile, [lambda:0,lambda:0,lambda:5, + lambda:2, lambda:0, lambda:0, + lambda:7, lambda:6, lambda:9, + lambda: 10, lambda:8, lambda:0, + lambda:0, lambda:0, lambda:17, + lambda:16, lambda:14, lambda:15, + lambda:19, lambda:18, lambda:22, + lambda:20, lambda:0, lambda:20, + lambda:0, lambda:28, lambda:27, + lambda:26, lambda:25]), + jax.lax.switch( new_player_tile, [lambda:0,lambda:0,lambda:5, + lambda:2, lambda:0, lambda:0, + lambda:7, lambda:6, lambda:9, + lambda: 10, lambda:8, lambda:0, + lambda:0, lambda:0, lambda:17, + lambda:16, lambda:14, lambda:15, + lambda:19, lambda:18, lambda:22, + lambda:20, lambda:0, lambda:20, + lambda:0, lambda:28, lambda:27, + lambda:26, lambda:25]), new_item_x+(160-new_player_x)), + lambda _: (new_player_x, new_player_tile, new_item_tile, new_item_x), + operand = None, + ) + + new_player_tile, new_player_x = jax.lax.cond( + jnp.logical_and(state.player[3]==self._env.consts.DOT_ID, jnp.logical_and(state.player[2]==3,state.player[0]>140)), + lambda: (29, 27), + lambda: (new_player_tile, new_player_x) + ) + + return state.replace( + step_counter = jnp.array(new_step_counter).astype(jnp.int32), + player = jnp.array([new_player_x,new_player_y,new_player_tile,state.player[3]]).astype(jnp.int32), #SEEMS NOT GOOD + key_yellow = jax.lax.cond(state.player[3]==self._env.consts.KEY_YELLOW_ID, + lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: op[3], + operand=(new_item_x,new_item_y,new_item_tile,state.key_yellow), + ), + key_black= jax.lax.cond(state.player[3]==self._env.consts.KEY_BLACK_ID, + lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: op[3], + operand=(new_item_x,new_item_y,new_item_tile,state.key_black) + ), + key_white = jax.lax.cond(state.player[3]==self._env.consts.KEY_WHITE_ID, + lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: op[3], + operand=(new_item_x,new_item_y,new_item_tile,state.key_white), + ), + sword= jax.lax.cond(state.player[3]==self._env.consts.SWORD_ID, + lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: op[3], + operand=(new_item_x,new_item_y,new_item_tile,state.sword) + ), + bridge= jax.lax.cond(state.player[3]==self._env.consts.BRIDGE_ID, + lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: op[3], + operand=(new_item_x,new_item_y,new_item_tile,state.bridge) + ), + magnet= jax.lax.cond(state.player[3]==self._env.consts.MAGNET_ID, + lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: op[3], + operand=(new_item_x,new_item_y,new_item_tile,state.magnet) + ), + chalice= jax.lax.cond(state.player[3]==self._env.consts.CHALICE_ID, + lambda op: jnp.array([op[0],op[1],op[2],op[3]]).astype(jnp.int32), + lambda op: op[4], + operand=(new_item_x,new_item_y,new_item_tile,state.chalice[3],state.chalice) + ), + dot= jax.lax.cond(state.player[3]==self._env.consts.DOT_ID, + lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: op[3], + operand=(new_item_x,new_item_y,new_item_tile,state.dot) + ) + ) + + #dragons with bat + @partial(jax.jit, static_argnums=(0,)) + def _dragon_step(self, state: AdventureState) -> AdventureState: + speed = self._env.consts.DRAGON_SPEED + + #get sword position to kill dragons + sword_x = state.sword[0] + sword_y = state.sword[1] + sword_room = state.sword[2] + + #yellow dragon + direction_x = jnp.sign(state.player[0] - state.dragon_yellow[0]) + direction_y = jnp.sign(state.player[1]- state.dragon_yellow[1]) + dragon_yellow_x = state.dragon_yellow[0] + dragon_yellow_y = state.dragon_yellow[1] + dragon_yellow_tile = state.dragon_yellow[2] + dragon_yellow_animation = state.dragon_yellow[3] + dragon_yellow_counter = state.dragon_yellow[4] + dragon_yellow_activate = state.dragon_yellow[6] + + # wait after attack + dragon_yellow_counter = jax.lax.cond( + dragon_yellow_animation == 1, + lambda f: f+1, + lambda f:f, + operand = dragon_yellow_counter + ) + dragon_yellow_freeze = dragon_yellow_counter % self._env.consts.DRAGON_BITE_TIMER != 0 + + #dragon starts looking for plyer room after first encounter + dragon_yellow_activate = jax.lax.cond(state.player[2] == dragon_yellow_tile, lambda:1, lambda: dragon_yellow_activate) + rndKey, subkey = jax.random.split(state.rndKey) + dragon_yellow_x, dragon_yellow_y, dragon_yellow_tile = jax.lax.cond( + jnp.logical_and(jnp.logical_and(dragon_yellow_tile != state.player[2], jnp.logical_not(dragon_yellow_freeze)),dragon_yellow_activate==1), + lambda: (jax.lax.cond(dragon_yellow_x>156, lambda:4, lambda:dragon_yellow_x +2), + jax.lax.cond(dragon_yellow_y>208, lambda:4, lambda:dragon_yellow_y+2), + jax.lax.cond(jnp.logical_or(dragon_yellow_x>156,dragon_yellow_y>208), lambda:jax.random.randint(subkey, (), 0, 28) , lambda:dragon_yellow_tile)), + lambda:(dragon_yellow_x, dragon_yellow_y, dragon_yellow_tile) + ) + + #dragon eats player + dragon_yellow_eat = jax.lax.cond( + jnp.logical_and(jnp.logical_and((state.player[0]-dragon_yellow_x)*direction_x<4,(state.player[1]-dragon_yellow_y)*direction_y<4),jnp.logical_and(dragon_yellow_animation==1,jnp.logical_not(dragon_yellow_freeze))), + lambda:1, + lambda:0 + ) + + #move towards player and attack + dragon_yellow_x, dragon_yellow_y, dragon_yellow_animation, dragon_yellow_counter= jax.lax.cond( + jnp.logical_and(state.player[2]==dragon_yellow_tile,jnp.logical_not(dragon_yellow_freeze)), + lambda _: (dragon_yellow_x + direction_x*speed, dragon_yellow_y + direction_y*speed, jax.lax.cond( + jnp.logical_and((state.player[0]-dragon_yellow_x)*direction_x<4,(state.player[1]-dragon_yellow_y)*direction_y<4), + lambda _:jax.lax.cond(dragon_yellow_animation==2, lambda _:2, lambda _:1, operand = None), + lambda _:jax.lax.cond(dragon_yellow_animation==2, lambda _:2, lambda _:0, operand = None), + operand = None + ),0), + lambda _: (dragon_yellow_x, dragon_yellow_y, jax.lax.cond(jnp.logical_not(dragon_yellow_freeze), lambda _: jax.lax.cond(dragon_yellow_animation==2, lambda _:2, lambda _:0, operand = None), lambda _: jax.lax.cond(dragon_yellow_animation==2, lambda _:2, lambda _:1, operand = None), operand = None), dragon_yellow_counter), + operand = None + ) + + #kill dragon + direction_x = jnp.sign(sword_x - state.dragon_yellow[0]) + direction_y = jnp.sign(sword_y- state.dragon_yellow[1]) + dragon_yellow_animation = jax.lax.cond( + jnp.logical_and(dragon_yellow_tile==sword_room, jnp.logical_and((sword_x-dragon_yellow_x)*direction_x<4, (sword_y-dragon_yellow_y)*direction_y<22)), + lambda _:2, + lambda a:a, + operand= dragon_yellow_animation + ) + + # dont ever move again when dead + dragon_yellow_counter = jax.lax.cond( + dragon_yellow_animation == 2, + lambda _: 1, + lambda f:f, + operand=dragon_yellow_counter + ) + + + #green dragon + direction_x = jnp.sign(state.player[0] - state.dragon_green[0]) + direction_y = jnp.sign(state.player[1]- state.dragon_green[1]) + dragon_green_x = state.dragon_green[0] + dragon_green_y = state.dragon_green[1] + dragon_green_tile = state.dragon_green[2] + dragon_green_animation = state.dragon_green[3] + dragon_green_counter = state.dragon_green[4] + dragon_green_activate = state.dragon_green[6] + + # wait after attack + dragon_green_counter = jax.lax.cond( + dragon_green_animation == 1, + lambda f: f+1, + lambda f:f, + operand = dragon_green_counter + ) + dragon_green_freeze = dragon_green_counter % self._env.consts.DRAGON_BITE_TIMER != 0 + + #dragon starts looking for plyer room after first encounter + dragon_green_activate = jax.lax.cond(state.player[2] == dragon_green_tile, lambda:1, lambda: dragon_green_activate) + rndKey, subkey = jax.random.split(rndKey) + dragon_green_x, dragon_green_y, dragon_green_tile = jax.lax.cond( + jnp.logical_and(jnp.logical_and(dragon_green_tile != state.player[2], jnp.logical_not(dragon_green_freeze)),dragon_green_activate==1), + lambda: (jax.lax.cond(dragon_green_x>156, lambda:4, lambda:dragon_green_x +2), + jax.lax.cond(dragon_green_y>208, lambda:4, lambda:dragon_green_y+2), + jax.lax.cond(jnp.logical_or(dragon_green_x>156,dragon_green_y>208), lambda:jax.random.randint(subkey, (), 0, 28) , lambda:dragon_green_tile)), + lambda:(dragon_green_x, dragon_green_y, dragon_green_tile) + ) + + #dragon eats player + dragon_green_eat = jax.lax.cond( + jnp.logical_and(jnp.logical_and((state.player[0]-dragon_green_x)*direction_x<4,(state.player[1]-dragon_green_y)*direction_y<4),jnp.logical_and(dragon_green_animation==1,jnp.logical_not(dragon_green_freeze))), + lambda:1, + lambda:0 + ) + + #move towards player and attack + dragon_green_x, dragon_green_y, dragon_green_animation, dragon_green_counter= jax.lax.cond( + jnp.logical_and(state.player[2]==dragon_green_tile,jnp.logical_not(dragon_green_freeze)), + lambda _: (dragon_green_x + direction_x*speed, dragon_green_y + direction_y*speed, jax.lax.cond( + jnp.logical_and(jnp.logical_and((state.player[0]-dragon_green_x)*direction_x<4,(state.player[1]-dragon_green_y)*direction_y<4),dragon_green_animation!=2), + lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:1, operand = None), + lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:0, operand = None), + operand = None + ),0), + lambda _: (dragon_green_x, dragon_green_y, jax.lax.cond(jnp.logical_not(dragon_green_freeze), lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:0, operand = None), lambda _: jax.lax.cond(dragon_green_animation==2, lambda _:2, lambda _:1, operand = None), operand = None), dragon_green_counter), + operand = None + ) + + #kill dragon + direction_x = jnp.sign(sword_x - state.dragon_green[0]) + direction_y = jnp.sign(sword_y- state.dragon_green[1]) + dragon_green_animation = jax.lax.cond( + jnp.logical_and(dragon_green_tile==sword_room, jnp.logical_and((sword_x-dragon_green_x)*direction_x<4, (sword_y-dragon_green_y)*direction_y<22)), + lambda _:2, + lambda a:a, + operand = dragon_green_animation + ) + + # dont ever move again when dead + dragon_green_counter = jax.lax.cond( + dragon_green_animation == 2, + lambda _: 1, + lambda f:f, + operand=dragon_green_counter + ) + + #red dragon + direction_x = jnp.sign(state.player[0] - state.dragon_red[0]) + direction_y = jnp.sign(state.player[1]- state.dragon_red[1]) + dragon_red_x = state.dragon_red[0] + dragon_red_y = state.dragon_red[1] + dragon_red_tile = state.dragon_red[2] + dragon_red_animation = state.dragon_red[3] + dragon_red_counter = state.dragon_red[4] + dragon_red_activate = state.dragon_red[6] + + # wait after attack + dragon_red_counter = jax.lax.cond( + dragon_red_animation == 1, + lambda f: f+1, + lambda f:f, + operand = dragon_red_counter + ) + dragon_red_freeze = dragon_red_counter % self._env.consts.DRAGON_BITE_TIMER != 0 + + #dragon starts looking for plyer room after first encounter + dragon_red_activate = jax.lax.cond(state.player[2] == dragon_red_tile, lambda:1, lambda: dragon_red_activate) + rndKey, subkey = jax.random.split(state.rndKey) + dragon_red_x, dragon_red_y, dragon_red_tile = jax.lax.cond( + jnp.logical_and(jnp.logical_and(dragon_red_tile != state.player[2], jnp.logical_not(dragon_red_freeze)),dragon_red_activate==1), + lambda: (jax.lax.cond(dragon_red_x>156, lambda:4, lambda:dragon_red_x +2), + jax.lax.cond(dragon_red_y>208, lambda:4, lambda:dragon_red_y+2), + jax.lax.cond(jnp.logical_or(dragon_red_x>156,dragon_red_y>208), lambda:jax.random.randint(subkey, (), 0, 28) , lambda:dragon_red_tile)), + lambda:(dragon_red_x, dragon_red_y, dragon_red_tile) + ) + + #dragon eats player + dragon_red_eat = jax.lax.cond( + jnp.logical_and(jnp.logical_and((state.player[0]-dragon_red_x)*direction_x<4,(state.player[1]-dragon_red_y)*direction_y<4),jnp.logical_and(dragon_red_animation==1,jnp.logical_not(dragon_red_freeze))), + lambda:1, + lambda:0 + ) + + #move towards player and attack + dragon_red_x, dragon_red_y, dragon_red_animation, dragon_red_counter= jax.lax.cond( + jnp.logical_and(state.player[2]==dragon_red_tile,jnp.logical_not(dragon_red_freeze)), + lambda _: (dragon_red_x + direction_x*speed, dragon_red_y + direction_y*speed, jax.lax.cond( + jnp.logical_and((state.player[0]-dragon_red_x)*direction_x<4,(state.player[1]-dragon_red_y)*direction_y<4), + lambda _:jax.lax.cond(dragon_red_animation==2, lambda _:2, lambda _:1, operand = None), + lambda _:jax.lax.cond(dragon_red_animation==2, lambda _:2, lambda _:0, operand = None), + operand = None + ),0), + lambda _: (dragon_red_x, dragon_red_y, jax.lax.cond(jnp.logical_not(dragon_red_freeze), lambda _: jax.lax.cond(dragon_red_animation==2, lambda _:2, lambda _:0, operand = None), lambda _: jax.lax.cond(dragon_red_animation==2, lambda _:2, lambda _:1, operand = None), operand = None), dragon_red_counter), + operand = None + ) + + #kill dragon + direction_x = jnp.sign(sword_x - state.dragon_red[0]) + direction_y = jnp.sign(sword_y- state.dragon_red[1]) + dragon_red_animation = jax.lax.cond( + jnp.logical_and(dragon_red_tile==sword_room, jnp.logical_and((sword_x-dragon_red_x)*direction_x<4, (sword_y-dragon_red_y)*direction_y<22)), + lambda _:2, + lambda a:a, + operand= dragon_red_animation + ) + + # dont ever move again when dead + dragon_red_counter = jax.lax.cond( + dragon_red_animation == 2, + lambda _: 1, + lambda f:f, + operand=dragon_red_counter + ) + + + return state.replace( + dragon_yellow = jnp.array([dragon_yellow_x,dragon_yellow_y,dragon_yellow_tile,dragon_yellow_animation,dragon_yellow_counter,dragon_yellow_eat, dragon_yellow_activate]).astype(jnp.int32), + dragon_green = jnp.array([dragon_green_x,dragon_green_y,dragon_green_tile,dragon_green_animation,dragon_green_counter,dragon_green_eat, dragon_green_activate]).astype(jnp.int32), + dragon_red = jnp.array([dragon_red_x,dragon_red_y,dragon_red_tile,dragon_red_animation,dragon_red_counter,dragon_red_eat, dragon_red_activate]).astype(jnp.int32), + rndKey=rndKey + ) + + @partial(jax.jit, static_argnums=(0,)) + def _get_reward(self, previous_state: AdventureState, state: AdventureState): + reward = jax.lax.cond( + jnp.logical_or(jnp.logical_or(state.dragon_yellow[5]==1,state.dragon_green[5]==1),state.dragon_red[5]==1), #lose when eaten by dragon + lambda :-1, + lambda : jax.lax.cond( + state.player[2]==29, #win when player is in easteregg room + lambda :state.step_counter, + lambda :0 #this should happen on reset? + ) + ) + return reward + + @partial(jax.jit, static_argnums=(0,)) + def _get_done(self, state: AdventureState) -> bool: + return jnp.logical_or(jnp.logical_or(jnp.logical_or(state.dragon_yellow[5]==1,state.dragon_green[5]==1),state.dragon_red[5]==1), state.player[2]==29) From 545ed8cc63735a91b49a5b666d5bb1eb79f89d8e Mon Sep 17 00:00:00 2001 From: DanielCress Date: Mon, 30 Mar 2026 17:45:40 +0200 Subject: [PATCH 075/102] add complex mods --- src/jaxatari/games/mods/adventure_mods.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/jaxatari/games/mods/adventure_mods.py b/src/jaxatari/games/mods/adventure_mods.py index d17369422..0b0949c6d 100644 --- a/src/jaxatari/games/mods/adventure_mods.py +++ b/src/jaxatari/games/mods/adventure_mods.py @@ -1,6 +1,6 @@ import os from jaxatari.modification import JaxAtariModController -from jaxatari.games.mods.adventure.adventure_mod_plugins import FasterDragonsMod, FasterBiteMod, FleaingDragonMod, DragonReviveMod, RandomPlayerSpawnMod +from jaxatari.games.mods.adventure.adventure_mod_plugins import FasterDragonsMod, FasterBiteMod, FleaingDragonMod, DragonReviveMod, RandomPlayerSpawnMod, LevelTwoMod, LevelThreeMod, EasterEggMod class AdventureEnvMod(JaxAtariModController): """ Game-specific Mod Controller for Adventure. @@ -12,7 +12,10 @@ class AdventureEnvMod(JaxAtariModController): "faster_bite": FasterBiteMod, "fleaing_dragon": FleaingDragonMod, "dragon_revive": DragonReviveMod, - "random_player_spawn": RandomPlayerSpawnMod + "random_player_spawn": RandomPlayerSpawnMod, + "level_two": LevelTwoMod, + "level_three": LevelThreeMod, + "easter_egg": EasterEggMod } _mod_sprite_dir = os.path.join(os.path.dirname(__file__), "adventure", "sprites") From 3e391665274caa47b5eaf85cbcfd1ab0fddb1358 Mon Sep 17 00:00:00 2001 From: lschwass Date: Mon, 30 Mar 2026 19:06:50 +0200 Subject: [PATCH 076/102] added eobservers, fixed typo Player_Green_Yellow.npy --- src/jaxatari/games/jax_adventure.py | 148 +++++++++++++++++++++++++++- 1 file changed, 145 insertions(+), 3 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index f7f3a07b9..9e6d69114 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -40,7 +40,7 @@ def _get_default_asset_config() -> tuple: "Player_Green.npy", "Player_Purple.npy", "Player_Pink.npy", - "Player_Green_yellow.npy", + "Player_Green_Yellow.npy", "Player_Blue.npy", "Player_Blue.npy", "Player_Blue.npy", @@ -221,6 +221,11 @@ class AdventureObservation(struct.PyTreeNode): bridge: EntityPosition magnet: EntityPosition chalice: EntityPosition + dragon_red: EntityPosition + key_white: EntityPosition + gate_white: EntityPosition + bat: EntityPosition + dot: EntityPosition class AdventureInfo(struct.PyTreeNode): @@ -1492,6 +1497,46 @@ def _get_observation(self, state: AdventureState): height=self.consts.CHALICE_SIZE[1], state=0 #Chalice has no relevant state ) + dragon_red = EntityPosition( + x=state.dragon_red[0], + y=state.dragon_red[1], + tile=state.dragon_red[2], + width=self.consts.DRAGON_SIZE[0], + height=self.consts.DRAGON_SIZE[1], + state=state.dragon_red[3] + ) + key_white = EntityPosition( + x=state.key_white[0], + y=state.key_white[1], + tile=state.key_white[2], + width=self.consts.KEY_SIZE[0], + height=self.consts.KEY_SIZE[1], + state=0 #Key has no relevant state + ) + gate_white = EntityPosition( + x=self.consts.WHITE_GATE_POS[0], + y=self.consts.WHITE_GATE_POS[1], + tile=self.consts.WHITE_GATE_POS[2], + width=self.consts.GATE_SIZE[0], + height=self.consts.GATE_SIZE[1], + state=state.gate_white[0] + ) + bat = EntityPosition( + x=state.bat[0], + y=state.bat[1], + tile=state.bat[2], + width=0, #bat has no hitbox + height=0, + state=0 #bat has no relevant state + ) + dot = EntityPosition( + x=state.dot[0], + y=state.dot[1], + tile=state.dot[2], + width=self.consts.DOT_SIZE[0], + height=self.consts.DOT_SIZE[1], + state=0 #Dot has no relevant state + ) return AdventureObservation( player=player, @@ -1504,7 +1549,12 @@ def _get_observation(self, state: AdventureState): sword=sword, bridge=bridge, magnet=magnet, - chalice=chalice + chalice=chalice, + dragon_red=dragon_red, + key_white=key_white, + gate_white=gate_white, + bat=bat, + dot=dot ) #ToDo, no clue what this is used for @@ -1513,8 +1563,100 @@ def obs_to_flat_array(self, obs: AdventureObservation) -> jnp.ndarray: return jnp.concatenate([ obs.player.x.flatten(), obs.player.y.flatten(), + obs.player.tile.flatten(), obs.player.height.flatten(), - obs.player.width.flatten() + obs.player.width.flatten(), + obs.player.state.flatten(), + obs.dragon_yellow.x.flatten(), + obs.dragon_yellow.y.flatten(), + obs.dragon_yellow.tile.flatten(), + obs.dragon_yellow.height.flatten(), + obs.dragon_yellow.width.flatten(), + obs.dragon_yellow.state.flatten(), + obs.dragon_green.x.flatten(), + obs.dragon_green.y.flatten(), + obs.dragon_green.tile.flatten(), + obs.dragon_green.height.flatten(), + obs.dragon_green.width.flatten(), + obs.dragon_green.state.flatten(), + obs.key_yellow.x.flatten(), + obs.key_yellow.y.flatten(), + obs.key_yellow.tile.flatten(), + obs.key_yellow.height.flatten(), + obs.key_yellow.width.flatten(), + obs.key_yellow.state.flatten(), + obs.key_black.x.flatten(), + obs.key_black.y.flatten(), + obs.key_black.tile.flatten(), + obs.key_black.height.flatten(), + obs.key_black.width.flatten(), + obs.key_black.state.flatten(), + obs.gate_yellow.x.flatten(), + obs.gate_yellow.y.flatten(), + obs.gate_yellow.tile.flatten(), + obs.gate_yellow.height.flatten(), + obs.gate_yellow.width.flatten(), + obs.gate_yellow.state.flatten(), + obs.gate_black.x.flatten(), + obs.gate_black.y.flatten(), + obs.gate_black.tile.flatten(), + obs.gate_black.height.flatten(), + obs.gate_black.width.flatten(), + obs.gate_black.state.flatten(), + obs.sword.x.flatten(), + obs.sword.y.flatten(), + obs.sword.tile.flatten(), + obs.sword.height.flatten(), + obs.sword.width.flatten(), + obs.sword.state.flatten(), + obs.bridge.x.flatten(), + obs.bridge.y.flatten(), + obs.bridge.tile.flatten(), + obs.bridge.height.flatten(), + obs.bridge.width.flatten(), + obs.bridge.state.flatten(), + obs.magnet.x.flatten(), + obs.magnet.y.flatten(), + obs.magnet.tile.flatten(), + obs.magnet.height.flatten(), + obs.magnet.width.flatten(), + obs.magnet.state.flatten(), + obs.chalice.x.flatten(), + obs.chalice.y.flatten(), + obs.chalice.tile.flatten(), + obs.chalice.height.flatten(), + obs.chalice.width.flatten(), + obs.chalice.state.flatten(), + obs.dragon_red.x.flatten(), + obs.dragon_red.y.flatten(), + obs.dragon_red.tile.flatten(), + obs.dragon_red.height.flatten(), + obs.dragon_red.width.flatten(), + obs.dragon_red.state.flatten(), + obs.key_white.x.flatten(), + obs.key_white.y.flatten(), + obs.key_white.tile.flatten(), + obs.key_white.height.flatten(), + obs.key_white.width.flatten(), + obs.key_white.state.flatten(), + obs.gate_white.x.flatten(), + obs.gate_white.y.flatten(), + obs.gate_white.tile.flatten(), + obs.gate_white.height.flatten(), + obs.gate_white.width.flatten(), + obs.gate_white.state.flatten(), + obs.bat.x.flatten(), + obs.bat.y.flatten(), + obs.bat.tile.flatten(), + obs.bat.height.flatten(), + obs.bat.width.flatten(), + obs.bat.state.flatten(), + obs.dot.x.flatten(), + obs.dot.y.flatten(), + obs.dot.tile.flatten(), + obs.dot.height.flatten(), + obs.dot.width.flatten(), + obs.dot.state.flatten(), ] ) From 265fe70b31dfffb22ff237f36aa31b9ce42c82f1 Mon Sep 17 00:00:00 2001 From: lschwass Date: Mon, 30 Mar 2026 19:44:45 +0200 Subject: [PATCH 077/102] error fix 1 for pipeline --- src/jaxatari/games/jax_adventure.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 9e6d69114..ed853a735 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -827,9 +827,9 @@ def _gate_interaction(self, state: AdventureState) -> AdventureState: operand = gate_white_counter ) - new_gate_yellow = [gate_yellow_state, gate_yellow_counter] - new_gate_black = [gate_black_state, gate_black_counter] - new_gate_white = [gate_white_state, gate_white_counter] + new_gate_yellow = (gate_yellow_state, gate_yellow_counter) + new_gate_black = (gate_black_state, gate_black_counter) + new_gate_white = (gate_white_state, gate_white_counter) return state.replace( gate_yellow=new_gate_yellow, From b2f67fc06602b206ee05755c4042444816f7b7f1 Mon Sep 17 00:00:00 2001 From: lschwass Date: Mon, 30 Mar 2026 19:48:00 +0200 Subject: [PATCH 078/102] reverted core.py changes --- src/jaxatari/core.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/jaxatari/core.py b/src/jaxatari/core.py index 6cad5699e..d76f64ea1 100644 --- a/src/jaxatari/core.py +++ b/src/jaxatari/core.py @@ -26,7 +26,6 @@ def _warn_deprecated_obs_to_flat_array(env: JaxEnvironment) -> None: # Map of game names to their module paths GAME_MODULES = { - "adventure": "jaxatari.games.jax_adventure", "amidar": "jaxatari.games.jax_amidar", "airraid": "jaxatari.games.jax_airraid", "alien": "jaxatari.games.jax_alien", @@ -78,7 +77,6 @@ def _warn_deprecated_obs_to_flat_array(env: JaxEnvironment) -> None: # Mod modules registry: for each game, provide the Controller class path MOD_MODULES = { - "adventure": "jaxatari.games.mods.adventure_mods.AdventureEnvMod", "pong": "jaxatari.games.mods.pong_mods.PongEnvMod", "kangaroo": "jaxatari.games.mods.kangaroo_mods.KangarooEnvMod", "freeway": "jaxatari.games.mods.freeway_mods.FreewayEnvMod", From a737e4f0d4a14f7a723d5d3939bb220a1d790e1d Mon Sep 17 00:00:00 2001 From: DanielCress Date: Mon, 30 Mar 2026 19:58:29 +0200 Subject: [PATCH 079/102] Pipeline fix --- src/jaxatari/games/jax_adventure.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index ed853a735..6fc5cfcfc 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -827,14 +827,10 @@ def _gate_interaction(self, state: AdventureState) -> AdventureState: operand = gate_white_counter ) - new_gate_yellow = (gate_yellow_state, gate_yellow_counter) - new_gate_black = (gate_black_state, gate_black_counter) - new_gate_white = (gate_white_state, gate_white_counter) - return state.replace( - gate_yellow=new_gate_yellow, - gate_black=new_gate_black, - gate_white=new_gate_white, + gate_yellow=jnp.array([gate_yellow_state, gate_yellow_counter]).astype(jnp.int32), + gate_black=jnp.array([gate_black_state, gate_black_counter]).astype(jnp.int32), + gate_white=jnp.array([gate_white_state, gate_white_counter]).astype(jnp.int32), ) def _item_pickup(self, state: AdventureState, action: chex.Array) -> AdventureState: From 5f4742edd39715cda322526bafd3a58973ab9cde Mon Sep 17 00:00:00 2001 From: DanielCress Date: Mon, 30 Mar 2026 20:08:13 +0200 Subject: [PATCH 080/102] pipeline --- src/jaxatari/games/jax_adventure.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 6fc5cfcfc..f78ce2e39 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -1305,17 +1305,23 @@ def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureOb self.consts.DRAGON_YELLOW_SPAWN[1], self.consts.DRAGON_YELLOW_SPAWN[2], self.consts.DRAGON_YELLOW_SPAWN[3], - self.consts.DRAGON_YELLOW_SPAWN[4]]).astype(jnp.int32), #ToDo + self.consts.DRAGON_YELLOW_SPAWN[4], + self.consts.DRAGON_YELLOW_SPAWN[5], + self.consts.DRAGON_YELLOW_SPAWN[6]]).astype(jnp.int32), #ToDo dragon_green = jnp.array([self.consts.DRAGON_GREEN_SPAWN[0], self.consts.DRAGON_GREEN_SPAWN[1], self.consts.DRAGON_GREEN_SPAWN[2], self.consts.DRAGON_GREEN_SPAWN[3], - self.consts.DRAGON_GREEN_SPAWN[4]]).astype(jnp.int32), + self.consts.DRAGON_GREEN_SPAWN[4], + self.consts.DRAGON_GREEN_SPAWN[5], + self.consts.DRAGON_GREEN_SPAWN[6]]).astype(jnp.int32), dragon_red = jnp.array([self.consts.DRAGON_RED_SPAWN[0], self.consts.DRAGON_RED_SPAWN[1], self.consts.DRAGON_RED_SPAWN[2], self.consts.DRAGON_RED_SPAWN[3], - self.consts.DRAGON_RED_SPAWN[4]]).astype(jnp.int32), #ToDo + self.consts.DRAGON_RED_SPAWN[4], + self.consts.DRAGON_RED_SPAWN[5], + self.consts.DRAGON_RED_SPAWN[6]]).astype(jnp.int32), #Keys: x ,y, tile key_yellow = jnp.array([self.consts.KEY_YELLOW_SPAWN[0], self.consts.KEY_YELLOW_SPAWN[1], From 6adce2cf4d3c4956096c8ad3847f01b5a58238a2 Mon Sep 17 00:00:00 2001 From: lschwass Date: Mon, 30 Mar 2026 20:51:56 +0200 Subject: [PATCH 081/102] added rest of the observation space --- src/jaxatari/games/jax_adventure.py | 125 ++++++++++++++++++++++++++-- 1 file changed, 120 insertions(+), 5 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 6fc5cfcfc..42e68c294 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -1665,16 +1665,131 @@ def observation_space(self) -> spaces: "player": spaces.Dict({ "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), - "width": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), - "height": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), + "tile": spaces.Box(low=0, high=30, shape=(), dtype=jnp.int32), + "width": spaces.Box(low=self.const.PLAYER_SIZE[0], high=self.const.PLAYER_SIZE[0], shape=(), dtype=jnp.int32), + "height": spaces.Box(low=self.const.PLAYER_SIZE[1], high=self.const.PLAYER_SIZE[1], shape=(), dtype=jnp.int32), + "state": spaces.Box(low=0, high=5, shape=(), dtype=jnp.int32), + }), + "dragon_yellow": spaces.Dict({ + "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), + "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), + "tile": spaces.Box(low=0, high=30, shape=(), dtype=jnp.int32), + "width": spaces.Box(low=self.consts.DRAGON_SIZE[0], high=self.consts.DRAGON_SIZE[0], shape=(), dtype=jnp.int32), + "height": spaces.Box(low=self.consts.DRAGON_SIZE[1], high=self.consts.DRAGON_SIZE[1], shape=(), dtype=jnp.int32), + "state": spaces.Box(low=0, high=5, shape=(), dtype=jnp.int32), + }), + "dragon_green": spaces.Dict({ + "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), + "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), + "tile": spaces.Box(low=0, high=30, shape=(), dtype=jnp.int32), + "width": spaces.Box(low=self.consts.DRAGON_SIZE[0], high=self.consts.DRAGON_SIZE[0], shape=(), dtype=jnp.int32), + "height": spaces.Box(low=self.consts.DRAGON_SIZE[1], high=self.consts.DRAGON_SIZE[1], shape=(), dtype=jnp.int32), + "state": spaces.Box(low=0, high=5, shape=(), dtype=jnp.int32), + }), + "dragon_red": spaces.Dict({ + "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), + "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), + "tile": spaces.Box(low=0, high=30, shape=(), dtype=jnp.int32), + "width": spaces.Box(low=self.consts.DRAGON_SIZE[0], high=self.consts.DRAGON_SIZE[0], shape=(), dtype=jnp.int32), + "height": spaces.Box(low=self.consts.DRAGON_SIZE[1], high=self.consts.DRAGON_SIZE[1], shape=(), dtype=jnp.int32), + "state": spaces.Box(low=0, high=5, shape=(), dtype=jnp.int32), }), "key_yellow": spaces.Dict({ "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), - "width": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), - "height": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), + "tile": spaces.Box(low=0, high=30, shape=(), dtype=jnp.int32), + "width": spaces.Box(low=self.consts.KEY_SIZE[0], high=self.consts.KEY_SIZE[0], shape=(), dtype=jnp.int32), + "height": spaces.Box(low=self.consts.KEY_SIZE[1], high=self.consts.KEY_SIZE[1], shape=(), dtype=jnp.int32), + "state": spaces.Box(low=0, high=5, shape=(), dtype=jnp.int32), }), - + "key_black": spaces.Dict({ + "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), + "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), + "tile": spaces.Box(low=0, high=30, shape=(), dtype=jnp.int32), + "width": spaces.Box(low=self.consts.KEY_SIZE[0], high=self.consts.KEY_SIZE[0], shape=(), dtype=jnp.int32), + "height": spaces.Box(low=self.consts.KEY_SIZE[1], high=self.consts.KEY_SIZE[1], shape=(), dtype=jnp.int32), + "state": spaces.Box(low=0, high=5, shape=(), dtype=jnp.int32), + }), + "key_white": spaces.Dict({ + "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), + "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), + "tile": spaces.Box(low=0, high=30, shape=(), dtype=jnp.int32), + "width": spaces.Box(low=self.consts.KEY_SIZE[0], high=self.consts.KEY_SIZE[0], shape=(), dtype=jnp.int32), + "height": spaces.Box(low=self.consts.KEY_SIZE[1], high=self.consts.KEY_SIZE[1], shape=(), dtype=jnp.int32), + "state": spaces.Box(low=0, high=5, shape=(), dtype=jnp.int32), + }), + "gate_yellow": spaces.Dict({ + "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), + "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), + "tile": spaces.Box(low=0, high=30, shape=(), dtype=jnp.int32), + "width": spaces.Box(low=self.consts.GATE_SIZE[0], high=self.consts.GATE_SIZE[0], shape=(), dtype=jnp.int32), + "height": spaces.Box(low=self.consts.GATE_SIZE[1], high=self.consts.GATE_SIZE[1], shape=(), dtype=jnp.int32), + "state": spaces.Box(low=0, high=5, shape=(), dtype=jnp.int32), + }), + "gate_black": spaces.Dict({ + "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), + "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), + "tile": spaces.Box(low=0, high=30, shape=(), dtype=jnp.int32), + "width": spaces.Box(low=self.consts.GATE_SIZE[0], high=self.consts.GATE_SIZE[0], shape=(), dtype=jnp.int32), + "height": spaces.Box(low=self.consts.GATE_SIZE[1], high=self.consts.GATE_SIZE[1], shape=(), dtype=jnp.int32), + "state": spaces.Box(low=0, high=5, shape=(), dtype=jnp.int32), + }), + "gate_white": spaces.Dict({ + "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), + "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), + "tile": spaces.Box(low=0, high=30, shape=(), dtype=jnp.int32), + "width": spaces.Box(low=self.consts.GATE_SIZE[0], high=self.consts.GATE_SIZE[0], shape=(), dtype=jnp.int32), + "height": spaces.Box(low=self.consts.GATE_SIZE[1], high=self.consts.GATE_SIZE[1], shape=(), dtype=jnp.int32), + "state": spaces.Box(low=0, high=5, shape=(), dtype=jnp.int32), + }), + "sword": spaces.Dict({ + "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), + "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), + "tile": spaces.Box(low=0, high=30, shape=(), dtype=jnp.int32), + "width": spaces.Box(low=self.consts.SWORD_SIZE[0], high=self.consts.SWORD_SIZE[0], shape=(), dtype=jnp.int32), + "height": spaces.Box(low=self.consts.SWORD_SIZE[1], high=self.consts.SWORD_SIZE[1], shape=(), dtype=jnp.int32), + "state": spaces.Box(low=0, high=5, shape=(), dtype=jnp.int32), + }), + "bridge": spaces.Dict({ + "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), + "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), + "tile": spaces.Box(low=0, high=30, shape=(), dtype=jnp.int32), + "width": spaces.Box(low=self.consts.BRIDGE_SIZE[0], high=self.consts.BRIDGE_SIZE[0], shape=(), dtype=jnp.int32), + "height": spaces.Box(low=self.consts.BRIDGE_SIZE[1], high=self.consts.BRIDGE_SIZE[1], shape=(), dtype=jnp.int32), + "state": spaces.Box(low=0, high=5, shape=(), dtype=jnp.int32), + }), + "magnet": spaces.Dict({ + "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), + "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), + "tile": spaces.Box(low=0, high=30, shape=(), dtype=jnp.int32), + "width": spaces.Box(low=self.consts.MAGNET_SIZE[0], high=self.consts.MAGNET_SIZE[0], shape=(), dtype=jnp.int32), + "height": spaces.Box(low=self.consts.MAGNET_SIZE[1], high=self.consts.MAGNET_SIZE[1], shape=(), dtype=jnp.int32), + "state": spaces.Box(low=0, high=5, shape=(), dtype=jnp.int32), + }), + "chalice": spaces.Dict({ + "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), + "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), + "tile": spaces.Box(low=0, high=30, shape=(), dtype=jnp.int32), + "width": spaces.Box(low=self.consts.CHALICE_SIZE[0], high=self.consts.CHALICE_SIZE[0], shape=(), dtype=jnp.int32), + "height": spaces.Box(low=self.consts.CHALICE_SIZE[1], high=self.consts.CHALICE_SIZE[1], shape=(), dtype=jnp.int32), + "state": spaces.Box(low=0, high=5, shape=(), dtype=jnp.int32), + }), + "bat": spaces.Dict({ + "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), + "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), + "tile": spaces.Box(low=0, high=30, shape=(), dtype=jnp.int32), + "width": spaces.Box(low=0, high=0, shape=(), dtype=jnp.int32), + "height": spaces.Box(low=0, high=0, shape=(), dtype=jnp.int32), + "state": spaces.Box(low=0, high=0, shape=(), dtype=jnp.int32), + }), + "key_yellow": spaces.Dict({ + "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), + "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), + "tile": spaces.Box(low=0, high=30, shape=(), dtype=jnp.int32), + "width": spaces.Box(low=self.consts.DOT_SIZE[0], high=self.consts.DOT_SIZE[0], shape=(), dtype=jnp.int32), + "height": spaces.Box(low=self.consts.DOT_SIZE[1], high=self.consts.DOT_SIZE[1], shape=(), dtype=jnp.int32), + "state": spaces.Box(low=0, high=5, shape=(), dtype=jnp.int32), + }) #ToDo for the rest of the dragons, items etc..... ? }) From 7260fae80da8920f0cda5055975efb781d354fd1 Mon Sep 17 00:00:00 2001 From: DanielCress Date: Mon, 30 Mar 2026 23:04:58 +0200 Subject: [PATCH 082/102] typo fix --- src/jaxatari/games/jax_adventure.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 0fefac007..9fa9ae356 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -1672,8 +1672,8 @@ def observation_space(self) -> spaces: "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), "tile": spaces.Box(low=0, high=30, shape=(), dtype=jnp.int32), - "width": spaces.Box(low=self.const.PLAYER_SIZE[0], high=self.const.PLAYER_SIZE[0], shape=(), dtype=jnp.int32), - "height": spaces.Box(low=self.const.PLAYER_SIZE[1], high=self.const.PLAYER_SIZE[1], shape=(), dtype=jnp.int32), + "width": spaces.Box(low=self.consts.PLAYER_SIZE[0], high=self.consts.PLAYER_SIZE[0], shape=(), dtype=jnp.int32), + "height": spaces.Box(low=self.consts.PLAYER_SIZE[1], high=self.consts.PLAYER_SIZE[1], shape=(), dtype=jnp.int32), "state": spaces.Box(low=0, high=5, shape=(), dtype=jnp.int32), }), "dragon_yellow": spaces.Dict({ From 4c282735b5bb3f0bbd1dbfe6bde5b85bf95bb2bc Mon Sep 17 00:00:00 2001 From: DanielCress Date: Mon, 30 Mar 2026 23:12:21 +0200 Subject: [PATCH 083/102] Update jax_adventure.py --- src/jaxatari/games/jax_adventure.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 9fa9ae356..6c34f7ece 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -1788,7 +1788,7 @@ def observation_space(self) -> spaces: "height": spaces.Box(low=0, high=0, shape=(), dtype=jnp.int32), "state": spaces.Box(low=0, high=0, shape=(), dtype=jnp.int32), }), - "key_yellow": spaces.Dict({ + "dot": spaces.Dict({ "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), "tile": spaces.Box(low=0, high=30, shape=(), dtype=jnp.int32), From 1cf5fff1b22e4bd5e386b4d2b5bb4b7bd447ca92 Mon Sep 17 00:00:00 2001 From: DanielCress Date: Tue, 31 Mar 2026 00:01:05 +0200 Subject: [PATCH 084/102] Update jax_adventure.py --- src/jaxatari/games/jax_adventure.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 6c34f7ece..6a4c36cd6 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -1666,7 +1666,7 @@ def action_space(self) -> spaces.Discrete: return spaces.Discrete(6) #ToDo, used for the RL? - def observation_space(self) -> spaces: + def observation_space(self) -> spaces.Dict: return spaces.Dict({ "player": spaces.Dict({ "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), From a27bd7f7c6fa02a918970cfbab6170d839cb3d73 Mon Sep 17 00:00:00 2001 From: DanielCress Date: Tue, 31 Mar 2026 00:07:29 +0200 Subject: [PATCH 085/102] Update jax_adventure.py --- src/jaxatari/games/jax_adventure.py | 145 +++------------------------- 1 file changed, 16 insertions(+), 129 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 6a4c36cd6..f461ec47d 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -1668,135 +1668,22 @@ def action_space(self) -> spaces.Discrete: #ToDo, used for the RL? def observation_space(self) -> spaces.Dict: return spaces.Dict({ - "player": spaces.Dict({ - "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), - "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), - "tile": spaces.Box(low=0, high=30, shape=(), dtype=jnp.int32), - "width": spaces.Box(low=self.consts.PLAYER_SIZE[0], high=self.consts.PLAYER_SIZE[0], shape=(), dtype=jnp.int32), - "height": spaces.Box(low=self.consts.PLAYER_SIZE[1], high=self.consts.PLAYER_SIZE[1], shape=(), dtype=jnp.int32), - "state": spaces.Box(low=0, high=5, shape=(), dtype=jnp.int32), - }), - "dragon_yellow": spaces.Dict({ - "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), - "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), - "tile": spaces.Box(low=0, high=30, shape=(), dtype=jnp.int32), - "width": spaces.Box(low=self.consts.DRAGON_SIZE[0], high=self.consts.DRAGON_SIZE[0], shape=(), dtype=jnp.int32), - "height": spaces.Box(low=self.consts.DRAGON_SIZE[1], high=self.consts.DRAGON_SIZE[1], shape=(), dtype=jnp.int32), - "state": spaces.Box(low=0, high=5, shape=(), dtype=jnp.int32), - }), - "dragon_green": spaces.Dict({ - "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), - "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), - "tile": spaces.Box(low=0, high=30, shape=(), dtype=jnp.int32), - "width": spaces.Box(low=self.consts.DRAGON_SIZE[0], high=self.consts.DRAGON_SIZE[0], shape=(), dtype=jnp.int32), - "height": spaces.Box(low=self.consts.DRAGON_SIZE[1], high=self.consts.DRAGON_SIZE[1], shape=(), dtype=jnp.int32), - "state": spaces.Box(low=0, high=5, shape=(), dtype=jnp.int32), - }), - "dragon_red": spaces.Dict({ - "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), - "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), - "tile": spaces.Box(low=0, high=30, shape=(), dtype=jnp.int32), - "width": spaces.Box(low=self.consts.DRAGON_SIZE[0], high=self.consts.DRAGON_SIZE[0], shape=(), dtype=jnp.int32), - "height": spaces.Box(low=self.consts.DRAGON_SIZE[1], high=self.consts.DRAGON_SIZE[1], shape=(), dtype=jnp.int32), - "state": spaces.Box(low=0, high=5, shape=(), dtype=jnp.int32), - }), - "key_yellow": spaces.Dict({ - "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), - "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), - "tile": spaces.Box(low=0, high=30, shape=(), dtype=jnp.int32), - "width": spaces.Box(low=self.consts.KEY_SIZE[0], high=self.consts.KEY_SIZE[0], shape=(), dtype=jnp.int32), - "height": spaces.Box(low=self.consts.KEY_SIZE[1], high=self.consts.KEY_SIZE[1], shape=(), dtype=jnp.int32), - "state": spaces.Box(low=0, high=5, shape=(), dtype=jnp.int32), - }), - "key_black": spaces.Dict({ - "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), - "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), - "tile": spaces.Box(low=0, high=30, shape=(), dtype=jnp.int32), - "width": spaces.Box(low=self.consts.KEY_SIZE[0], high=self.consts.KEY_SIZE[0], shape=(), dtype=jnp.int32), - "height": spaces.Box(low=self.consts.KEY_SIZE[1], high=self.consts.KEY_SIZE[1], shape=(), dtype=jnp.int32), - "state": spaces.Box(low=0, high=5, shape=(), dtype=jnp.int32), - }), - "key_white": spaces.Dict({ - "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), - "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), - "tile": spaces.Box(low=0, high=30, shape=(), dtype=jnp.int32), - "width": spaces.Box(low=self.consts.KEY_SIZE[0], high=self.consts.KEY_SIZE[0], shape=(), dtype=jnp.int32), - "height": spaces.Box(low=self.consts.KEY_SIZE[1], high=self.consts.KEY_SIZE[1], shape=(), dtype=jnp.int32), - "state": spaces.Box(low=0, high=5, shape=(), dtype=jnp.int32), - }), - "gate_yellow": spaces.Dict({ - "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), - "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), - "tile": spaces.Box(low=0, high=30, shape=(), dtype=jnp.int32), - "width": spaces.Box(low=self.consts.GATE_SIZE[0], high=self.consts.GATE_SIZE[0], shape=(), dtype=jnp.int32), - "height": spaces.Box(low=self.consts.GATE_SIZE[1], high=self.consts.GATE_SIZE[1], shape=(), dtype=jnp.int32), - "state": spaces.Box(low=0, high=5, shape=(), dtype=jnp.int32), - }), - "gate_black": spaces.Dict({ - "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), - "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), - "tile": spaces.Box(low=0, high=30, shape=(), dtype=jnp.int32), - "width": spaces.Box(low=self.consts.GATE_SIZE[0], high=self.consts.GATE_SIZE[0], shape=(), dtype=jnp.int32), - "height": spaces.Box(low=self.consts.GATE_SIZE[1], high=self.consts.GATE_SIZE[1], shape=(), dtype=jnp.int32), - "state": spaces.Box(low=0, high=5, shape=(), dtype=jnp.int32), - }), - "gate_white": spaces.Dict({ - "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), - "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), - "tile": spaces.Box(low=0, high=30, shape=(), dtype=jnp.int32), - "width": spaces.Box(low=self.consts.GATE_SIZE[0], high=self.consts.GATE_SIZE[0], shape=(), dtype=jnp.int32), - "height": spaces.Box(low=self.consts.GATE_SIZE[1], high=self.consts.GATE_SIZE[1], shape=(), dtype=jnp.int32), - "state": spaces.Box(low=0, high=5, shape=(), dtype=jnp.int32), - }), - "sword": spaces.Dict({ - "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), - "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), - "tile": spaces.Box(low=0, high=30, shape=(), dtype=jnp.int32), - "width": spaces.Box(low=self.consts.SWORD_SIZE[0], high=self.consts.SWORD_SIZE[0], shape=(), dtype=jnp.int32), - "height": spaces.Box(low=self.consts.SWORD_SIZE[1], high=self.consts.SWORD_SIZE[1], shape=(), dtype=jnp.int32), - "state": spaces.Box(low=0, high=5, shape=(), dtype=jnp.int32), - }), - "bridge": spaces.Dict({ - "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), - "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), - "tile": spaces.Box(low=0, high=30, shape=(), dtype=jnp.int32), - "width": spaces.Box(low=self.consts.BRIDGE_SIZE[0], high=self.consts.BRIDGE_SIZE[0], shape=(), dtype=jnp.int32), - "height": spaces.Box(low=self.consts.BRIDGE_SIZE[1], high=self.consts.BRIDGE_SIZE[1], shape=(), dtype=jnp.int32), - "state": spaces.Box(low=0, high=5, shape=(), dtype=jnp.int32), - }), - "magnet": spaces.Dict({ - "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), - "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), - "tile": spaces.Box(low=0, high=30, shape=(), dtype=jnp.int32), - "width": spaces.Box(low=self.consts.MAGNET_SIZE[0], high=self.consts.MAGNET_SIZE[0], shape=(), dtype=jnp.int32), - "height": spaces.Box(low=self.consts.MAGNET_SIZE[1], high=self.consts.MAGNET_SIZE[1], shape=(), dtype=jnp.int32), - "state": spaces.Box(low=0, high=5, shape=(), dtype=jnp.int32), - }), - "chalice": spaces.Dict({ - "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), - "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), - "tile": spaces.Box(low=0, high=30, shape=(), dtype=jnp.int32), - "width": spaces.Box(low=self.consts.CHALICE_SIZE[0], high=self.consts.CHALICE_SIZE[0], shape=(), dtype=jnp.int32), - "height": spaces.Box(low=self.consts.CHALICE_SIZE[1], high=self.consts.CHALICE_SIZE[1], shape=(), dtype=jnp.int32), - "state": spaces.Box(low=0, high=5, shape=(), dtype=jnp.int32), - }), - "bat": spaces.Dict({ - "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), - "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), - "tile": spaces.Box(low=0, high=30, shape=(), dtype=jnp.int32), - "width": spaces.Box(low=0, high=0, shape=(), dtype=jnp.int32), - "height": spaces.Box(low=0, high=0, shape=(), dtype=jnp.int32), - "state": spaces.Box(low=0, high=0, shape=(), dtype=jnp.int32), - }), - "dot": spaces.Dict({ - "x": spaces.Box(low=0, high=160, shape=(), dtype=jnp.int32), - "y": spaces.Box(low=0, high=250, shape=(), dtype=jnp.int32), - "tile": spaces.Box(low=0, high=30, shape=(), dtype=jnp.int32), - "width": spaces.Box(low=self.consts.DOT_SIZE[0], high=self.consts.DOT_SIZE[0], shape=(), dtype=jnp.int32), - "height": spaces.Box(low=self.consts.DOT_SIZE[1], high=self.consts.DOT_SIZE[1], shape=(), dtype=jnp.int32), - "state": spaces.Box(low=0, high=5, shape=(), dtype=jnp.int32), - }) - #ToDo for the rest of the dragons, items etc..... ? + "player": spaces.get_object_space(n=None, screen_size=(self.consts.SCREEN_HEIGHT, self.consts.SCREEN_WIDTH)), + "dragon_yellow": spaces.get_object_space(n=None, screen_size=(self.consts.SCREEN_HEIGHT, self.consts.SCREEN_WIDTH)), + "dragon_green": spaces.get_object_space(n=None, screen_size=(self.consts.SCREEN_HEIGHT, self.consts.SCREEN_WIDTH)), + "key_yellow": spaces.get_object_space(n=None, screen_size=(self.consts.SCREEN_HEIGHT, self.consts.SCREEN_WIDTH)), + "key_black": spaces.get_object_space(n=None, screen_size=(self.consts.SCREEN_HEIGHT, self.consts.SCREEN_WIDTH)), + "gate_yellow": spaces.get_object_space(n=None, screen_size=(self.consts.SCREEN_HEIGHT, self.consts.SCREEN_WIDTH)), + "gate_black":spaces.get_object_space(n=None, screen_size=(self.consts.SCREEN_HEIGHT, self.consts.SCREEN_WIDTH)), + "sword": spaces.get_object_space(n=None, screen_size=(self.consts.SCREEN_HEIGHT, self.consts.SCREEN_WIDTH)), + "bridge":spaces.get_object_space(n=None, screen_size=(self.consts.SCREEN_HEIGHT, self.consts.SCREEN_WIDTH)), + "magnet": spaces.get_object_space(n=None, screen_size=(self.consts.SCREEN_HEIGHT, self.consts.SCREEN_WIDTH)), + "chalice": spaces.get_object_space(n=None, screen_size=(self.consts.SCREEN_HEIGHT, self.consts.SCREEN_WIDTH)), + "dragon_red": spaces.get_object_space(n=None, screen_size=(self.consts.SCREEN_HEIGHT, self.consts.SCREEN_WIDTH)), + "key_white": spaces.get_object_space(n=None, screen_size=(self.consts.SCREEN_HEIGHT, self.consts.SCREEN_WIDTH)), + "gate_white": spaces.get_object_space(n=None, screen_size=(self.consts.SCREEN_HEIGHT, self.consts.SCREEN_WIDTH)), + "bat": spaces.get_object_space(n=None, screen_size=(self.consts.SCREEN_HEIGHT, self.consts.SCREEN_WIDTH)), + "dot":spaces.get_object_space(n=None, screen_size=(self.consts.SCREEN_HEIGHT, self.consts.SCREEN_WIDTH)) }) def image_space(self) -> spaces.Box: From e34473fb24668283d37fa6892b58208fdf036255 Mon Sep 17 00:00:00 2001 From: DanielCress Date: Tue, 31 Mar 2026 00:12:56 +0200 Subject: [PATCH 086/102] Update jax_adventure.py --- src/jaxatari/games/jax_adventure.py | 32 ++++++++++++++--------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index f461ec47d..ac22b1659 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -1668,22 +1668,22 @@ def action_space(self) -> spaces.Discrete: #ToDo, used for the RL? def observation_space(self) -> spaces.Dict: return spaces.Dict({ - "player": spaces.get_object_space(n=None, screen_size=(self.consts.SCREEN_HEIGHT, self.consts.SCREEN_WIDTH)), - "dragon_yellow": spaces.get_object_space(n=None, screen_size=(self.consts.SCREEN_HEIGHT, self.consts.SCREEN_WIDTH)), - "dragon_green": spaces.get_object_space(n=None, screen_size=(self.consts.SCREEN_HEIGHT, self.consts.SCREEN_WIDTH)), - "key_yellow": spaces.get_object_space(n=None, screen_size=(self.consts.SCREEN_HEIGHT, self.consts.SCREEN_WIDTH)), - "key_black": spaces.get_object_space(n=None, screen_size=(self.consts.SCREEN_HEIGHT, self.consts.SCREEN_WIDTH)), - "gate_yellow": spaces.get_object_space(n=None, screen_size=(self.consts.SCREEN_HEIGHT, self.consts.SCREEN_WIDTH)), - "gate_black":spaces.get_object_space(n=None, screen_size=(self.consts.SCREEN_HEIGHT, self.consts.SCREEN_WIDTH)), - "sword": spaces.get_object_space(n=None, screen_size=(self.consts.SCREEN_HEIGHT, self.consts.SCREEN_WIDTH)), - "bridge":spaces.get_object_space(n=None, screen_size=(self.consts.SCREEN_HEIGHT, self.consts.SCREEN_WIDTH)), - "magnet": spaces.get_object_space(n=None, screen_size=(self.consts.SCREEN_HEIGHT, self.consts.SCREEN_WIDTH)), - "chalice": spaces.get_object_space(n=None, screen_size=(self.consts.SCREEN_HEIGHT, self.consts.SCREEN_WIDTH)), - "dragon_red": spaces.get_object_space(n=None, screen_size=(self.consts.SCREEN_HEIGHT, self.consts.SCREEN_WIDTH)), - "key_white": spaces.get_object_space(n=None, screen_size=(self.consts.SCREEN_HEIGHT, self.consts.SCREEN_WIDTH)), - "gate_white": spaces.get_object_space(n=None, screen_size=(self.consts.SCREEN_HEIGHT, self.consts.SCREEN_WIDTH)), - "bat": spaces.get_object_space(n=None, screen_size=(self.consts.SCREEN_HEIGHT, self.consts.SCREEN_WIDTH)), - "dot":spaces.get_object_space(n=None, screen_size=(self.consts.SCREEN_HEIGHT, self.consts.SCREEN_WIDTH)) + "player": spaces.get_object_space(n=None, screen_size=(self.consts.HEIGHT, self.consts.WIDTH)), + "dragon_yellow": spaces.get_object_space(n=None, screen_size=(self.consts.HEIGHT, self.consts.WIDTH)), + "dragon_green": spaces.get_object_space(n=None, screen_size=(self.consts.HEIGHT, self.consts.WIDTH)), + "key_yellow": spaces.get_object_space(n=None, screen_size=(self.consts.HEIGHT, self.consts.WIDTH)), + "key_black": spaces.get_object_space(n=None, screen_size=(self.consts.HEIGHT, self.consts.WIDTH)), + "gate_yellow": spaces.get_object_space(n=None, screen_size=(self.consts.HEIGHT, self.consts.WIDTH)), + "gate_black":spaces.get_object_space(n=None, screen_size=(self.consts.HEIGHT, self.consts.WIDTH)), + "sword": spaces.get_object_space(n=None, screen_size=(self.consts.HEIGHT, self.consts.WIDTH)), + "bridge":spaces.get_object_space(n=None, screen_size=(self.consts.HEIGHT, self.consts.WIDTH)), + "magnet": spaces.get_object_space(n=None, screen_size=(self.consts.HEIGHT, self.consts.WIDTH)), + "chalice": spaces.get_object_space(n=None, screen_size=(self.consts.HEIGHT, self.consts.WIDTH)), + "dragon_red": spaces.get_object_space(n=None, screen_size=(self.consts.HEIGHT, self.consts.WIDTH)), + "key_white": spaces.get_object_space(n=None, screen_size=(self.consts.HEIGHT, self.consts.WIDTH)), + "gate_white": spaces.get_object_space(n=None, screen_size=(self.consts.HEIGHT, self.consts.WIDTH)), + "bat": spaces.get_object_space(n=None, screen_size=(self.consts.HEIGHT, self.consts.WIDTH)), + "dot":spaces.get_object_space(n=None, screen_size=(self.consts.HEIGHT, self.consts.WIDTH)) }) def image_space(self) -> spaces.Box: From d0600537bb6333a9bfa4948a3ed3535f3874f922 Mon Sep 17 00:00:00 2001 From: DanielCress Date: Tue, 31 Mar 2026 13:05:49 +0200 Subject: [PATCH 087/102] Update jax_adventure.py --- src/jaxatari/games/jax_adventure.py | 134 ++++++++++++---------------- 1 file changed, 58 insertions(+), 76 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index ac22b1659..4a106c2f3 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -10,7 +10,7 @@ import jaxatari.spaces as spaces from jaxatari.renderers import JAXGameRenderer from jaxatari.rendering import jax_rendering_utils as render_utils -from jaxatari.environment import JaxEnvironment, JAXAtariAction as Action +from jaxatari.environment import JaxEnvironment, JAXAtariAction as Action, ObjectObservation def _get_default_asset_config() -> tuple: """ @@ -200,32 +200,23 @@ class AdventureState(struct.PyTreeNode): dot: chex.Array -class EntityPosition(struct.PyTreeNode): - x: jnp.ndarray - y: jnp.ndarray - tile: jnp.ndarray - width: jnp.ndarray - height: jnp.ndarray - state: jnp.ndarray - - class AdventureObservation(struct.PyTreeNode): - player: EntityPosition - dragon_yellow: EntityPosition - dragon_green: EntityPosition - key_yellow: EntityPosition - key_black: EntityPosition - gate_yellow: EntityPosition - gate_black: EntityPosition - sword: EntityPosition - bridge: EntityPosition - magnet: EntityPosition - chalice: EntityPosition - dragon_red: EntityPosition - key_white: EntityPosition - gate_white: EntityPosition - bat: EntityPosition - dot: EntityPosition + player: ObjectObservation + dragon_yellow: ObjectObservation + dragon_green: ObjectObservation + key_yellow: ObjectObservation + key_black: ObjectObservation + gate_yellow: ObjectObservation + gate_black: ObjectObservation + sword: ObjectObservation + bridge: ObjectObservation + magnet: ObjectObservation + chalice: ObjectObservation + dragon_red: ObjectObservation + key_white: ObjectObservation + gate_white: ObjectObservation + bat: ObjectObservation + dot: ObjectObservation class AdventureInfo(struct.PyTreeNode): @@ -1279,7 +1270,7 @@ def _magnet_step(self, state: AdventureState) -> AdventureState: chalice=jnp.array([chalice_x,chalice_y,state.chalice[2],state.chalice[3]]).astype(jnp.int32) ) - """This function solely exists for maing the chalice change colors""" + def _chalice_step(self, state:AdventureState) -> AdventureState: chalice_color=state.chalice[3] @@ -1411,133 +1402,123 @@ def render(self, state: AdventureState) -> jnp.ndarray: #ToDo, done for all movable entities, why, no clue def _get_observation(self, state: AdventureState): - player = EntityPosition( + player = ObjectObservation.create( x=state.player[0], y=state.player[1], - tile=state.player[2], width=self.consts.PLAYER_SIZE[0], height=self.consts.PLAYER_SIZE[1], state=state.player[4] ) - dragon_yellow = EntityPosition( + dragon_yellow = ObjectObservation.create( x=state.dragon_yellow[0], y=state.dragon_yellow[1], - tile=state.dragon_yellow[2], + active=state.dragon_yellow[2]==state.player[2], width=self.consts.DRAGON_SIZE[0], height=self.consts.DRAGON_SIZE[1], state=state.dragon_yellow[3] ) - dragon_green = EntityPosition( + dragon_green = ObjectObservation.create( x=state.dragon_green[0], y=state.dragon_green[1], - tile=state.dragon_green[2], + active=state.dragon_green[2]==state.player[2], width=self.consts.DRAGON_SIZE[0], height=self.consts.DRAGON_SIZE[1], state=state.dragon_green[3] ) - key_yellow = EntityPosition( + key_yellow = ObjectObservation.create( x=state.key_yellow[0], y=state.key_yellow[1], - tile=state.key_yellow[2], + active=state.key_yellow[2]==state.player[2], width=self.consts.KEY_SIZE[0], - height=self.consts.KEY_SIZE[1], - state=0 #Key has no relevant state + height=self.consts.KEY_SIZE[1] ) - key_black = EntityPosition( + key_black = ObjectObservation.create( x=state.key_black[0], y=state.key_black[1], - tile=state.key_black[2], + active=state.key_black[2]==state.player[2], width=self.consts.KEY_SIZE[0], height=self.consts.KEY_SIZE[1], - state=0 #Key has no relevant state ) - gate_yellow = EntityPosition( + gate_yellow = ObjectObservation.create( x=self.consts.YELLOW_GATE_POS[0], y=self.consts.YELLOW_GATE_POS[1], - tile=self.consts.YELLOW_GATE_POS[2], + active=self.consts.YELLOW_GATE_POS[2]==state.player[2], width=self.consts.GATE_SIZE[0], height=self.consts.GATE_SIZE[1], state=state.gate_yellow[0] ) - gate_black = EntityPosition( + gate_black = ObjectObservation.create( x=self.consts.BLACK_GATE_POS[0], y=self.consts.BLACK_GATE_POS[1], - tile=self.consts.BLACK_GATE_POS[2], + active=self.consts.BLACK_GATE_POS[2]==state.player[2], width=self.consts.GATE_SIZE[0], height=self.consts.GATE_SIZE[1], state=state.gate_black[0] ) - sword = EntityPosition( + sword = ObjectObservation.create( x=state.sword[0], y=state.sword[1], - tile=state.sword[2], + active=state.sword[2]==state.player[2], width=self.consts.SWORD_SIZE[0], - height=self.consts.SWORD_SIZE[1], - state=0 #Sword has no relevant state + height=self.consts.SWORD_SIZE[1] ) - bridge = EntityPosition( + bridge = ObjectObservation.create( x=state.bridge[0], y=state.bridge[1], - tile=state.bridge[2], + active=state.bridge[2]==state.player[2], width=self.consts.BRIDGE_SIZE[0], - height=self.consts.BRIDGE_SIZE[1], - state=0 #Bridge has no relevant state + height=self.consts.BRIDGE_SIZE[1] ) - magnet = EntityPosition( + magnet = ObjectObservation.create( x=state.magnet[0], y=state.magnet[1], - tile=state.magnet[2], + active=state.magnet[2]==state.player[2], width=self.consts.MAGNET_SIZE[0], - height=self.consts.MAGNET_SIZE[1], - state=0 #Magnet has no relevant state + height=self.consts.MAGNET_SIZE[1] ) - chalice = EntityPosition( + chalice = ObjectObservation.create( x=state.chalice[0], y=state.chalice[1], - tile=state.chalice[2], + active=state.chalice[2]==state.player[2], width=self.consts.CHALICE_SIZE[0], - height=self.consts.CHALICE_SIZE[1], - state=0 #Chalice has no relevant state + height=self.consts.CHALICE_SIZE[1] ) - dragon_red = EntityPosition( + dragon_red = ObjectObservation.create( x=state.dragon_red[0], y=state.dragon_red[1], - tile=state.dragon_red[2], + active=state.dragon_red[2]==state.player[2], width=self.consts.DRAGON_SIZE[0], height=self.consts.DRAGON_SIZE[1], state=state.dragon_red[3] ) - key_white = EntityPosition( + key_white = ObjectObservation.create( x=state.key_white[0], y=state.key_white[1], - tile=state.key_white[2], + active=state.key_white[2]==state.player[2], width=self.consts.KEY_SIZE[0], - height=self.consts.KEY_SIZE[1], - state=0 #Key has no relevant state + height=self.consts.KEY_SIZE[1] ) - gate_white = EntityPosition( + gate_white = ObjectObservation.create( x=self.consts.WHITE_GATE_POS[0], y=self.consts.WHITE_GATE_POS[1], - tile=self.consts.WHITE_GATE_POS[2], + active=self.consts.WHITE_GATE_POS[2]==state.player[2], width=self.consts.GATE_SIZE[0], height=self.consts.GATE_SIZE[1], state=state.gate_white[0] ) - bat = EntityPosition( + bat = ObjectObservation.create( x=state.bat[0], y=state.bat[1], - tile=state.bat[2], + active=state.bat[2]==state.player[2], width=0, #bat has no hitbox - height=0, - state=0 #bat has no relevant state + height=0 ) - dot = EntityPosition( + dot = ObjectObservation.create( x=state.dot[0], y=state.dot[1], - tile=state.dot[2], + active=state.dot[2]==state.player[2], width=self.consts.DOT_SIZE[0], - height=self.consts.DOT_SIZE[1], - state=0 #Dot has no relevant state + height=self.consts.DOT_SIZE[1] ) return AdventureObservation( @@ -1667,6 +1648,7 @@ def action_space(self) -> spaces.Discrete: #ToDo, used for the RL? def observation_space(self) -> spaces.Dict: + return spaces.Dict({ "player": spaces.get_object_space(n=None, screen_size=(self.consts.HEIGHT, self.consts.WIDTH)), "dragon_yellow": spaces.get_object_space(n=None, screen_size=(self.consts.HEIGHT, self.consts.WIDTH)), From 7325ccf25b22732361ab6ec00b54b62ea8c95870 Mon Sep 17 00:00:00 2001 From: DanielCress Date: Tue, 31 Mar 2026 13:18:23 +0200 Subject: [PATCH 088/102] Update jax_adventure.py --- src/jaxatari/games/jax_adventure.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 4a106c2f3..8f802c1b3 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -1704,14 +1704,17 @@ def _get_done(self, state: AdventureState) -> bool: class AdventureRenderer(JAXGameRenderer): - def __init__(self, consts: AdventureConstants = None): + def __init__(self, consts: AdventureConstants = None, config: render_utils.RendererConfig = None): super().__init__(consts) self.consts = consts or AdventureConstants() - self.config = render_utils.RendererConfig( - game_dimensions=(250, 160), - channels=3, - #ownscale=(200, 128) - ) + if config is None: + self.config = render_utils.RendererConfig( + game_dimensions=(self.consts.HEIGHT, self.consts.WIDTH), + channels=3, + downscale=None + ) + else: + self.config = config self.jr = render_utils.JaxRenderingUtils(self.config) # 1. Start from (possibly modded) asset config provided via constants From 8d3626a321de90cb2a368ca3ec1052411dceaeab Mon Sep 17 00:00:00 2001 From: DanielCress Date: Tue, 31 Mar 2026 13:27:05 +0200 Subject: [PATCH 089/102] Update jax_adventure.py --- src/jaxatari/games/jax_adventure.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 8f802c1b3..472048728 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -615,7 +615,7 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt ) return state.replace( - step_counter = jnp.array(new_step_counter).astype(jnp.int32), + step_counter = jnp.array(new_step_counter), player = jnp.array([new_player_x,new_player_y,new_player_tile,state.player[3]]).astype(jnp.int32), #SEEMS NOT GOOD key_yellow = jax.lax.cond(state.player[3]==self.consts.KEY_YELLOW_ID, lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), @@ -1285,7 +1285,7 @@ def _chalice_step(self, state:AdventureState) -> AdventureState: def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureObservation, AdventureState]: state_key, _step_key = jax.random.split(key) state = AdventureState( - step_counter = jnp.array(0).astype(jnp.int32), + step_counter = jnp.array(0), #Player Spawn: x, y, tile, inventory player = jnp.array([self.consts.PLAYER_SPAWN[0], self.consts.PLAYER_SPAWN[1], From d13cd455a62506f073af7502e0ef920c08180571 Mon Sep 17 00:00:00 2001 From: DanielCress Date: Tue, 31 Mar 2026 13:37:46 +0200 Subject: [PATCH 090/102] Update jax_adventure.py --- src/jaxatari/games/jax_adventure.py | 78 ++++++++++++++--------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 472048728..848284af9 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -616,44 +616,44 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt return state.replace( step_counter = jnp.array(new_step_counter), - player = jnp.array([new_player_x,new_player_y,new_player_tile,state.player[3]]).astype(jnp.int32), #SEEMS NOT GOOD + player = jnp.array([new_player_x,new_player_y,new_player_tile,state.player[3]]), #SEEMS NOT GOOD key_yellow = jax.lax.cond(state.player[3]==self.consts.KEY_YELLOW_ID, - lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: jnp.array([op[0],op[1],op[2]]), lambda op: op[3], operand=(new_item_x,new_item_y,new_item_tile,state.key_yellow), ), key_black= jax.lax.cond(state.player[3]==self.consts.KEY_BLACK_ID, - lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: jnp.array([op[0],op[1],op[2]]), lambda op: op[3], operand=(new_item_x,new_item_y,new_item_tile,state.key_black) ), key_white= jax.lax.cond(state.player[3]==self.consts.KEY_WHITE_ID, - lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: jnp.array([op[0],op[1],op[2]]), lambda op: op[3], operand=(new_item_x,new_item_y,new_item_tile,state.key_white) ), sword= jax.lax.cond(state.player[3]==self.consts.SWORD_ID, - lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: jnp.array([op[0],op[1],op[2]]), lambda op: op[3], operand=(new_item_x,new_item_y,new_item_tile,state.sword) ), bridge= jax.lax.cond(state.player[3]==self.consts.BRIDGE_ID, - lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: jnp.array([op[0],op[1],op[2]]), lambda op: op[3], operand=(new_item_x,new_item_y,new_item_tile,state.bridge) ), magnet= jax.lax.cond(state.player[3]==self.consts.MAGNET_ID, - lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: jnp.array([op[0],op[1],op[2]]), lambda op: op[3], operand=(new_item_x,new_item_y,new_item_tile,state.magnet) ), chalice= jax.lax.cond(state.player[3]==self.consts.CHALICE_ID, - lambda op: jnp.array([op[0],op[1],op[2],op[3]]).astype(jnp.int32), + lambda op: jnp.array([op[0],op[1],op[2],op[3]]), lambda op: op[4], operand=(new_item_x,new_item_y,new_item_tile,state.chalice[3],state.chalice) ), dot= jax.lax.cond(state.player[3]==self.consts.DOT_ID, - lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: jnp.array([op[0],op[1],op[2]]), lambda op: op[3], operand=(new_item_x,new_item_y,new_item_tile,state.dot) ), @@ -819,9 +819,9 @@ def _gate_interaction(self, state: AdventureState) -> AdventureState: ) return state.replace( - gate_yellow=jnp.array([gate_yellow_state, gate_yellow_counter]).astype(jnp.int32), - gate_black=jnp.array([gate_black_state, gate_black_counter]).astype(jnp.int32), - gate_white=jnp.array([gate_white_state, gate_white_counter]).astype(jnp.int32), + gate_yellow=jnp.array([gate_yellow_state, gate_yellow_counter]), + gate_black=jnp.array([gate_black_state, gate_black_counter]), + gate_white=jnp.array([gate_white_state, gate_white_counter]), ) def _item_pickup(self, state: AdventureState, action: chex.Array) -> AdventureState: @@ -1015,7 +1015,7 @@ def diff_of_4(val1:int, val2:int) -> bool: return state.replace( - player = jnp.array([state.player[0],state.player[1],state.player[2],new_player_inventory]).astype(jnp.int32) + player = jnp.array([state.player[0],state.player[1],state.player[2],new_player_inventory]) ) def _item_drop(self, state: AdventureState, action: chex.Array) -> AdventureState: @@ -1029,7 +1029,7 @@ def _item_drop(self, state: AdventureState, action: chex.Array) -> AdventureStat ) return state.replace( - player = jnp.array([state.player[0],state.player[1],state.player[2],new_player_inventory]).astype(jnp.int32) + player = jnp.array([state.player[0],state.player[1],state.player[2],new_player_inventory]) ) @@ -1180,8 +1180,8 @@ def _dragon_step(self, state: AdventureState) -> AdventureState: return state.replace( - dragon_yellow = jnp.array([dragon_yellow_x,dragon_yellow_y,dragon_yellow_tile,dragon_yellow_animation,dragon_yellow_counter,dragon_yellow_eat, dragon_yellow_activate]).astype(jnp.int32), - dragon_green = jnp.array([dragon_green_x,dragon_green_y,dragon_green_tile,dragon_green_animation,dragon_green_counter,dragon_green_eat, dragon_green_activate]).astype(jnp.int32), + dragon_yellow = jnp.array([dragon_yellow_x,dragon_yellow_y,dragon_yellow_tile,dragon_yellow_animation,dragon_yellow_counter,dragon_yellow_eat, dragon_yellow_activate]), + dragon_green = jnp.array([dragon_green_x,dragon_green_y,dragon_green_tile,dragon_green_animation,dragon_green_counter,dragon_green_eat, dragon_green_activate]), rndKey=rndKey ) @@ -1262,12 +1262,12 @@ def _magnet_step(self, state: AdventureState) -> AdventureState: ) return state.replace( - key_yellow=jnp.array([key_yellow_x,key_yellow_y,state.key_yellow[2]]).astype(jnp.int32), - key_black=jnp.array([key_black_x,key_black_y,state.key_black[2]]).astype(jnp.int32), - key_white=jnp.array([key_white_x,key_white_y,state.key_white[2]]).astype(jnp.int32), - sword=jnp.array([sword_x,sword_y,state.sword[2]]).astype(jnp.int32), - bridge=jnp.array([bridge_x,bridge_y,state.bridge[2]]).astype(jnp.int32), - chalice=jnp.array([chalice_x,chalice_y,state.chalice[2],state.chalice[3]]).astype(jnp.int32) + key_yellow=jnp.array([key_yellow_x,key_yellow_y,state.key_yellow[2]]), + key_black=jnp.array([key_black_x,key_black_y,state.key_black[2]]), + key_white=jnp.array([key_white_x,key_white_y,state.key_white[2]]), + sword=jnp.array([sword_x,sword_y,state.sword[2]]), + bridge=jnp.array([bridge_x,bridge_y,state.bridge[2]]), + chalice=jnp.array([chalice_x,chalice_y,state.chalice[2],state.chalice[3]]) ) @@ -1277,7 +1277,7 @@ def _chalice_step(self, state:AdventureState) -> AdventureState: chalice_color = (chalice_color +1) % 10 return state.replace( - chalice=jnp.array([state.chalice[0],state.chalice[1],state.chalice[2],chalice_color]).astype(jnp.int32) + chalice=jnp.array([state.chalice[0],state.chalice[1],state.chalice[2],chalice_color]) ) """This function is called when the game starts and when it is reseted @@ -1290,7 +1290,7 @@ def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureOb player = jnp.array([self.consts.PLAYER_SPAWN[0], self.consts.PLAYER_SPAWN[1], self.consts.PLAYER_SPAWN[2], - self.consts.EMPTY_HAND_ID]).astype(jnp.int32), + self.consts.EMPTY_HAND_ID]), #Dragons: x, y ,tile ,state(neutral,dead,atacking), counter( ToDo for?? ) dragon_yellow = jnp.array([self.consts.DRAGON_YELLOW_SPAWN[0], self.consts.DRAGON_YELLOW_SPAWN[1], @@ -1298,58 +1298,58 @@ def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureOb self.consts.DRAGON_YELLOW_SPAWN[3], self.consts.DRAGON_YELLOW_SPAWN[4], self.consts.DRAGON_YELLOW_SPAWN[5], - self.consts.DRAGON_YELLOW_SPAWN[6]]).astype(jnp.int32), #ToDo + self.consts.DRAGON_YELLOW_SPAWN[6]]), #ToDo dragon_green = jnp.array([self.consts.DRAGON_GREEN_SPAWN[0], self.consts.DRAGON_GREEN_SPAWN[1], self.consts.DRAGON_GREEN_SPAWN[2], self.consts.DRAGON_GREEN_SPAWN[3], self.consts.DRAGON_GREEN_SPAWN[4], self.consts.DRAGON_GREEN_SPAWN[5], - self.consts.DRAGON_GREEN_SPAWN[6]]).astype(jnp.int32), + self.consts.DRAGON_GREEN_SPAWN[6]]), dragon_red = jnp.array([self.consts.DRAGON_RED_SPAWN[0], self.consts.DRAGON_RED_SPAWN[1], self.consts.DRAGON_RED_SPAWN[2], self.consts.DRAGON_RED_SPAWN[3], self.consts.DRAGON_RED_SPAWN[4], self.consts.DRAGON_RED_SPAWN[5], - self.consts.DRAGON_RED_SPAWN[6]]).astype(jnp.int32), + self.consts.DRAGON_RED_SPAWN[6]]), #Keys: x ,y, tile key_yellow = jnp.array([self.consts.KEY_YELLOW_SPAWN[0], self.consts.KEY_YELLOW_SPAWN[1], - self.consts.KEY_YELLOW_SPAWN[2]]).astype(jnp.int32), + self.consts.KEY_YELLOW_SPAWN[2]]), key_black = jnp.array([self.consts.KEY_BLACK_SPAWN[0], self.consts.KEY_BLACK_SPAWN[1], - self.consts.KEY_BLACK_SPAWN[2]]).astype(jnp.int32), + self.consts.KEY_BLACK_SPAWN[2]]), key_white = jnp.array([self.consts.KEY_WHITE_SPAWN[0], self.consts.KEY_WHITE_SPAWN[1], - self.consts.KEY_WHITE_SPAWN[2]]).astype(jnp.int32), + self.consts.KEY_WHITE_SPAWN[2]]), #Gate: state, counter (ToDo for animation?) - gate_yellow=jnp.array([0,0]).astype(jnp.int32), - gate_black=jnp.array([0,0]).astype(jnp.int32), - gate_white=jnp.array([0,0]).astype(jnp.int32), + gate_yellow=jnp.array([0,0]), + gate_black=jnp.array([0,0]), + gate_white=jnp.array([0,0]), #Items: x, y, tile sword = jnp.array([self.consts.SWORD_SPAWN[0], self.consts.SWORD_SPAWN[1], - self.consts.SWORD_SPAWN[2]]).astype(jnp.int32), #ToDo + self.consts.SWORD_SPAWN[2]]), #ToDo bridge = jnp.array([self.consts.BRIDGE_SPAWN[0], self.consts.BRIDGE_SPAWN[1], - self.consts.BRIDGE_SPAWN[2]]).astype(jnp.int32), #ToDo + self.consts.BRIDGE_SPAWN[2]]), #ToDo magnet= jnp.array([self.consts.MAGNET_SPAWN[0], self.consts.MAGNET_SPAWN[1], - self.consts.MAGNET_SPAWN[2]]).astype(jnp.int32), #ToDo + self.consts.MAGNET_SPAWN[2]]), #ToDo #Chalice: x, y, tile, color (ToDo move color to constants) chalice = jnp.array([self.consts.CHALICE_SPAWN[0], self.consts.CHALICE_SPAWN[1], - self.consts.CHALICE_SPAWN[2],7]).astype(jnp.int32), #ToDo + self.consts.CHALICE_SPAWN[2],7]), #ToDo #random key rndKey = state_key, bat = jnp.array([self.consts.BAT_SPAWN[0], self.consts.BAT_SPAWN[1], self.consts.BAT_SPAWN[2], - self.consts.BAT_SPAWN[3]]).astype(jnp.int32), + self.consts.BAT_SPAWN[3]]), dot = jnp.array([self.consts.DOT_SPAWN[0], self.consts.DOT_SPAWN[1], - self.consts.DOT_SPAWN[2]]).astype(jnp.int32) + self.consts.DOT_SPAWN[2]]) ) initial_obs = self._get_observation(state) From f5bed52a22b772d07c588dc5a808264c3f1e533a Mon Sep 17 00:00:00 2001 From: DanielCress Date: Tue, 31 Mar 2026 13:57:02 +0200 Subject: [PATCH 091/102] Update jax_adventure.py --- src/jaxatari/games/jax_adventure.py | 86 ++++++++++++++--------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 848284af9..6f50df588 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -499,13 +499,13 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt new_player_y = state.player[1] new_player_y, new_item_y, new_step_counter = jax.lax.cond( down_no_wall, - lambda y: (y[0]+8,y[1]+8,y[2]), + lambda y: (y[0]+8,y[1]+8,y[2]+1), lambda y: y, operand = (new_player_y,new_item_y,new_step_counter) ) new_player_y, new_item_y, new_step_counter = jax.lax.cond( up_no_wall, - lambda y: (y[0]-8,y[1]-8,y[2]), + lambda y: (y[0]-8,y[1]-8,y[2]+1), lambda y: y, operand = (new_player_y,new_item_y,new_step_counter) ) @@ -616,44 +616,44 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt return state.replace( step_counter = jnp.array(new_step_counter), - player = jnp.array([new_player_x,new_player_y,new_player_tile,state.player[3]]), #SEEMS NOT GOOD + player = jnp.array([new_player_x,new_player_y,new_player_tile,state.player[3]]).astype(jnp.int32), #SEEMS NOT GOOD key_yellow = jax.lax.cond(state.player[3]==self.consts.KEY_YELLOW_ID, - lambda op: jnp.array([op[0],op[1],op[2]]), + lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), lambda op: op[3], operand=(new_item_x,new_item_y,new_item_tile,state.key_yellow), ), key_black= jax.lax.cond(state.player[3]==self.consts.KEY_BLACK_ID, - lambda op: jnp.array([op[0],op[1],op[2]]), + lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), lambda op: op[3], operand=(new_item_x,new_item_y,new_item_tile,state.key_black) ), key_white= jax.lax.cond(state.player[3]==self.consts.KEY_WHITE_ID, - lambda op: jnp.array([op[0],op[1],op[2]]), + lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), lambda op: op[3], operand=(new_item_x,new_item_y,new_item_tile,state.key_white) ), sword= jax.lax.cond(state.player[3]==self.consts.SWORD_ID, - lambda op: jnp.array([op[0],op[1],op[2]]), + lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), lambda op: op[3], operand=(new_item_x,new_item_y,new_item_tile,state.sword) ), bridge= jax.lax.cond(state.player[3]==self.consts.BRIDGE_ID, - lambda op: jnp.array([op[0],op[1],op[2]]), + lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), lambda op: op[3], operand=(new_item_x,new_item_y,new_item_tile,state.bridge) ), magnet= jax.lax.cond(state.player[3]==self.consts.MAGNET_ID, - lambda op: jnp.array([op[0],op[1],op[2]]), + lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), lambda op: op[3], operand=(new_item_x,new_item_y,new_item_tile,state.magnet) ), chalice= jax.lax.cond(state.player[3]==self.consts.CHALICE_ID, - lambda op: jnp.array([op[0],op[1],op[2],op[3]]), + lambda op: jnp.array([op[0],op[1],op[2],op[3]]).astype(jnp.int32), lambda op: op[4], operand=(new_item_x,new_item_y,new_item_tile,state.chalice[3],state.chalice) ), dot= jax.lax.cond(state.player[3]==self.consts.DOT_ID, - lambda op: jnp.array([op[0],op[1],op[2]]), + lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), lambda op: op[3], operand=(new_item_x,new_item_y,new_item_tile,state.dot) ), @@ -819,9 +819,9 @@ def _gate_interaction(self, state: AdventureState) -> AdventureState: ) return state.replace( - gate_yellow=jnp.array([gate_yellow_state, gate_yellow_counter]), - gate_black=jnp.array([gate_black_state, gate_black_counter]), - gate_white=jnp.array([gate_white_state, gate_white_counter]), + gate_yellow=jnp.array([gate_yellow_state, gate_yellow_counter]).astype(jnp.int32), + gate_black=jnp.array([gate_black_state, gate_black_counter]).astype(jnp.int32), + gate_white=jnp.array([gate_white_state, gate_white_counter]).astype(jnp.int32), ) def _item_pickup(self, state: AdventureState, action: chex.Array) -> AdventureState: @@ -1015,7 +1015,7 @@ def diff_of_4(val1:int, val2:int) -> bool: return state.replace( - player = jnp.array([state.player[0],state.player[1],state.player[2],new_player_inventory]) + player = jnp.array([state.player[0],state.player[1],state.player[2],new_player_inventory]).astype(jnp.int32) ) def _item_drop(self, state: AdventureState, action: chex.Array) -> AdventureState: @@ -1029,7 +1029,7 @@ def _item_drop(self, state: AdventureState, action: chex.Array) -> AdventureStat ) return state.replace( - player = jnp.array([state.player[0],state.player[1],state.player[2],new_player_inventory]) + player = jnp.array([state.player[0],state.player[1],state.player[2],new_player_inventory]).astype(jnp.int32) ) @@ -1180,8 +1180,8 @@ def _dragon_step(self, state: AdventureState) -> AdventureState: return state.replace( - dragon_yellow = jnp.array([dragon_yellow_x,dragon_yellow_y,dragon_yellow_tile,dragon_yellow_animation,dragon_yellow_counter,dragon_yellow_eat, dragon_yellow_activate]), - dragon_green = jnp.array([dragon_green_x,dragon_green_y,dragon_green_tile,dragon_green_animation,dragon_green_counter,dragon_green_eat, dragon_green_activate]), + dragon_yellow = jnp.array([dragon_yellow_x,dragon_yellow_y,dragon_yellow_tile,dragon_yellow_animation,dragon_yellow_counter,dragon_yellow_eat, dragon_yellow_activate]).astype(jnp.int32), + dragon_green = jnp.array([dragon_green_x,dragon_green_y,dragon_green_tile,dragon_green_animation,dragon_green_counter,dragon_green_eat, dragon_green_activate]).astype(jnp.int32), rndKey=rndKey ) @@ -1262,12 +1262,12 @@ def _magnet_step(self, state: AdventureState) -> AdventureState: ) return state.replace( - key_yellow=jnp.array([key_yellow_x,key_yellow_y,state.key_yellow[2]]), - key_black=jnp.array([key_black_x,key_black_y,state.key_black[2]]), - key_white=jnp.array([key_white_x,key_white_y,state.key_white[2]]), - sword=jnp.array([sword_x,sword_y,state.sword[2]]), - bridge=jnp.array([bridge_x,bridge_y,state.bridge[2]]), - chalice=jnp.array([chalice_x,chalice_y,state.chalice[2],state.chalice[3]]) + key_yellow=jnp.array([key_yellow_x,key_yellow_y,state.key_yellow[2]]).astype(jnp.int32), + key_black=jnp.array([key_black_x,key_black_y,state.key_black[2]]).astype(jnp.int32), + key_white=jnp.array([key_white_x,key_white_y,state.key_white[2]]).astype(jnp.int32), + sword=jnp.array([sword_x,sword_y,state.sword[2]]).astype(jnp.int32), + bridge=jnp.array([bridge_x,bridge_y,state.bridge[2]]).astype(jnp.int32), + chalice=jnp.array([chalice_x,chalice_y,state.chalice[2],state.chalice[3]]).astype(jnp.int32) ) @@ -1277,20 +1277,20 @@ def _chalice_step(self, state:AdventureState) -> AdventureState: chalice_color = (chalice_color +1) % 10 return state.replace( - chalice=jnp.array([state.chalice[0],state.chalice[1],state.chalice[2],chalice_color]) + chalice=jnp.array([state.chalice[0],state.chalice[1],state.chalice[2],chalice_color]).astype(jnp.int32) ) """This function is called when the game starts and when it is reseted It initializes the Adventure state, for the most part these Values are pulled from the consts""" - def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureObservation, AdventureState]: + def reset(self, key: jax.random.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureObservation, AdventureState]: state_key, _step_key = jax.random.split(key) state = AdventureState( - step_counter = jnp.array(0), + step_counter = jnp.array(0, dtype=jnp.int32), #Player Spawn: x, y, tile, inventory player = jnp.array([self.consts.PLAYER_SPAWN[0], self.consts.PLAYER_SPAWN[1], self.consts.PLAYER_SPAWN[2], - self.consts.EMPTY_HAND_ID]), + self.consts.EMPTY_HAND_ID]).astype(jnp.int32), #Dragons: x, y ,tile ,state(neutral,dead,atacking), counter( ToDo for?? ) dragon_yellow = jnp.array([self.consts.DRAGON_YELLOW_SPAWN[0], self.consts.DRAGON_YELLOW_SPAWN[1], @@ -1298,58 +1298,58 @@ def reset(self, key: chex.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureOb self.consts.DRAGON_YELLOW_SPAWN[3], self.consts.DRAGON_YELLOW_SPAWN[4], self.consts.DRAGON_YELLOW_SPAWN[5], - self.consts.DRAGON_YELLOW_SPAWN[6]]), #ToDo + self.consts.DRAGON_YELLOW_SPAWN[6]]).astype(jnp.int32), #ToDo dragon_green = jnp.array([self.consts.DRAGON_GREEN_SPAWN[0], self.consts.DRAGON_GREEN_SPAWN[1], self.consts.DRAGON_GREEN_SPAWN[2], self.consts.DRAGON_GREEN_SPAWN[3], self.consts.DRAGON_GREEN_SPAWN[4], self.consts.DRAGON_GREEN_SPAWN[5], - self.consts.DRAGON_GREEN_SPAWN[6]]), + self.consts.DRAGON_GREEN_SPAWN[6]]).astype(jnp.int32), dragon_red = jnp.array([self.consts.DRAGON_RED_SPAWN[0], self.consts.DRAGON_RED_SPAWN[1], self.consts.DRAGON_RED_SPAWN[2], self.consts.DRAGON_RED_SPAWN[3], self.consts.DRAGON_RED_SPAWN[4], self.consts.DRAGON_RED_SPAWN[5], - self.consts.DRAGON_RED_SPAWN[6]]), + self.consts.DRAGON_RED_SPAWN[6]]).astype(jnp.int32), #Keys: x ,y, tile key_yellow = jnp.array([self.consts.KEY_YELLOW_SPAWN[0], self.consts.KEY_YELLOW_SPAWN[1], - self.consts.KEY_YELLOW_SPAWN[2]]), + self.consts.KEY_YELLOW_SPAWN[2]]).astype(jnp.int32), key_black = jnp.array([self.consts.KEY_BLACK_SPAWN[0], self.consts.KEY_BLACK_SPAWN[1], - self.consts.KEY_BLACK_SPAWN[2]]), + self.consts.KEY_BLACK_SPAWN[2]]).astype(jnp.int32), key_white = jnp.array([self.consts.KEY_WHITE_SPAWN[0], self.consts.KEY_WHITE_SPAWN[1], - self.consts.KEY_WHITE_SPAWN[2]]), + self.consts.KEY_WHITE_SPAWN[2]]).astype(jnp.int32), #Gate: state, counter (ToDo for animation?) - gate_yellow=jnp.array([0,0]), - gate_black=jnp.array([0,0]), - gate_white=jnp.array([0,0]), + gate_yellow=jnp.array([0,0]).astype(jnp.int32), + gate_black=jnp.array([0,0]).astype(jnp.int32), + gate_white=jnp.array([0,0]).astype(jnp.int32), #Items: x, y, tile sword = jnp.array([self.consts.SWORD_SPAWN[0], self.consts.SWORD_SPAWN[1], - self.consts.SWORD_SPAWN[2]]), #ToDo + self.consts.SWORD_SPAWN[2]]).astype(jnp.int32), #ToDo bridge = jnp.array([self.consts.BRIDGE_SPAWN[0], self.consts.BRIDGE_SPAWN[1], - self.consts.BRIDGE_SPAWN[2]]), #ToDo + self.consts.BRIDGE_SPAWN[2]]).astype(jnp.int32), #ToDo magnet= jnp.array([self.consts.MAGNET_SPAWN[0], self.consts.MAGNET_SPAWN[1], - self.consts.MAGNET_SPAWN[2]]), #ToDo + self.consts.MAGNET_SPAWN[2]]).astype(jnp.int32), #ToDo #Chalice: x, y, tile, color (ToDo move color to constants) chalice = jnp.array([self.consts.CHALICE_SPAWN[0], self.consts.CHALICE_SPAWN[1], - self.consts.CHALICE_SPAWN[2],7]), #ToDo + self.consts.CHALICE_SPAWN[2],7]).astype(jnp.int32), #ToDo #random key rndKey = state_key, bat = jnp.array([self.consts.BAT_SPAWN[0], self.consts.BAT_SPAWN[1], self.consts.BAT_SPAWN[2], - self.consts.BAT_SPAWN[3]]), + self.consts.BAT_SPAWN[3]]).astype(jnp.int32), dot = jnp.array([self.consts.DOT_SPAWN[0], self.consts.DOT_SPAWN[1], - self.consts.DOT_SPAWN[2]]) + self.consts.DOT_SPAWN[2]]).astype(jnp.int32) ) initial_obs = self._get_observation(state) From e4b304081f6e45e996eac30815570734d62a76e9 Mon Sep 17 00:00:00 2001 From: DanielCress Date: Tue, 31 Mar 2026 14:10:27 +0200 Subject: [PATCH 092/102] Update jax_adventure.py --- src/jaxatari/games/jax_adventure.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 6f50df588..70e203f39 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -1285,7 +1285,7 @@ def _chalice_step(self, state:AdventureState) -> AdventureState: def reset(self, key: jax.random.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureObservation, AdventureState]: state_key, _step_key = jax.random.split(key) state = AdventureState( - step_counter = jnp.array(0, dtype=jnp.int32), + step_counter = jnp.array(0).astype(jnp.int32), #Player Spawn: x, y, tile, inventory player = jnp.array([self.consts.PLAYER_SPAWN[0], self.consts.PLAYER_SPAWN[1], @@ -1401,7 +1401,7 @@ def render(self, state: AdventureState) -> jnp.ndarray: return self.renderer.render(state) #ToDo, done for all movable entities, why, no clue - def _get_observation(self, state: AdventureState): + def _get_observation(self, state: AdventureState) -> AdventureObservation: player = ObjectObservation.create( x=state.player[0], y=state.player[1], @@ -1510,8 +1510,8 @@ def _get_observation(self, state: AdventureState): x=state.bat[0], y=state.bat[1], active=state.bat[2]==state.player[2], - width=0, #bat has no hitbox - height=0 + width=self.consts.DOT_SIZE[0], + height=self.consts.DOT_SIZE[1] ) dot = ObjectObservation.create( x=state.dot[0], From de4d8f037e12fa8983c1b43f945f6da2247cbb88 Mon Sep 17 00:00:00 2001 From: DanielCress Date: Tue, 31 Mar 2026 14:27:10 +0200 Subject: [PATCH 093/102] Update jax_adventure.py --- src/jaxatari/games/jax_adventure.py | 108 ++++++++++++++-------------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 70e203f39..a40f1249b 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -94,76 +94,76 @@ def _get_default_asset_config() -> tuple: class AdventureConstants(struct.PyTreeNode): #Map Size, coordinates are (x,y) and the upper left corner is (0,0) - WIDTH: int = 160 - HEIGHT: int = 250 + WIDTH: int = struct.field(pytree_node=False, default = 160) + HEIGHT: int = struct.field(pytree_node=False, default= 250) #Entity Sizes - PLAYER_SIZE: Tuple[int, int] = (4, 8) - KEY_SIZE: Tuple[int, int] = (8, 6) - DRAGON_SIZE: Tuple[int, int] = (8, 44) - GATE_SIZE: Tuple[int, int] = (7, 32) - SWORD_SIZE: Tuple[int, int] = (8, 10) - BRIDGE_SIZE: Tuple[int, int] = (4, 48) - MAGNET_SIZE: Tuple[int, int] = (8, 16) - CHALICE_SIZE: Tuple[int, int] = (8, 18) - DOT_SIZE: Tuple[int, int] = (1,1) + PLAYER_SIZE: Tuple[int, int] = struct.field(pytree_node=False, default= (4, 8)) + KEY_SIZE: Tuple[int, int] = struct.field(pytree_node=False, default= (8, 6)) + DRAGON_SIZE: Tuple[int, int] = struct.field(pytree_node=False, default= (8, 44)) + GATE_SIZE: Tuple[int, int] = struct.field(pytree_node=False, default= (7, 32)) + SWORD_SIZE: Tuple[int, int] = struct.field(pytree_node=False, default= (8, 10)) + BRIDGE_SIZE: Tuple[int, int] = struct.field(pytree_node=False, default= (4, 48)) + MAGNET_SIZE: Tuple[int, int] = struct.field(pytree_node=False, default= (8, 16)) + CHALICE_SIZE: Tuple[int, int] = struct.field(pytree_node=False, default= (8, 18)) + DOT_SIZE: Tuple[int, int] = struct.field(pytree_node=False, default= (1,1)) #Inventory IDs - EMPTY_HAND_ID: int = 0 - KEY_YELLOW_ID: int = 1 - KEY_BLACK_ID: int = 2 - SWORD_ID: int = 3 - BRIDGE_ID: int = 4 - MAGNET_ID: int = 5 - CHALICE_ID: int = 6 - KEY_WHITE_ID: int = 7 - DOT_ID: int = 8 + EMPTY_HAND_ID: int = struct.field(pytree_node=False, default= 0) + KEY_YELLOW_ID: int = struct.field(pytree_node=False, default= 1) + KEY_BLACK_ID: int = struct.field(pytree_node=False, default= 2) + SWORD_ID: int = struct.field(pytree_node=False, default= 3) + BRIDGE_ID: int = struct.field(pytree_node=False, default= 4) + MAGNET_ID: int = struct.field(pytree_node=False, default= 5) + CHALICE_ID: int = struct.field(pytree_node=False, default= 6) + KEY_WHITE_ID: int = struct.field(pytree_node=False, default= 7) + DOT_ID: int = struct.field(pytree_node=False, default= 8) #dragons (X,Y, Room, state, counter, eat, activate) - DRAGON_YELLOW_SPAWN: Tuple[int, int, int, int ,int, int, int] = (80, 170, 5, 0, 0, 0, 0) - DRAGON_GREEN_SPAWN: Tuple[int, int, int, int, int, int, int] = (80, 130, 4, 0, 0, 0, 0) - DRAGON_RED_SPAWN: Tuple[int, int, int, int, int, int, int] = (80, 130, 19, 0, 0, 0, 0) + DRAGON_YELLOW_SPAWN: Tuple[int, int, int, int ,int, int, int] = struct.field(pytree_node=False, default= (80, 170, 5, 0, 0, 0, 0)) + DRAGON_GREEN_SPAWN: Tuple[int, int, int, int, int, int, int] = struct.field(pytree_node=False, default= (80, 130, 4, 0, 0, 0, 0)) + DRAGON_RED_SPAWN: Tuple[int, int, int, int, int, int, int] = struct.field(pytree_node=False, default= (80, 130, 19, 0, 0, 0, 0)) #Spawn Locations of all Entities: (X, Y, Room/Tile) - YELLOW_GATE_POS: Tuple[int, int, int] = (76, 140, 0) - BLACK_GATE_POS: Tuple[int, int, int] = (76, 140, 11) - WHITE_GATE_POS: Tuple[int, int, int] = (76, 140, 24) - PLAYER_SPAWN: Tuple[int, int, int] = (78, 174, 0) #Changed from (78, 174, 0) - KEY_YELLOW_SPAWN: Tuple[int, int, int] = (31, 110, 0) #Changed from (31, 110, 0) for Testing - KEY_BLACK_SPAWN: Tuple[int, int, int] = (31, 100, 4) - KEY_WHITE_SPAWN: Tuple[int, int, int] = (31, 110, 19) - SWORD_SPAWN: Tuple[int, int, int] = (31,180,1) - BRIDGE_SPAWN: Tuple[int, int, int] = (40,130,10) - MAGNET_SPAWN: Tuple[int, int, int] = (120,180,12) - CHALICE_SPAWN: Tuple[int, int, int] = (35,180,13) - BAT_SPAWN: Tuple[int, int, int, int] = (76, 140, 19, 0) - DOT_SPAWN: Tuple[int, int, int] = (76, 140, 29) + YELLOW_GATE_POS: Tuple[int, int, int] = struct.field(pytree_node=False, default= (76, 140, 0)) + BLACK_GATE_POS: Tuple[int, int, int] = struct.field(pytree_node=False, default= (76, 140, 11)) + WHITE_GATE_POS: Tuple[int, int, int] = struct.field(pytree_node=False, default= (76, 140, 24)) + PLAYER_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default= (78, 174, 0)) #Changed from (78, 174, 0) + KEY_YELLOW_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default= (31, 110, 0)) #Changed from (31, 110, 0) for Testing + KEY_BLACK_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default= (31, 100, 4)) + KEY_WHITE_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default= (31, 110, 19)) + SWORD_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default= (31,180,1)) + BRIDGE_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default= (40,130,10)) + MAGNET_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default= (120,180,12)) + CHALICE_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default= (35,180,13)) + BAT_SPAWN: Tuple[int, int, int, int] = struct.field(pytree_node=False, default= (76, 140, 19, 0)) + DOT_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default= (76, 140, 29)) #Constants that are used for restricting player movement, for easy of fine tuning # Wall coordinates the player cannot pass through - LEFT_WALL_X: int = 8 - RIGHT_WALL_X: int = 148 - UPPER_WALL_Y: int = 43 - LOWER_WALL_Y: int = 199 + LEFT_WALL_X: int = struct.field(pytree_node=False, default= 8) + RIGHT_WALL_X: int = struct.field(pytree_node=False, default= 148) + UPPER_WALL_Y: int = struct.field(pytree_node=False, default= 43) + LOWER_WALL_Y: int = struct.field(pytree_node=False, default= 199) #special black borders to the left and right - SPECIAL_WALL_LEFT: int = 12 - SPECIAL_WALL_RIGHT: int = 145 + SPECIAL_WALL_LEFT: int = struct.field(pytree_node=False, default= 12) + SPECIAL_WALL_RIGHT: int = struct.field(pytree_node=False, default= 145) # Path South and North to another Room, X-Coordinates that offer hole in the wall - PATH_VERTICAL_LEFT: int = 64 - PATH_VERTICAL_RIGHT: int = 95 + PATH_VERTICAL_LEFT: int = struct.field(pytree_node=False, default= 64) + PATH_VERTICAL_RIGHT: int = struct.field(pytree_node=False, default= 95) # Path East and West, Y-Coordinates that offer hole in the wall - PATH_HORIZONTAL_UP: int = 40 - PATH_HORIZONTAL_DOWN: int = 200 + PATH_HORIZONTAL_UP: int = struct.field(pytree_node=False, default= 40) + PATH_HORIZONTAL_DOWN: int = struct.field(pytree_node=False, default= 200) # Castle Edges - CASTLE_TOWER_LEFT_X: int = 35 - CASTLE_TOWER_RIGHT_X: int = 120 - CASTLE_BASE_LEFT_X: int = 45 - CASTLE_BASE_RIGHT_X: int = 113 - CASTLE_TOWER_CORNER_Y: int = 105 - CASTLE_BASE_CORNER_Y: int = 170 + CASTLE_TOWER_LEFT_X: int = struct.field(pytree_node=False, default= 35) + CASTLE_TOWER_RIGHT_X: int = struct.field(pytree_node=False, default= 120) + CASTLE_BASE_LEFT_X: int = struct.field(pytree_node=False, default= 45) + CASTLE_BASE_RIGHT_X: int = struct.field(pytree_node=False, default= 113) + CASTLE_TOWER_CORNER_Y: int = struct.field(pytree_node=False, default= 105) + CASTLE_BASE_CORNER_Y: int = struct.field(pytree_node=False, default= 170) # sset config baked into constants (immutable default) for asset overrides ASSET_CONFIG: tuple = _get_default_asset_config() #Dragon constants - DRAGON_SPEED: int = 2 - DRAGON_BITE_TIMER: int = 15 + DRAGON_SPEED: int = struct.field(pytree_node=False, default= 2) + DRAGON_BITE_TIMER: int = struct.field(pytree_node=False, default= 15) # immutable state container From cc854f27208e38e45dc1d32e4d9119dc7bf61b8f Mon Sep 17 00:00:00 2001 From: DanielCress Date: Tue, 31 Mar 2026 14:48:51 +0200 Subject: [PATCH 094/102] Update jax_adventure.py --- src/jaxatari/games/jax_adventure.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index a40f1249b..96e034bcc 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -131,9 +131,10 @@ class AdventureConstants(struct.PyTreeNode): SWORD_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default= (31,180,1)) BRIDGE_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default= (40,130,10)) MAGNET_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default= (120,180,12)) - CHALICE_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default= (35,180,13)) + CHALICE_SPAWN: Tuple[int, int, int, int] = struct.field(pytree_node=False, default= (35,180,13, 7)) BAT_SPAWN: Tuple[int, int, int, int] = struct.field(pytree_node=False, default= (76, 140, 19, 0)) DOT_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default= (76, 140, 29)) + GATE_SPAWN: Tuple[int, int] = struct.field(pytree_node=False, default=(0, 0)) #Constants that are used for restricting player movement, for easy of fine tuning # Wall coordinates the player cannot pass through @@ -159,7 +160,7 @@ class AdventureConstants(struct.PyTreeNode): CASTLE_BASE_CORNER_Y: int = struct.field(pytree_node=False, default= 170) # sset config baked into constants (immutable default) for asset overrides - ASSET_CONFIG: tuple = _get_default_asset_config() + ASSET_CONFIG: tuple = struct.field(pytree_node=False, default_factory= _get_default_asset_config) #Dragon constants DRAGON_SPEED: int = struct.field(pytree_node=False, default= 2) @@ -1283,6 +1284,7 @@ def _chalice_step(self, state:AdventureState) -> AdventureState: """This function is called when the game starts and when it is reseted It initializes the Adventure state, for the most part these Values are pulled from the consts""" def reset(self, key: jax.random.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[AdventureObservation, AdventureState]: + state_key, _step_key = jax.random.split(key) state = AdventureState( step_counter = jnp.array(0).astype(jnp.int32), @@ -1324,9 +1326,12 @@ def reset(self, key: jax.random.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[Adven self.consts.KEY_WHITE_SPAWN[1], self.consts.KEY_WHITE_SPAWN[2]]).astype(jnp.int32), #Gate: state, counter (ToDo for animation?) - gate_yellow=jnp.array([0,0]).astype(jnp.int32), - gate_black=jnp.array([0,0]).astype(jnp.int32), - gate_white=jnp.array([0,0]).astype(jnp.int32), + gate_yellow=jnp.array([self.consts.GATE_SPAWN[0], + self.consts.GATE_SPAWN[1]]).astype(jnp.int32), + gate_black=jnp.array([self.consts.GATE_SPAWN[0], + self.consts.GATE_SPAWN[1]]).astype(jnp.int32), + gate_white=jnp.array([self.consts.GATE_SPAWN[0], + self.consts.GATE_SPAWN[1]]).astype(jnp.int32), #Items: x, y, tile sword = jnp.array([self.consts.SWORD_SPAWN[0], self.consts.SWORD_SPAWN[1], @@ -1340,7 +1345,8 @@ def reset(self, key: jax.random.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[Adven #Chalice: x, y, tile, color (ToDo move color to constants) chalice = jnp.array([self.consts.CHALICE_SPAWN[0], self.consts.CHALICE_SPAWN[1], - self.consts.CHALICE_SPAWN[2],7]).astype(jnp.int32), #ToDo + self.consts.CHALICE_SPAWN[2], + self.consts.CHALICE_SPAWN[3]]).astype(jnp.int32), #ToDo #random key rndKey = state_key, bat = jnp.array([self.consts.BAT_SPAWN[0], From 99b77226a358000987aa8aec95bc376419ed7df9 Mon Sep 17 00:00:00 2001 From: DanielCress Date: Tue, 31 Mar 2026 15:11:58 +0200 Subject: [PATCH 095/102] Update jax_adventure.py --- src/jaxatari/games/jax_adventure.py | 30 ++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 96e034bcc..21c172be1 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -1418,7 +1418,7 @@ def _get_observation(self, state: AdventureState) -> AdventureObservation: dragon_yellow = ObjectObservation.create( x=state.dragon_yellow[0], y=state.dragon_yellow[1], - active=state.dragon_yellow[2]==state.player[2], + active=state.dragon_yellow[2]==state.player[2].astype(jnp.bool_), width=self.consts.DRAGON_SIZE[0], height=self.consts.DRAGON_SIZE[1], state=state.dragon_yellow[3] @@ -1426,7 +1426,7 @@ def _get_observation(self, state: AdventureState) -> AdventureObservation: dragon_green = ObjectObservation.create( x=state.dragon_green[0], y=state.dragon_green[1], - active=state.dragon_green[2]==state.player[2], + active=state.dragon_green[2]==state.player[2].astype(jnp.bool_), width=self.consts.DRAGON_SIZE[0], height=self.consts.DRAGON_SIZE[1], state=state.dragon_green[3] @@ -1434,21 +1434,21 @@ def _get_observation(self, state: AdventureState) -> AdventureObservation: key_yellow = ObjectObservation.create( x=state.key_yellow[0], y=state.key_yellow[1], - active=state.key_yellow[2]==state.player[2], + active=state.key_yellow[2]==state.player[2].astype(jnp.bool_), width=self.consts.KEY_SIZE[0], height=self.consts.KEY_SIZE[1] ) key_black = ObjectObservation.create( x=state.key_black[0], y=state.key_black[1], - active=state.key_black[2]==state.player[2], + active=state.key_black[2]==state.player[2].astype(jnp.bool_), width=self.consts.KEY_SIZE[0], height=self.consts.KEY_SIZE[1], ) gate_yellow = ObjectObservation.create( x=self.consts.YELLOW_GATE_POS[0], y=self.consts.YELLOW_GATE_POS[1], - active=self.consts.YELLOW_GATE_POS[2]==state.player[2], + active=self.consts.YELLOW_GATE_POS[2]==state.player[2].astype(jnp.bool_), width=self.consts.GATE_SIZE[0], height=self.consts.GATE_SIZE[1], state=state.gate_yellow[0] @@ -1456,7 +1456,7 @@ def _get_observation(self, state: AdventureState) -> AdventureObservation: gate_black = ObjectObservation.create( x=self.consts.BLACK_GATE_POS[0], y=self.consts.BLACK_GATE_POS[1], - active=self.consts.BLACK_GATE_POS[2]==state.player[2], + active=self.consts.BLACK_GATE_POS[2]==state.player[2].astype(jnp.bool_), width=self.consts.GATE_SIZE[0], height=self.consts.GATE_SIZE[1], state=state.gate_black[0] @@ -1464,35 +1464,35 @@ def _get_observation(self, state: AdventureState) -> AdventureObservation: sword = ObjectObservation.create( x=state.sword[0], y=state.sword[1], - active=state.sword[2]==state.player[2], + active=state.sword[2]==state.player[2].astype(jnp.bool_), width=self.consts.SWORD_SIZE[0], height=self.consts.SWORD_SIZE[1] ) bridge = ObjectObservation.create( x=state.bridge[0], y=state.bridge[1], - active=state.bridge[2]==state.player[2], + active=state.bridge[2]==state.player[2].astype(jnp.bool_), width=self.consts.BRIDGE_SIZE[0], height=self.consts.BRIDGE_SIZE[1] ) magnet = ObjectObservation.create( x=state.magnet[0], y=state.magnet[1], - active=state.magnet[2]==state.player[2], + active=state.magnet[2]==state.player[2].astype(jnp.bool_), width=self.consts.MAGNET_SIZE[0], height=self.consts.MAGNET_SIZE[1] ) chalice = ObjectObservation.create( x=state.chalice[0], y=state.chalice[1], - active=state.chalice[2]==state.player[2], + active=state.chalice[2]==state.player[2].astype(jnp.bool_), width=self.consts.CHALICE_SIZE[0], height=self.consts.CHALICE_SIZE[1] ) dragon_red = ObjectObservation.create( x=state.dragon_red[0], y=state.dragon_red[1], - active=state.dragon_red[2]==state.player[2], + active=state.dragon_red[2]==state.player[2].astype(jnp.bool_), width=self.consts.DRAGON_SIZE[0], height=self.consts.DRAGON_SIZE[1], state=state.dragon_red[3] @@ -1500,14 +1500,14 @@ def _get_observation(self, state: AdventureState) -> AdventureObservation: key_white = ObjectObservation.create( x=state.key_white[0], y=state.key_white[1], - active=state.key_white[2]==state.player[2], + active=state.key_white[2]==state.player[2].astype(jnp.bool_), width=self.consts.KEY_SIZE[0], height=self.consts.KEY_SIZE[1] ) gate_white = ObjectObservation.create( x=self.consts.WHITE_GATE_POS[0], y=self.consts.WHITE_GATE_POS[1], - active=self.consts.WHITE_GATE_POS[2]==state.player[2], + active=self.consts.WHITE_GATE_POS[2]==state.player[2].astype(jnp.bool_), width=self.consts.GATE_SIZE[0], height=self.consts.GATE_SIZE[1], state=state.gate_white[0] @@ -1515,14 +1515,14 @@ def _get_observation(self, state: AdventureState) -> AdventureObservation: bat = ObjectObservation.create( x=state.bat[0], y=state.bat[1], - active=state.bat[2]==state.player[2], + active=state.bat[2]==state.player[2].astype(jnp.bool_), width=self.consts.DOT_SIZE[0], height=self.consts.DOT_SIZE[1] ) dot = ObjectObservation.create( x=state.dot[0], y=state.dot[1], - active=state.dot[2]==state.player[2], + active=state.dot[2]==state.player[2].astype(jnp.bool_), width=self.consts.DOT_SIZE[0], height=self.consts.DOT_SIZE[1] ) From 03beb8ee5e570ae82954496f74aad053fb8694f7 Mon Sep 17 00:00:00 2001 From: DanielCress Date: Tue, 31 Mar 2026 15:49:31 +0200 Subject: [PATCH 096/102] Update jax_adventure.py --- src/jaxatari/games/jax_adventure.py | 89 +++++++++++++++-------------- 1 file changed, 45 insertions(+), 44 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 21c172be1..7bb298b89 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -11,6 +11,7 @@ from jaxatari.renderers import JAXGameRenderer from jaxatari.rendering import jax_rendering_utils as render_utils from jaxatari.environment import JaxEnvironment, JAXAtariAction as Action, ObjectObservation +from jaxatari.modification import AutoDerivedConstants def _get_default_asset_config() -> tuple: """ @@ -92,20 +93,20 @@ def _get_default_asset_config() -> tuple: ) -class AdventureConstants(struct.PyTreeNode): +class AdventureConstants(AutoDerivedConstants): #Map Size, coordinates are (x,y) and the upper left corner is (0,0) WIDTH: int = struct.field(pytree_node=False, default = 160) HEIGHT: int = struct.field(pytree_node=False, default= 250) #Entity Sizes - PLAYER_SIZE: Tuple[int, int] = struct.field(pytree_node=False, default= (4, 8)) - KEY_SIZE: Tuple[int, int] = struct.field(pytree_node=False, default= (8, 6)) - DRAGON_SIZE: Tuple[int, int] = struct.field(pytree_node=False, default= (8, 44)) - GATE_SIZE: Tuple[int, int] = struct.field(pytree_node=False, default= (7, 32)) - SWORD_SIZE: Tuple[int, int] = struct.field(pytree_node=False, default= (8, 10)) - BRIDGE_SIZE: Tuple[int, int] = struct.field(pytree_node=False, default= (4, 48)) - MAGNET_SIZE: Tuple[int, int] = struct.field(pytree_node=False, default= (8, 16)) - CHALICE_SIZE: Tuple[int, int] = struct.field(pytree_node=False, default= (8, 18)) - DOT_SIZE: Tuple[int, int] = struct.field(pytree_node=False, default= (1,1)) + PLAYER_SIZE: Tuple[int, int] = struct.field(pytree_node=False, default_factory=lambda: (4, 8)) + KEY_SIZE: Tuple[int, int] = struct.field(pytree_node=False, default_factory=lambda: (8, 6)) + DRAGON_SIZE: Tuple[int, int] = struct.field(pytree_node=False, default_factory=lambda: (8, 44)) + GATE_SIZE: Tuple[int, int] = struct.field(pytree_node=False, default_factory=lambda: (7, 32)) + SWORD_SIZE: Tuple[int, int] = struct.field(pytree_node=False, default_factory=lambda: (8, 10)) + BRIDGE_SIZE: Tuple[int, int] = struct.field(pytree_node=False, default_factory=lambda: (4, 48)) + MAGNET_SIZE: Tuple[int, int] = struct.field(pytree_node=False, default_factory=lambda: (8, 16)) + CHALICE_SIZE: Tuple[int, int] = struct.field(pytree_node=False, default_factory=lambda: (8, 18)) + DOT_SIZE: Tuple[int, int] = struct.field(pytree_node=False, default_factory=lambda: (1,1)) #Inventory IDs EMPTY_HAND_ID: int = struct.field(pytree_node=False, default= 0) KEY_YELLOW_ID: int = struct.field(pytree_node=False, default= 1) @@ -117,24 +118,24 @@ class AdventureConstants(struct.PyTreeNode): KEY_WHITE_ID: int = struct.field(pytree_node=False, default= 7) DOT_ID: int = struct.field(pytree_node=False, default= 8) #dragons (X,Y, Room, state, counter, eat, activate) - DRAGON_YELLOW_SPAWN: Tuple[int, int, int, int ,int, int, int] = struct.field(pytree_node=False, default= (80, 170, 5, 0, 0, 0, 0)) - DRAGON_GREEN_SPAWN: Tuple[int, int, int, int, int, int, int] = struct.field(pytree_node=False, default= (80, 130, 4, 0, 0, 0, 0)) - DRAGON_RED_SPAWN: Tuple[int, int, int, int, int, int, int] = struct.field(pytree_node=False, default= (80, 130, 19, 0, 0, 0, 0)) + DRAGON_YELLOW_SPAWN: Tuple[int, int, int, int ,int, int, int] = struct.field(pytree_node=False, default_factory=lambda: (80, 170, 5, 0, 0, 0, 0)) + DRAGON_GREEN_SPAWN: Tuple[int, int, int, int, int, int, int] = struct.field(pytree_node=False, default_factory=lambda: (80, 130, 4, 0, 0, 0, 0)) + DRAGON_RED_SPAWN: Tuple[int, int, int, int, int, int, int] = struct.field(pytree_node=False, default_factory=lambda: (80, 130, 19, 0, 0, 0, 0)) #Spawn Locations of all Entities: (X, Y, Room/Tile) - YELLOW_GATE_POS: Tuple[int, int, int] = struct.field(pytree_node=False, default= (76, 140, 0)) - BLACK_GATE_POS: Tuple[int, int, int] = struct.field(pytree_node=False, default= (76, 140, 11)) - WHITE_GATE_POS: Tuple[int, int, int] = struct.field(pytree_node=False, default= (76, 140, 24)) - PLAYER_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default= (78, 174, 0)) #Changed from (78, 174, 0) - KEY_YELLOW_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default= (31, 110, 0)) #Changed from (31, 110, 0) for Testing - KEY_BLACK_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default= (31, 100, 4)) - KEY_WHITE_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default= (31, 110, 19)) - SWORD_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default= (31,180,1)) - BRIDGE_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default= (40,130,10)) - MAGNET_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default= (120,180,12)) - CHALICE_SPAWN: Tuple[int, int, int, int] = struct.field(pytree_node=False, default= (35,180,13, 7)) - BAT_SPAWN: Tuple[int, int, int, int] = struct.field(pytree_node=False, default= (76, 140, 19, 0)) - DOT_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default= (76, 140, 29)) - GATE_SPAWN: Tuple[int, int] = struct.field(pytree_node=False, default=(0, 0)) + YELLOW_GATE_POS: Tuple[int, int, int] = struct.field(pytree_node=False, default_factory=lambda: (76, 140, 0)) + BLACK_GATE_POS: Tuple[int, int, int] = struct.field(pytree_node=False, default_factory=lambda: (76, 140, 11)) + WHITE_GATE_POS: Tuple[int, int, int] = struct.field(pytree_node=False, default_factory=lambda: (76, 140, 24)) + PLAYER_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default_factory=lambda: (78, 174, 0)) #Changed from (78, 174, 0) + KEY_YELLOW_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default_factory=lambda: (31, 110, 0)) #Changed from (31, 110, 0) for Testing + KEY_BLACK_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default_factory=lambda: (31, 100, 4)) + KEY_WHITE_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default_factory=lambda: (31, 110, 19)) + SWORD_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default_factory=lambda: (31,180,1)) + BRIDGE_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default_factory=lambda: (40,130,10)) + MAGNET_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default_factory=lambda: (120,180,12)) + CHALICE_SPAWN: Tuple[int, int, int, int] = struct.field(pytree_node=False, default_factory=lambda: (35,180,13, 7)) + BAT_SPAWN: Tuple[int, int, int, int] = struct.field(pytree_node=False, default_factory=lambda: (76, 140, 19, 0)) + DOT_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default_factory=lambda: (76, 140, 29)) + GATE_SPAWN: Tuple[int, int] = struct.field(pytree_node=False, default_factory=lambda: (0, 0)) #Constants that are used for restricting player movement, for easy of fine tuning # Wall coordinates the player cannot pass through @@ -1287,12 +1288,12 @@ def reset(self, key: jax.random.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[Adven state_key, _step_key = jax.random.split(key) state = AdventureState( - step_counter = jnp.array(0).astype(jnp.int32), + step_counter = jnp.array(0), #Player Spawn: x, y, tile, inventory player = jnp.array([self.consts.PLAYER_SPAWN[0], self.consts.PLAYER_SPAWN[1], self.consts.PLAYER_SPAWN[2], - self.consts.EMPTY_HAND_ID]).astype(jnp.int32), + self.consts.EMPTY_HAND_ID]), #Dragons: x, y ,tile ,state(neutral,dead,atacking), counter( ToDo for?? ) dragon_yellow = jnp.array([self.consts.DRAGON_YELLOW_SPAWN[0], self.consts.DRAGON_YELLOW_SPAWN[1], @@ -1300,62 +1301,62 @@ def reset(self, key: jax.random.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[Adven self.consts.DRAGON_YELLOW_SPAWN[3], self.consts.DRAGON_YELLOW_SPAWN[4], self.consts.DRAGON_YELLOW_SPAWN[5], - self.consts.DRAGON_YELLOW_SPAWN[6]]).astype(jnp.int32), #ToDo + self.consts.DRAGON_YELLOW_SPAWN[6]]), #ToDo dragon_green = jnp.array([self.consts.DRAGON_GREEN_SPAWN[0], self.consts.DRAGON_GREEN_SPAWN[1], self.consts.DRAGON_GREEN_SPAWN[2], self.consts.DRAGON_GREEN_SPAWN[3], self.consts.DRAGON_GREEN_SPAWN[4], self.consts.DRAGON_GREEN_SPAWN[5], - self.consts.DRAGON_GREEN_SPAWN[6]]).astype(jnp.int32), + self.consts.DRAGON_GREEN_SPAWN[6]]), dragon_red = jnp.array([self.consts.DRAGON_RED_SPAWN[0], self.consts.DRAGON_RED_SPAWN[1], self.consts.DRAGON_RED_SPAWN[2], self.consts.DRAGON_RED_SPAWN[3], self.consts.DRAGON_RED_SPAWN[4], self.consts.DRAGON_RED_SPAWN[5], - self.consts.DRAGON_RED_SPAWN[6]]).astype(jnp.int32), + self.consts.DRAGON_RED_SPAWN[6]]), #Keys: x ,y, tile key_yellow = jnp.array([self.consts.KEY_YELLOW_SPAWN[0], self.consts.KEY_YELLOW_SPAWN[1], - self.consts.KEY_YELLOW_SPAWN[2]]).astype(jnp.int32), + self.consts.KEY_YELLOW_SPAWN[2]]), key_black = jnp.array([self.consts.KEY_BLACK_SPAWN[0], self.consts.KEY_BLACK_SPAWN[1], - self.consts.KEY_BLACK_SPAWN[2]]).astype(jnp.int32), + self.consts.KEY_BLACK_SPAWN[2]]), key_white = jnp.array([self.consts.KEY_WHITE_SPAWN[0], self.consts.KEY_WHITE_SPAWN[1], - self.consts.KEY_WHITE_SPAWN[2]]).astype(jnp.int32), + self.consts.KEY_WHITE_SPAWN[2]]), #Gate: state, counter (ToDo for animation?) gate_yellow=jnp.array([self.consts.GATE_SPAWN[0], - self.consts.GATE_SPAWN[1]]).astype(jnp.int32), + self.consts.GATE_SPAWN[1]]), gate_black=jnp.array([self.consts.GATE_SPAWN[0], - self.consts.GATE_SPAWN[1]]).astype(jnp.int32), + self.consts.GATE_SPAWN[1]]), gate_white=jnp.array([self.consts.GATE_SPAWN[0], - self.consts.GATE_SPAWN[1]]).astype(jnp.int32), + self.consts.GATE_SPAWN[1]]), #Items: x, y, tile sword = jnp.array([self.consts.SWORD_SPAWN[0], self.consts.SWORD_SPAWN[1], - self.consts.SWORD_SPAWN[2]]).astype(jnp.int32), #ToDo + self.consts.SWORD_SPAWN[2]]), #ToDo bridge = jnp.array([self.consts.BRIDGE_SPAWN[0], self.consts.BRIDGE_SPAWN[1], - self.consts.BRIDGE_SPAWN[2]]).astype(jnp.int32), #ToDo + self.consts.BRIDGE_SPAWN[2]]), #ToDo magnet= jnp.array([self.consts.MAGNET_SPAWN[0], self.consts.MAGNET_SPAWN[1], - self.consts.MAGNET_SPAWN[2]]).astype(jnp.int32), #ToDo + self.consts.MAGNET_SPAWN[2]]), #ToDo #Chalice: x, y, tile, color (ToDo move color to constants) chalice = jnp.array([self.consts.CHALICE_SPAWN[0], self.consts.CHALICE_SPAWN[1], self.consts.CHALICE_SPAWN[2], - self.consts.CHALICE_SPAWN[3]]).astype(jnp.int32), #ToDo + self.consts.CHALICE_SPAWN[3]]), #ToDo #random key rndKey = state_key, bat = jnp.array([self.consts.BAT_SPAWN[0], self.consts.BAT_SPAWN[1], self.consts.BAT_SPAWN[2], - self.consts.BAT_SPAWN[3]]).astype(jnp.int32), + self.consts.BAT_SPAWN[3]]), dot = jnp.array([self.consts.DOT_SPAWN[0], self.consts.DOT_SPAWN[1], - self.consts.DOT_SPAWN[2]]).astype(jnp.int32) + self.consts.DOT_SPAWN[2]]) ) initial_obs = self._get_observation(state) From 47641d85d4f6e814fa6ef1b6f2e1ecfefaaa8052 Mon Sep 17 00:00:00 2001 From: DanielCress Date: Tue, 31 Mar 2026 15:58:29 +0200 Subject: [PATCH 097/102] Update jax_adventure.py --- src/jaxatari/games/jax_adventure.py | 76 ++++++++++++++--------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 7bb298b89..957b1f0c4 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -618,44 +618,44 @@ def _player_step(self, state: AdventureState, action: chex.Array) -> AdventureSt return state.replace( step_counter = jnp.array(new_step_counter), - player = jnp.array([new_player_x,new_player_y,new_player_tile,state.player[3]]).astype(jnp.int32), #SEEMS NOT GOOD + player = jnp.array([new_player_x,new_player_y,new_player_tile,state.player[3]]), #SEEMS NOT GOOD key_yellow = jax.lax.cond(state.player[3]==self.consts.KEY_YELLOW_ID, - lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: jnp.array([op[0],op[1],op[2]]), lambda op: op[3], operand=(new_item_x,new_item_y,new_item_tile,state.key_yellow), ), key_black= jax.lax.cond(state.player[3]==self.consts.KEY_BLACK_ID, - lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: jnp.array([op[0],op[1],op[2]]), lambda op: op[3], operand=(new_item_x,new_item_y,new_item_tile,state.key_black) ), key_white= jax.lax.cond(state.player[3]==self.consts.KEY_WHITE_ID, - lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: jnp.array([op[0],op[1],op[2]]), lambda op: op[3], operand=(new_item_x,new_item_y,new_item_tile,state.key_white) ), sword= jax.lax.cond(state.player[3]==self.consts.SWORD_ID, - lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: jnp.array([op[0],op[1],op[2]]), lambda op: op[3], operand=(new_item_x,new_item_y,new_item_tile,state.sword) ), bridge= jax.lax.cond(state.player[3]==self.consts.BRIDGE_ID, - lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: jnp.array([op[0],op[1],op[2]]), lambda op: op[3], operand=(new_item_x,new_item_y,new_item_tile,state.bridge) ), magnet= jax.lax.cond(state.player[3]==self.consts.MAGNET_ID, - lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: jnp.array([op[0],op[1],op[2]]), lambda op: op[3], operand=(new_item_x,new_item_y,new_item_tile,state.magnet) ), chalice= jax.lax.cond(state.player[3]==self.consts.CHALICE_ID, - lambda op: jnp.array([op[0],op[1],op[2],op[3]]).astype(jnp.int32), + lambda op: jnp.array([op[0],op[1],op[2],op[3]]), lambda op: op[4], operand=(new_item_x,new_item_y,new_item_tile,state.chalice[3],state.chalice) ), dot= jax.lax.cond(state.player[3]==self.consts.DOT_ID, - lambda op: jnp.array([op[0],op[1],op[2]]).astype(jnp.int32), + lambda op: jnp.array([op[0],op[1],op[2]]), lambda op: op[3], operand=(new_item_x,new_item_y,new_item_tile,state.dot) ), @@ -821,9 +821,9 @@ def _gate_interaction(self, state: AdventureState) -> AdventureState: ) return state.replace( - gate_yellow=jnp.array([gate_yellow_state, gate_yellow_counter]).astype(jnp.int32), - gate_black=jnp.array([gate_black_state, gate_black_counter]).astype(jnp.int32), - gate_white=jnp.array([gate_white_state, gate_white_counter]).astype(jnp.int32), + gate_yellow=jnp.array([gate_yellow_state, gate_yellow_counter]), + gate_black=jnp.array([gate_black_state, gate_black_counter]), + gate_white=jnp.array([gate_white_state, gate_white_counter]), ) def _item_pickup(self, state: AdventureState, action: chex.Array) -> AdventureState: @@ -1017,7 +1017,7 @@ def diff_of_4(val1:int, val2:int) -> bool: return state.replace( - player = jnp.array([state.player[0],state.player[1],state.player[2],new_player_inventory]).astype(jnp.int32) + player = jnp.array([state.player[0],state.player[1],state.player[2],new_player_inventory]) ) def _item_drop(self, state: AdventureState, action: chex.Array) -> AdventureState: @@ -1031,7 +1031,7 @@ def _item_drop(self, state: AdventureState, action: chex.Array) -> AdventureStat ) return state.replace( - player = jnp.array([state.player[0],state.player[1],state.player[2],new_player_inventory]).astype(jnp.int32) + player = jnp.array([state.player[0],state.player[1],state.player[2],new_player_inventory]) ) @@ -1182,8 +1182,8 @@ def _dragon_step(self, state: AdventureState) -> AdventureState: return state.replace( - dragon_yellow = jnp.array([dragon_yellow_x,dragon_yellow_y,dragon_yellow_tile,dragon_yellow_animation,dragon_yellow_counter,dragon_yellow_eat, dragon_yellow_activate]).astype(jnp.int32), - dragon_green = jnp.array([dragon_green_x,dragon_green_y,dragon_green_tile,dragon_green_animation,dragon_green_counter,dragon_green_eat, dragon_green_activate]).astype(jnp.int32), + dragon_yellow = jnp.array([dragon_yellow_x,dragon_yellow_y,dragon_yellow_tile,dragon_yellow_animation,dragon_yellow_counter,dragon_yellow_eat, dragon_yellow_activate]), + dragon_green = jnp.array([dragon_green_x,dragon_green_y,dragon_green_tile,dragon_green_animation,dragon_green_counter,dragon_green_eat, dragon_green_activate]), rndKey=rndKey ) @@ -1264,12 +1264,12 @@ def _magnet_step(self, state: AdventureState) -> AdventureState: ) return state.replace( - key_yellow=jnp.array([key_yellow_x,key_yellow_y,state.key_yellow[2]]).astype(jnp.int32), - key_black=jnp.array([key_black_x,key_black_y,state.key_black[2]]).astype(jnp.int32), - key_white=jnp.array([key_white_x,key_white_y,state.key_white[2]]).astype(jnp.int32), - sword=jnp.array([sword_x,sword_y,state.sword[2]]).astype(jnp.int32), - bridge=jnp.array([bridge_x,bridge_y,state.bridge[2]]).astype(jnp.int32), - chalice=jnp.array([chalice_x,chalice_y,state.chalice[2],state.chalice[3]]).astype(jnp.int32) + key_yellow=jnp.array([key_yellow_x,key_yellow_y,state.key_yellow[2]]), + key_black=jnp.array([key_black_x,key_black_y,state.key_black[2]]), + key_white=jnp.array([key_white_x,key_white_y,state.key_white[2]]), + sword=jnp.array([sword_x,sword_y,state.sword[2]]), + bridge=jnp.array([bridge_x,bridge_y,state.bridge[2]]), + chalice=jnp.array([chalice_x,chalice_y,state.chalice[2],state.chalice[3]]) ) @@ -1279,7 +1279,7 @@ def _chalice_step(self, state:AdventureState) -> AdventureState: chalice_color = (chalice_color +1) % 10 return state.replace( - chalice=jnp.array([state.chalice[0],state.chalice[1],state.chalice[2],chalice_color]).astype(jnp.int32) + chalice=jnp.array([state.chalice[0],state.chalice[1],state.chalice[2],chalice_color]) ) """This function is called when the game starts and when it is reseted @@ -1419,7 +1419,7 @@ def _get_observation(self, state: AdventureState) -> AdventureObservation: dragon_yellow = ObjectObservation.create( x=state.dragon_yellow[0], y=state.dragon_yellow[1], - active=state.dragon_yellow[2]==state.player[2].astype(jnp.bool_), + active=state.dragon_yellow[2]==state.player[2], width=self.consts.DRAGON_SIZE[0], height=self.consts.DRAGON_SIZE[1], state=state.dragon_yellow[3] @@ -1427,7 +1427,7 @@ def _get_observation(self, state: AdventureState) -> AdventureObservation: dragon_green = ObjectObservation.create( x=state.dragon_green[0], y=state.dragon_green[1], - active=state.dragon_green[2]==state.player[2].astype(jnp.bool_), + active=state.dragon_green[2]==state.player[2], width=self.consts.DRAGON_SIZE[0], height=self.consts.DRAGON_SIZE[1], state=state.dragon_green[3] @@ -1435,21 +1435,21 @@ def _get_observation(self, state: AdventureState) -> AdventureObservation: key_yellow = ObjectObservation.create( x=state.key_yellow[0], y=state.key_yellow[1], - active=state.key_yellow[2]==state.player[2].astype(jnp.bool_), + active=state.key_yellow[2]==state.player[2], width=self.consts.KEY_SIZE[0], height=self.consts.KEY_SIZE[1] ) key_black = ObjectObservation.create( x=state.key_black[0], y=state.key_black[1], - active=state.key_black[2]==state.player[2].astype(jnp.bool_), + active=state.key_black[2]==state.player[2], width=self.consts.KEY_SIZE[0], height=self.consts.KEY_SIZE[1], ) gate_yellow = ObjectObservation.create( x=self.consts.YELLOW_GATE_POS[0], y=self.consts.YELLOW_GATE_POS[1], - active=self.consts.YELLOW_GATE_POS[2]==state.player[2].astype(jnp.bool_), + active=self.consts.YELLOW_GATE_POS[2]==state.player[2], width=self.consts.GATE_SIZE[0], height=self.consts.GATE_SIZE[1], state=state.gate_yellow[0] @@ -1457,7 +1457,7 @@ def _get_observation(self, state: AdventureState) -> AdventureObservation: gate_black = ObjectObservation.create( x=self.consts.BLACK_GATE_POS[0], y=self.consts.BLACK_GATE_POS[1], - active=self.consts.BLACK_GATE_POS[2]==state.player[2].astype(jnp.bool_), + active=self.consts.BLACK_GATE_POS[2]==state.player[2], width=self.consts.GATE_SIZE[0], height=self.consts.GATE_SIZE[1], state=state.gate_black[0] @@ -1465,35 +1465,35 @@ def _get_observation(self, state: AdventureState) -> AdventureObservation: sword = ObjectObservation.create( x=state.sword[0], y=state.sword[1], - active=state.sword[2]==state.player[2].astype(jnp.bool_), + active=state.sword[2]==state.player[2], width=self.consts.SWORD_SIZE[0], height=self.consts.SWORD_SIZE[1] ) bridge = ObjectObservation.create( x=state.bridge[0], y=state.bridge[1], - active=state.bridge[2]==state.player[2].astype(jnp.bool_), + active=state.bridge[2]==state.player[2], width=self.consts.BRIDGE_SIZE[0], height=self.consts.BRIDGE_SIZE[1] ) magnet = ObjectObservation.create( x=state.magnet[0], y=state.magnet[1], - active=state.magnet[2]==state.player[2].astype(jnp.bool_), + active=state.magnet[2]==state.player[2], width=self.consts.MAGNET_SIZE[0], height=self.consts.MAGNET_SIZE[1] ) chalice = ObjectObservation.create( x=state.chalice[0], y=state.chalice[1], - active=state.chalice[2]==state.player[2].astype(jnp.bool_), + active=state.chalice[2]==state.player[2], width=self.consts.CHALICE_SIZE[0], height=self.consts.CHALICE_SIZE[1] ) dragon_red = ObjectObservation.create( x=state.dragon_red[0], y=state.dragon_red[1], - active=state.dragon_red[2]==state.player[2].astype(jnp.bool_), + active=state.dragon_red[2]==state.player[2], width=self.consts.DRAGON_SIZE[0], height=self.consts.DRAGON_SIZE[1], state=state.dragon_red[3] @@ -1501,14 +1501,14 @@ def _get_observation(self, state: AdventureState) -> AdventureObservation: key_white = ObjectObservation.create( x=state.key_white[0], y=state.key_white[1], - active=state.key_white[2]==state.player[2].astype(jnp.bool_), + active=state.key_white[2]==state.player[2], width=self.consts.KEY_SIZE[0], height=self.consts.KEY_SIZE[1] ) gate_white = ObjectObservation.create( x=self.consts.WHITE_GATE_POS[0], y=self.consts.WHITE_GATE_POS[1], - active=self.consts.WHITE_GATE_POS[2]==state.player[2].astype(jnp.bool_), + active=self.consts.WHITE_GATE_POS[2]==state.player[2], width=self.consts.GATE_SIZE[0], height=self.consts.GATE_SIZE[1], state=state.gate_white[0] @@ -1516,14 +1516,14 @@ def _get_observation(self, state: AdventureState) -> AdventureObservation: bat = ObjectObservation.create( x=state.bat[0], y=state.bat[1], - active=state.bat[2]==state.player[2].astype(jnp.bool_), + active=state.bat[2]==state.player[2], width=self.consts.DOT_SIZE[0], height=self.consts.DOT_SIZE[1] ) dot = ObjectObservation.create( x=state.dot[0], y=state.dot[1], - active=state.dot[2]==state.player[2].astype(jnp.bool_), + active=state.dot[2]==state.player[2], width=self.consts.DOT_SIZE[0], height=self.consts.DOT_SIZE[1] ) From 5f5b57fa1f548627f15897831739ad79180e58d1 Mon Sep 17 00:00:00 2001 From: DanielCress Date: Tue, 31 Mar 2026 18:53:13 +0200 Subject: [PATCH 098/102] add rewards --- src/jaxatari/games/jax_adventure.py | 47 ++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 957b1f0c4..29fc2f373 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -1691,18 +1691,49 @@ def _get_info(self, state: AdventureState, ) -> AdventureInfo: def _get_reward(self, previous_state: AdventureState, state: AdventureState): reward = jax.lax.cond( jnp.logical_or(jnp.logical_or(state.dragon_yellow[5]==1,state.dragon_green[5]==1),state.dragon_red[5]==1), #lose when eaten by dragon - lambda :-1, + lambda :-1000, lambda : jax.lax.cond( state.chalice[2]==1, #win when chalice in yellow castle - lambda :state.step_counter, - lambda :0 #this should happen on reset? + lambda :1000, + lambda :0 ) ) - #reward = jax.lax.cond( - # state.chalice[2]==1, - # lambda :1, - # lambda :0 - #) + + #reward for goto black key + reward = reward + jax.lax.cond( + jnp.logical_and(jnp.logical_and(previous_state.player[2]==0, state.player[2]==2),state.player[3]==0), + lambda :1, + lambda :0 + ) + reward = reward + jax.lax.cond( + jnp.logical_and(jnp.logical_and(previous_state.player[2]==2, state.player[2]==0),state.player[3]==0), + lambda :-1, + lambda :0 + ) + reward = reward + jax.lax.cond( + jnp.logical_and(jnp.logical_and(previous_state.player[2]==2, state.player[2]==3),state.player[3]==0), + lambda :1, + lambda :0 + ) + reward = reward + jax.lax.cond( + jnp.logical_and(jnp.logical_and(previous_state.player[2]==3, state.player[2]==2),state.player[3]==0), + lambda :-1, + lambda :0 + ) + + #reward for pickup black key + reward = reward + jax.lax.cond( + jnp.logical_and(previous_state.player[3]==0, state.player[2]==2), + lambda :1, + lambda :0 + ) + reward = reward + jax.lax.cond( + jnp.logical_and(previous_state.player[3]==2, state.player[2]==0), + lambda :1, + lambda :0 + ) + #jax.debug.print("reward {a}", a = reward) + return reward @partial(jax.jit, static_argnums=(0,)) From 23df4dfb2fb87040e877a766b25e35ac573588ff Mon Sep 17 00:00:00 2001 From: DanielCress Date: Tue, 31 Mar 2026 18:58:07 +0200 Subject: [PATCH 099/102] black key finish --- src/jaxatari/games/jax_adventure.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 29fc2f373..16f016084 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -1720,16 +1720,27 @@ def _get_reward(self, previous_state: AdventureState, state: AdventureState): lambda :-1, lambda :0 ) + reward = reward + jax.lax.cond( + jnp.logical_and(jnp.logical_and(previous_state.player[2]==3, state.player[2]==4),state.player[3]==0), + lambda :1, + lambda :0 + ) + reward = reward + jax.lax.cond( + jnp.logical_and(jnp.logical_and(previous_state.player[2]==4, state.player[2]==3),state.player[3]==0), + lambda :-1, + lambda :0 + ) + #reward for pickup black key reward = reward + jax.lax.cond( - jnp.logical_and(previous_state.player[3]==0, state.player[2]==2), + jnp.logical_and(previous_state.player[3]==0, state.player[3]==2), lambda :1, lambda :0 ) reward = reward + jax.lax.cond( - jnp.logical_and(previous_state.player[3]==2, state.player[2]==0), - lambda :1, + jnp.logical_and(previous_state.player[3]==2, state.player[3]==0), + lambda :-1, lambda :0 ) #jax.debug.print("reward {a}", a = reward) @@ -1738,7 +1749,7 @@ def _get_reward(self, previous_state: AdventureState, state: AdventureState): @partial(jax.jit, static_argnums=(0,)) def _get_done(self, state: AdventureState) -> bool: - return jnp.logical_or(jnp.logical_or(jnp.logical_or(state.dragon_yellow[5]==1,state.dragon_green[5]==1),state.dragon_red[5]==1), state.chalice[2]==1) + return state.player[3]==2#jnp.logical_or(jnp.logical_or(jnp.logical_or(state.dragon_yellow[5]==1,state.dragon_green[5]==1),state.dragon_red[5]==1), state.chalice[2]==1) class AdventureRenderer(JAXGameRenderer): From 6509ddabd51693b4f6771ec162588a49287bba6f Mon Sep 17 00:00:00 2001 From: DanielCress Date: Tue, 31 Mar 2026 19:43:38 +0200 Subject: [PATCH 100/102] better rewards --- src/jaxatari/games/jax_adventure.py | 188 ++++++++++++++++++++++++++-- 1 file changed, 177 insertions(+), 11 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 16f016084..9b2b21877 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -1694,7 +1694,7 @@ def _get_reward(self, previous_state: AdventureState, state: AdventureState): lambda :-1000, lambda : jax.lax.cond( state.chalice[2]==1, #win when chalice in yellow castle - lambda :1000, + lambda :100000, lambda :0 ) ) @@ -1702,7 +1702,7 @@ def _get_reward(self, previous_state: AdventureState, state: AdventureState): #reward for goto black key reward = reward + jax.lax.cond( jnp.logical_and(jnp.logical_and(previous_state.player[2]==0, state.player[2]==2),state.player[3]==0), - lambda :1, + lambda :100, lambda :0 ) reward = reward + jax.lax.cond( @@ -1712,44 +1712,210 @@ def _get_reward(self, previous_state: AdventureState, state: AdventureState): ) reward = reward + jax.lax.cond( jnp.logical_and(jnp.logical_and(previous_state.player[2]==2, state.player[2]==3),state.player[3]==0), - lambda :1, + lambda :100, lambda :0 ) reward = reward + jax.lax.cond( jnp.logical_and(jnp.logical_and(previous_state.player[2]==3, state.player[2]==2),state.player[3]==0), - lambda :-1, + lambda :-100, lambda :0 ) reward = reward + jax.lax.cond( jnp.logical_and(jnp.logical_and(previous_state.player[2]==3, state.player[2]==4),state.player[3]==0), - lambda :1, + lambda :100, lambda :0 ) reward = reward + jax.lax.cond( jnp.logical_and(jnp.logical_and(previous_state.player[2]==4, state.player[2]==3),state.player[3]==0), - lambda :-1, + lambda :-100, lambda :0 ) #reward for pickup black key reward = reward + jax.lax.cond( - jnp.logical_and(previous_state.player[3]==0, state.player[3]==2), - lambda :1, + jnp.logical_and(jnp.logical_and(previous_state.player[3]==0, state.player[3]==2),state.player[2]==4), + lambda :100, lambda :0 ) reward = reward + jax.lax.cond( - jnp.logical_and(previous_state.player[3]==2, state.player[3]==0), - lambda :-1, + jnp.logical_and(jnp.logical_and(previous_state.player[3]==2, state.player[3]==0),state.player[2]==4), + lambda :-100, + lambda :0 + ) + + #reward for go to b castle with b key + reward = reward + jax.lax.cond( + jnp.logical_and(jnp.logical_and(previous_state.player[2]==4, state.player[2]==3),state.player[3]==2), + lambda :100, + lambda :0 + ) + reward = reward + jax.lax.cond( + jnp.logical_and(jnp.logical_and(previous_state.player[2]==3, state.player[2]==4),state.player[3]==2), + lambda :-100, + lambda :0 + ) + reward = reward + jax.lax.cond( + jnp.logical_and(jnp.logical_and(previous_state.player[2]==3, state.player[2]==2),state.player[3]==2), + lambda :100, + lambda :0 + ) + reward = reward + jax.lax.cond( + jnp.logical_and(jnp.logical_and(previous_state.player[2]==2, state.player[2]==3),state.player[3]==2), + lambda :-100, + lambda :0 + ) + reward = reward + jax.lax.cond( + jnp.logical_and(jnp.logical_and(previous_state.player[2]==2, state.player[2]==5),state.player[3]==2), + lambda :100, + lambda :0 + ) + reward = reward + jax.lax.cond( + jnp.logical_and(jnp.logical_and(previous_state.player[2]==5, state.player[2]==2),state.player[3]==2), + lambda :-100, + lambda :0 + ) + reward = reward + jax.lax.cond( + jnp.logical_and(jnp.logical_and(previous_state.player[2]==5, state.player[2]==6),state.player[3]==2), + lambda :100, + lambda :0 + ) + reward = reward + jax.lax.cond( + jnp.logical_and(jnp.logical_and(previous_state.player[2]==6, state.player[2]==5),state.player[3]==2), + lambda :-100, + lambda :0 + ) + reward = reward + jax.lax.cond( + jnp.logical_and(jnp.logical_and(previous_state.player[2]==6, state.player[2]==7),state.player[3]==2), + lambda :100, + lambda :0 + ) + reward = reward + jax.lax.cond( + jnp.logical_and(jnp.logical_and(previous_state.player[2]==7, state.player[2]==6),state.player[3]==2), + lambda :-100, + lambda :0 + ) + reward = reward + jax.lax.cond( + jnp.logical_and(jnp.logical_and(previous_state.player[2]==7, state.player[2]==10),state.player[3]==2), + lambda :100, + lambda :0 + ) + reward = reward + jax.lax.cond( + jnp.logical_and(jnp.logical_and(previous_state.player[2]==10, state.player[2]==7),state.player[3]==2), + lambda :-100, + lambda :0 + ) + reward = reward + jax.lax.cond( + jnp.logical_and(jnp.logical_and(previous_state.player[2]==10, state.player[2]==11),state.player[3]==2), + lambda :100, lambda :0 ) + reward = reward + jax.lax.cond( + jnp.logical_and(jnp.logical_and(previous_state.player[2]==11, state.player[2]==10),state.player[3]==2), + lambda :-100, + lambda :0 + ) + + #reward for opening black gate and drop key afterwards + reward = reward + jax.lax.cond( + previous_state.gate_black[0] < state.gate_black[0], + lambda :100, + lambda :0 + ) + reward = reward + jax.lax.cond( + previous_state.gate_black[0] > state.gate_black[0], + lambda :-100, + lambda :0 + ) + reward = reward + jax.lax.cond( + jnp.logical_and(jnp.logical_and(previous_state.player[3]==2, state.gate_black[0]==6), state.player[3]==0), + lambda :100, + lambda :0 + ) + reward = reward + jax.lax.cond( + jnp.logical_and(jnp.logical_and(previous_state.player[3]==0, state.gate_black[0]==6), state.player[3]==2), + lambda :-100, + lambda :0 + ) + + #step rewards down + reward = reward +jax.lax.cond( + jnp.logical_and( + jnp.logical_and(jnp.logical_or(state.player[2]==0,state.player[2]==3),state.player[3]==0),#down empty + state.player[1]>previous_state.player[1] + ), + lambda: 1, + lambda: 0 + ) + reward = reward +jax.lax.cond( + jnp.logical_and( + jnp.logical_and(jnp.logical_or(state.player[2]==0,state.player[2]==3),state.player[3]==0),#down empty + state.player[1]previous_state.player[1] + ), + lambda: -1, + lambda: 0 + ) + #step rewards right + reward = reward +jax.lax.cond( + jnp.logical_and( + jnp.logical_or(jnp.logical_and(state.player[2]==2,state.player[3]==0),#right with empty hand + jnp.logical_and(state.player[2]==6,state.player[3]==2)),#right with black key + state.player[0]>previous_state.player[0] + ), + lambda: 1, + lambda: 0 + ) + reward = reward +jax.lax.cond( + jnp.logical_and( + jnp.logical_or(jnp.logical_and(state.player[2]==2,state.player[3]==0),#right with empty hand + jnp.logical_and(state.player[2]==6,state.player[3]==2)),#right with black key + state.player[0]previous_state.player[0] + ), + lambda: -1, + lambda: 0 + ) + #jax.debug.print("reward {a}", a = reward) return reward @partial(jax.jit, static_argnums=(0,)) def _get_done(self, state: AdventureState) -> bool: - return state.player[3]==2#jnp.logical_or(jnp.logical_or(jnp.logical_or(state.dragon_yellow[5]==1,state.dragon_green[5]==1),state.dragon_red[5]==1), state.chalice[2]==1) + return jnp.logical_or(state.gate_black[0]==6,jnp.logical_or(jnp.logical_or(jnp.logical_or(state.dragon_yellow[5]==1,state.dragon_green[5]==1),state.dragon_red[5]==1), state.chalice[2]==1)) class AdventureRenderer(JAXGameRenderer): From 1283ab817dfdfe454c4111cea080dbf4fbddfc4c Mon Sep 17 00:00:00 2001 From: DanielCress Date: Tue, 31 Mar 2026 19:45:40 +0200 Subject: [PATCH 101/102] fix --- src/jaxatari/games/jax_adventure.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 9b2b21877..1889ba2e7 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -1707,7 +1707,7 @@ def _get_reward(self, previous_state: AdventureState, state: AdventureState): ) reward = reward + jax.lax.cond( jnp.logical_and(jnp.logical_and(previous_state.player[2]==2, state.player[2]==0),state.player[3]==0), - lambda :-1, + lambda :-100, lambda :0 ) reward = reward + jax.lax.cond( From e8fe8a3964ced026ae7e6f2ec485115887eb4eef Mon Sep 17 00:00:00 2001 From: DanielCress Date: Tue, 31 Mar 2026 22:00:33 +0200 Subject: [PATCH 102/102] Update jax_adventure.py --- src/jaxatari/games/jax_adventure.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/jaxatari/games/jax_adventure.py b/src/jaxatari/games/jax_adventure.py index 1889ba2e7..a15365d01 100644 --- a/src/jaxatari/games/jax_adventure.py +++ b/src/jaxatari/games/jax_adventure.py @@ -132,7 +132,7 @@ class AdventureConstants(AutoDerivedConstants): SWORD_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default_factory=lambda: (31,180,1)) BRIDGE_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default_factory=lambda: (40,130,10)) MAGNET_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default_factory=lambda: (120,180,12)) - CHALICE_SPAWN: Tuple[int, int, int, int] = struct.field(pytree_node=False, default_factory=lambda: (35,180,13, 7)) + CHALICE_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default_factory=lambda: (35,180,13)) BAT_SPAWN: Tuple[int, int, int, int] = struct.field(pytree_node=False, default_factory=lambda: (76, 140, 19, 0)) DOT_SPAWN: Tuple[int, int, int] = struct.field(pytree_node=False, default_factory=lambda: (76, 140, 29)) GATE_SPAWN: Tuple[int, int] = struct.field(pytree_node=False, default_factory=lambda: (0, 0)) @@ -1347,7 +1347,7 @@ def reset(self, key: jax.random.PRNGKey = jax.random.PRNGKey(42)) -> Tuple[Adven chalice = jnp.array([self.consts.CHALICE_SPAWN[0], self.consts.CHALICE_SPAWN[1], self.consts.CHALICE_SPAWN[2], - self.consts.CHALICE_SPAWN[3]]), #ToDo + 7]), #ToDo #random key rndKey = state_key, bat = jnp.array([self.consts.BAT_SPAWN[0], @@ -1915,7 +1915,7 @@ def _get_reward(self, previous_state: AdventureState, state: AdventureState): @partial(jax.jit, static_argnums=(0,)) def _get_done(self, state: AdventureState) -> bool: - return jnp.logical_or(state.gate_black[0]==6,jnp.logical_or(jnp.logical_or(jnp.logical_or(state.dragon_yellow[5]==1,state.dragon_green[5]==1),state.dragon_red[5]==1), state.chalice[2]==1)) + return jnp.logical_or(jnp.logical_or(jnp.logical_or(state.dragon_yellow[5]==1,state.dragon_green[5]==1),state.dragon_red[5]==1), state.chalice[2]==1) class AdventureRenderer(JAXGameRenderer):