Files
basic-computer-games/07_Basketball/perl/basketball.pl
2023-04-20 12:33:38 -05:00

394 lines
9.7 KiB
Perl
Executable File

#!/usr/bin/perl
# Basketball program in Perl
# While this should play the same way as the fairly faithful translation version,
# there are no GOTOs in this code. That was achieved by restructuring the program
# in the 2 *_play() subs. All of the percentages remain the same. If writing this
# from scratch, we really should have only a play() sub which uses the same code
# for both teams, but the percent edge to Darmouth has been maintained here.
# Translated by Kevin Brannen (kbrannen)
use strict;
use warnings;
# globals
my $Defense=0; # dartmouth defense value
my $Opponent; # name of opponent
my @Score = (0, 0); # scores, dart is [0], opponent is [1]
my $Player = 0; # player, 0 = dart, 1 = opp
my $Timer = 0; # time tick, 100 ticks per game, 50 is end of first half, if tie at end then back to T=93
my $DoPlay = 1; # true if game is still being played
my $ConTeam; # controlling team, "dart" or "opp"
my $ShotType = 0; # current shot type
print "\n";
print " " x 31, "BASKETBALL";
print " " x 15, "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY";
print "\n\n\n";
print "THIS IS DARTMOUTH COLLEGE BASKETBALL. YOU WILL BE DARTMOUTH\n";
print "CAPTAIN AND PLAYMAKER. CALL SHOTS AS FOLLOWS:\n";
print " 1. LONG (30 FT.) JUMP SHOT;\n";
print " 2. SHORT (15 FT.) JUMP SHOT;\n";
print " 3. LAY UP;\n";
print " 4. SET SHOT.\n";
print "BOTH TEAMS WILL USE THE SAME DEFENSE. CALL DEFENSE AS FOLLOWS:\n";
print " 6. PRESS;\n";
print " 6.5 MAN-TO MAN;\n";
print " 7. ZONE;\n";
print " 7.5 NONE.\n";
print "TO CHANGE DEFENSE, JUST TYPE 0 AS YOUR NEXT SHOT.\n\n";
get_defense();
print "\n";
print "CHOOSE YOUR OPPONENT: ";
chomp($Opponent = <>);
$ConTeam = center_jump();
while ($DoPlay)
{
print "\n";
if ($ConTeam eq "dart")
{
get_your_shot();
dartmouth_play();
}
else
{
$ShotType = 10.0 / 4 * rand(1) + 1;
opponent_play();
}
if ($Timer >= 100)
{
check_end_game();
last if (!$DoPlay);
$Timer = 93;
$ConTeam = center_jump();
}
}
exit(0);
###############################################################
sub dartmouth_play
{
$Player = 0;
print "\n";
while (1)
{
$Timer++;
if ($Timer == 50) { end_first_half(); return; }
if ($Timer == 92) { two_min_left(); }
if ($ShotType == 0)
{
get_defense();
return; # for new ShotType
}
elsif ($ShotType == 1 || $ShotType == 2)
{
print "JUMP SHOT\n";
if (rand(1) <= 0.341 * $Defense / 8)
{
print "SHOT IS GOOD.\n";
dartmouth_score();
last;
}
if (rand(1) <= 0.682*$Defense/8)
{
print "SHOT IS OFF TARGET.\n";
if ($Defense/6*rand(1) > 0.45)
{
print "REBOUND TO $Opponent\n";
last;
}
print "DARTMOUTH CONTROLS THE REBOUND.\n";
if (rand(1) <= 0.4)
{
$ShotType = (rand(1) <= 0.5) ? 3 : 4;
next;
}
if ($Defense == 6)
{
if (rand(1) <= 0.6)
{
print "PASS STOLEN BY $Opponent, EASY LAYUP.\n";
opp_score();
next;
}
}
print "BALL PASSED BACK TO YOU.\n";
next;
}
if (rand(1) <= 0.782*$Defense/8)
{
print "SHOT IS BLOCKED. BALL CONTROLLED BY "; # no NL
if (rand(1) > 0.5)
{
print "$Opponent.\n";
last;
}
else
{
print "DARTMOUTH.\n";
next;
}
}
if (rand(1) > 0.843*$Defense/8)
{
print "CHARGING FOUL. DARTMOUTH LOSES BALL.\n";
last;
}
else
{
print "SHOOTER IS FOULED. TWO SHOTS.\n";
foul_shooting();
last;
}
}
else # elsif ($ShotType >= 3)
{
print '', ($ShotType > 3 ? "SET SHOT." : "LAY UP."), "\n";
if (7 / $Defense * rand(1) <= 0.4)
{
print "SHOT IS GOOD. TWO POINTS.\n";
dartmouth_score();
last;
}
if (7 / $Defense * rand(1) <= 0.7)
{
print "SHOT IS OFF THE RIM.\n";
if (rand(1) <= 0.667)
{
print "$Opponent CONTROLS THE REBOUND.\n";
last;
}
print "DARTMOUTH CONTROLS THE REBOUND.\n";
next if (rand(1) <= 0.4);
print "BALL PASSED BACK TO YOU.\n";
next;
}
if (7 / $Defense * rand(1) <= 0.875)
{
print "SHOOTER FOULED. TWO SHOTS.\n";
foul_shooting();
last;
}
if (7 / $Defense * rand(1) <= 0.925)
{
print "SHOT BLOCKED. $Opponent\'S BALL.\n";
last;
}
print "CHARGING FOUL. DARTMOUTH LOSES THE BALL.\n";
last;
}
}
$ConTeam = "opp";
}
sub get_defense
{
$Defense = 0;
do {
print "YOUR NEW DEFENSIVE ALLIGNMENT IS (6, 6.5, 7. 7.5): ";
chomp($Defense = <>);
($Defense) =~ m/(\d(\.\d)?)/;
} while ($Defense < 6.0 || $Defense > 7.5)
}
sub opponent_play
{
$Player = 1;
print "\n";
while (1)
{
$Timer++;
if ($Timer == 50) { end_first_half(); return; }
if ($Timer == 92) { two_min_left(); }
if ($ShotType <= 2.0)
{
print "JUMP SHOT.\n";
if (8.0 / $Defense * rand(1) <= 0.35)
{
print "SHOT IS GOOD.\n";
opp_score();
last;
}
if (8.0 / $Defense * rand(1) <= 0.75)
{
print "SHOT IS OFF RIM.\n";
opp_missed();
return; # for possible new ShotType or team change
}
if (8.0 / $Defense * rand(1) <= 0.9)
{
print "PLAYER FOULED. TWO SHOTS.\n";
foul_shooting();
last;
}
print "OFFENSIVE FOUL. DARTMOUTH'S BALL.\n";
last;
}
else # ShotType >= 3
{
print ($ShotType > 3 ? "SET SHOT.\n" : "LAY UP.\n");
if (7.0 / $Defense * rand(1) > 0.413)
{
print "SHOT IS MISSED.\n";
{
opp_missed();
return; # for possible new ShotType or team change
}
}
else
{
print "SHOT IS GOOD.\n";
opp_score();
last;
}
}
}
$ConTeam = "dart";
}
sub opp_missed
{
if ($Defense / 6.0 * rand(1) <= 0.5)
{
print "DARTMOUTH CONTROLS THE REBOUND.\n";
$ConTeam = "dart";
}
else
{
print "$Opponent CONTROLS THE REBOUND.\n";
if ($Defense == 6)
{
if (rand(1) <= 0.75)
{
print "BALL STOLEN. EASY LAY UP FOR DARTMOUTH.\n";
dartmouth_score();
#$ConTeam = "opp";
return; # for possible new ShotType
}
}
if (rand(1) <= 0.5)
{
print "PASS BACK TO $Opponent GUARD.\n";
#$ConTeam = "opp";
return; # for possible new ShotType
}
$ShotType = (rand(1) <= 0.5) ? 3 : 4;
}
}
sub opp_score
{
$Score[0] += 2;
print_score();
}
sub dartmouth_score
{
$Score[1] += 2;
print_score();
}
sub print_score
{
print "SCORE: $Score[1] TO $Score[0]\n";
print "TIME: $Timer\n";
}
sub end_first_half
{
print "\n ***** END OF FIRST HALF *****\n\n";
print "SCORE: DARTMOUTH: $Score[1] $Opponent: $Score[0]\n\n\n";
$ConTeam = center_jump();
}
sub get_your_shot
{
$ShotType = -1;
while ($ShotType < 0 || $ShotType > 4)
{
print "YOUR SHOT (0-4): ";
chomp($ShotType = <>);
$ShotType = int($ShotType);
if ($ShotType < 0 || $ShotType > 4)
{
print "INCORRECT ANSWER. RETYPE IT. ";
}
}
}
sub center_jump
{
print "CENTER JUMP\n";
if (rand(1) <= 0.6)
{
print "$Opponent CONTROLS THE TAP.\n";
return "opp";
}
print "DARTMOUTH CONTROLS THE TAP.\n";
return "dart";
}
sub check_end_game
{
print "\n";
if ($Score[1] != $Score[0])
{
print " ***** END OF GAME *****\n";
print "FINAL SCORE: DARTMOUTH: $Score[1] $Opponent: $Score[0]\n\n";
$DoPlay = 0;
}
else
{
print "\n ***** END OF SECOND HALF *****\n";
print "SCORE AT END OF REGULATION TIME:\n";
print " DARTMOUTH: $Score[1] $Opponent: $Score[0]\n\n";
print "BEGIN TWO MINUTE OVERTIME PERIOD\n";
}
}
sub two_min_left
{
print "\n *** TWO MINUTES LEFT IN THE GAME ***\n\n";
}
sub foul_shooting
{
if (rand(1) > 0.49)
{
if (rand(1) > 0.75)
{
print "BOTH SHOTS MISSED.\n";
}
else
{
print "SHOOTER MAKES ONE SHOT AND MISSES ONE.\n";
$Score[1 - $Player]++;
}
}
else
{
print "SHOOTER MAKES BOTH SHOTS.\n";
$Score[1 - $Player] += 2;
}
print_score();
}