Attempt to add opponent to yahtzee. Readme enhanced.
This commit is contained in:
105
yahtzee/README
105
yahtzee/README
@@ -1,5 +1,106 @@
|
||||
Yahtzee by Storm Dragon
|
||||
Released under the terms of the WTFPL: http://wtfpl.net/
|
||||
|
||||
Playing
|
||||
Each player gets up to 3 rolls of the dice. To select the dice to reroll, enter the number shown. For example, if you roll 1, 2, 4, 5 and 6, you can choose to reroll 1 and 6 by typing 16 or 61 or 1 6 or 6 1. To select no dice, just press enter. To select a slot on the score sheet, press the letter of the slot you want, s for small straight, l for large straight, 3 for 3s etc. To select 3 of a kind press #. To select four of a kind press $. Yahtzee is currently PVP only. You can play with one player, in solataire mode.
|
||||
OVERVIEW
|
||||
|
||||
Yahtzee is a classic dice game where you roll five dice and try to make specific combinations to score points. The goal is to fill all 13 scoring categories on your score sheet with the highest possible scores.
|
||||
|
||||
GETTING STARTED
|
||||
|
||||
Running the game:
|
||||
./yahtzee - Play against CPU opponent (2 player mode)
|
||||
./yahtzee 1 - Play solo (solitaire mode)
|
||||
./yahtzee 3 - Play with 3 human players
|
||||
./yahtzee N - Play with N human players
|
||||
|
||||
GAME RULES
|
||||
|
||||
On each turn, you get up to 3 rolls of five dice:
|
||||
1. First roll - All 5 dice are rolled
|
||||
2. After seeing the results, choose which dice to keep and which to reroll
|
||||
3. Second roll - Selected dice are rerolled
|
||||
4. Choose again which dice to keep/reroll
|
||||
5. Third roll - Final reroll
|
||||
6. Choose a scoring category to mark on your score sheet
|
||||
|
||||
The game ends when all players have filled all 13 categories on their score sheet. The player with the highest total score wins!
|
||||
|
||||
HOW TO REROLL DICE
|
||||
|
||||
After each roll, you'll see your current dice (for example: "1, 2, 4, 5, 6").
|
||||
To reroll dice, type the specific dice you want to REROLL:
|
||||
- Type "16" to reroll one 1 and one 6
|
||||
- Type "223" to reroll two 2s and one 3
|
||||
- Type "4444" to reroll four 4s
|
||||
- Type "2" to reroll just one 2 (if you have "2, 2, 3, 4, 5")
|
||||
- Press Enter with no input to keep all dice (skip remaining rolls)
|
||||
|
||||
The game removes dice one at a time as you type them, so you can reroll specific quantities
|
||||
|
||||
SCORING CATEGORIES
|
||||
|
||||
Upper Section (1s through 6s):
|
||||
1, 2, 3, 4, 5, 6 - Sum of all dice showing that number
|
||||
Example: Roll 2, 2, 3, 2, 5 and choose "2s" = 6 points (2+2+2)
|
||||
Bonus: If upper section totals 63+ points, earn 35 point bonus
|
||||
|
||||
Lower Section (special combinations):
|
||||
3 of a kind (#) - At least 3 dice the same = sum of ALL dice
|
||||
4 of a kind ($) - At least 4 dice the same = sum of ALL dice
|
||||
Full House (F) - 3 of one number + 2 of another = 25 points
|
||||
Small Straight (S) - Sequence of 4 dice (1234, 2345, or 3456) = 30 points
|
||||
Large Straight (L) - Sequence of 5 dice (12345 or 23456) = 40 points
|
||||
Yahtzee (Y) - All 5 dice the same = 50 points
|
||||
(additional Yahtzees = 100 points each!)
|
||||
Chance (C) - Any combination = sum of all dice
|
||||
|
||||
SELECTING A SCORING SLOT
|
||||
|
||||
After your final roll, choose where to score by pressing:
|
||||
1-6 - Number categories (1s, 2s, 3s, 4s, 5s, 6s)
|
||||
# - Three of a kind
|
||||
$ - Four of a kind
|
||||
F - Full house
|
||||
S - Small straight
|
||||
L - Large straight
|
||||
Y - Yahtzee
|
||||
C - Chance
|
||||
|
||||
Important: Each category can only be used once per game. If you don't match a category's requirements, you'll score 0 points for that category.
|
||||
|
||||
STRATEGY TIPS
|
||||
|
||||
- Try to get the upper section bonus (63+ points) by maximizing high numbers (4s, 5s, 6s)
|
||||
- Keep pairs and three-of-a-kind when going for Full House or Yahtzee
|
||||
- Watch for straight possibilities (consecutive numbers)
|
||||
- Save Chance for when nothing else scores
|
||||
- The CPU opponent uses smart strategy - it keeps multiples and potential straights, and prioritizes high-value scoring categories
|
||||
|
||||
CPU OPPONENT
|
||||
|
||||
When playing against the CPU (default mode), the computer will:
|
||||
- Automatically decide which dice to reroll based on the current hand
|
||||
- Choose the best available scoring category
|
||||
- Display its decisions so you can see what it's doing
|
||||
|
||||
EXAMPLE TURN
|
||||
|
||||
Roll 1: "2, 2, 3, 5, 6"
|
||||
- Keep the pair of 2s, reroll the others
|
||||
- Type: "356" and press Enter (rerolls the 3, 5, and 6)
|
||||
|
||||
Roll 2: "2, 2, 2, 4, 6"
|
||||
- Nice! Three 2s. Keep them, reroll the 4 and 6
|
||||
- Type: "46" and press Enter (rerolls the 4 and 6)
|
||||
|
||||
Roll 3: "2, 2, 2, 2, 5"
|
||||
- Four of a kind! Sum = 2+2+2+2+5 = 13
|
||||
- Press "$" to score 13 points in the 4-of-a-kind category
|
||||
|
||||
REQUIREMENTS
|
||||
|
||||
- bash 4.0 or higher
|
||||
- sox (for sound effects)
|
||||
- rolldice utility
|
||||
|
||||
Have fun and may the dice be in your favor!
|
||||
|
182
yahtzee/yahtzee
182
yahtzee/yahtzee
@@ -224,12 +224,58 @@ score_sheet()
|
||||
echo "|"
|
||||
}
|
||||
|
||||
cpu_decide_reroll()
|
||||
{
|
||||
#CPU logic for deciding which dice to reroll
|
||||
#Strategy: Keep pairs, three-of-a-kind, or higher; reroll singletons
|
||||
local rerollDice=""
|
||||
|
||||
#Count occurrences of each die value
|
||||
local count1=$(echo "$dice" | tr -cd "1" | wc -c)
|
||||
local count2=$(echo "$dice" | tr -cd "2" | wc -c)
|
||||
local count3=$(echo "$dice" | tr -cd "3" | wc -c)
|
||||
local count4=$(echo "$dice" | tr -cd "4" | wc -c)
|
||||
local count5=$(echo "$dice" | tr -cd "5" | wc -c)
|
||||
local count6=$(echo "$dice" | tr -cd "6" | wc -c)
|
||||
|
||||
#Check for potential straights first - if we have 4 in a row, keep them all
|
||||
if [[ "$dice" =~ "1" && "$dice" =~ "2" && "$dice" =~ "3" && "$dice" =~ "4" ]] ; then
|
||||
#Keep 1,2,3,4 - reroll anything that's not those
|
||||
rerollDice=$(echo "$dice" | tr -d " 1234")
|
||||
continue="$rerollDice"
|
||||
return
|
||||
fi
|
||||
if [[ "$dice" =~ "2" && "$dice" =~ "3" && "$dice" =~ "4" && "$dice" =~ "5" ]] ; then
|
||||
#Keep 2,3,4,5 - reroll anything that's not those
|
||||
rerollDice=$(echo "$dice" | tr -d " 2345")
|
||||
continue="$rerollDice"
|
||||
return
|
||||
fi
|
||||
if [[ "$dice" =~ "3" && "$dice" =~ "4" && "$dice" =~ "5" && "$dice" =~ "6" ]] ; then
|
||||
#Keep 3,4,5,6 - reroll anything that's not those
|
||||
rerollDice=$(echo "$dice" | tr -d " 3456")
|
||||
continue="$rerollDice"
|
||||
return
|
||||
fi
|
||||
|
||||
#Otherwise, reroll dice that only appear once (singletons)
|
||||
#Only add a die to reroll list if it exists AND appears only once
|
||||
[ $count1 -eq 1 ] && rerollDice="${rerollDice}1"
|
||||
[ $count2 -eq 1 ] && rerollDice="${rerollDice}2"
|
||||
[ $count3 -eq 1 ] && rerollDice="${rerollDice}3"
|
||||
[ $count4 -eq 1 ] && rerollDice="${rerollDice}4"
|
||||
[ $count5 -eq 1 ] && rerollDice="${rerollDice}5"
|
||||
[ $count6 -eq 1 ] && rerollDice="${rerollDice}6"
|
||||
|
||||
continue="$rerollDice"
|
||||
}
|
||||
|
||||
dice_parser()
|
||||
{
|
||||
error="true"
|
||||
while [ "$error" == "true" ] ; do
|
||||
#Remove spaces from the reroll string.
|
||||
continue="$(echo "$continue" | tr -d "[:space:]")"
|
||||
continue="${continue//[[:space:]]/}"
|
||||
#Make sure the reroll string contains valid dice options.
|
||||
if ! [[ "$continue" =~ ^[1-6]+$ ]] ; then
|
||||
error="true"
|
||||
@@ -251,8 +297,8 @@ dice_parser()
|
||||
if [ "$error" == "false" ] ; then
|
||||
i=0
|
||||
while [ $i -lt ${#continue} ] ; do
|
||||
#Remove all the selected dice from the dice string.
|
||||
dice=$(echo "$dice" | sed "s/${continue:$i:1} //")
|
||||
#Remove the selected dice from the dice string (one at a time).
|
||||
dice="${dice/${continue:$i:1} /}"
|
||||
let i++
|
||||
done
|
||||
else
|
||||
@@ -267,6 +313,103 @@ dice_parser()
|
||||
done
|
||||
}
|
||||
|
||||
get_slot_name()
|
||||
{
|
||||
#Convert slot number to readable name
|
||||
case $1 in
|
||||
1) echo "1s" ;;
|
||||
2) echo "2s" ;;
|
||||
3) echo "3s" ;;
|
||||
4) echo "4s" ;;
|
||||
5) echo "5s" ;;
|
||||
6) echo "6s" ;;
|
||||
7) echo "3 of a kind" ;;
|
||||
8) echo "4 of a kind" ;;
|
||||
9) echo "Chance" ;;
|
||||
10) echo "Full house" ;;
|
||||
11) echo "Large straight" ;;
|
||||
12) echo "Small straight" ;;
|
||||
13) echo "Yahtzee" ;;
|
||||
*) echo "Unknown" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
cpu_choose_score()
|
||||
{
|
||||
#CPU logic for choosing best available scoring slot
|
||||
#Priority: Yahtzee > Large Straight > Full House > 4-of-kind > 3-of-kind > Small Straight > high value slots > low value slots > Chance
|
||||
local bestSlot=0
|
||||
|
||||
#Check available slots in priority order
|
||||
i=13
|
||||
while [ $i -ge 1 ] ; do
|
||||
#Only consider slots that are available (still "false")
|
||||
if [[ $(echo "${player[$1]}" | cut -d ":" -f $i) == "false" ]] ; then
|
||||
#Check if this slot has a score available
|
||||
if [ ${score[$i]} -gt 0 ] ; then
|
||||
#Prioritize high-value special combinations
|
||||
case $i in
|
||||
13) #Yahtzee - highest priority
|
||||
bestSlot=$i
|
||||
break
|
||||
;;
|
||||
11) #Large straight
|
||||
if [ $bestSlot -eq 0 ] ; then
|
||||
bestSlot=$i
|
||||
fi
|
||||
;;
|
||||
10) #Full house
|
||||
if [ $bestSlot -eq 0 -o $bestSlot -eq 12 -o $bestSlot -lt 7 ] ; then
|
||||
bestSlot=$i
|
||||
fi
|
||||
;;
|
||||
8) #4 of a kind
|
||||
if [ $bestSlot -eq 0 -o $bestSlot -eq 12 -o $bestSlot -lt 7 ] ; then
|
||||
bestSlot=$i
|
||||
fi
|
||||
;;
|
||||
7) #3 of a kind
|
||||
if [ $bestSlot -eq 0 -o $bestSlot -lt 7 ] ; then
|
||||
bestSlot=$i
|
||||
fi
|
||||
;;
|
||||
12) #Small straight
|
||||
if [ $bestSlot -eq 0 -o $bestSlot -lt 7 ] ; then
|
||||
bestSlot=$i
|
||||
fi
|
||||
;;
|
||||
*) #Number slots (1-6) - prefer higher numbers
|
||||
if [ $bestSlot -eq 0 -o \( $bestSlot -lt 7 -a $i -gt $bestSlot \) ] ; then
|
||||
bestSlot=$i
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
let i--
|
||||
done
|
||||
|
||||
#If no scoring slot found, use chance or lowest available slot
|
||||
if [ $bestSlot -eq 0 ] ; then
|
||||
if [[ $(echo "${player[$1]}" | cut -d ":" -f 9) == "false" ]] ; then
|
||||
bestSlot=9
|
||||
else
|
||||
#Find any available slot
|
||||
i=1
|
||||
while [ $i -le 13 ] ; do
|
||||
if [[ $(echo "${player[$1]}" | cut -d ":" -f $i) == "false" ]] ; then
|
||||
bestSlot=$i
|
||||
break
|
||||
fi
|
||||
let i++
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
fieldIndex=$bestSlot
|
||||
sleep 1
|
||||
}
|
||||
|
||||
score_dice()
|
||||
{
|
||||
error="true"
|
||||
@@ -332,9 +475,11 @@ score_dice()
|
||||
if [ $# -eq 1 ] ; then
|
||||
initializer $1
|
||||
totalPlayers="$1"
|
||||
cpu="false"
|
||||
else
|
||||
initializer 1
|
||||
totalPlayers=1
|
||||
initializer 2
|
||||
totalPlayers=2
|
||||
cpu="true"
|
||||
fi
|
||||
#If the word false is in any player varaible the game is not over.
|
||||
while [[ $(echo "${player[@]}" | grep "false") ]] ; do
|
||||
@@ -352,13 +497,36 @@ while [[ $(echo "${player[@]}" | grep "false") ]] ; do
|
||||
score_sheet $playerIndex
|
||||
let rollCounter++
|
||||
if [ $rollCounter -lt 3 ] ; then
|
||||
read -p "Enter the dice you would like to reroll or enter to keep all the dice." continue
|
||||
#CPU logic for rerolls
|
||||
if [ "$cpu" == "true" -a $playerIndex -eq 2 ] ; then
|
||||
cpu_decide_reroll
|
||||
echo "CPU decides to reroll: $continue"
|
||||
sleep 1
|
||||
else
|
||||
read -p "Enter the dice you would like to reroll (e.g. '223' rerolls two 2s and one 3): " continue
|
||||
fi
|
||||
if [ "$continue" != "" ] ; then
|
||||
dice_parser $playerIndex
|
||||
fi
|
||||
fi
|
||||
done
|
||||
score_dice $playerIndex
|
||||
#Clear continue variable before scoring
|
||||
unset continue
|
||||
#CPU logic for scoring
|
||||
if [ "$cpu" == "true" -a $playerIndex -eq 2 ] ; then
|
||||
cpu_choose_score $playerIndex
|
||||
slotName=$(get_slot_name $fieldIndex)
|
||||
echo "CPU chooses $slotName for ${score[$fieldIndex]} points."
|
||||
#Set the score in the player variable.
|
||||
player[$playerIndex]="$(echo "${player[$playerIndex]}" | sed 's/:/\n/g' | sed -e $fieldIndex"s/false/${score[$fieldIndex]}/" | tr "\n" ":" | sed 's/:$//')"
|
||||
playerScore="$(echo "${player[$playerIndex]}" | tr -d "[:alpha:]" | tr -s ":" | tr ":" "+" | sed -e 's/^\+//' -e 's/\+$//')"
|
||||
echo "Player $playerIndex's score is $(($playerScore))."
|
||||
echo
|
||||
read -n 1 -p "Press enter to continue..." continue
|
||||
echo
|
||||
else
|
||||
score_dice $playerIndex
|
||||
fi
|
||||
if [ $playerIndex -ge $totalPlayers ] ; then
|
||||
playerIndex=1
|
||||
else
|
||||
|
Reference in New Issue
Block a user