#!/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();
}
