From 7c755b30cd2c90ffa9fef3ccbdf58c57697d2ccf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ismael=20Venegas=20Castell=C3=B3?= Date: Tue, 27 Aug 2024 09:30:42 -0600 Subject: [PATCH] add demos --- etc/src/demos/tac-toe-tic.rom | Bin 0 -> 1747 bytes etc/src/demos/tac-toe-tic.rom.sym | Bin 0 -> 1531 bytes etc/src/demos/tac-toe-tic.sh | 17 ++ etc/src/demos/tac-toe-tic.tal | 275 ++++++++++++++++++++++++++++++ etc/src/demos/uxnsh.tal | 46 +++++ etc/src/heart.tal | 24 +++ etc/src/tic-tac-toe.tal | 269 +++++++++++++++++++++++++++++ 7 files changed, 631 insertions(+) create mode 100644 etc/src/demos/tac-toe-tic.rom create mode 100644 etc/src/demos/tac-toe-tic.rom.sym create mode 100755 etc/src/demos/tac-toe-tic.sh create mode 100644 etc/src/demos/tac-toe-tic.tal create mode 100644 etc/src/demos/uxnsh.tal create mode 100644 etc/src/heart.tal create mode 100644 etc/src/tic-tac-toe.tal diff --git a/etc/src/demos/tac-toe-tic.rom b/etc/src/demos/tac-toe-tic.rom new file mode 100644 index 0000000000000000000000000000000000000000..0ab8497ee5bf6bd1cfdfb1498936e323530290ed GIT binary patch literal 1747 zcmds2O=uHQ5PtjL-3o1OwY5ogTM#RvWYfl`E@Jv8MTCfWsN^z5iY?u=wpI`cIC>K4 z!9x@g4^OCwQt(hu;z1M?L=U|Qf?`DwJSh|p;;!?OY)EP2K|Hzp-kYB{GjHdc;VqY< zpx1F}C)W3HV;*#c8&^R41qx%4%poThi;XkfycH#zb)tla8)^C8sAHdLvl?zJg0?I( z9s7&o5@^qaI8YQHgSI5Z!J_yQv;`q%OqAMeW+20RjY1KjeIb1ziQ<2x_zI~SxN#S> z8E#w$ZIWYMGnqQ1ujSGU&`zQR(pQiV$n>Soez$j+;Rv=gtH@Mtq?22`64T_N5=BOi z8d_xFap`ADYqjjc6UlTXvJ@b@lAmA6V>lK=hBTG@wMZswF)klWsc+XuxLx7(qzb=K zif}Qd-dG;lxxvZN6 zHA*@rdt7lrt%qQVEA5~f5Ihi!;zMwUD;ZE$J%T6c#$6}Tq)SuBlv+sfNJ?@E<}j2mXBsrojJPEE1X$N|Yb?yQQmku-f5~t>5OM41Ti* z!3Q*vHBgP~QHpwGSgWFCwGkQ~_?jT-Y$Ln(1$+psrzxh;N)D26gy0j+ceL@G@_tPX zLNJ;Tyn!H7zy^X_Tpa@WTj6^O3j`?$UI8Ac6C!z7Hy~ij??QVifx+C(OcT8sEX*|k(`|y3BA^Q#J@Or zZ;sxL53bx=oBh8yI8A9)$(ZuZ+5cn4e^+CI;*Sj$_MxD{G;G{~6UUG48L;Q3?XmL{ zb1YBSNPFH6esp*$FuHWr9YnA$s-tP)uGSWewTOFky@rL)5XG68I&D!)$FtOvbYG-x zc5LF*q&+${JvTl!YoDDtH#$4Ek1p@{5n6_6(*LHrcRXY~!Ne0KBGi2}i1gDSGEg2Q H43@`lJO~2K? z1qBrn4Fyzmk&vK4q)G!+>C%Bjg+zsfpaJo@w#W09>YQ`$nLBfR#{(Q}tfLz6M7%?} zYYZ?O6N1*Q)K)bbnETMmI^a4lOfRnYq9!K`=_GK&lm>3}bP3$#X$IWvX+c@XnOnTH zPC5c^J=^7eghGYTUKFPLMcTUP}T3&qDBv(fDWsgmojOm*^evlg?Zq1Xh z$$eu&tW@Dj;DnbYsb$IiKIpaVTmwAh)o_A`y;uW}db$A~pB5AaZ~MfwK&`0)gqOA* zPl-;qmE2H)2{x5UqT zsisw>G@ti(F7Yg)KMH9}vT4bm5Yb;-N{k${QxiEol91SVch#&gd-q5L!)04GtLZ4S zYrLbx>=%X%v%eW~hAoRAU10X_p6=?5j75C!L`AFk;>6DdT}!j%5yWqWNM1EOhWO%8 zFKeVJ5Py^v_r_Rl4mQ=EvAg z4BOGcJ->U=Rn>U#`HSpYVE$4FiA-uu2FV?KHMN^itV+fIW^(-bwxsnLBqv59G9-_A znj<+qEK0S?vfjNvek+e+X9vkELr9!t`szq`nZ7nszQf6ZH!ywO8VoS9D)Nfu z2UCWhqkg(PQOhGwJ`8bLIWn4GwKVG%i@w^&Ay?2sc9jd6PeZ0u1%+athwyOcradl& baMvRFDyX7aX(ZnSUD1L^_g&Ctc*On#`cVNO literal 0 HcmV?d00001 diff --git a/etc/src/demos/tac-toe-tic.sh b/etc/src/demos/tac-toe-tic.sh new file mode 100755 index 0000000..38b2ba9 --- /dev/null +++ b/etc/src/demos/tac-toe-tic.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env sh + +STTY=`stty -g` # save tty settings + +uxnasm tac-toe-tic.tal tac-toe-tic.rom + +stty -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon \ + -ixoff -icanon onlcr -echo -isig -iuclc -ixany -imaxbel -xcase min 1 time 0 + +uxncli tac-toe-tic.rom + +# Exit +EXIT=`echo $?` +stty $STTY +exit $EXIT + + diff --git a/etc/src/demos/tac-toe-tic.tal b/etc/src/demos/tac-toe-tic.tal new file mode 100644 index 0000000..d0d11d2 --- /dev/null +++ b/etc/src/demos/tac-toe-tic.tal @@ -0,0 +1,275 @@ +|00 @System [ + &vector $2 &expansion $2 &wst $1 &rst $1 &metadata $2 &r $2 &g $2 + &b $2 &debug $1 &state $1 ] + +|10 @Console [ &vector $2 &read $1 &pad $4 &type $1 &write $1 &error $1 ] + +|20 @Screen [ + &vector $2 &width $2 &height $2 &auto $1 &pad $1 &x $2 &y $2 &addr $2 + &pixel $1 &sprite $1 ] + +%\n { 0a } +%\0 { 00 } +%\s { 20 } +%\e { 1b } +%\e[ { \e "[ } + +%\PURPLE { \e[ "35m } +%\BOLD { \e[ "1m } +%\ITALIC { \e[ "3m ]} +%\NORMAL { \e[ "m } + +%\DARK-PURPLE { "51; "0; "34 } +%\LIGHT-GREY { "204; "187; "187 } +%\LIGHT-RED { "238; "119; "55 } +%\LIGHT-PURPLE { "153; "85; "153 } + +%\bg-color-0 { \e[ "48;2; \DARK-PURPLE "m } +%\bg-color-1 { \e[ "48;2; \LIGHT-GREY "m "} +%\bg-color-2 { \e[ "48;2; \LIGHT-RED "m "} +%\bg-color-3 { \e[ "48;2; \LIGHT-PURPLE "m "} + +%\fg-color-0 { \e[ "38;2; \DARK-PURPLE "m } +%\fg-color-1 { \e[ "38;2; \LIGHT-GREY "m "} +%\fg-color-2 { \e[ "38;2; \LIGHT-RED "m "} +%\fg-color-3 { \e[ "38;2; \LIGHT-PURPLE "m "} + +%:SQUARES { #09 } +%: { .Console/write DEO } +%: { LIT \n : } +%: { LIT \s : } +%:NOT { #00 EQU } +%:DBG { #010e DEO } + + + +|0 @unplayed $1 + +|100 @Main ( -> ) + %:alternate-buffer { ;Commands/alternate-buffer print } + %:reset-cursor { ;Commands/reset-cursor print } + ;&mouse print + ;on-console .Console/vector DEO2 + + ( hide-cursor ) + :alternate-buffer + :reset-cursor + full-game + BRK + + &mouse \e[ "?1000h \0 + +@on-console + %:ctrl+c { #03 } + %:up-arrow { #41 } + %:down-arrow { #42 } + %:left-arrow { #43 } + %:right-arrow { #44 } + + %:cursor-up { ;Commands/up print } + %:cursor-down { ;Commands/down print } + %:cursor-left { ;Commands/left print } + %:cursor-right { ;Commands/right print } + + %:seen-esc { #00 ,&in-esc STR } + %:seen-csi { #00 ,&in-csi STR } + %:unsee-esc { #01 ,&in-esc STR } + %:unsee-csi { #01 ,&in-csi STR } + + %:read-user-input { .Console/read DEI } + + %:default-buffer { ;Commands/default-buffer print } + %:show-cursor { ;Commands/show-cursor print } + + %:quit { :show-cursor :default-buffer [ LIT2 80 -System/state ] DEO BRK } + + :read-user-input + + [ LIT &in-csi 01 ] ?{ + :unsee-esc + :unsee-csi + + DUP :up-arrow NEQ ?{ + :cursor-up + POP BRK } + + DUP :down-arrow NEQ ?{ + :cursor-down + POP BRK } } + + DUP :left-arrow NEQ ?{ + :cursor-left + POP BRK } + + DUP :right-arrow NEQ ?{ + :cursor-right + POP BRK } + + DUP LIT "[ NEQ [ LIT &in-esc 01 ] ORA ?{ + :seen-csi + POP BRK } + + DUP LIT \e NEQ ?{ + :seen-esc + POP BRK } + :unsee-esc + + DUP :ctrl+c NEQ ?{ + :quit } + + DUP #31 NEQ ?{ + ;&square-1 print #01 set-X } + + player-input + POP BRK + + &square-1 \e[ "16;9H \0 + +@set-square ( i val -- ) LIT "X : SWP #00 SWP ;board ADD2 STA JMP2r +@get-square ( i -- val ) #00 SWP ;board ADD2 LDA JMP2r +@3-newline ( i -- ) #03 AND #00 NEQ ?{ : } JMP2r + +@dashes-high ( -- ) + ;&dashes !print + &dashes \n \s \s \s \s \s \s \PURPLE \BOLD "┌───┬───┬───┐ \NORMAL \n \0 + +@dashes ( -- ) + ;&dashes !print + &dashes \n \s \s \s \s \s \s \PURPLE \BOLD "├───┼───┼───┤ \NORMAL \n \0 + +@dashes-low ( -- ) + ;&dashes !print + &dashes \n \s \s \s \s \s \s \PURPLE \BOLD "└───┴───┴───┘ \NORMAL \n \0 + + +@show-square ( i -- ) + %:space { LIT \s : } + + DUP get-square + DUP #00 EQU :NOT ?{ SWP print-nibble :space !&end } + DUP #01 EQU :NOT ?{ ;Messages/X print POP !&end } + DUP #02 EQU :NOT ?{ ;Messages/O print POP !&end } + + &end + POP JMP2r + + +@3numbers ( a b c -- ) + ;&margin print show-square ;&pipe print + show-square ;&pipe print + show-square ;&close print + JMP2r + + &pipe \fg-color-3 "│ \NORMAL \s \0 + &margin \s \s \s \s \s \s \fg-color-3 "│ \NORMAL \s \0 + &close \fg-color-3 "│ \0 + +@show-board ( -- ) + dashes-high + #0908 #0706 #0504 #0302 #01 + 3numbers dashes + 3numbers dashes + 3numbers dashes-low : + JMP2r + + +@clear-game ( -- ) + :SQUARES INC #01 + &for + DUP #00 set-square + INC GTHk ?&for + POP2 + JMP2r + + +@set-X ( i -- ) %:x { #01 } :x set-square JMP2r +@set-O ( i -- ) %:o { #02 } :o set-square JMP2r +@start ( -- ) clear-game :SQUARES .unplayed STZ JMP2r +@current-player ( -- f ) .unplayed LDZ #01 AND JMP2r +@range? ( n -- ) DUP #00 LTH SWP #0a GTH ORA #00 EQU JMP2r +@empty? ( n -- ) get-square #00 EQU JMP2r + +@ascii># ( char -- n ) + %:zero { #31 } + :zero SUB JMP2r + +@place-symbol ( square -- ) + current-player :NOT ?{ set-X !&end } + set-O + &end + .unplayed LDZ INC .unplayed STZ + JMP2r + +@ps ( -- ) place-symbol JMP2r + +@player-input ( -- ) + ascii># DUP range? OVR empty? AND :NOT ?{ place-symbol show-board !&end } + + &end + POP JMP2r + +@full-game ( -- ) + + start + ;&banner print : : + show-board player-input + { \e[ "18;13H \0 } STH2r print + JMP2r + + &banner [ + \n \n + \s \s \s \s \s \s \bg-color-1 \s \s \s \s \s \s \s \s \s \s \s \s \s \s \NORMAL \n + \s \s \s \s \s \s \bg-color-1 \s \s \fg-color-0 \bg-color-2 \BOLD "O| "O "|O \bg-color-3 \BOLD "X| \s "|X \bg-color-1 \s \s \NORMAL \n + \s \s \s \s \s \s \bg-color-1 \s \s \fg-color-0 \bg-color-2 \BOLD "-| "- "|- \bg-color-3 \BOLD "-| "- "|- \bg-color-1 \s \s \NORMAL \n + \s \s \s \s \s \s \bg-color-1 \s \s \fg-color-0 \bg-color-2 \BOLD "O| \s "|O \bg-color-3 \BOLD \s "|X| \s \bg-color-1 \s \s \NORMAL \n + \s \s \s \s \s \s \bg-color-1 \s \s \fg-color-0 \bg-color-2 \BOLD "-| "- "|- \bg-color-3 \BOLD "-| "- "|- \bg-color-1 \s \s \NORMAL \n + \s \s \s \s \s \s \bg-color-1 \s \s \fg-color-0 \bg-color-2 \BOLD "O| "O "|O \bg-color-3 \BOLD "X| \s "|X \bg-color-1 \s \s \NORMAL \s \NORMAL \n + \s \s \s \s \s \s \bg-color-1 \s \s \s \s \s \s \s \s \s \s \s \s \s \s \NORMAL \n \n \n + \s \s \s \s \s \s "CTRL+C \s "to \s "exit \0 ] + + + +@print ( str^ -- ) + &while + LDAk : + INC2 LDAk ?&while + POP2 JMP2r + +@ ( short* -: ) + SWP /b + &b ( byte -: ) + DUP #04 SFT /c + &c ( byte -: ) + #0f AND DUP #09 GTH #27 MUL ADD [ LIT "0 ] ADD #18 DEO + JMP2r + +@print-nibble ( u -- ) + #0f AND DUP #09 GTH #27 MUL ADD + [ LIT "0 ] ADD : + JMP2r + +@board [ + &00 00 &10 00 &20 00 + &01 00 &11 00 &21 00 + &02 00 &12 00 &22 00 ] + +@Messages + &exiting "Exiting \n + + &X \e[ "32m "X \NORMAL \s \0 + &O "O \s \0 + + + &pick-another "Pick \s "another \s "square. \0 + +@Commands + &cls \e[ "2J \0 + &reset-cursor \e[ "H \0 + &alternate-buffer \e[ "?1049h \0 + &default-buffer \e[ "?1049l \0 + &hide-cursor \e[ "?25l \0 + &show-cursor \e[ "?25h \0 + &up \e[ "A \e[ "A \0 + &down \e[ "B \e[ "B \0 + &left \e[ "C \e[ "C \e[ "C \e[ "C \0 + &right \e[ "D \e[ "D \e[ "D \e[ "D \0 diff --git a/etc/src/demos/uxnsh.tal b/etc/src/demos/uxnsh.tal new file mode 100644 index 0000000..3e2a32c --- /dev/null +++ b/etc/src/demos/uxnsh.tal @@ -0,0 +1,46 @@ +( uxnasm uxnsh.tal uxnsh.rom && uxn11 uxnsh.rom ) + +%emit { .Console/write DEO } + +|10 @Console [ + &vector $2 &read $1 &pad0 $2 &live $1 &exit $1 &type $1 + &write $1 &error $1 &pad1 $2 &addr $2 &mode $1 &exec $1 ] + +|0100 + reset + ;prompt/first print + ;on-console .Console/vector DEO2 + BRK + +@print ( str* -- ) + LDAk emit + INC2 LDAk ?print + POP2 JMP2r + +@on-console ( -> ) + .Console/read DEI STHk #0a EQU ?newline + ;Command/pos LDA2k STH2k STAr + INC2 SWP2 STA2 BRK + +@newline ( -> ) + POP + #00 ;Command/pos LDA2 STA + ;Command/buf syscall-sync + ;prompt print + reset + BRK + +@syscall-sync ( cmd* -- ) + .Console/addr DEO2 + #01 .Console/exec DEO + + &sync + .Console/live DEI #ff NEQ ?&sync + +@reset ( -- ) + ;Command/buf ;Command/pos STA2 + JMP2r + +@prompt 0a &first "փsh> 2000 + +@Command &pos $2 &buf \ No newline at end of file diff --git a/etc/src/heart.tal b/etc/src/heart.tal new file mode 100644 index 0000000..44dc5d0 --- /dev/null +++ b/etc/src/heart.tal @@ -0,0 +1,24 @@ +|00 @System &vector $2 &expansion $2 &wst $1 &rst $1 &metadata $2 + &r $2 &g $2 &b $2 &debug $1 &state $1 + +|20 @Screen &vector $2 &width $2 &height $2 &auto $1 &pad $1 + &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 + +|100 + #000a DUP2 + .Screen/width DEO2 + .Screen/height DEO2 + + #3ce9 .System/r DEO2 + #0b75 .System/g DEO2 + #2b59 .System/b DEO2 + + #0000 DUP2 + .Screen/x DEO2 + .Screen/y DEO2 + + ;heart .Screen/addr DEO2 + #02 .Screen/sprite DEO + BRK + +@heart [ 0066 ffff ff7e 3c18 ] diff --git a/etc/src/tic-tac-toe.tal b/etc/src/tic-tac-toe.tal new file mode 100644 index 0000000..dd7135e --- /dev/null +++ b/etc/src/tic-tac-toe.tal @@ -0,0 +1,269 @@ +( +@|constants ) +|0e @System/debug |0f @System/state |18 @Console/write +|80 @Controller/vector |83 @Controller/key + +|09 @t |0a @n |20 @s + +( 9 constant #squares ) +|09 @squares + +( 48 constant zero ) +|31 @zero + +( 113 constant q-char ) +|71 @q-char + +( 1 constant X 2 constant O ) +|01 @X |02 @O + + +|0000 + +( +@|variables ) +( variable unplayed ) +@unplayed $1 @user-input $1 + + +|0100 + +( +@|main ) +@on-reset ( -> ) + ;on-controller .Controller/vector DEO2 + + full-game + + print-stacks +BRK + + +@on-controller + .Controller/key DEI .user-input STZ +BRK + + +( : square! ( square # --- ) board rot 1- cells ! ; ) +@set-square ( i val -- ) SWP #00 SWP ;board ADD2 STA JMP2r + +( : square@ ( square --- # ) board swap 1- cells @ ; ) +@get-square ( i -- val ) #00 SWP ;board ADD2 LDA JMP2r + +( : 3-cr ( n --- ) 3 mod 0= if cr then ; ) +@3-cr ( i -- ) #03 AND #00 NEQ ?{ cr } JMP2r + +( : dashes ( --- ) cr tab ." ---------" cr ; ) +@dashes ( -- ) cr tab { "--------- $1 } print cr JMP2r + + +( +: .square ( n --- ) + dup square@ + dup 0 = if + swap . + then dup 1 = if + ." X " drop + then dup 2 = if + ." O " drop + then + drop +) +@show-square ( i -- ) + DUP get-square + DUP #00 EQU not ?{ SWP print-nibble spc !&end } + DUP #01 EQU not ?{ { "X -s $1 } print POP !&end } + DUP #02 EQU not ?{ { "O -s $1 } print POP !&end } + &end + POP +JMP2r + + +( +: 3numbers ( a b c --- ) + tab .square ." | " + .square ." | " + .square ; +) +@3numbers ( a b c -- ) + tab show-square { "| -s $1 } print + show-square { "| -s $1 } print + show-square +JMP2r + + +( +: .board ( --- ) + 9 8 7 6 5 4 3 2 1 + 3numbers dashes + 3numbers dashes + 3numbers cr ; +) +@show-board ( -- ) + #0908 #0706 #0504 #0302 #01 + 3numbers dashes + 3numbers dashes + 3numbers cr +JMP2r + +( +: clear-game ( --- ) + #squares 1+ 1 + do + i 0 square! + loop ; +) +@clear-game ( -- ) + .squares INC #01 + &for + DUP #00 set-square + INC GTHk ?&for + POP2 +JMP2r + + +( : X! ( i --- ) X square! ; ) +@set-X ( i -- ) .X set-square JMP2r + +( : O! ( i --- ) O square! ; ) +@set-O ( i -- ) .O set-square JMP2r + + +( : start ( --- ) clear-game #squares unplayed ! ; ) +@start ( -- ) clear-game .squares .unplayed STZ JMP2r + +( : current-player ( --- f ) unplayed @ 1 and ; ) +@current-player ( -- f ) .unplayed LDZ #01 AND JMP2r + +( : ascii># ( char --- n ) zero - ; ) +@ascii># ( char -- n ) .zero SUB JMP2r + +( : range? ( n --- ) dup 1 < swap 9 > or 0= ; ) +@range? ( n -- ) DUP #00 LTH SWP #0a GTH ORA #00 EQU JMP2r + +( : empty? ( n --- ) square@ 0= ) +@empty? ( n -- ) get-square #00 EQU JMP2r + +( +: place-symbol ( square --- ) + current-player if + X! + else + O! + then + unplayed @ 1+ unplayed ! ; +) +@place-symbol ( square -- ) + current-player not ?{ set-X !&end } + set-O + &end + .unplayed LDZ INC .unplayed STZ +JMP2r + + +( : ps ( --- ) place-symbol ; ) +@ps ( -- ) place-symbol JMP2r + +( +: player-input ( --- ) + begin + cr ." Square number for " + + current-player + if + ." X: " + else + ." O: " + then + + key dup q-char = + if + drop cr ." Exiting " bye + then + + ascii># dup range? over empty? and + if + place-symbol .board + else + drop ." Pick another square. " + then + while + true + repeat ; +) +@player-input ( -- ) + &while + cr { "Square -s "number -s "for -s $1 } print + + current-player not ?{ { "X: -s $1 } print !&continue } + { "O: -s $1 } print + + &continue + key DUP .q-char EQU not ?{ POP cr { "Exiting $1 } print exit } + + ascii># DUP range? OVR empty? AND not ?{ place-symbol show-board !&end } + POP { "Pick -s "another -s "square. $1 } print + + &end + ( !&while ) +JSR2 + + +( : next ( --- ) player-input ; ) +@next ( -- ) player-input JMP2r + +( +: full-game ( --- ) + start cr ." Enter 'q' to exit. " + begin + .game player-input + if exit then + unplayed + 0= until ; +) +@full-game ( -- ) + start { "Enter -s ""q" -s "to -s "exit. $1 } print cr cr + show-board player-input +JMP2r + + +( +@|stdlib ) +@print ( {str}* -- ) + SWP2r STH2r + &while + LDAk emit + INC2 LDAk ?&while + POP2 +JMP2r + + +@print-nibble ( u -- ) + #0f AND DUP #09 GTH #27 MUL ADD + [ LIT "0 ] ADD emit +JMP2r + + +@emit ( char -- ) .Console/write DEO JMP2r +@cr ( -- ) .n emit JMP2r +@tab ( -- ) .t emit JMP2r +@spc ( -- ) .s emit JMP2r +@not ( f -- ) #00 EQU JMP2r +@key ( -- char ) .user-input LDZ JMP2r +@exit ( -> ) [ LIT2 80 -System/state ] DEO BRK + +@print-stacks ( -- ) + STH2r ,&rtn STR2 + cr [ LIT2 01 -System/debug ] DEO + [ LIT2 &rtn $2 ] STH2 +JMP2r + + +( +@|data ) +( create board squares cells allot ) +@board [ + 00 00 00 + 00 00 00 + 00 00 00 +]