2024-12-18 02:49:26 +02:00
#!/bin/bash
## matches.sh
2024-12-19 23:27:10 +02:00
## version 1.20
2024-12-18 02:49:26 +02:00
## Matches is based on a two player game from the trenches of World War One.
## Author: Ze'ev Schurmann
## License: GPL3.0 or later
## Git Repo: https://git.zaks.web.za/thisiszeev/matches
## How to play
## 1. The game is two player.
## 2. You have four sets of matches. Set A has 4 matches, Set B has 3 matches, Set C has 2 matches and Set D hs 1 match.
## 3. During your turn, you first select the Set you want to burn matches from by inputing A, B, C or D.
## 4. Then you input how many matches in that set you want to burn. You can burn all the matches in the set or even just 1 match. It's upto you.
## 5. Watch the matches burn and let your opponent have their turn.
## 6. The secret of the game is to make sure you get to burn the last match. He he burns the last match wins.
2024-12-19 23:27:10 +02:00
2024-12-18 02:49:26 +02:00
## Note: In the trenches of World War One, matches were valuable, so they didn't burn the matches, they simply removed the desired of matches from the set.
2024-12-19 23:27:10 +02:00
2024-12-18 02:49:26 +02:00
## When you develop a good strategy to the game, you will be unbeatable by novice players.
## Why did I make this game?
## Proof of concept. I wanted to learn how to work with manipulating cursor positions, how to work with colours and also how to do simple text animations in Bash. So this game seemed like the challenge to help me make that happen. It took me less than two hours from start to working version 1.0
## What next?
## I will like to develop the logic so you can play against the computer. I will make several levels of difficulty from Easy to Super Hard (using all my own strategies - I am virtually unbeaten.)
## My grandfather taught me this game when I was about 5 or 6. I am now 46 and I have been teaching friends and partners my entire life. I have developed some strong strategies, and you may not think it, but the game can be come mentally challenging when you play a good opponent.
2024-12-19 22:02:54 +02:00
# FOREGROUND COLOURS
2024-12-18 02:49:26 +02:00
declare -A fgCol
fgCol[ black] = "30"
fgCol[ red] = "31"
fgCol[ green] = "32"
fgCol[ orange] = "33"
fgCol[ blue] = "34"
fgCol[ magenta] = "35"
fgCol[ cyan] = "36"
fgCol[ white] = "37"
2024-12-19 22:02:54 +02:00
# BACKGROUND COLOURS
2024-12-18 02:49:26 +02:00
declare -A bgCol
bgCol[ black] = ";40"
bgCol[ red] = ";41"
bgCol[ green] = ";42"
bgCol[ orange] = ";43"
bgCol[ blue] = ";44"
bgCol[ magenta] = ";45"
bgCol[ cyan] = ";46"
bgCol[ white] = ";47"
2024-12-19 22:02:54 +02:00
# ATTRIBUTES
declare attBright = "1;"
declare attUnderline = "4;"
declare attBlink = "5;"
declare attReverse = "7;"
2024-12-18 02:49:26 +02:00
2024-12-19 22:02:54 +02:00
# FLAME POSITIONS
declare -a f = ( 5 4 3 2)
2024-12-18 02:49:26 +02:00
2024-12-19 22:02:54 +02:00
# MATCH POSITIONS
declare -a match = ( 5 8 11 14 23 26 29 38 41 50)
2024-12-18 02:49:26 +02:00
2024-12-19 22:02:54 +02:00
# MATCH INDEXES
declare -a setA = ( 3 2 1 0)
declare -a setB = ( 6 5 4)
declare -a setC = ( 8 7)
declare -a setD = ( 9)
declare player
declare sets
2024-12-19 23:27:10 +02:00
declare -a names
function burnMatches {
# LET'S BURN SOME MATCHES
local n
local q
local go
local played
local range
local regex
local -a setQ
go = "true"
if [ [ ${ 1 ^^ } = "A" ] ] && [ [ ${# setA [@] } -gt 0 ] ] ; then
q = ${# setA [@] }
setQ = ( " ${ setA [@] } " )
elif [ [ ${ 1 ^^ } = "B" ] ] && [ [ ${# setB [@] } -gt 0 ] ] ; then
q = ${# setB [@] }
setQ = ( " ${ setB [@] } " )
elif [ [ ${ 1 ^^ } = "C" ] ] && [ [ ${# setC [@] } -gt 0 ] ] ; then
q = ${# setC [@] }
setQ = ( " ${ setC [@] } " )
elif [ [ ${ 1 ^^ } = "D" ] ] && [ [ ${# setD [@] } -gt 0 ] ] ; then
q = ${# setD [@] }
setQ = ( " ${ setD [@] } " )
else
echo -en "\e[15;5HInvalid set selection\e[0m"
sleep 3s
echo -en "\e[15;5H\e[K\e[0m"
go = "false"
fi
if [ [ ${ go } = = "true" ] ] ; then
played = "false"
if [ [ ${ q } -gt 1 ] ] ; then
range = " 1- ${ q } "
else
range = "1"
fi
while [ [ ${ played } = = "false" ] ] ; do
echo -en " \e[15;5HNumber of matches to burn ( ${ range } ): \e[0m "
if [ [ ${ player } = = "COMPUTER" ] ] ; then
input = $( computerPlayer ${ q } )
echo ${ input }
sleep 1s
else
read -r input
fi
echo -en "\e[15;5H\e[K\e[0m"
regex = " ^[ ${ range } ] $"
if [ [ ${ input } = ~ ${ regex } ] ] ; then
for ( ( n = 0; n<${ input } ; n++) ) ; do
drawFlame ${ setQ [0] }
setQ = ( " ${ setQ [@] : 1 } " )
done
played = "true"
else
echo -en "\e[15;5HInvalid number of matches\e[0m"
sleep 3s
echo -en "\e[15;5H\e[K\e[0m"
fi
done
if [ [ ${ 1 ^^ } = "A" ] ] ; then
setA = ( " ${ setQ [@] } " )
elif [ [ ${ 1 ^^ } = "B" ] ] ; then
setB = ( " ${ setQ [@] } " )
elif [ [ ${ 1 ^^ } = "C" ] ] ; then
setC = ( " ${ setQ [@] } " )
elif [ [ ${ 1 ^^ } = "D" ] ] ; then
setD = ( " ${ setQ [@] } " )
fi
fi
}
function computerPlayer {
local r
local maj
local min
local -a setarray
maj = $(( RANDOM%5))
min = $(( RANDOM%10))
if [ [ ${ maj } = = 0 ] ] && [ [ ${ min } = = 0 ] ] ; then
sleep 5.0s
else
sleep ${ maj } .${ min } s
fi
if [ [ ${ 1 } = = "SET" ] ] ; then
if [ [ ${# setA [@] } -gt 0 ] ] ; then
setarray += ( "A" )
fi
if [ [ ${# setB [@] } -gt 0 ] ] ; then
setarray += ( "B" )
fi
if [ [ ${# setC [@] } -gt 0 ] ] ; then
setarray += ( "C" )
fi
if [ [ ${# setD [@] } -gt 0 ] ] ; then
setarray += ( "D" )
fi
r = $(( RANDOM%${# setarray [@] } ))
echo ${ setarray [ ${ r } ] }
elif [ [ ${ 1 } = "1" ] ] || [ [ ${ 1 } = = "2" ] ] || [ [ ${ 1 } = = "3" ] ] || [ [ ${ 1 } = = "4" ] ] ; then
r = $(( ( RANDOM%${ 1 } ) + 1 ))
echo ${ r }
fi
}
2024-12-18 02:49:26 +02:00
function drawBoard {
2024-12-19 22:02:54 +02:00
# DRAW BOARD
local n
local -a board = (
" \e[0 ${ bgCol [white] } m \e[0m "
" \e[0 ${ bgCol [white] } m \e[0m "
" \e[0 ${ bgCol [white] } m \e[0m "
" \e[0 ${ bgCol [white] } m \e[0m "
" \e[ ${ fgCol [green] } ${ bgCol [white] } m ▓ ▓ ▓ ▓ ▓ ▓ ▓ ▓ ▓ ▓ \e[0m "
" \e[ ${ attBright } ${ fgCol [orange] } ${ bgCol [white] } m █ █ █ █ █ █ █ █ █ █ \e[0m "
" \e[ ${ attBright } ${ fgCol [orange] } ${ bgCol [white] } m █ █ █ █ █ █ █ █ █ █ \e[0m "
" \e[ ${ attBright } ${ fgCol [orange] } ${ bgCol [white] } m █ █ █ █ █ █ █ █ █ █ \e[0m "
" \e[ ${ attBright } ${ fgCol [orange] } ${ bgCol [white] } m █ █ █ █ █ █ █ █ █ █ \e[0m "
" \e[0 ${ bgCol [white] } m \e[0m "
" \e[ ${ attBright } ${ fgCol [blue] } ${ bgCol [white] } m [A] [B] [C] [D] \e[0m "
" \e[0 ${ bgCol [white] } m \e[0m "
)
2024-12-18 02:49:26 +02:00
clear
2024-12-19 22:02:54 +02:00
for ( ( n = 0; n<${# board [@] } ; n++) ) ; do
echo -e " ${ board [ ${ n } ] } "
done
2024-12-18 02:49:26 +02:00
}
function drawFlame {
2024-12-19 22:02:54 +02:00
# ANIMATE FLAME
2024-12-18 02:49:26 +02:00
local m = ${ match [ $1 ] }
2024-12-19 22:02:54 +02:00
local n
local -a flame = (
" \e[s\e[5; $(( ${ m } - 1 )) H\e[ ${ attBright } ${ fgCol [red] } ${ bgCol [white] } m▒▓▒\e[u\e[0m "
" \e[s\e[4; $(( ${ m } - 1 )) H\e[ ${ fgCol [orange] } ${ bgCol [white] } m░▒\e[u\e[0m "
" \e[s\e[3; ${ m } H\e[ ${ attBright } ${ fgCol [orange] } ${ bgCol [white] } m░\e[u\e[0m "
" \e[s\e[3; ${ m } H\e[ ${ attBright } ${ fgCol [orange] } ${ bgCol [white] } m \e[u\e[0m "
" \e[s\e[4; $(( ${ m } - 1 )) H\e[ ${ fgCol [orange] } ${ bgCol [white] } m \e[u\e[0m "
" \e[s\e[4; ${ m } H\e[ ${ fgCol [orange] } ${ bgCol [white] } m▒░\e[u\e[0m "
" \e[s\e[3; ${ m } H\e[ ${ attBright } ${ fgCol [orange] } ${ bgCol [white] } m░\e[u\e[0m "
" \e[s\e[3; ${ m } H\e[ ${ attBright } ${ fgCol [orange] } ${ bgCol [white] } m \e[u\e[0m "
" \e[s\e[4; ${ m } H\e[ ${ fgCol [orange] } ${ bgCol [white] } m \e[u\e[0m "
" \e[s\e[4; $(( ${ m } - 1 )) H\e[ ${ fgCol [orange] } ${ bgCol [white] } m░▒\e[u\e[0m "
" \e[s\e[3; ${ m } H\e[ ${ attBright } ${ fgCol [orange] } ${ bgCol [white] } m░\e[u\e[0m "
" \e[s\e[3; ${ m } H\e[ ${ attBright } ${ fgCol [orange] } ${ bgCol [white] } m \e[u\e[0m "
" \e[s\e[4; $(( ${ m } - 1 )) H\e[ ${ fgCol [orange] } ${ bgCol [white] } m \e[u\e[0m "
" \e[s\e[5; $(( ${ m } - 1 )) H\e[ ${ fgCol [black] } ${ bgCol [white] } m ▓ \e[u\e[0m "
" \e[s\e[4; ${ m } H\e[ ${ attBright } ${ fgCol [black] } ${ bgCol [white] } m≈\e[u\e[0m "
" \e[s\e[3; ${ m } H\e[ ${ attBright } ${ fgCol [black] } ${ bgCol [white] } m≈\e[u\e[0m "
" \e[s\e[2; ${ m } H\e[ ${ attBright } ${ fgCol [black] } ${ bgCol [white] } m≈\e[u\e[0m "
" \e[s\e[4; ${ m } H\e[ ${ attBright } ${ fgCol [black] } ${ bgCol [white] } m \e[u\e[0m "
" \e[s\e[3; ${ m } H\e[ ${ attBright } ${ fgCol [black] } ${ bgCol [white] } m \e[u\e[0m "
" \e[s\e[2; ${ m } H\e[ ${ attBright } ${ fgCol [black] } ${ bgCol [white] } m \e[u\e[0m "
)
for ( ( n = 0; n<${# flame [@] } ; n++) ) ; do
echo -en " ${ flame [ $n ] } "
sleep 0.1s
done
2024-12-18 02:49:26 +02:00
}
2024-12-19 23:27:10 +02:00
function initGame {
local r
local players
2024-12-19 22:02:54 +02:00
2024-12-19 23:27:10 +02:00
cat $0 | head -n 21 | tail -n 19 | sed 's/## //g' | fold -s
echo
until [ [ ${ players } = = "1" ] ] || [ [ ${ players } = = "2" ] ] ; do
echo -n "Select number of human players (1/2) : "
read -r players
if [ [ ${ players } != "1" ] ] && [ [ ${ players } != "2" ] ] ; then
echo -e "\e[1AInvalid selection\e[K\e[0m"
sleep 3s
echo -e "\e[1A\e[K\e[0m"
echo -en "\e[1A\e[0m"
2024-12-18 02:49:26 +02:00
fi
2024-12-19 23:27:10 +02:00
done
if [ [ ${ players } = = 1 ] ] ; then
names = ( "PLAYER" "PLAYER" )
r = $(( RANDOM%2))
names[ ${ r } ] = "COMPUTER"
else
names = ( "PLAYER ONE" "PLAYER TWO" )
2024-12-18 02:49:26 +02:00
fi
2024-12-19 23:27:10 +02:00
echo "Thank you"
sleep 3s
2024-12-18 02:49:26 +02:00
}
2024-12-19 23:27:10 +02:00
initGame
2024-12-18 02:49:26 +02:00
drawBoard
2024-12-19 23:27:10 +02:00
player = ${ names [0] }
2024-12-18 02:49:26 +02:00
while [ [ ${# setA [@] } -gt 0 ] ] || [ [ ${# setB [@] } -gt 0 ] ] || [ [ ${# setC [@] } -gt 0 ] ] || [ [ ${# setD [@] } -gt 0 ] ] ; do
2024-12-19 22:02:54 +02:00
sets = "("
if [ [ ${# setA [@] } -gt 0 ] ] ; then
sets = " ${ sets } A/ "
fi
if [ [ ${# setB [@] } -gt 0 ] ] ; then
sets = " ${ sets } B/ "
fi
if [ [ ${# setC [@] } -gt 0 ] ] ; then
sets = " ${ sets } C/ "
2024-12-18 02:49:26 +02:00
fi
2024-12-19 22:02:54 +02:00
if [ [ ${# setD [@] } -gt 0 ] ] ; then
sets = " ${ sets } D/ "
fi
sets = " ${ sets : 0 :- 1 } ) "
2024-12-19 23:27:10 +02:00
if [ [ ${ player } = = ${ names [0] } ] ] ; then
player = " ${ names [1] } "
else
player = " ${ names [0] } "
fi
echo -e " \e[14;3H\e[4m ${ player } \e[K\e[0m "
2024-12-19 22:02:54 +02:00
echo -en " \e[15;5HChoose a set ${ sets } : \e[0m "
2024-12-19 23:27:10 +02:00
if [ [ ${ player } = = "COMPUTER" ] ] ; then
input = $( computerPlayer SET)
echo ${ input }
sleep 1s
else
read -r input
fi
echo -en "\e[15;5H\e[K\e[0m"
2024-12-19 22:02:54 +02:00
burnMatches ${ input : 0 : 1 }
2024-12-18 02:49:26 +02:00
done
echo -e " \e[14;3H ${ player } WINS!!!\e[0m "