Very powerful shell-written Tetris

Source: Internet
Author: User
Tags imap

Very powerful shell-written Tetris

On the Internet, you can see a Russian box written using linux shell scripts. It is the most awesome shell I have ever written. Share.

The original author information is included in the comments of the script.

: Click to download


#! /Bin/bash # Tetris Game #10.21.2003 xhchen <[email] xhchen@winbond.com.tw [/email]> # APP declarationAPP_NAME = "$ {0 # * [\/]}" APP_VERSION = "1.0" # color definition cRed = 1 cGreen = 2 cYellow = 3 cBlue = 4 cFuchsia = 5 cCyan = 6 cWhite = 7 colorTable = ($ cRed $ cGreen $ cYellow $ cBlue $ cFuchsia $ cCyan $ cWhite) # position and size iLeft = 3 iTop = 2 (iTrayLeft = iLeft + 2) (iTrayTop = iTop + 1) (iTrayWidth = 10 )) (iTrayHeight = 15) # color settings cBorder = $ cGreencScore = $ CFuchsiacScoreValue = $ cCyan # control signal # change the game to use two processes, one for receiving input, and the other for the game process and display interface. # When the former receives buttons such as top, bottom, and left, notify the latter by sending signal to the backend. SigRotate = 25 sigLeft = 26 sigRight = 27 sigDown = 28 sigAllDown = 29 sigExit = 30 # definitions of different squares in seven # by rotation, there may be several kinds of box0 = (0 0 0 1 1 0 1) box1 = (0 2 1 2 2 2 2 2 1 1 1 1 1 2 1 3) box2 = (0 0 0 1 1 1 1 1 2 0 1 1 1 1 1 1 2 0) box3 = (0 1 0 2 1 0 1 1 0 1 0 1 1 1 2 1) box4 = (0 1 0 2 1 1 1 1 1 1 1 1 1 2 2 2 2 0 1 1 2 0 2 1 0 1 0 1 1 1 1 1 2) box5 = (0 1 1 1 1 2 2 2 1 1 1 1 1 2 2 0 0 0 0 1 1 1 2 1 0 2 1 1 1 1 2) box6 = (0 1 1 1 1 2 2 1 1 0 1 1 1 2 2 1 0 1 1 1 1 1 2 1 1 1 1 1 1 2) # Put all the definitions of squares in the box variable box = ($ {box0 [@] }$ {box1 [@] }$ {box2 [@] }$ {box3 [@] }$ {box4 [@] }$ {box5 [@] }$ {box6 [@]}) # Number of possible styles after rotation of various squares countBox = (1 2 2 2 4 4 4) # offset offsetBox = (0 1 3 5 7 11 15) in the box array of various squares) # The score iScoreEachLevel = 50 # be greater than 7 # runtime data sig = 0 # received signaliScore = 0 # Total iLevel = 0 # speed level boxNew = () # cBoxNew = 0 # iBoxNewType = 0 # iBoxNewType = 0 # iBoxN EwRotate = 0 # Rotation Angle of the new falling square boxCur = () # define the position of the current square cBoxCur = 0 # the color of the current square iBoxCurType = 0 # the type of the current square iBoxCurRotate = 0 # The Rotation Angle of the current square boxCurX =-1 # The x of the current square coordinate Position boxCurY =-1 # y coordinate position of the current square iMap = () # # Initialize all the background blocks as-1, indicating that there is no square for (I = 0; I <iTrayHeight * iTrayWidth; I ++ )); do iMap [$ I] =-1; done # receives the input process's main function runaskeycycler () {local pidDisplayer key aKey sig cESC sTTY pidDisplayer = $1 aKey = (0 0) cESC = 'echo-ne "\ 033" 'cspa Ce = 'echo-ne "\ 040" '# Save terminal properties. When read-s reads the terminal key, the properties of the terminal are temporarily changed. # If the program is killed unfortunately during read-s, terminal confusion may occur. # restore terminal attributes when the program exits. STTY = 'stty-G' # capture exit signal trap "MyExit;" int term trap "MyExitNoSub;" $ sigExit # Hide the cursor echo-ne "\ 033 [? 25l "while: do # Read input. Note-s does not show back, -n returns read-s-n 1 key aKey [0] =$ {aKey [1]} aKey [1] =$ {aKey [2]} aKey [2] = $ key sig = 0 # determine the Input key. if [[$ key = $ cESC & $ {aKey [1] }== $ cESC] then # ESC key MyExit elif [[$ {aKey [0] }=$ cESC & $ {aKey [1] }== "["] then if [[$ key = = "A"]; then sig = $ sigRotate # <up key> elif [[$ key = "B"]; then sig = $ sigDown # <down key> elif [[$ key = "D"]; then sig = $ sigLeft # <left arrow> elif [[$ key = "C"]; then Sig = $ sigRight # <right-click> fi elif [[$ key = "W" | $ key = "w"]; then sig = $ sigRotate # W, w elif [[$ key = "S" | $ key = "s"]; then sig = $ sigDown # S, s elif [[$ key = "A" | $ key = "a"]; then sig = $ sigLeft #, a elif [[$ key = "D" | $ key = "d"]; then sig = $ sigRight # D, d elif [["[$ key]" = "[]"]; then sig = $ sigAllDown # Space key elif [[$ key = "Q" | $ key = "q"] # Q, q then MyExit fi if [[$ Sig! = 0] then # send the message kill-$ sig $ pidDisplayer fi done} to another process # restore function MyExitNoSub () before exiting () {local y # restore terminal attributes stty $ sTTY (y = iTop + iTrayHeight + 4) # display the cursor echo-e "\ 033 [? 25h \ 033 [$ {y}; 0 H "exit} function MyExit () {# The Notification display process needs to exit kill-$ sigExit $ pidDisplayer MyExitNoSub} # Main function RunAsDisplayer () for processing display and game flows () {local sigThis InitDraw # handler for mounting various signals trap "sig = $ sigRotate;" $ sigRotate trap "sig = $ sigLeft;" $ sigLeft trap "sig = $ sigRight; "$ sigRight trap" sig = $ sigDown; "$ sigDown trap" sig = $ sigAllDown; "$ sigAllDown trap" ShowExit; "$ sigExit while: do # set the number of cycles based on the current speed level iLevel For (I = 0; I <21-iLevel; I ++ )) do sleep 0.02 sigThis = $ sig = 0 # determine whether to receive the corresponding signal if (sigThis = sigRotate) based on the sig variable; then BoxRotate; # rotating elif (sigThis = sigLeft); then BoxLeft; # moving the left column of elif (sigThis = sigRight); then BoxRight; # shift a column to the right of elif (sigThis = sigDown); then BoxDown; # Drop a row of elif (sigThis = sigAllDown); then BoxAllDown; # Drop fi done # kill-$ sigDown $ BoxDown # Drop a row done} # BoxMove (y, X) to test whether the square in the movement can be moved to the position of (x, y). If 0 is returned, 1 cannot be function BoxMove () {local j I x y xTest yTest = $1 xTest = $2 for (j = 0; j <8; j ++ = 2 )) do (I = j + 1) (y =$ {boxCur [$ j]} + yTest )) (x =$ {boxCur [$ I]} + xTest )) if (y <0 | y> = iTrayHeight | x <0 | x> = iTrayWidth )) then # hit the wall and return 1 fi if ($ {iMap [y * iTrayWidth + x]}! =-1) then # Hit another existing square, return 1 fi done return 0;} # Put the square in the current movement in the background square, # Calculate the new score and speed level. (That is, once the square falls to the bottom) function Box2Map () {local j I x y xp yp line # Place the square in the current movement in the background square for (j = 0; j <8; j + = 2) do (I = j + 1) (y =$ {boxCur [$ j]} + boxCurY )) (x =$ {boxCur [$ I]} + boxCurX) (I = y * iTrayWidth + x )) iMap [$ I] = $ cBoxCur done # Delete rows that can be eliminated line = 0 for (j = 0; j <iTrayWidth * iTrayHeight; j + = iTrayWidth )) do for (I = j + iTrayWidth-1; I >=j; I --) do if ($ {iMap [$ I] }==-1 )); then break; Fi done if (I> = j); then continue; fi (line ++) for (I = j-1; I> = 0; I --) do (x = I + iTrayWidth) iMap [$ x] =$ {iMap [$ I]} done for (I = 0; I <iTrayWidth; I ++) do iMap [$ I] =-1 done if (line = 0); then return; fi # Calculate the score and speed level based on the line of the deleted rows (x = iLeft + iTrayWidth * 2 + 7) (y = iTop + 11 )) (iScore + = line * 2-1 )) # display the new score echo-ne "\ 033 [1 m \ 033 [3 $ {cScoreValue} m \ 033 [$ {y}; $ {x} H $ {iScore} "If (iScore % iScoreEachLevel <line * 2-1) then if (iLevel <20) then (iLevel ++ )) (y = iTop + 14) # display the new speed echo-ne "\ 033 [3 $ {cScoreValue} m \ 033 [$ {y }; $ {x} H $ {iLevel} "fi echo-ne" \ 033 [0 m "# re-display the background square for (y = 0; y <iTrayHeight; y ++) do (yp = y + iTrayTop + 1) (xp = iTrayLeft + 1) (I = y * iTrayWidth )) echo-ne "\ 033 [$ {yp}; $ {xp} H" for (x = 0; x <iTrayWidth; x ++ )) do (j = I + X) if ($ {iMap [$ j]} =-1 )) then echo-ne "" else echo-ne "\ 033 [1 m \ 033 [7m \ 033 [3 $ {iMap [$ j]} m \ 033 [4 $ {iMap [$ j]} m [] \ 033 [0 m "fi done} # function BoxDown () {local y s (y = boxCurY + 1 )) # New y coordinate if BoxMove $ y $ boxCurX # test whether a row can be dropped by then s = "'drawcurbox 0'" # erase the old square (boxCurY = y )) s = "$ s 'drawcurbox 1'" # display the new lower-left square echo-ne $ s else # Go here, if Box2Map cannot be dropped # paste the box in the current movement to the background box, RandomBox # generate a new box fi} # Move the column to the left Function BoxLeft () {local x s (x = boxCurX-1) if BoxMove $ boxCurY $ x then s = 'drawcurbox 0' (boxCurX = x )) s = $ s 'drawcurbox 1' echo-ne $ s fi} # Right Shift a column function BoxRight () {local x s (x = boxCurX + 1 )) if BoxMove $ boxCurY $ x then s = 'drawcurbox 0' (boxCurX = x )) s = $ s 'drawcurbox 1' echo-ne $ s fi} # function BoxAllDown () {local k j I x y iDown s iDown = $ iTrayHeight # calculate the total number of rows to be dropped for (j = 0; j <8; J + = 2) do (I = j + 1) (y =$ {boxCur [$ j]} + boxCurY )) (x =$ {boxCur [$ I]} + boxCurX) for (k = y + 1; k <iTrayHeight; k ++ )) do (I = k * iTrayWidth + x) if ($ {iMap [$ I]}! =-1); then break; fi done (k-= y + 1) if ($ iDown> $ k); then iDown = $ k; fi done s = 'drawcurbox 0' # erase the old square (boxCurY + = iDown )) s = $ s 'drawcurbox 1' # display the new backward square echo-ne $ s Box2Map # paste the square in the current movement to the background box RandomBox # generate a new square }# rotate the box function BoxRotate () {local iCount iTestRotate boxTest j I s iCount =$ {countBox [$ iBoxCurType]} # Number of styles that can be generated when the current square is rotated # Calculate the new style after rotation (( iTestRotate = iBoxCurRotate + 1 )) if (iTestR Otate> = iCount) then (iTestRotate = 0) fi # update to the new style and save the old style (but not displayed) for (j = 0, I = ($ {offsetBox [$ iBoxCurType]} + $ iTestRotate) * 8; j <8; j ++, I ++ )) do boxTest [$ j] =$ {boxCur [$ j]} boxCur [$ j] =$ {box [$ I]} done if BoxMove $ boxCurY $ boxCurX # After testing Rotation whether there is space to put then # erase the old square for (j = 0; j <8; j ++ )) do boxCur [$ j] =$ {boxTest [$ j]} done s = 'drawcurbox 0' # draw a new square for (j = 0, I = ($ {offsetBox [$ iBoxCurType]} + $ I TestRotate) * 8; j <8; j ++, I ++ )) do boxCur [$ j] =$ {box [$ I]} done s = $ s 'drawcurbox 1 'echo-ne $ s iBoxCurRotate = $ iTestRotate else # cannot be rotated, continue to use the old style for (j = 0; j <8; j ++ )) do boxCur [$ j] =$ {boxTest [$ j]} done fi} # DrawCurBox (bDraw), draw the square in the current movement, set bDraw to 1, draw, and bDraw to 0, erase the square. Function DrawCurBox () {local I j t bDraw sBox s bDraw = $1 s = "" if (bDraw = 0 )) then sBox = "\ 040 \ 040" else sBox = "[]" s = $ s "\ 033 [1 m \ 033 [7m \ 033 [3 $ {cBoxCur} m \ 033 [4 $ {cBoxCur} m "fi for (j = 0; j <8; j + = 2) do (I = iTrayTop + 1 + $ {boxCur [$ j]} + boxCurY )) (t = iTrayLeft + 1 + 2 * (boxCurX + $ {boxCur [$ j + 1]}) # \ 033 [y; xH, cursor to (x, y) s = $ s "\ 033 [$ {I }; $ {t} H $ {sBox} "done s = $ s" \ 033 [0 m "echo-n $ s} # update the new Square function RandomBox () {local I j t # update the currently moved box iBoxCurType =$ {iBoxNewType} iBoxCurRotate =$ {iBoxNewRotate} cBoxCur =$ {cBoxNew} for (j = 0; j <$ {# boxNew [@]}; j ++ )) do boxCur [$ j] =$ {boxNew [$ j]} done # display the currently moved box if ($ {# boxCur [@] }== 8 )) then # Calculate the row from the top of the current square for (j = 0, t = 4; j <8; j + = 2 )) do if ($ {boxCur [$ j]} <t); then t =$ {boxCur [$ j]}; fi done (boxCurY =-t )) for (j = 1, I =-4, t = 20; J <8; j + = 2) do if ($ {boxCur [$ j]}> I); then I =$ {boxCur [$ j]}; fi if ($ {boxCur [$ j]} <t); then t =$ {boxCur [$ j]}; fi done (boxCurX = (iTrayWidth-1-I-t)/2 )) # display the currently moved square echo-ne 'drawcurbox 1' # If the square is displayed, it will not be placed. Game over! If! BoxMove $ boxCurY $ boxCurX then kill-$ sigExit $ {PPID} ShowExit fi # Clear the pre-displayed box for (j = 0; j <4; j ++) on the right )) do (I = iTop + 1 + j) (t = iLeft + 2 * iTrayWidth + 7) echo-ne "\ 033 [$ {I }; $ {t} H "done # randomly generate new blocks (iBoxNewType = RANDOM % $ {# offsetBox [@]}) (iBoxNewRotate = RANDOM % $ {countBox [$ iBoxNewType]}) for (j = 0, I = ($ {offsetBox [$ iBoxNewType]} + $ iBoxNewRotate) * 8; j <8; j ++, I ++) do box New [$ j] =$ {box [$ I]}; done (cBoxNew =$ {colorTable [RANDOM % $ {# colorTable [@]}) # display the pre-displayed box echo-ne "\ 033 [1 m \ 033 [7m \ 033 [3 $ {cBoxNew} m \ 033 [4 $ {cBoxNew} m" ((j = 0; j <8; j + = 2) do (I = iTop + 1 + $ {boxNew [$ j]}) (t = iLeft + 2 * iTrayWidth + 7 + 2 * $ {boxNew [$ j + 1]}) echo-ne "\ 033 [$ {I }; $ {t} H [] "done echo-ne" \ 033 [0 m "} # initial draw function InitDraw () {clear RandomBox # random generate blocks, at this time, there is a square in the pre-display window on the right, Rand OmBox # generate blocks randomly, and the blocks in the pre-display window on the right are updated, the original square will start to fall into the local I t1 t2 t3 # display the border echo-ne "\ 033 [1 m" echo-ne "\ 033 [3 $ {cBorder} m \ 033 [4 $ {cBorder} m "(t2 = iLeft + 1 )) (t3 = iLeft + iTrayWidth * 2 + 3) for (I = 0; I <iTrayHeight; I ++ )) do (t1 = I + iTop + 2) echo-ne "\ 033 [$ {t1 }; $ {t2} H | "echo-ne" \ 033 [$ {t1}; $ {t3} H | "done (t2 = iTop + iTrayHeight + 2 )) for (I = 0; I <iTrayWidth + 2; I ++) do (t1 = I * 2 + ILeft + 1) echo-ne "\ 033 [$ {iTrayTop };; {t1} H =" echo-ne "\ 033 [$ {t2 }; $ {t1} H = "done echo-ne" \ 033 [0 m "# Show" Score "and" Level "echo-ne" \ 033 [1 m "( (t1 = iLeft + iTrayWidth * 2 + 7 )) (t2 = iTop + 10) echo-ne "\ 033 [3 $ {cScore} m \ 033 [$ {t2 }; $ {t1} HScore "(t2 = iTop + 11) echo-ne" \ 033 [3 $ {cScoreValue} m \ 033 [$ {t2 }; $ {t1} H $ {iScore} "(t2 = iTop + 13) echo-ne" \ 033 [3 $ {cScore} m \ 033 [$ {t2 }; $ {t1} HLevel "(t 2 = iTop + 14) echo-ne "\ 033 [3 $ {cScoreValue} m \ 033 [$ {t2 }; $ {t1} H $ {iLevel} "echo-ne" \ 033 [0 m "} # GameOVer displayed when exiting! Function ShowExit () {local y (y = iTrayHeight + iTrayTop + 3) echo-e "\ 033 [$ {y}; 0 HGameOver! \ 033 [0 m "exit} # display usage. function Usage {cat <EOFUsage: $ APP_NAMEStart tetris game. -h, -- help display this help and exit -- version output version information and exitEOF} # The main game program starts here. if [["$1" = "-h" | "$1" = "-- help"]; then Usageelif [["$1" = "-- version"]; then echo "$ APP_NAME $ APP_VERSION" elif [["$1" = "-- show"]; then # When the -- show parameter is found, run the display function RunAsDisplayerelse bash $0 -- show & # With the -- sh Parameter Ow runs this program again. runaskeycycler $! # The process ID generated by the preceding line is used as the parameter fi


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.