Bashのネットワークゲーム:チェス

長い間、bashで何らかの種類のネットワークゲームを書きたいと思っていましたが、キーボードから通常のカーソルキーを使用して制御するのが便利であることが望ましいです。 一般的に、bashのインタラクティブな対話のトピックは、「数字を入力して「Enter」」を押します。 私は自分ですべてを発明し、研究しなければなりませんでした。 インタラクティブ性の点で似たようなものを見つけるために非常に一生懸命努力しましたが、それは見つかりませんでした。



キーボードによる微妙な制御が私の時間の多くを費やしたので、私は互換性の微妙なことを気にしませんでした。したがって、ゲームはMac OS Xでのみテストされました。



動作させるには、ゲームにnc(別名Netcat )と256色をサポートする端末が必要です(Mac OSの場合はiTerm2をお勧めします )。 ゲームに興味があれば、16色と/ dev / tcpで端末を仕上げます。 ところで、すべてのシェルクラフトをGithubにアップロードし始めました。



Bashのネットワークチェス








ゲームはネットワーク化されているため、2つのパラメーターを指定する必要があります。パラメーターを指定せずに起動するかどうかを通知します。 最初は敵のマシンのアドレス、2番目はポートです。 ポートは両方のマシンで同じように選択されます。 ゲームは、同じマシンで2つのコンソールで実行できます(スクリーンショットはそのような場合です)。



プレイするのは簡単です-各瞬間にアクティブなボードは1つだけです(スクリーンショット-右のボードでは、ボードの周りに明るい文字と数字があります)、アクティブなボードではカーソルキーでカーソルが移動します-←、→、↑、↓ -スペースバーまたはEnterを押します。 ボードに駒を置くとすぐに、相手に動きが移ります。 対戦相手の作品を「食べる」のは簡単です-自分の作品を他の人の作品に置くだけです。 ゲームには保護があります。フィギュアを「食べる」ことはできません。



ゲームにはこれ以外に何もありません-移動の制御が正しく行われず、ゲームを完了するためのチェックがありません。対戦相手の駒を歩くことさえできます。 シェルでクリックを処理する方法を理解することは非常に困難でした。そのため、残りの時間はありませんでした。「夕方のおもちゃ」の形式には収まりませんでした。



すべてを独立して動作させる方法を理解できるように、コードにコメントを付けて構造化された方法で記述しようとしました。





#!/bin/bash # Network chess by Evgeny Stepanischev http://bolknote.ru 2011 if [ $# -ne 2 ]; then echo Usage: $0 host-of-opponent port exit fi #   HOST="$1" #   PORT="$2" #     SEQLEN=(1b5b4. [2-7]. [cd]... [89ab].{5} f.{7}) #  WHITE=(♙ ♙ ♙ ♙ ♙ ♙ ♙ ♙ ♖ ♘ ♗ ♕ ♔ ♗ ♘ ♖) BLACK=(♜ ♞ ♝ ♛ ♚ ♝ ♞ ♜ ♟ ♟ ♟ ♟ ♟ ♟ ♟ ♟) #  ? OURMOVE= #    ? MYCOLOR= #  declare -a XY #  CX=1 CY=7 TAKEN= #     KUP=1b5b41 KDOWN=1b5b42 KLEFT=1b5b44 KRIGHT=1b5b43 KSPACE=20 #   function Restore { echo -ne "\033[5B\033[5B\033[?25h\033[m" stty "$ORIG" 2>/dev/null (bind '"\r":accept-line' 2>/dev/null) } trap Restore EXIT #  Enter (bind -r '\r' 2>/dev/null) #    ORIG=`stty -g` stty -echo #   echo -e "\033[?25l" #      function ToNet { echo $1 | nc "$HOST" "$PORT" } #     function React { case $1 in $KLEFT) if [ $CX -gt 1 ]; then CX=$(($CX-1)) PrintBoard fi ;; $KRIGHT) if [ $CX -lt 8 ]; then CX=$(($CX+1)) PrintBoard fi ;; $KUP) if [ $CY -gt 1 ]; then CY=$(($CY-1)) PrintBoard fi ;; $KDOWN) if [ $CY -lt 8 ]; then CY=$(($CY+1)) PrintBoard fi esac #      [ "$OURMOVE" ] && ToNet $1 } #       function CheckCons { local i for i in ${SEQLEN[@]}; do if [[ $1 =~ ^$i ]]; then return 0 fi done return 1 } #    ,  React    , #  KSPACE —     function PressEvents { local real code action #   ,    , #         #   while true; do #     read      # akw NR==1||NR==4    №1 (  real)  №4 ( ) eval $( (time -p read -r -s -n1 ch; printf 'code %d\n' "'$ch") 2>&1 | awk 'NR==1||NR==4 {print $1 "=" $2}' | tr '\r\n' ' ') # read    Enter  ,    20, #        UTF8 if [ "$code" = 0 ]; then code=20 else [ $code -lt 0 ] && code=$((256+$code)) code=$(printf '%02x' $code) fi if [ $code = $KSPACE ]; then [ "$OURMOVE" ] && ToNet $KSPACE SpaceEvent && return continue fi #     (   ) if [ $real = 0.00 ]; then seq="$seq$code" if CheckCons $seq; then React $seq seq= fi #     (      ), #   ,    else [ "$seq" ] && React $seq seq=$code #       if CheckCons $seq; then React $seq seq= fi fi done } #      function CheckColor { echo -n ${1:0:1} } #    function FillBoard { local xy ch for y in {1..8}; do for x in {1..8}; do ch='S ' if [ $y -le 2 ]; then ch=B${BLACK[$x+8*$y-9]} else if [ $y -ge 7 ]; then ch=W${WHITE[$x+8*$y-57]} fi fi XY[$x+100*$y]=$ch done done } #      function PrintBoardLetters { local letters=abcdefgh [ -z "$OURMOVE" ] && echo -ne "\033[30m" || echo -ne "\033[0m" echo -n ' ' for x in {0..7}; do echo -n "${letters:$x:1} " done echo } #      function PrintBoardDigit { [ -z "$OURMOVE" ] && echo -ne "\033[30m" echo -en " $((9-$1))\033[0m " } #   function PrintBoard { local xyc ch local colors=('48;5;209;37;1' '48;5;94;37;1') PrintBoardLetters for y in {1..8}; do PrintBoardDigit $y for x in {1..8}; do c=${colors[($x+$y) & 1]} ch=${XY[$x+100*$y]} if [[ $CX == $x && $CY == $y ]]; then c="$c;7" [ "$TAKEN" ] && ch=$TAKEN [ $MYCOLOR == B ] && c="$c;38;5;16" fi [[ $(CheckColor "$ch") == "B" ]] && c="$c;38;5;16" echo -en "\033[${c}m${ch:1:1} \033[m" done PrintBoardDigit $y echo done PrintBoardLetters echo -e "\033[11A" } #   function NetListen { nc -l $PORT } #     function NetEvents { local code while true; do code=$(NetListen) [[ "$code" == "$KSPACE" ]] && SpaceEvent && return React $code done } #    Space  Enter —     function SpaceEvent { local xy # ,      let xy="$CX+$CY*100" #   if [ "${XY[$xy]:-S }" = "S " ]; then if [ -z "$TAKEN" ]; then echo -en "\007" else #   XY[$xy]=$TAKEN TAKEN= return 0 fi #   else #     «»   if [[ $(CheckColor "$TAKEN") == $(CheckColor "${XY[$xy]}") ]]; then echo -en "\007" else #   « »,  «»  if [ "$TAKEN" ]; then XY[$xy]=$TAKEN TAKEN= return 0 else # « »   ,    TAKEN=${XY[$xy]} XY[$xy]="S " fi fi fi return 1 } #    function ClearKeyboardBuffer { #  —  zsh which zsh &>/dev/null && zsh -c 'while {} {read -rstk1 || break}' && return #  —  bash local delta while true; do delta=`(time -p read -rs -n1 -t1) 2>&1 | awk 'NR==1{print $2}'` [[ "$delta" == "0.00" ]] || break done } FillBoard #     ToNet HI [[ "$(NetListen)" == "HI" ]] && OURMOVE=1 sleep 0.2 ToNet ULOOSE [ "$OURMOVE" ] && MYCOLOR=W || MYCOLOR=B PrintBoard #   —        while true; do if [ -n "$OURMOVE" ]; then ClearKeyboardBuffer PressEvents OURMOVE= else NetEvents OURMOVE=1 fi PrintBoard done
      
      







残念ながら、すべてのレコーダーはコンピューター上で非常に重く、ゲームの速度が低下し始めますが、一般的なアイデアを得ることができます。






All Articles