From 1f5ca02ca4339343f876465808a8efe6033eb918 Mon Sep 17 00:00:00 2001 From: Vladyslav Doloman Date: Tue, 7 Oct 2025 20:54:56 +0300 Subject: [PATCH] Repo hygiene: restore IDEAS.md; add .gitignore for __pycache__ and pyc; untrack cached bytecode --- .gitignore | 12 +++++++++ IDEAS.md | 27 +++++++++++++++++++ server/__pycache__/__init__.cpython-311.pyc | Bin 167 -> 0 bytes server/__pycache__/config.cpython-311.pyc | Bin 2091 -> 0 bytes server/__pycache__/model.cpython-311.pyc | Bin 4866 -> 0 bytes server/__pycache__/protocol.cpython-311.pyc | Bin 22691 -> 0 bytes server/__pycache__/server.cpython-311.pyc | Bin 29832 -> 0 bytes server/__pycache__/transport.cpython-311.pyc | Bin 3976 -> 0 bytes 8 files changed, 39 insertions(+) create mode 100644 .gitignore create mode 100644 IDEAS.md delete mode 100644 server/__pycache__/__init__.cpython-311.pyc delete mode 100644 server/__pycache__/config.cpython-311.pyc delete mode 100644 server/__pycache__/model.cpython-311.pyc delete mode 100644 server/__pycache__/protocol.cpython-311.pyc delete mode 100644 server/__pycache__/server.cpython-311.pyc delete mode 100644 server/__pycache__/transport.cpython-311.pyc diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3f7d4e5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +# Byte-compiled / cache +__pycache__/ +*.py[cod] + +# Virtual environments +.venv/ +venv/ + +# Certs (provide via env variables or local path) +*.pem +*.crt +*.key diff --git a/IDEAS.md b/IDEAS.md new file mode 100644 index 0000000..4736cfe --- /dev/null +++ b/IDEAS.md @@ -0,0 +1,27 @@ +This project will be a network mutiplayer Snake game. + +python 3 server and a web client that uses webtransport datagrams. + +the logic of the game: When the snake hits something, it doesn't die, the head stays in place, but the tail shortens by 1 every tick the head is turned in the direction of the obstacle. The player can change the direction the head is turned and the snake continues to move in new direction. The snake can not be shorter than its head, so the head always lives, even when the tail is all gone. +consider the possibility of stucking on anothers player snake (head or tail)? when the other player's snake have passed by and no more considered the obstacle, the current player's snake should continue moving. +self-collision is not permanent, because the tail keeps shrinking, there will be a moment, when the segment of a tail that was an obstacle will cease to exist +other snake collision can be auto-cleared when the other snake is moved away or shrinks to the point when it is no longer an obstacle +if a player is disconnected - his snake and score dissapears from the game, so there is no game-over state. the server runs constantly, without "rounds" of gameplay. new players connect directly into the game. There is no end game to detect winner or loser, there is continuous gameplay and in each moment there is a length of each snake. The longest snake is the "winner" at each moment (considering it can shorten or be outrunned by another player and lose its winning position). +keep the snake color the same for the whole duration of client connection +instead of a score based on eaten apples display the snakes current lengths +when only the head is left - it can turn 180 degrees as well as 90 + +make a small input buffer to buffer 3 direction changes for next ticks. if the new direction the user is pressing is directly opposite to the last in the buffer - replace the last in the buffer (do not add it as a new step). +instead of ignoring overflowinf inputs - replace the last one. +do not add to the buffer repeating inputs. before calculating next position when consuming 1 direction from buffer check if it is 180 turn when snake length>1, if so - ignore this input and consume the next one. + +when connected to server - show the current gameplay on the background with the text overlay "press space to join" +when 0 players left - populate the field with 3 apples + +field size 60 by 40 (by default). allow room in the protocol it to be changed between 3x3 up to 255x255 + +when using webtransport datagrams (UDP) for the game protocol, add packet number into the message to ignore late packets. make possible to wrap numbering from the beginnig in a case of integer overflow. use compression for the data in packets, so the full field update can be transmitted as one UDP datagram (typically up to 1500 bytes) +in UDP (webtransport datagrams) Protocol Design - allow room for lost packets before/after wrapping; +make room for up to 32 simultaneous players with different colors; limit player name length to 16 characters + +if UDP packet size exceeds 1280 bytes - split the update in several parts that do not exceed this size by updating different snakes info in different independant packets, so if one of them is lost - some of the information still reaches the recipient. If a snake is so long that its update doesn't fit into one packet by itself - then find a way to split it into several updates, preferably of the similar size (split the snake into the equal size parts) diff --git a/server/__pycache__/__init__.cpython-311.pyc b/server/__pycache__/__init__.cpython-311.pyc deleted file mode 100644 index 85d27a05c2977e48b0a21e93bc2ca125e7bfd1f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 167 zcmZ3^%ge<81b=OxX7B;&#~=<2FhUuhK}x1Gq%%Y@q%Z_CXfpa~GTvg3k5A0WiH~2& z@EN4+mtl}qOkRFUs&1K)k)Dx(o`G(8W}a?^nMq7CP}C@TZlX-=wL5gX71kZr{vH+*1bWMsU-#nZqJf<-JqApkQwCw+Yzx~a;H@|r^^XAR? z$3!BIpv*4*xiu#v^aoW=ON2LslMkWs2wBJy98?l?L7;8X5lfOT2?$Ff`T$wd0kY&n z5uqpW@p1^&lT!uhvK3iHxoC@8azdz>u3Pp^-!8izs4>g*&7xy^Ua>m_8WLB8lkcGM z2w|iP7ShGfVKKU7iCDIz1?aJ4J;JmI)1rEmX?;xV*ZZs(Fyl;9^nTW-GA*IUn0AF} z1A5#_0&|dQny#?EA*Nlkh7V+2wbHPOOsKA6vV+O{Wp~5gY*9ie*{&Z(c5TbwYTclQ z=oYp&xBM0jaTxRM;Wz>^GTR2mP-|aJr4qCl*$%vWhq;!IOao4Jfmdpg;9e2Dse-31%?&r zB&UVO6+Yo)53F#w!q@1l(>_!b_rz_+CJ@I?EA5H`a#M`i^>i828+0K>{7(8%r%(p_zjm(JcVS&MSs z3;2khuEbJz1TxSQfy8;fg&>cvth8tlhz78q-LSD^Wj%WzXG>Mj&#vR_uI+ExZgx7K zFU-ue=ptL!Dfh*0Hg%~p`TX=`_Wq}_K0j3;^s4S>{>`s$_avJz zCz2E}!afUcIFPyfubH&`b_wr~p1q*?^WAiIPld^9sF@u6{{9bokbDi~nBn7TUUM7Z(bUiK zFG_IhJ&1u&mLP|yk-dIoCp0zfVi_8W$4mat)jaf3cHRfo1! z!+20N9p1x^IUF#IGcUSfuyf~UJwW~S9yqy1ZLa|QgvhJ3{W1l5g&5F=_bWi{%Loeo3zyp#`FFK9`8jm0Uh*acn<*Dk{}38G#2#AQ}j~MEA1!}mA04?=xQ&= TXUzT=!)FrE4>A`AuqFKi7@-F! diff --git a/server/__pycache__/model.cpython-311.pyc b/server/__pycache__/model.cpython-311.pyc deleted file mode 100644 index 3f8903c7a2fdbed153308a2942706317c2925be7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4866 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 bamGs3oAH@?&`+81<@CVo!v~fD1eN|TkKGt4 diff --git a/server/__pycache__/server.cpython-311.pyc b/server/__pycache__/server.cpython-311.pyc deleted file mode 100644 index fc291abf1f0b36d4523cff4f793b157affe1b6b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29832 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�>CKA2POXajHN1@CW>9^t!^WR|vG@VCD=Weh zTQJFJ#o2Uka6oBJYr@^EFwW#wJxEE*P?Jf-zPZjFI9G(v)Dohy$-San(T#=}x}l{K zQPpr1tGl?Rgy}jD(!D4w!=pYk*k&CR#_;j*TiHe7hH(O}BY-q0NMj%c2Mu!*Q>Z^T z*%9D{l1E*xpOHol9YMj)w9>79z`oSG!ENrljx0Kc0n*7KDk3UffWx%#BhxK?PG5SQ zU)s+vHH@%Kj3Lbbt%Z0OHV=tbVW{A1AxYuCz^cSj04TJk zKogg?mE78QtHiRh%_}|LKH|B!$F4B5Ojd@+Crsg`q6$B%Dbl<7MBk#yjC3 zkaxvJScU-Z{Q+n*p(x4$Io*g~Pe^`8{tn1&BYqu_HyXcpHFc7oyti?G^`84+>$_+E z^-W{)!hY_Jois4i3{;uQI2f{z9OB$lB!>x*yL}>*G?EGwrTyd(=bm;MW8(_IY(Hr{ dH-CuJPrJOcc?G>Vm^Pk2e<)c`hX_b_{sv<#Xo&y-