Merge branch 'main' into pr/860

This commit is contained in:
amjadkofahi
2023-05-25 01:27:20 +03:00
218 changed files with 12077 additions and 39 deletions
@@ -0,0 +1,112 @@
package main
import (
"bufio"
"fmt"
"math/rand"
"os"
"sort"
"strconv"
"strings"
"time"
)
var welcome = `
Acey-Ducey is played in the following manner
The dealer (computer) deals two cards face up
You have an option to bet or not bet depending
on whether or not you feel the card will have
a value between the first two.
If you do not want to bet, input a 0
`
func main() {
rand.Seed(time.Now().UnixNano())
scanner := bufio.NewScanner(os.Stdin)
fmt.Println(welcome)
for {
play(100)
fmt.Println("TRY AGAIN (YES OR NO)")
scanner.Scan()
response := scanner.Text()
if strings.ToUpper(response) != "YES" {
break
}
}
fmt.Println("O.K., HOPE YOU HAD FUN!")
}
func play(money int) {
scanner := bufio.NewScanner(os.Stdin)
var bet int
for {
// Shuffle the cards
cards := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}
rand.Shuffle(len(cards), func(i, j int) { cards[i], cards[j] = cards[j], cards[i] })
// Take the first two for the dealer and sort
dealerCards := cards[0:2]
sort.Ints(dealerCards)
fmt.Printf("YOU NOW HAVE %d DOLLARS.\n\n", money)
fmt.Printf("HERE ARE YOUR NEXT TWO CARDS:\n%s\n%s", getCardName(dealerCards[0]), getCardName(dealerCards[1]))
fmt.Printf("\n\n")
//Check if Bet is Valid
for {
fmt.Println("WHAT IS YOUR BET:")
scanner.Scan()
b, err := strconv.Atoi(scanner.Text())
if err != nil {
fmt.Println("PLEASE ENTER A POSITIVE NUMBER")
continue
}
bet = b
if bet == 0 {
fmt.Printf("CHICKEN!\n\n")
goto there
}
if (bet > 0) && (bet <= money) {
break
}
}
// Draw Players Card
fmt.Printf("YOUR CARD: %s\n", getCardName(cards[2]))
if (cards[2] > dealerCards[0]) && (cards[2] < dealerCards[1]) {
fmt.Println("YOU WIN!!!")
money = money + bet
} else {
fmt.Println("SORRY, YOU LOSE")
money = money - bet
}
fmt.Println()
if money <= 0 {
fmt.Printf("%s\n", "SORRY, FRIEND, BUT YOU BLEW YOUR WAD.")
return
}
there:
}
}
func getCardName(c int) string {
switch c {
case 11:
return "JACK"
case 12:
return "QUEEN"
case 13:
return "KING"
case 14:
return "ACE"
default:
return strconv.Itoa(c)
}
}
@@ -0,0 +1,217 @@
package main
import (
"bufio"
"fmt"
"log"
"math/rand"
"os"
"strconv"
"time"
)
func main() {
rand.Seed(time.Now().UnixNano())
printWelcome()
h, w := getDimensions()
m := NewMaze(h, w)
m.draw()
}
type direction int64
const (
LEFT direction = iota
UP
RIGHT
DOWN
)
const (
EXIT_DOWN = 1
EXIT_RIGHT = 2
)
type maze struct {
width int
length int
used [][]int
walls [][]int
enterCol int
}
func NewMaze(w, l int) maze {
if (w < 2) || (l < 2) {
log.Fatal("invalid dimensions supplied")
}
m := maze{width: w, length: l}
m.used = make([][]int, l)
for i := range m.used {
m.used[i] = make([]int, w)
}
m.walls = make([][]int, l)
for i := range m.walls {
m.walls[i] = make([]int, w)
}
// randomly determine the entry column
m.enterCol = rand.Intn(w)
// determine layout of walls
m.build()
// add an exit
col := rand.Intn(m.width - 1)
row := m.length - 1
m.walls[row][col] = m.walls[row][col] + 1
return m
}
func (m *maze) build() {
row := 0
col := 0
count := 2
for {
possibleDirs := m.getPossibleDirections(row, col)
if len(possibleDirs) != 0 {
row, col, count = m.makeOpening(possibleDirs, row, col, count)
} else {
for {
if col != m.width-1 {
col = col + 1
} else if row != m.length-1 {
row = row + 1
col = 0
} else {
row = 0
col = 0
}
if m.used[row][col] != 0 {
break
}
}
}
if count == (m.width*m.length)+1 {
break
}
}
}
func (m *maze) getPossibleDirections(row, col int) []direction {
possible_dirs := make(map[direction]bool, 4)
possible_dirs[LEFT] = true
possible_dirs[UP] = true
possible_dirs[RIGHT] = true
possible_dirs[DOWN] = true
if (col == 0) || (m.used[row][col-1] != 0) {
possible_dirs[LEFT] = false
}
if (row == 0) || (m.used[row-1][col] != 0) {
possible_dirs[UP] = false
}
if (col == m.width-1) || (m.used[row][col+1] != 0) {
possible_dirs[RIGHT] = false
}
if (row == m.length-1) || (m.used[row+1][col] != 0) {
possible_dirs[DOWN] = false
}
ret := make([]direction, 0)
for d, v := range possible_dirs {
if v {
ret = append(ret, d)
}
}
return ret
}
func (m *maze) makeOpening(dirs []direction, row, col, count int) (int, int, int) {
dir := rand.Intn(len(dirs))
if dirs[dir] == LEFT {
col = col - 1
m.walls[row][col] = int(EXIT_RIGHT)
} else if dirs[dir] == UP {
row = row - 1
m.walls[row][col] = int(EXIT_DOWN)
} else if dirs[dir] == RIGHT {
m.walls[row][col] = m.walls[row][col] + EXIT_RIGHT
col = col + 1
} else if dirs[dir] == DOWN {
m.walls[row][col] = m.walls[row][col] + EXIT_DOWN
row = row + 1
}
m.used[row][col] = count
count = count + 1
return row, col, count
}
// draw the maze
func (m *maze) draw() {
for col := 0; col < m.width; col++ {
if col == m.enterCol {
fmt.Print(". ")
} else {
fmt.Print(".--")
}
}
fmt.Println(".")
for row := 0; row < m.length; row++ {
fmt.Print("|")
for col := 0; col < m.width; col++ {
if m.walls[row][col] < 2 {
fmt.Print(" |")
} else {
fmt.Print(" ")
}
}
fmt.Println()
for col := 0; col < m.width; col++ {
if (m.walls[row][col] == 0) || (m.walls[row][col] == 2) {
fmt.Print(":--")
} else {
fmt.Print(": ")
}
}
fmt.Println(".")
}
}
func printWelcome() {
fmt.Println(" AMAZING PROGRAM")
fmt.Print(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n")
}
func getDimensions() (int, int) {
scanner := bufio.NewScanner(os.Stdin)
fmt.Println("Enter a width ( > 1 ):")
scanner.Scan()
w, err := strconv.Atoi(scanner.Text())
if err != nil {
log.Fatal("invalid dimension")
}
fmt.Println("Enter a height ( > 1 ):")
scanner.Scan()
h, err := strconv.Atoi(scanner.Text())
if err != nil {
log.Fatal("invalid dimension")
}
return w, h
}
+159
View File
@@ -0,0 +1,159 @@
package main
import (
"bufio"
"fmt"
"log"
"os"
"strings"
)
type node struct {
text string
yesNode *node
noNode *node
}
func newNode(text string, yes_node, no_node *node) *node {
n := node{text: text}
if yes_node != nil {
n.yesNode = yes_node
}
if no_node != nil {
n.noNode = no_node
}
return &n
}
func (n *node) update(newQuestion, newAnswer, newAnimal string) {
oldAnimal := n.text
n.text = newQuestion
if newAnswer == "y" {
n.yesNode = newNode(newAnimal, nil, nil)
n.noNode = newNode(oldAnimal, nil, nil)
} else {
n.yesNode = newNode(oldAnimal, nil, nil)
n.noNode = newNode(newAnimal, nil, nil)
}
}
func (n *node) isLeaf() bool {
return (n.yesNode == nil) && (n.noNode == nil)
}
func listKnownAnimals(root *node) {
if root == nil {
return
}
if root.isLeaf() {
fmt.Printf("%s ", root.text)
return
}
if root.yesNode != nil {
listKnownAnimals(root.yesNode)
}
if root.noNode != nil {
listKnownAnimals(root.noNode)
}
}
func parseInput(message string, checkList bool, rootNode *node) string {
scanner := bufio.NewScanner(os.Stdin)
token := ""
for {
fmt.Println(message)
scanner.Scan()
inp := strings.ToLower(scanner.Text())
if checkList && inp == "list" {
fmt.Println("Animals I already know are:")
listKnownAnimals(rootNode)
fmt.Println()
}
if len(inp) > 0 {
token = inp
} else {
token = ""
}
if token == "y" || token == "n" {
break
}
}
return token
}
func avoidVoidInput(message string) string {
scanner := bufio.NewScanner(os.Stdin)
answer := ""
for {
fmt.Println(message)
scanner.Scan()
answer = scanner.Text()
if answer != "" {
break
}
}
return answer
}
func printIntro() {
fmt.Println(" Animal")
fmt.Println(" Creative Computing Morristown, New Jersey")
fmt.Println("\nPlay 'Guess the Animal'")
fmt.Println("Think of an animal and the computer will try to guess it")
}
func main() {
yesChild := newNode("Fish", nil, nil)
noChild := newNode("Bird", nil, nil)
rootNode := newNode("Does it swim?", yesChild, noChild)
printIntro()
keepPlaying := (parseInput("Are you thinking of an animal?", true, rootNode) == "y")
for keepPlaying {
keepAsking := true
actualNode := rootNode
for keepAsking {
if !actualNode.isLeaf() {
answer := parseInput(actualNode.text, false, nil)
if answer == "y" {
if actualNode.yesNode == nil {
log.Fatal("invalid node")
}
actualNode = actualNode.yesNode
} else {
if actualNode.noNode == nil {
log.Fatal("invalid node")
}
actualNode = actualNode.noNode
}
} else {
answer := parseInput(fmt.Sprintf("Is it a %s?", actualNode.text), false, nil)
if answer == "n" {
newAnimal := avoidVoidInput("The animal you were thinking of was a ?")
newQuestion := avoidVoidInput(fmt.Sprintf("Please type in a question that would distinguish a '%s' from a '%s':", newAnimal, actualNode.text))
newAnswer := parseInput(fmt.Sprintf("For a '%s' the answer would be", newAnimal), false, nil)
actualNode.update(newQuestion+"?", newAnswer, newAnimal)
} else {
fmt.Println("Why not try another animal?")
}
keepAsking = false
}
}
keepPlaying = (parseInput("Are you thinking of an animal?", true, rootNode) == "y")
}
}
+166
View File
@@ -0,0 +1,166 @@
package main
import (
"bufio"
"fmt"
"math/rand"
"os"
"strconv"
"strings"
"time"
)
const MAXGUESSES int = 20
func printWelcome() {
fmt.Println("\n Bagels")
fmt.Println("Creative Computing Morristown, New Jersey")
fmt.Println()
}
func printRules() {
fmt.Println()
fmt.Println("I am thinking of a three-digit number. Try to guess")
fmt.Println("my number and I will give you clues as follows:")
fmt.Println(" PICO - One digit correct but in the wrong position")
fmt.Println(" FERMI - One digit correct and in the right position")
fmt.Println(" BAGELS - No digits correct")
}
func getNumber() []string {
numbers := []string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}
rand.Shuffle(len(numbers), func(i, j int) { numbers[i], numbers[j] = numbers[j], numbers[i] })
return numbers[:3]
}
func getValidGuess(guessNumber int) string {
var guess string
scanner := bufio.NewScanner(os.Stdin)
valid := false
for !valid {
fmt.Printf("Guess # %d?\n", guessNumber)
scanner.Scan()
guess = strings.TrimSpace(scanner.Text())
// guess must be 3 characters
if len(guess) == 3 {
// and should be numeric
_, err := strconv.Atoi(guess)
if err != nil {
fmt.Println("What?")
} else {
// and the numbers should be unique
if (guess[0:1] != guess[1:2]) && (guess[0:1] != guess[2:3]) && (guess[1:2] != guess[2:3]) {
valid = true
} else {
fmt.Println("Oh, I forgot to tell you that the number I have in mind")
fmt.Println("has no two digits the same.")
}
}
} else {
fmt.Println("Try guessing a three-digit number.")
}
}
return guess
}
func buildResultString(num []string, guess string) string {
result := ""
// correct digits in wrong place
for i := 0; i < 2; i++ {
if num[i] == guess[i+1:i+2] {
result += "PICO "
}
if num[i+1] == guess[i:i+1] {
result += "PICO "
}
}
if num[0] == guess[2:3] {
result += "PICO "
}
if num[2] == guess[0:1] {
result += "PICO "
}
// correct digits in right place
for i := 0; i < 3; i++ {
if num[i] == guess[i:i+1] {
result += "FERMI "
}
}
// nothing right?
if result == "" {
result = "BAGELS"
}
return result
}
func main() {
rand.Seed(time.Now().UnixNano())
scanner := bufio.NewScanner(os.Stdin)
printWelcome()
fmt.Println("Would you like the rules (Yes or No)? ")
scanner.Scan()
response := scanner.Text()
if len(response) > 0 {
if strings.ToUpper(response[0:1]) != "N" {
printRules()
}
} else {
printRules()
}
gamesWon := 0
stillRunning := true
for stillRunning {
num := getNumber()
numStr := strings.Join(num, "")
guesses := 1
fmt.Println("\nO.K. I have a number in mind.")
guessing := true
for guessing {
guess := getValidGuess(guesses)
if guess == numStr {
fmt.Println("You got it!!")
gamesWon++
guessing = false
} else {
fmt.Println(buildResultString(num, guess))
guesses++
if guesses > MAXGUESSES {
fmt.Println("Oh well")
fmt.Printf("That's %d guesses. My number was %s\n", MAXGUESSES, numStr)
guessing = false
}
}
}
validRespone := false
for !validRespone {
fmt.Println("Play again (Yes or No)?")
scanner.Scan()
response := scanner.Text()
if len(response) > 0 {
validRespone = true
if strings.ToUpper(response[0:1]) != "Y" {
stillRunning = false
}
}
}
}
if gamesWon > 0 {
fmt.Printf("\nA %d point Bagels buff!!\n", gamesWon)
}
fmt.Println("Hope you had fun. Bye")
}
+248
View File
@@ -0,0 +1,248 @@
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
type StartOption int8
const (
StartUndefined StartOption = iota
ComputerFirst
PlayerFirst
)
type WinOption int8
const (
WinUndefined WinOption = iota
TakeLast
AvoidLast
)
type GameOptions struct {
pileSize int
winOption WinOption
startOption StartOption
minSelect int
maxSelect int
}
func NewOptions() *GameOptions {
g := GameOptions{}
g.pileSize = getPileSize()
if g.pileSize < 0 {
return &g
}
g.winOption = getWinOption()
g.minSelect, g.maxSelect = getMinMax()
g.startOption = getStartOption()
return &g
}
func getPileSize() int {
ps := 0
var err error
scanner := bufio.NewScanner(os.Stdin)
for {
fmt.Println("Enter Pile Size ")
scanner.Scan()
ps, err = strconv.Atoi(scanner.Text())
if err == nil {
break
}
}
return ps
}
func getWinOption() WinOption {
scanner := bufio.NewScanner(os.Stdin)
for {
fmt.Println("ENTER WIN OPTION - 1 TO TAKE LAST, 2 TO AVOID LAST:")
scanner.Scan()
w, err := strconv.Atoi(scanner.Text())
if err == nil && (w == 1 || w == 2) {
return WinOption(w)
}
}
}
func getStartOption() StartOption {
scanner := bufio.NewScanner(os.Stdin)
for {
fmt.Println("ENTER START OPTION - 1 COMPUTER FIRST, 2 YOU FIRST ")
scanner.Scan()
s, err := strconv.Atoi(scanner.Text())
if err == nil && (s == 1 || s == 2) {
return StartOption(s)
}
}
}
func getMinMax() (int, int) {
minSelect := 0
maxSelect := 0
var minErr error
var maxErr error
scanner := bufio.NewScanner(os.Stdin)
for {
fmt.Println("ENTER MIN AND MAX ")
scanner.Scan()
enteredValues := scanner.Text()
vals := strings.Split(enteredValues, " ")
minSelect, minErr = strconv.Atoi(vals[0])
maxSelect, maxErr = strconv.Atoi(vals[1])
if (minErr == nil) && (maxErr == nil) && (minSelect > 0) && (maxSelect > 0) && (maxSelect > minSelect) {
return minSelect, maxSelect
}
}
}
// This handles the player's turn - asking the player how many objects
// to take and doing some basic validation around that input. Then it
// checks for any win conditions.
// Returns a boolean indicating whether the game is over and the new pile_size.
func playerMove(pile, min, max int, win WinOption) (bool, int) {
scanner := bufio.NewScanner(os.Stdin)
done := false
for !done {
fmt.Println("YOUR MOVE")
scanner.Scan()
m, err := strconv.Atoi(scanner.Text())
if err != nil {
continue
}
if m == 0 {
fmt.Println("I TOLD YOU NOT TO USE ZERO! COMPUTER WINS BY FORFEIT.")
return true, pile
}
if m > max || m < min {
fmt.Println("ILLEGAL MOVE, REENTER IT")
continue
}
pile -= m
done = true
if pile <= 0 {
if win == AvoidLast {
fmt.Println("TOUGH LUCK, YOU LOSE.")
} else {
fmt.Println("CONGRATULATIONS, YOU WIN.")
}
return true, pile
}
}
return false, pile
}
// This handles the logic to determine how many objects the computer
// will select on its turn.
func computerPick(pile, min, max int, win WinOption) int {
var q int
if win == AvoidLast {
q = pile - 1
} else {
q = pile
}
c := min + max
pick := q - (c * int(q/c))
if pick < min {
pick = min
} else if pick > max {
pick = max
}
return pick
}
// This handles the computer's turn - first checking for the various
// win/lose conditions and then calculating how many objects
// the computer will take.
// Returns a boolean indicating whether the game is over and the new pile_size.
func computerMove(pile, min, max int, win WinOption) (bool, int) {
// first check for end-game conditions
if win == TakeLast && pile <= max {
fmt.Printf("COMPUTER TAKES %d AND WINS\n", pile)
return true, pile
}
if win == AvoidLast && pile <= min {
fmt.Printf("COMPUTER TAKES %d AND LOSES\n", pile)
return true, pile
}
// otherwise determine the computer's selection
selection := computerPick(pile, min, max, win)
pile -= selection
fmt.Printf("COMPUTER TAKES %d AND LEAVES %d\n", selection, pile)
return false, pile
}
// This is the main game loop - repeating each turn until one
// of the win/lose conditions is met.
func play(pile, min, max int, start StartOption, win WinOption) {
gameOver := false
playersTurn := (start == PlayerFirst)
for !gameOver {
if playersTurn {
gameOver, pile = playerMove(pile, min, max, win)
playersTurn = false
if gameOver {
return
}
}
if !playersTurn {
gameOver, pile = computerMove(pile, min, max, win)
playersTurn = true
}
}
}
// Print out the introduction and rules of the game
func printIntro() {
fmt.Printf("%33s%s\n", " ", "BATNUM")
fmt.Printf("%15s%s\n", " ", "CREATIVE COMPUTING MORRISSTOWN, NEW JERSEY")
fmt.Printf("\n\n\n")
fmt.Println("THIS PROGRAM IS A 'BATTLE OF NUMBERS' GAME, WHERE THE")
fmt.Println("COMPUTER IS YOUR OPPONENT.")
fmt.Println()
fmt.Println("THE GAME STARTS WITH AN ASSUMED PILE OF OBJECTS. YOU")
fmt.Println("AND YOUR OPPONENT ALTERNATELY REMOVE OBJECTS FROM THE PILE.")
fmt.Println("WINNING IS DEFINED IN ADVANCE AS TAKING THE LAST OBJECT OR")
fmt.Println("NOT. YOU CAN ALSO SPECIFY SOME OTHER BEGINNING CONDITIONS.")
fmt.Println("DON'T USE ZERO, HOWEVER, IN PLAYING THE GAME.")
fmt.Println("ENTER A NEGATIVE NUMBER FOR NEW PILE SIZE TO STOP PLAYING.")
fmt.Println()
}
func main() {
for {
printIntro()
g := NewOptions()
if g.pileSize < 0 {
return
}
play(g.pileSize, g.minSelect, g.maxSelect, g.startOption, g.winOption)
}
}
+266
View File
@@ -0,0 +1,266 @@
package main
import (
"bufio"
"fmt"
"math/rand"
"os"
"strconv"
"strings"
"time"
)
const (
SEA_WIDTH = 6
DESTROYER_LENGTH = 2
CRUISER_LENGTH = 3
CARRIER_LENGTH = 4
)
type Point [2]int
type Vector Point
type Sea [][]int
func NewSea() Sea {
s := make(Sea, 6)
for r := 0; r < SEA_WIDTH; r++ {
c := make([]int, 6)
s[r] = c
}
return s
}
func getRandomVector() Vector {
v := Vector{}
for {
v[0] = rand.Intn(3) - 1
v[1] = rand.Intn(3) - 1
if !(v[0] == 0 && v[1] == 0) {
break
}
}
return v
}
func addVector(p Point, v Vector) Point {
newPoint := Point{}
newPoint[0] = p[0] + v[0]
newPoint[1] = p[1] + v[1]
return newPoint
}
func isWithinSea(p Point, s Sea) bool {
return (1 <= p[0] && p[0] <= len(s)) && (1 <= p[1] && p[1] <= len(s))
}
func valueAt(p Point, s Sea) int {
return s[p[1]-1][p[0]-1]
}
func reportInputError() {
fmt.Printf("INVALID. SPECIFY TWO NUMBERS FROM 1 TO %d, SEPARATED BY A COMMA.\n", SEA_WIDTH)
}
func getNextTarget(s Sea) Point {
scanner := bufio.NewScanner(os.Stdin)
for {
fmt.Println("\n?")
scanner.Scan()
vals := strings.Split(scanner.Text(), ",")
if len(vals) != 2 {
reportInputError()
continue
}
x, xErr := strconv.Atoi(strings.TrimSpace(vals[0]))
y, yErr := strconv.Atoi(strings.TrimSpace(vals[1]))
if (len(vals) != 2) || (xErr != nil) || (yErr != nil) {
reportInputError()
continue
}
p := Point{}
p[0] = x
p[1] = y
if isWithinSea(p, s) {
return p
}
}
}
func setValueAt(value int, p Point, s Sea) {
s[p[1]-1][p[0]-1] = value
}
func hasShip(s Sea, code int) bool {
hasShip := false
for r := 0; r < SEA_WIDTH; r++ {
for c := 0; c < SEA_WIDTH; c++ {
if s[r][c] == code {
hasShip = true
break
}
}
}
return hasShip
}
func countSunk(s Sea, codes []int) int {
sunk := 0
for _, c := range codes {
if !hasShip(s, c) {
sunk += 1
}
}
return sunk
}
func placeShip(s Sea, size, code int) {
for {
start := Point{}
start[0] = rand.Intn(SEA_WIDTH) + 1
start[1] = rand.Intn(SEA_WIDTH) + 1
vector := getRandomVector()
point := start
points := []Point{}
for i := 0; i < size; i++ {
point = addVector(point, vector)
points = append(points, point)
}
clearPosition := true
for _, p := range points {
if !isWithinSea(p, s) {
clearPosition = false
break
}
if valueAt(p, s) > 0 {
clearPosition = false
break
}
}
if !clearPosition {
continue
}
for _, p := range points {
setValueAt(code, p, s)
}
break
}
}
func setupShips(s Sea) {
placeShip(s, DESTROYER_LENGTH, 1)
placeShip(s, DESTROYER_LENGTH, 2)
placeShip(s, CRUISER_LENGTH, 3)
placeShip(s, CRUISER_LENGTH, 4)
placeShip(s, CARRIER_LENGTH, 5)
placeShip(s, CARRIER_LENGTH, 6)
}
func printIntro() {
fmt.Println(" BATTLE")
fmt.Println("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY")
fmt.Println()
fmt.Println("THE FOLLOWING CODE OF THE BAD GUYS' FLEET DISPOSITION")
fmt.Println("HAS BEEN CAPTURED BUT NOT DECODED: ")
fmt.Println()
}
func printInstructions() {
fmt.Println()
fmt.Println()
fmt.Println("DE-CODE IT AND USE IT IF YOU CAN")
fmt.Println("BUT KEEP THE DE-CODING METHOD A SECRET.")
fmt.Println()
fmt.Println("START GAME")
}
func printEncodedSea(s Sea) {
for x := 0; x < SEA_WIDTH; x++ {
fmt.Println()
for y := SEA_WIDTH - 1; y > -1; y-- {
fmt.Printf(" %d", s[y][x])
}
}
fmt.Println()
}
func wipeout(s Sea) bool {
for c := 1; c <= 7; c++ {
if hasShip(s, c) {
return false
}
}
return true
}
func main() {
rand.Seed(time.Now().UnixNano())
s := NewSea()
setupShips(s)
printIntro()
printEncodedSea(s)
printInstructions()
splashes := 0
hits := 0
for {
target := getNextTarget(s)
targetValue := valueAt(target, s)
if targetValue < 0 {
fmt.Printf("YOU ALREADY PUT A HOLE IN SHIP NUMBER %d AT THAT POINT.\n", targetValue)
}
if targetValue <= 0 {
fmt.Println("SPLASH! TRY AGAIN.")
splashes += 1
continue
}
fmt.Printf("A DIRECT HIT ON SHIP NUMBER %d\n", targetValue)
hits += 1
setValueAt(targetValue*-1, target, s)
if !hasShip(s, targetValue) {
fmt.Println("AND YOU SUNK IT. HURRAH FOR THE GOOD GUYS.")
fmt.Println("SO FAR, THE BAD GUYS HAVE LOST")
fmt.Printf("%d DESTROYER(S), %d CRUISER(S), AND %d AIRCRAFT CARRIER(S).\n", countSunk(s, []int{1, 2}), countSunk(s, []int{3, 4}), countSunk(s, []int{5, 6}))
}
if !wipeout(s) {
fmt.Printf("YOUR CURRENT SPLASH/HIT RATIO IS %2f\n", float32(splashes)/float32(hits))
continue
}
fmt.Printf("YOU HAVE TOTALLY WIPED OUT THE BAD GUYS' FLEET WITH A FINAL SPLASH/HIT RATIO OF %2f\n", float32(splashes)/float32(hits))
if splashes == 0 {
fmt.Println("CONGRATULATIONS -- A DIRECT HIT EVERY TIME.")
}
fmt.Println("\n****************************")
break
}
}
@@ -0,0 +1,181 @@
package main
import (
"bufio"
"fmt"
"math/rand"
"os"
"strconv"
"strings"
"time"
)
// Messages correspond to outposts remaining (3, 2, 1, 0)
var PLAYER_PROGRESS_MESSAGES = []string{
"YOU GOT ME, I'M GOING FAST. BUT I'LL GET YOU WHEN\nMY TRANSISTO&S RECUP%RA*E!",
"THREE DOWN, ONE TO GO.\n\n",
"TWO DOWN, TWO TO GO.\n\n",
"ONE DOWN, THREE TO GO.\n\n",
}
var ENEMY_PROGRESS_MESSAGES = []string{
"YOU'RE DEAD. YOUR LAST OUTPOST WAS AT %d. HA, HA, HA.\nBETTER LUCK NEXT TIME.",
"YOU HAVE ONLY ONE OUTPOST LEFT.\n\n",
"YOU HAVE ONLY TWO OUTPOSTS LEFT.\n\n",
"YOU HAVE ONLY THREE OUTPOSTS LEFT.\n\n",
}
func displayField() {
for r := 0; r < 5; r++ {
initial := r*5 + 1
for c := 0; c < 5; c++ {
//x := strconv.Itoa(initial + c)
fmt.Printf("\t%d", initial+c)
}
fmt.Println()
}
fmt.Print("\n\n\n\n\n\n\n\n\n")
}
func printIntro() {
fmt.Println(" BOMBARDMENT")
fmt.Println(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY")
fmt.Println()
fmt.Println()
fmt.Println("YOU ARE ON A BATTLEFIELD WITH 4 PLATOONS AND YOU")
fmt.Println("HAVE 25 OUTPOSTS AVAILABLE WHERE THEY MAY BE PLACED.")
fmt.Println("YOU CAN ONLY PLACE ONE PLATOON AT ANY ONE OUTPOST.")
fmt.Println("THE COMPUTER DOES THE SAME WITH ITS FOUR PLATOONS.")
fmt.Println()
fmt.Println("THE OBJECT OF THE GAME IS TO FIRE MISSLES AT THE")
fmt.Println("OUTPOSTS OF THE COMPUTER. IT WILL DO THE SAME TO YOU.")
fmt.Println("THE ONE WHO DESTROYS ALL FOUR OF THE ENEMY'S PLATOONS")
fmt.Println("FIRST IS THE WINNER.")
fmt.Println()
fmt.Println("GOOD LUCK... AND TELL US WHERE YOU WANT THE BODIES SENT!")
fmt.Println()
fmt.Println("TEAR OFF MATRIX AND USE IT TO CHECK OFF THE NUMBERS.")
fmt.Print("\n\n\n\n")
}
func positionList() []int {
positions := make([]int, 25)
for i := 0; i < 25; i++ {
positions[i] = i + 1
}
return positions
}
// Randomly choose 4 'positions' out of a range of 1 to 25
func generateEnemyPositions() []int {
positions := positionList()
rand.Shuffle(len(positions), func(i, j int) { positions[i], positions[j] = positions[j], positions[i] })
return positions[:4]
}
func isValidPosition(p int) bool {
return p >= 1 && p <= 25
}
func promptForPlayerPositions() []int {
scanner := bufio.NewScanner(os.Stdin)
var positions []int
for {
fmt.Println("\nWHAT ARE YOUR FOUR POSITIONS (1-25)?")
scanner.Scan()
rawPositions := strings.Split(scanner.Text(), " ")
if len(rawPositions) != 4 {
fmt.Println("PLEASE ENTER FOUR UNIQUE POSITIONS")
goto there
}
for _, p := range rawPositions {
pos, err := strconv.Atoi(p)
if (err != nil) || !isValidPosition(pos) {
fmt.Println("ALL POSITIONS MUST RANGE (1-25)")
goto there
}
positions = append(positions, pos)
}
if len(positions) == 4 {
return positions
}
there:
}
}
func promptPlayerForTarget() int {
scanner := bufio.NewScanner(os.Stdin)
for {
fmt.Println("\nWHERE DO YOU WISH TO FIRE YOUR MISSILE?")
scanner.Scan()
target, err := strconv.Atoi(scanner.Text())
if (err != nil) || !isValidPosition(target) {
fmt.Println("POSITIONS MUST RANGE (1-25)")
continue
}
return target
}
}
func generateAttackSequence() []int {
positions := positionList()
rand.Shuffle(len(positions), func(i, j int) { positions[i], positions[j] = positions[j], positions[i] })
return positions
}
// Performs attack procedure returning True if we are to continue.
func attack(target int, positions *[]int, hitMsg, missMsg string, progressMsg []string) bool {
for i := 0; i < len(*positions); i++ {
if target == (*positions)[i] {
fmt.Print(hitMsg)
// remove the target just hit
(*positions)[i] = (*positions)[len((*positions))-1]
(*positions)[len((*positions))-1] = 0
(*positions) = (*positions)[:len((*positions))-1]
if len((*positions)) != 0 {
fmt.Print(progressMsg[len((*positions))])
} else {
fmt.Printf(progressMsg[len((*positions))], target)
}
return len((*positions)) > 0
}
}
fmt.Print(missMsg)
return len((*positions)) > 0
}
func main() {
rand.Seed(time.Now().UnixNano())
printIntro()
displayField()
enemyPositions := generateEnemyPositions()
enemyAttacks := generateAttackSequence()
enemyAttackCounter := 0
playerPositions := promptForPlayerPositions()
for {
// player attacks
if !attack(promptPlayerForTarget(), &enemyPositions, "YOU GOT ONE OF MY OUTPOSTS!\n\n", "HA, HA YOU MISSED. MY TURN NOW:\n\n", PLAYER_PROGRESS_MESSAGES) {
break
}
// computer attacks
hitMsg := fmt.Sprintf("I GOT YOU. IT WON'T BE LONG NOW. POST %d WAS HIT.\n", enemyAttacks[enemyAttackCounter])
missMsg := fmt.Sprintf("I MISSED YOU, YOU DIRTY RAT. I PICKED %d. YOUR TURN:\n\n", enemyAttacks[enemyAttackCounter])
if !attack(enemyAttacks[enemyAttackCounter], &playerPositions, hitMsg, missMsg, ENEMY_PROGRESS_MESSAGES) {
break
}
enemyAttackCounter += 1
}
}
@@ -0,0 +1,188 @@
package main
import (
"bufio"
"fmt"
"math/rand"
"os"
"strconv"
"strings"
"time"
)
type Choice struct {
idx string
msg string
}
func playerSurvived() {
fmt.Println("YOU MADE IT THROUGH TREMENDOUS FLAK!!")
}
func playerDeath() {
fmt.Println("* * * * BOOM * * * *")
fmt.Println("YOU HAVE BEEN SHOT DOWN.....")
fmt.Println("DEARLY BELOVED, WE ARE GATHERED HERE TODAY TO PAY OUR")
fmt.Println("LAST TRIBUTE...")
}
func missionSuccess() {
fmt.Printf("DIRECT HIT!!!! %d KILLED.\n", int(100*rand.Int()))
fmt.Println("MISSION SUCCESSFUL.")
}
// Takes a float between 0 and 1 and returns a boolean
// if the player has survived (based on random chance)
// Returns True if death, False if survived
func deathWithChance(probability float64) bool {
return probability > rand.Float64()
}
func startNonKamikaziAttack() {
numMissions := getIntInput("HOW MANY MISSIONS HAVE YOU FLOWN? ")
for numMissions > 160 {
fmt.Println("MISSIONS, NOT MILES...")
fmt.Println("150 MISSIONS IS HIGH EVEN FOR OLD-TIMERS")
numMissions = getIntInput("HOW MANY MISSIONS HAVE YOU FLOWN? ")
}
if numMissions > 100 {
fmt.Println("THAT'S PUSHING THE ODDS!")
}
if numMissions < 25 {
fmt.Println("FRESH OUT OF TRAINING, EH?")
}
fmt.Println()
if float32(numMissions) > (160 * rand.Float32()) {
missionSuccess()
} else {
missionFailure()
}
}
func missionFailure() {
fmt.Printf("MISSED TARGET BY %d MILES!\n", int(2+30*rand.Float32()))
fmt.Println("NOW YOU'RE REALLY IN FOR IT !!")
fmt.Println()
enemyWeapons := getInputFromList("DOES THE ENEMY HAVE GUNS(1), MISSILES(2), OR BOTH(3)? ", []Choice{{idx: "1", msg: "GUNS"}, {idx: "2", msg: "MISSILES"}, {idx: "3", msg: "BOTH"}})
// If there are no gunners (i.e. weapon choice 2) then
// we say that the gunners have 0 accuracy for the purposes
// of calculating probability of player death
enemyGunnerAccuracy := 0.0
if enemyWeapons.idx != "2" {
enemyGunnerAccuracy = float64(getIntInput("WHAT'S THE PERCENT HIT RATE OF ENEMY GUNNERS (10 TO 50)? "))
if enemyGunnerAccuracy < 10.0 {
fmt.Println("YOU LIE, BUT YOU'LL PAY...")
playerDeath()
}
}
missileThreatWeighting := 35.0
if enemyWeapons.idx == "1" {
missileThreatWeighting = 0
}
death := deathWithChance((enemyGunnerAccuracy + missileThreatWeighting) / 100)
if death {
playerDeath()
} else {
playerSurvived()
}
}
func playItaly() {
targets := []Choice{{idx: "1", msg: "SHOULD BE EASY -- YOU'RE FLYING A NAZI-MADE PLANE."}, {idx: "2", msg: "BE CAREFUL!!!"}, {idx: "3", msg: "YOU'RE GOING FOR THE OIL, EH?"}}
target := getInputFromList("YOUR TARGET -- ALBANIA(1), GREECE(2), NORTH AFRICA(3)", targets)
fmt.Println(target.msg)
startNonKamikaziAttack()
}
func playAllies() {
aircraftMessages := []Choice{{idx: "1", msg: "YOU'VE GOT 2 TONS OF BOMBS FLYING FOR PLOESTI."}, {idx: "2", msg: "YOU'RE DUMPING THE A-BOMB ON HIROSHIMA."}, {idx: "3", msg: "YOU'RE CHASING THE BISMARK IN THE NORTH SEA."}, {idx: "4", msg: "YOU'RE BUSTING A GERMAN HEAVY WATER PLANT IN THE RUHR."}}
aircraft := getInputFromList("AIRCRAFT -- LIBERATOR(1), B-29(2), B-17(3), LANCASTER(4): ", aircraftMessages)
fmt.Println(aircraft.msg)
startNonKamikaziAttack()
}
func playJapan() {
acknowledgeMessage := []Choice{{idx: "Y", msg: "Y"}, {idx: "N", msg: "N"}}
firstMission := getInputFromList("YOU'RE FLYING A KAMIKAZE MISSION OVER THE USS LEXINGTON.\nYOUR FIRST KAMIKAZE MISSION? (Y OR N): ", acknowledgeMessage)
if firstMission.msg == "N" {
playerDeath()
}
if rand.Float64() > 0.65 {
missionSuccess()
} else {
playerDeath()
}
}
func playGermany() {
targets := []Choice{{idx: "1", msg: "YOU'RE NEARING STALINGRAD."}, {idx: "2", msg: "NEARING LONDON. BE CAREFUL, THEY'VE GOT RADAR."}, {idx: "3", msg: "NEARING VERSAILLES. DUCK SOUP. THEY'RE NEARLY DEFENSELESS."}}
target := getInputFromList("A NAZI, EH? OH WELL. ARE YOU GOING FOR RUSSIA(1),\nENGLAND(2), OR FRANCE(3)? ", targets)
fmt.Println(target.msg)
startNonKamikaziAttack()
}
func playGame() {
fmt.Println("YOU ARE A PILOT IN A WORLD WAR II BOMBER.")
side := getInputFromList("WHAT SIDE -- ITALY(1), ALLIES(2), JAPAN(3), GERMANY(4): ", []Choice{{idx: "1", msg: "ITALY"}, {idx: "2", msg: "ALLIES"}, {idx: "3", msg: "JAPAN"}, {idx: "4", msg: "GERMANY"}})
switch side.idx {
case "1":
playItaly()
case "2":
playAllies()
case "3":
playJapan()
case "4":
playGermany()
}
}
func main() {
rand.Seed(time.Now().UnixNano())
for {
playGame()
if getInputFromList("ANOTHER MISSION (Y OR N):", []Choice{{idx: "Y", msg: "Y"}, {idx: "N", msg: "N"}}).msg == "N" {
break
}
}
}
func getInputFromList(prompt string, choices []Choice) Choice {
scanner := bufio.NewScanner(os.Stdin)
for {
fmt.Println(prompt)
scanner.Scan()
choice := scanner.Text()
for _, c := range choices {
if strings.EqualFold(strings.ToUpper(choice), strings.ToUpper(c.idx)) {
return c
}
}
fmt.Println("TRY AGAIN...")
}
}
func getIntInput(prompt string) int {
scanner := bufio.NewScanner(os.Stdin)
for {
fmt.Println(prompt)
scanner.Scan()
choice, err := strconv.Atoi(scanner.Text())
if err != nil {
fmt.Println("TRY AGAIN...")
continue
} else {
return choice
}
}
}
@@ -0,0 +1,91 @@
package main
import (
"bufio"
"fmt"
"math/rand"
"os"
"strings"
"time"
)
func main() {
rand.Seed(time.Now().UnixNano())
words := [][]string{
{
"Ability",
"Basal",
"Behavioral",
"Child-centered",
"Differentiated",
"Discovery",
"Flexible",
"Heterogeneous",
"Homogenous",
"Manipulative",
"Modular",
"Tavistock",
"Individualized",
}, {
"learning",
"evaluative",
"objective",
"cognitive",
"enrichment",
"scheduling",
"humanistic",
"integrated",
"non-graded",
"training",
"vertical age",
"motivational",
"creative",
}, {
"grouping",
"modification",
"accountability",
"process",
"core curriculum",
"algorithm",
"performance",
"reinforcement",
"open classroom",
"resource",
"structure",
"facility",
"environment",
},
}
scanner := bufio.NewScanner(os.Stdin)
// Display intro text
fmt.Println("\n Buzzword Generator")
fmt.Println("Creative Computing Morristown, New Jersey")
fmt.Println("\n\n")
fmt.Println("This program prints highly acceptable phrases in")
fmt.Println("'educator-speak' that you can work into reports")
fmt.Println("and speeches. Whenever a question mark is printed,")
fmt.Println("type a 'Y' for another phrase or 'N' to quit.")
fmt.Println("\n\nHere's the first phrase:")
for {
phrase := ""
for _, section := range words {
if len(phrase) > 0 {
phrase += " "
}
phrase += section[rand.Intn(len(section))]
}
fmt.Println(phrase)
fmt.Println()
// continue?
fmt.Println("?")
scanner.Scan()
if strings.ToUpper(scanner.Text())[0:1] != "Y" {
break
}
}
fmt.Println("Come back when you need help with another report!")
}
+115
View File
@@ -0,0 +1,115 @@
package main
import (
"bufio"
"fmt"
"math"
"os"
"strconv"
)
func printWelcome() {
fmt.Println(" CHANGE")
fmt.Println("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY")
fmt.Println()
fmt.Println()
fmt.Println()
fmt.Println("I, YOUR FRIENDLY MICROCOMPUTER, WILL DETERMINE")
fmt.Println("THE CORRECT CHANGE FOR ITEMS COSTING UP TO $100.")
fmt.Println()
}
func computeChange(cost, payment float64) {
change := int(math.Round((payment - cost) * 100))
if change == 0 {
fmt.Println("\nCORRECT AMOUNT, THANK YOU.")
return
}
if change < 0 {
fmt.Printf("\nSORRY, YOU HAVE SHORT-CHANGED ME $%0.2f\n", float64(change)/-100.0)
print()
return
}
fmt.Printf("\nYOUR CHANGE, $%0.2f:\n", float64(change)/100.0)
d := change / 1000
if d > 0 {
fmt.Printf(" %d TEN DOLLAR BILL(S)\n", d)
change -= d * 1000
}
d = change / 500
if d > 0 {
fmt.Printf(" %d FIVE DOLLAR BILL(S)\n", d)
change -= d * 500
}
d = change / 100
if d > 0 {
fmt.Printf(" %d ONE DOLLAR BILL(S)\n", d)
change -= d * 100
}
d = change / 50
if d > 0 {
fmt.Println(" 1 HALF DOLLAR")
change -= d * 50
}
d = change / 25
if d > 0 {
fmt.Printf(" %d QUARTER(S)\n", d)
change -= d * 25
}
d = change / 10
if d > 0 {
fmt.Printf(" %d DIME(S)\n", d)
change -= d * 10
}
d = change / 5
if d > 0 {
fmt.Printf(" %d NICKEL(S)\n", d)
change -= d * 5
}
if change > 0 {
fmt.Printf(" %d PENNY(S)\n", change)
}
}
func main() {
scanner := bufio.NewScanner(os.Stdin)
printWelcome()
var cost, payment float64
var err error
for {
fmt.Println("COST OF ITEM?")
scanner.Scan()
cost, err = strconv.ParseFloat(scanner.Text(), 64)
if err != nil || cost < 0.0 {
fmt.Println("INVALID INPUT. TRY AGAIN.")
continue
}
break
}
for {
fmt.Println("\nAMOUNT OF PAYMENT?")
scanner.Scan()
payment, err = strconv.ParseFloat(scanner.Text(), 64)
if err != nil {
fmt.Println("INVALID INPUT. TRY AGAIN.")
continue
}
break
}
computeChange(cost, payment)
fmt.Println()
}
+116
View File
@@ -0,0 +1,116 @@
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func printLightning() {
fmt.Println("************************************")
n := 24
for n > 16 {
var b strings.Builder
b.Grow(n + 3)
for i := 0; i < n; i++ {
b.WriteString(" ")
}
b.WriteString("x x")
fmt.Println(b.String())
n--
}
fmt.Println(" x xxx")
fmt.Println(" x x")
fmt.Println(" xx xx")
n--
for n > 8 {
var b strings.Builder
b.Grow(n + 3)
for i := 0; i < n; i++ {
b.WriteString(" ")
}
b.WriteString("x x")
fmt.Println(b.String())
n--
}
fmt.Println(" xx")
fmt.Println(" x")
fmt.Println("************************************")
}
func printSolution(n float64) {
fmt.Printf("\n%f plus 3 gives %f. This divided by 5 equals %f\n", n, n+3, (n+3)/5)
fmt.Printf("This times 8 gives %f. If we divide 5 and add 5.\n", ((n+3)/5)*8)
fmt.Printf("We get %f, which, minus 1 equals %f\n", (((n+3)/5)*8)/5+5, ((((n+3)/5)*8)/5+5)-1)
}
func play() {
fmt.Println("\nTake a Number and ADD 3. Now, Divide this number by 5 and")
fmt.Println("multiply by 8. Now, Divide by 5 and add the same. Subtract 1")
youHave := getFloat("\nWhat do you have?")
compGuess := (((youHave-4)*5)/8)*5 - 3
if getYesNo(fmt.Sprintf("\nI bet your number was %f was I right(Yes or No)? ", compGuess)) {
fmt.Println("\nHuh, I knew I was unbeatable")
fmt.Println("And here is how i did it")
printSolution(compGuess)
} else {
originalNumber := getFloat("\nHUH!! what was you original number? ")
if originalNumber == compGuess {
fmt.Println("\nThat was my guess, AHA i was right")
fmt.Println("Shamed to accept defeat i guess, don't worry you can master mathematics too")
fmt.Println("Here is how i did it")
printSolution(compGuess)
} else {
fmt.Println("\nSo you think you're so smart, EH?")
fmt.Println("Now, Watch")
printSolution(originalNumber)
if getYesNo("\nNow do you believe me? ") {
print("\nOk, Lets play again sometime bye!!!!")
} else {
fmt.Println("\nYOU HAVE MADE ME VERY MAD!!!!!")
fmt.Println("BY THE WRATH OF THE MATHEMATICS AND THE RAGE OF THE GODS")
fmt.Println("THERE SHALL BE LIGHTNING!!!!!!!")
printLightning()
fmt.Println("\nI Hope you believe me now, for your own sake")
}
}
}
}
func getFloat(prompt string) float64 {
scanner := bufio.NewScanner(os.Stdin)
for {
fmt.Println(prompt)
scanner.Scan()
val, err := strconv.ParseFloat(scanner.Text(), 64)
if err != nil {
fmt.Println("INVALID INPUT, TRY AGAIN")
continue
}
return val
}
}
func getYesNo(prompt string) bool {
scanner := bufio.NewScanner(os.Stdin)
fmt.Println(prompt)
scanner.Scan()
return (strings.ToUpper(scanner.Text())[0:1] == "Y")
}
func main() {
fmt.Println("I am CHIEF NUMBERS FREEK, The GREAT INDIAN MATH GOD.")
if getYesNo("\nAre you ready to take the test you called me out for(Yes or No)? ") {
play()
} else {
fmt.Println("Ok, Nevermind. Let me go back to my great slumber, Bye")
}
}
@@ -0,0 +1,156 @@
package main
import (
"bufio"
"fmt"
"math"
"math/rand"
"os"
"strconv"
"strings"
"time"
)
type Position []int
func NewPosition() Position {
p := make([]int, 3)
return Position(p)
}
func showWelcome() {
fmt.Print("\033[H\033[2J")
fmt.Println(" DEPTH CHARGE")
fmt.Println(" Creative Computing Morristown, New Jersey")
fmt.Println()
}
func getNumCharges() (int, int) {
scanner := bufio.NewScanner(os.Stdin)
for {
fmt.Println("Dimensions of search area?")
scanner.Scan()
dim, err := strconv.Atoi(scanner.Text())
if err != nil {
fmt.Println("Must enter an integer number. Please try again...")
continue
}
return dim, int(math.Log2(float64(dim))) + 1
}
}
func askForNewGame() {
scanner := bufio.NewScanner(os.Stdin)
fmt.Println("Another game (Y or N): ")
scanner.Scan()
if strings.ToUpper(scanner.Text()) == "Y" {
main()
}
fmt.Println("OK. Hope you enjoyed yourself")
os.Exit(1)
}
func showShotResult(shot, location Position) {
result := "Sonar reports shot was "
if shot[1] > location[1] { // y-direction
result += "north"
} else if shot[1] < location[1] { // y-direction
result += "south"
}
if shot[0] > location[0] { // x-direction
result += "east"
} else if shot[0] < location[0] { // x-direction
result += "west"
}
if shot[1] != location[1] || shot[0] != location[0] {
result += " and "
}
if shot[2] > location[2] {
result += "too low."
} else if shot[2] < location[2] {
result += "too high."
} else {
result += "depth OK."
}
fmt.Println(result)
}
func getShot() Position {
scanner := bufio.NewScanner(os.Stdin)
for {
shotPos := NewPosition()
fmt.Println("Enter coordinates: ")
scanner.Scan()
rawGuess := strings.Split(scanner.Text(), " ")
if len(rawGuess) != 3 {
goto there
}
for i := 0; i < 3; i++ {
val, err := strconv.Atoi(rawGuess[i])
if err != nil {
goto there
}
shotPos[i] = val
}
return shotPos
there:
fmt.Println("Please enter coordinates separated by spaces")
fmt.Println("Example: 3 2 1")
}
}
func getRandomPosition(searchArea int) Position {
pos := NewPosition()
for i := 0; i < 3; i++ {
pos[i] = rand.Intn(searchArea)
}
return pos
}
func playGame(searchArea, numCharges int) {
rand.Seed(time.Now().UTC().UnixNano())
fmt.Println("\nYou are the captain of the destroyer USS Computer.")
fmt.Println("An enemy sub has been causing you trouble. Your")
fmt.Printf("mission is to destroy it. You have %d shots.\n", numCharges)
fmt.Println("Specify depth charge explosion point with a")
fmt.Println("trio of numbers -- the first two are the")
fmt.Println("surface coordinates; the third is the depth.")
fmt.Println("\nGood luck!")
fmt.Println()
subPos := getRandomPosition(searchArea)
for c := 0; c < numCharges; c++ {
fmt.Printf("\nTrial #%d\n", c+1)
shot := getShot()
if shot[0] == subPos[0] && shot[1] == subPos[1] && shot[2] == subPos[2] {
fmt.Printf("\nB O O M ! ! You found it in %d tries!\n", c+1)
askForNewGame()
} else {
showShotResult(shot, subPos)
}
}
// out of depth charges
fmt.Println("\nYou have been torpedoed! Abandon ship!")
fmt.Printf("The submarine was at %d %d %d\n", subPos[0], subPos[1], subPos[2])
askForNewGame()
}
func main() {
showWelcome()
searchArea, numCharges := getNumCharges()
playGame(searchArea, numCharges)
}
@@ -0,0 +1,75 @@
#=
Port of Dice from BASIC Computer Games (1978)
This "game" simulates a given number of dice rolls, and returns the
count for each possible total.
The only change that has been made from the original program, is that
when asking if the user wants to play again, any string starting with
y or Y will be accepted, instead of only YES.
=#
function main()
# Array to store the counts for each total.
# There are 11 possible totals.
counts = [0 for i in 1:11]
# Print intro text
println("\n Dice")
println("Creative Computing Morristown, New Jersey")
println("\n\n")
println("This program simulates the rolling of a")
println("pair of dice.")
println("You enter the number of times you want the computer to")
println("'roll' the dice. Watch out, very large numbers take")
println("a long time. In particular, numbers over 5000.")
still_playing = true
while still_playing
println()
print("How many rolls? ")
# Get user input for number of dice rolls
rolls = readline()
rolls = parse(Int64, rolls)
# Roll dice the specified number of times and update total count
for _ in 1:rolls
dice_roll = rand(1:6, 2)
dice_sum = sum(dice_roll)
# The index is one less than the sum, as a sum of 1 is impossible,
# the array will only have 11 values
counts[dice_sum-1] += 1
end
# Display results
println("\nTotal Spots Number of Times")
for i in 1:8
print(" ")
print(i+1)
print(" ")
println(counts[i])
end
for i in 9:11
print(" ")
print(i+1)
print(" ")
println(counts[i])
end
# Ask try again
print("\nTry Again? ")
input = readline()
if length(input) > 0 && uppercase(input)[1] == 'Y'
# If game is continued, resets total counts
counts = [0 for i in 1:11]
else
still_playing = false
end
end
end
if abspath(PROGRAM_FILE) == @__FILE__
main()
end
@@ -0,0 +1,3 @@
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
Conversion to [Python](https://www.julialang.org/)
+64
View File
@@ -0,0 +1,64 @@
package main
import (
"bufio"
"fmt"
"math/rand"
"os"
"strconv"
"strings"
)
func printWelcome() {
fmt.Println("\n Dice")
fmt.Println("Creative Computing Morristown, New Jersey")
fmt.Println()
fmt.Println()
fmt.Println("This program simulates the rolling of a")
fmt.Println("pair of dice.")
fmt.Println("You enter the number of times you want the computer to")
fmt.Println("'roll' the dice. Watch out, very large numbers take")
fmt.Println("a long time. In particular, numbers over 5000.")
fmt.Println()
}
func main() {
printWelcome()
scanner := bufio.NewScanner(os.Stdin)
for {
fmt.Println("\nHow many rolls? ")
scanner.Scan()
numRolls, err := strconv.Atoi(scanner.Text())
if err != nil {
fmt.Println("Invalid input, try again...")
continue
}
// We'll track counts of roll outcomes in a 13-element list.
// The first two indices (0 & 1) are ignored, leaving just
// the indices that match the roll values (2 through 12).
results := make([]int, 13)
for n := 0; n < numRolls; n++ {
d1 := rand.Intn(6) + 1
d2 := rand.Intn(6) + 1
results[d1+d2] += 1
}
// Display final results
fmt.Println("\nTotal Spots Number of Times")
for i := 2; i < 13; i++ {
fmt.Printf(" %-14d%d\n", i, results[i])
}
fmt.Println("\nTry again? ")
scanner.Scan()
if strings.ToUpper(scanner.Text()) == "Y" {
continue
} else {
os.Exit(1)
}
}
}
+171
View File
@@ -0,0 +1,171 @@
package main
import (
"bufio"
"fmt"
"math/rand"
"os"
"strconv"
"time"
)
func printIntro() {
fmt.Println(" DIGITS")
fmt.Println(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY")
fmt.Println()
fmt.Println()
fmt.Println("THIS IS A GAME OF GUESSING.")
}
func readInteger(prompt string) int {
scanner := bufio.NewScanner(os.Stdin)
for {
fmt.Println(prompt)
scanner.Scan()
response, err := strconv.Atoi(scanner.Text())
if err != nil {
fmt.Println("INVALID INPUT, TRY AGAIN... ")
continue
}
return response
}
}
func printInstructions() {
fmt.Println()
fmt.Println("PLEASE TAKE A PIECE OF PAPER AND WRITE DOWN")
fmt.Println("THE DIGITS '0', '1', OR '2' THIRTY TIMES AT RANDOM.")
fmt.Println("ARRANGE THEM IN THREE LINES OF TEN DIGITS EACH.")
fmt.Println("I WILL ASK FOR THEN TEN AT A TIME.")
fmt.Println("I WILL ALWAYS GUESS THEM FIRST AND THEN LOOK AT YOUR")
fmt.Println("NEXT NUMBER TO SEE IF I WAS RIGHT. BY PURE LUCK,")
fmt.Println("I OUGHT TO BE RIGHT TEN TIMES. BUT I HOPE TO DO BETTER")
fmt.Println("THAN THAT *****")
fmt.Println()
}
func readTenNumbers() []int {
numbers := make([]int, 10)
numbers[0] = readInteger("FIRST NUMBER: ")
for i := 1; i < 10; i++ {
numbers[i] = readInteger("NEXT NUMBER:")
}
return numbers
}
func printSummary(correct int) {
fmt.Println()
if correct > 10 {
fmt.Println()
fmt.Println("I GUESSED MORE THAN 1/3 OF YOUR NUMBERS.")
fmt.Println("I WIN.\u0007")
} else if correct < 10 {
fmt.Println("I GUESSED LESS THAN 1/3 OF YOUR NUMBERS.")
fmt.Println("YOU BEAT ME. CONGRATULATIONS *****")
} else {
fmt.Println("I GUESSED EXACTLY 1/3 OF YOUR NUMBERS.")
fmt.Println("IT'S A TIE GAME.")
}
}
func buildArray(val, row, col int) [][]int {
a := make([][]int, row)
for r := 0; r < row; r++ {
b := make([]int, col)
for c := 0; c < col; c++ {
b[c] = val
}
a[r] = b
}
return a
}
func main() {
rand.Seed(time.Now().UnixNano())
printIntro()
if readInteger("FOR INSTRUCTIONS, TYPE '1', ELSE TYPE '0' ? ") == 1 {
printInstructions()
}
a := 0
b := 1
c := 3
m := buildArray(1, 27, 3)
k := buildArray(9, 3, 3)
l := buildArray(3, 9, 3)
for {
l[0][0] = 2
l[4][1] = 2
l[8][2] = 2
z := float64(26)
z1 := float64(8)
z2 := 2
runningCorrect := 0
var numbers []int
for round := 1; round <= 4; round++ {
validNumbers := false
for !validNumbers {
numbers = readTenNumbers()
validNumbers = true
for _, n := range numbers {
if n < 0 || n > 2 {
fmt.Println("ONLY USE THE DIGITS '0', '1', OR '2'.")
fmt.Println("LET'S TRY AGAIN.")
validNumbers = false
break
}
}
}
fmt.Printf("\n%-14s%-14s%-14s%-14s\n", "MY GUESS", "YOUR NO.", "RESULT", "NO. RIGHT")
for _, n := range numbers {
s := 0
myGuess := 0
for j := 0; j < 3; j++ {
s1 := a*k[z2][j] + b*l[int(z1)][j] + c*m[int(z)][j]
if s < s1 {
s = s1
myGuess = j
} else if s1 == s && rand.Float64() > 0.5 {
myGuess = j
}
}
result := ""
if myGuess != n {
result = "WRONG"
} else {
runningCorrect += 1
result = "RIGHT"
m[int(z)][n] = m[int(z)][n] + 1
l[int(z1)][n] = l[int(z1)][n] + 1
k[int(z2)][n] = k[int(z2)][n] + 1
z = z - (z/9)*9
z = 3.0*z + float64(n)
}
fmt.Printf("\n%-14d%-14d%-14s%-14d\n", myGuess, n, result, runningCorrect)
z1 = z - (z/9)*9
z2 = n
}
printSummary(runningCorrect)
if readInteger("\nDO YOU WANT TO TRY AGAIN (1 FOR YES, 0 FOR NO) ? ") != 1 {
fmt.Println("\nTHANKS FOR THE GAME.")
os.Exit(0)
}
}
}
}
@@ -0,0 +1,197 @@
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
const MAXTAKE = 4
type PlayerType int8
const (
HUMAN PlayerType = iota
COMPUTER
)
type Game struct {
table int
human int
computer int
}
func NewGame() Game {
g := Game{}
g.table = 27
return g
}
func printIntro() {
fmt.Println("Welcome to Even Wins!")
fmt.Println("Based on evenwins.bas from Creative Computing")
fmt.Println()
fmt.Println("Even Wins is a two-person game. You start with")
fmt.Println("27 marbles in the middle of the table.")
fmt.Println()
fmt.Println("Players alternate taking marbles from the middle.")
fmt.Println("A player can take 1 to 4 marbles on their turn, and")
fmt.Println("turns cannot be skipped. The game ends when there are")
fmt.Println("no marbles left, and the winner is the one with an even")
fmt.Println("number of marbles.")
fmt.Println()
}
func (g *Game) printBoard() {
fmt.Println()
fmt.Printf(" marbles in the middle: %d\n", g.table)
fmt.Printf(" # marbles you have: %d\n", g.human)
fmt.Printf("# marbles computer has: %d\n", g.computer)
fmt.Println()
}
func (g *Game) gameOver() {
fmt.Println()
fmt.Println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
fmt.Println("!! All the marbles are taken: Game Over!")
fmt.Println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
fmt.Println()
g.printBoard()
if g.human%2 == 0 {
fmt.Println("You are the winner! Congratulations!")
} else {
fmt.Println("The computer wins: all hail mighty silicon!")
}
fmt.Println()
}
func getPlural(count int) string {
m := "marble"
if count > 1 {
m += "s"
}
return m
}
func (g *Game) humanTurn() {
scanner := bufio.NewScanner(os.Stdin)
maxAvailable := MAXTAKE
if g.table < MAXTAKE {
maxAvailable = g.table
}
fmt.Println("It's your turn!")
for {
fmt.Printf("Marbles to take? (1 - %d) --> ", maxAvailable)
scanner.Scan()
n, err := strconv.Atoi(scanner.Text())
if err != nil {
fmt.Printf("\n Please enter a whole number from 1 to %d\n", maxAvailable)
continue
}
if n < 1 {
fmt.Println("\n You must take at least 1 marble!")
continue
}
if n > maxAvailable {
fmt.Printf("\n You can take at most %d %s\n", maxAvailable, getPlural(maxAvailable))
continue
}
fmt.Printf("\nOkay, taking %d %s ...\n", n, getPlural(n))
g.table -= n
g.human += n
return
}
}
func (g *Game) computerTurn() {
marblesToTake := 0
fmt.Println("It's the computer's turn ...")
r := float64(g.table - 6*int((g.table)/6))
if int(g.human/2) == g.human/2 {
if r < 1.5 || r > 5.3 {
marblesToTake = 1
} else {
marblesToTake = int(r - 1)
}
} else if float64(g.table) < 4.2 {
marblesToTake = 4
} else if r > 3.4 {
if r < 4.7 || r > 3.5 {
marblesToTake = 4
}
} else {
marblesToTake = int(r + 1)
}
fmt.Printf("Computer takes %d %s ...\n", marblesToTake, getPlural(marblesToTake))
g.table -= marblesToTake
g.computer += marblesToTake
}
func (g *Game) play(playersTurn PlayerType) {
g.printBoard()
for {
if g.table == 0 {
g.gameOver()
return
} else if playersTurn == HUMAN {
g.humanTurn()
g.printBoard()
playersTurn = COMPUTER
} else {
g.computerTurn()
g.printBoard()
playersTurn = HUMAN
}
}
}
func getFirstPlayer() PlayerType {
scanner := bufio.NewScanner(os.Stdin)
for {
fmt.Println("Do you want to play first? (y/n) --> ")
scanner.Scan()
if strings.ToUpper(scanner.Text()) == "Y" {
return HUMAN
} else if strings.ToUpper(scanner.Text()) == "N" {
return COMPUTER
} else {
fmt.Println()
fmt.Println("Please enter 'y' if you want to play first,")
fmt.Println("or 'n' if you want to play second.")
fmt.Println()
}
}
}
func main() {
scanner := bufio.NewScanner(os.Stdin)
printIntro()
for {
g := NewGame()
g.play(getFirstPlayer())
fmt.Println("\nWould you like to play again? (y/n) --> ")
scanner.Scan()
if strings.ToUpper(scanner.Text()) == "Y" {
fmt.Println("\nOk, let's play again ...")
} else {
fmt.Println("\nOk, thanks for playing ... goodbye!")
return
}
}
}
@@ -0,0 +1,326 @@
package main
import (
"bufio"
"fmt"
"log"
"math/rand"
"os"
"strconv"
"strings"
"time"
)
const (
MAXFURS = 190
STARTFUNDS = 600
)
type Fur int8
const (
FUR_MINK Fur = iota
FUR_BEAVER
FUR_ERMINE
FUR_FOX
)
type Fort int8
const (
FORT_MONTREAL Fort = iota
FORT_QUEBEC
FORT_NEWYORK
)
type GameState int8
const (
STARTING GameState = iota
TRADING
CHOOSINGFORT
TRAVELLING
)
func FURS() []string {
return []string{"MINK", "BEAVER", "ERMINE", "FOX"}
}
func FORTS() []string {
return []string{"HOCHELAGA (MONTREAL)", "STADACONA (QUEBEC)", "NEW YORK"}
}
type Player struct {
funds float32
furs []int
}
func NewPlayer() Player {
p := Player{}
p.funds = STARTFUNDS
p.furs = make([]int, 4)
return p
}
func (p *Player) totalFurs() int {
f := 0
for _, v := range p.furs {
f += v
}
return f
}
func (p *Player) lostFurs() {
for f := 0; f < len(p.furs); f++ {
p.furs[f] = 0
}
}
func printTitle() {
fmt.Println(" FUR TRADER")
fmt.Println(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY")
fmt.Println()
fmt.Println()
fmt.Println()
}
func printIntro() {
fmt.Println("YOU ARE THE LEADER OF A FRENCH FUR TRADING EXPEDITION IN ")
fmt.Println("1776 LEAVING THE LAKE ONTARIO AREA TO SELL FURS AND GET")
fmt.Println("SUPPLIES FOR THE NEXT YEAR. YOU HAVE A CHOICE OF THREE")
fmt.Println("FORTS AT WHICH YOU MAY TRADE. THE COST OF SUPPLIES")
fmt.Println("AND THE AMOUNT YOU RECEIVE FOR YOUR FURS WILL DEPEND")
fmt.Println("ON THE FORT THAT YOU CHOOSE.")
fmt.Println()
}
func getFortChoice() Fort {
scanner := bufio.NewScanner(os.Stdin)
for {
fmt.Println()
fmt.Println("YOU MAY TRADE YOUR FURS AT FORT 1, FORT 2,")
fmt.Println("OR FORT 3. FORT 1 IS FORT HOCHELAGA (MONTREAL)")
fmt.Println("AND IS UNDER THE PROTECTION OF THE FRENCH ARMY.")
fmt.Println("FORT 2 IS FORT STADACONA (QUEBEC) AND IS UNDER THE")
fmt.Println("PROTECTION OF THE FRENCH ARMY. HOWEVER, YOU MUST")
fmt.Println("MAKE A PORTAGE AND CROSS THE LACHINE RAPIDS.")
fmt.Println("FORT 3 IS FORT NEW YORK AND IS UNDER DUTCH CONTROL.")
fmt.Println("YOU MUST CROSS THROUGH IROQUOIS LAND.")
fmt.Println("ANSWER 1, 2, OR 3.")
fmt.Print(">> ")
scanner.Scan()
f, err := strconv.Atoi(scanner.Text())
if err != nil || f < 1 || f > 3 {
fmt.Println("Invalid input, Try again ... ")
continue
}
return Fort(f)
}
}
func printFortComment(f Fort) {
fmt.Println()
switch f {
case FORT_MONTREAL:
fmt.Println("YOU HAVE CHOSEN THE EASIEST ROUTE. HOWEVER, THE FORT")
fmt.Println("IS FAR FROM ANY SEAPORT. THE VALUE")
fmt.Println("YOU RECEIVE FOR YOUR FURS WILL BE LOW AND THE COST")
fmt.Println("OF SUPPLIES HIGHER THAN AT FORTS STADACONA OR NEW YORK.")
case FORT_QUEBEC:
fmt.Println("YOU HAVE CHOSEN A HARD ROUTE. IT IS, IN COMPARSION,")
fmt.Println("HARDER THAN THE ROUTE TO HOCHELAGA BUT EASIER THAN")
fmt.Println("THE ROUTE TO NEW YORK. YOU WILL RECEIVE AN AVERAGE VALUE")
fmt.Println("FOR YOUR FURS AND THE COST OF YOUR SUPPLIES WILL BE AVERAGE.")
case FORT_NEWYORK:
fmt.Println("YOU HAVE CHOSEN THE MOST DIFFICULT ROUTE. AT")
fmt.Println("FORT NEW YORK YOU WILL RECEIVE THE HIGHEST VALUE")
fmt.Println("FOR YOUR FURS. THE COST OF YOUR SUPPLIES")
fmt.Println("WILL BE LOWER THAN AT ALL THE OTHER FORTS.")
}
fmt.Println()
}
func getYesOrNo() string {
scanner := bufio.NewScanner(os.Stdin)
for {
fmt.Println("ANSWER YES OR NO")
scanner.Scan()
if strings.ToUpper(scanner.Text())[0:1] == "Y" {
return "Y"
} else if strings.ToUpper(scanner.Text())[0:1] == "N" {
return "N"
}
}
}
func getFursPurchase() []int {
scanner := bufio.NewScanner(os.Stdin)
fmt.Printf("YOUR %d FURS ARE DISTRIBUTED AMONG THE FOLLOWING\n", MAXFURS)
fmt.Println("KINDS OF PELTS: MINK, BEAVER, ERMINE AND FOX.")
fmt.Println()
purchases := make([]int, 4)
for i, f := range FURS() {
retry:
fmt.Printf("HOW MANY %s DO YOU HAVE: ", f)
scanner.Scan()
count, err := strconv.Atoi(scanner.Text())
if err != nil {
fmt.Println("INVALID INPUT, TRY AGAIN ...")
goto retry
}
purchases[i] = count
}
return purchases
}
func main() {
rand.Seed(time.Now().UnixNano())
printTitle()
gameState := STARTING
whichFort := FORT_NEWYORK
var (
minkPrice int
erminePrice int
beaverPrice int
foxPrice int
)
player := NewPlayer()
for {
switch gameState {
case STARTING:
printIntro()
fmt.Println("DO YOU WISH TO TRADE FURS?")
if getYesOrNo() == "N" {
os.Exit(0)
}
gameState = TRADING
case TRADING:
fmt.Println()
fmt.Printf("YOU HAVE $ %1.2f IN SAVINGS\n", player.funds)
fmt.Printf("AND %d FURS TO BEGIN THE EXPEDITION\n", MAXFURS)
player.furs = getFursPurchase()
if player.totalFurs() > MAXFURS {
fmt.Println()
fmt.Println("YOU MAY NOT HAVE THAT MANY FURS.")
fmt.Println("DO NOT TRY TO CHEAT. I CAN ADD.")
fmt.Println("YOU MUST START AGAIN.")
gameState = STARTING
} else {
gameState = CHOOSINGFORT
}
case CHOOSINGFORT:
whichFort = getFortChoice()
printFortComment(whichFort)
fmt.Println("DO YOU WANT TO TRADE AT ANOTHER FORT?")
changeFort := getYesOrNo()
if changeFort == "N" {
gameState = TRAVELLING
}
case TRAVELLING:
switch whichFort {
case FORT_MONTREAL:
minkPrice = (int((0.2*rand.Float64()+0.70)*100+0.5) / 100)
erminePrice = (int((0.2*rand.Float64()+0.65)*100+0.5) / 100)
beaverPrice = (int((0.2*rand.Float64()+0.75)*100+0.5) / 100)
foxPrice = (int((0.2*rand.Float64()+0.80)*100+0.5) / 100)
fmt.Println("SUPPLIES AT FORT HOCHELAGA COST $150.00.")
fmt.Println("YOUR TRAVEL EXPENSES TO HOCHELAGA WERE $10.00.")
player.funds -= 160
case FORT_QUEBEC:
minkPrice = (int((0.30*rand.Float64()+0.85)*100+0.5) / 100)
erminePrice = (int((0.15*rand.Float64()+0.80)*100+0.5) / 100)
beaverPrice = (int((0.20*rand.Float64()+0.90)*100+0.5) / 100)
foxPrice = (int((0.25*rand.Float64()+1.10)*100+0.5) / 100)
event := int(10*rand.Float64()) + 1
if event <= 2 {
fmt.Println("YOUR BEAVER WERE TOO HEAVY TO CARRY ACROSS")
fmt.Println("THE PORTAGE. YOU HAD TO LEAVE THE PELTS, BUT FOUND")
fmt.Println("THEM STOLEN WHEN YOU RETURNED.")
player.furs[FUR_BEAVER] = 0
} else if event <= 6 {
fmt.Println("YOU ARRIVED SAFELY AT FORT STADACONA.")
} else if event <= 8 {
fmt.Println("YOUR CANOE UPSET IN THE LACHINE RAPIDS. YOU")
fmt.Println("LOST ALL YOUR FURS.")
player.lostFurs()
} else if event <= 10 {
fmt.Println("YOUR FOX PELTS WERE NOT CURED PROPERLY.")
fmt.Println("NO ONE WILL BUY THEM.")
player.furs[FUR_FOX] = 0
} else {
log.Fatal("Unexpected error")
}
fmt.Println()
fmt.Println("SUPPLIES AT FORT STADACONA COST $125.00.")
fmt.Println("YOUR TRAVEL EXPENSES TO STADACONA WERE $15.00.")
player.funds -= 140
case FORT_NEWYORK:
minkPrice = (int((0.15*rand.Float64()+1.05)*100+0.5) / 100)
erminePrice = (int((0.15*rand.Float64()+0.95)*100+0.5) / 100)
beaverPrice = (int((0.25*rand.Float64()+1.00)*100+0.5) / 100)
foxPrice = (int((0.25*rand.Float64()+1.05)*100+0.5) / 100) // not in original code
event := int(10*rand.Float64()) + 1
if event <= 2 {
fmt.Println("YOU WERE ATTACKED BY A PARTY OF IROQUOIS.")
fmt.Println("ALL PEOPLE IN YOUR TRADING GROUP WERE")
fmt.Println("KILLED. THIS ENDS THE GAME.")
os.Exit(0)
} else if event <= 6 {
fmt.Println("YOU WERE LUCKY. YOU ARRIVED SAFELY")
fmt.Println("AT FORT NEW YORK.")
} else if event <= 8 {
fmt.Println("YOU NARROWLY ESCAPED AN IROQUOIS RAIDING PARTY.")
fmt.Println("HOWEVER, YOU HAD TO LEAVE ALL YOUR FURS BEHIND.")
player.lostFurs()
} else if event <= 10 {
minkPrice /= 2
foxPrice /= 2
fmt.Println("YOUR MINK AND BEAVER WERE DAMAGED ON YOUR TRIP.")
fmt.Println("YOU RECEIVE ONLY HALF THE CURRENT PRICE FOR THESE FURS.")
} else {
log.Fatal("Unexpected error")
}
fmt.Println()
fmt.Println("SUPPLIES AT NEW YORK COST $85.00.")
fmt.Println("YOUR TRAVEL EXPENSES TO NEW YORK WERE $25.00.")
player.funds -= 110
}
beaverValue := beaverPrice * player.furs[FUR_BEAVER]
foxValue := foxPrice * player.furs[FUR_FOX]
ermineValue := erminePrice * player.furs[FUR_ERMINE]
minkValue := minkPrice * player.furs[FUR_MINK]
fmt.Println()
fmt.Printf("YOUR BEAVER SOLD FOR $%6.2f\n", float64(beaverValue))
fmt.Printf("YOUR FOX SOLD FOR $%6.2f\n", float64(foxValue))
fmt.Printf("YOUR ERMINE SOLD FOR $%6.2f\n", float64(ermineValue))
fmt.Printf("YOUR MINK SOLD FOR $%6.2f\n", float64(minkValue))
player.funds += float32(beaverValue + foxValue + ermineValue + minkValue)
fmt.Println()
fmt.Printf("YOU NOW HAVE $%1.2f INCLUDING YOUR PREVIOUS SAVINGS\n", player.funds)
fmt.Println("\nDO YOU WANT TO TRADE FURS NEXT YEAR?")
if getYesOrNo() == "N" {
os.Exit(0)
} else {
gameState = TRADING
}
}
}
}
@@ -0,0 +1,95 @@
package main
import (
"bufio"
"fmt"
"math"
"math/rand"
"os"
"strconv"
"time"
)
func printIntro() {
fmt.Println(" Guess")
fmt.Println("Creative Computing Morristown, New Jersey")
fmt.Println()
fmt.Println()
fmt.Println()
fmt.Println("This is a number guessing game. I'll think")
fmt.Println("of a number between 1 and any limit you want.")
fmt.Println("Then you have to guess what it is")
}
func getLimit() (int, int) {
scanner := bufio.NewScanner(os.Stdin)
for {
fmt.Println("What limit do you want?")
scanner.Scan()
limit, err := strconv.Atoi(scanner.Text())
if err != nil || limit < 0 {
fmt.Println("Please enter a number greater or equal to 1")
continue
}
limitGoal := int((math.Log(float64(limit)) / math.Log(2)) + 1)
return limit, limitGoal
}
}
func main() {
rand.Seed(time.Now().UnixNano())
printIntro()
scanner := bufio.NewScanner(os.Stdin)
limit, limitGoal := getLimit()
guessCount := 1
stillGuessing := true
won := false
myGuess := int(float64(limit)*rand.Float64() + 1)
fmt.Printf("I'm thinking of a number between 1 and %d\n", limit)
fmt.Println("Now you try to guess what it is.")
for stillGuessing {
scanner.Scan()
n, err := strconv.Atoi(scanner.Text())
if err != nil {
fmt.Println("Please enter a number greater or equal to 1")
continue
}
if n < 0 {
break
}
fmt.Print("\n\n\n")
if n < myGuess {
fmt.Println("Too low. Try a bigger answer")
guessCount += 1
} else if n > myGuess {
fmt.Println("Too high. Try a smaller answer")
guessCount += 1
} else {
fmt.Printf("That's it! You got it in %d tries\n", guessCount)
won = true
stillGuessing = false
}
}
if won {
if guessCount < limitGoal {
fmt.Println("Very good.")
} else if guessCount == limitGoal {
fmt.Println("Good.")
} else {
fmt.Printf("You should have been able to get it in only %d guesses.\n", limitGoal)
}
fmt.Print("\n\n\n")
}
}
+125
View File
@@ -0,0 +1,125 @@
package main
import (
"bufio"
"fmt"
"math"
"math/rand"
"os"
"strconv"
"strings"
"time"
)
func printIntro() {
fmt.Println(" GUNNER")
fmt.Println(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY")
fmt.Print("\n\n\n")
fmt.Println("YOU ARE THE OFFICER-IN-CHARGE, GIVING ORDERS TO A GUN")
fmt.Println("CREW, TELLING THEM THE DEGREES OF ELEVATION YOU ESTIMATE")
fmt.Println("WILL PLACE A PROJECTILE ON TARGET. A HIT WITHIN 100 YARDS")
fmt.Println("OF THE TARGET WILL DESTROY IT.")
fmt.Println()
}
func getFloat() float64 {
scanner := bufio.NewScanner(os.Stdin)
for {
scanner.Scan()
fl, err := strconv.ParseFloat(scanner.Text(), 64)
if err != nil {
fmt.Println("Invalid input")
continue
}
return fl
}
}
func play() {
gunRange := int(40000*rand.Float64() + 20000)
fmt.Printf("\nMAXIMUM RANGE OF YOUR GUN IS %d YARDS\n", gunRange)
killedEnemies := 0
S1 := 0
for {
targetDistance := int(float64(gunRange) * (0.1 + 0.8*rand.Float64()))
shots := 0
fmt.Printf("\nDISTANCE TO THE TARGET IS %d YARDS\n", targetDistance)
for {
fmt.Print("\n\nELEVATION? ")
elevation := getFloat()
if elevation > 89 {
fmt.Println("MAXIMUM ELEVATION IS 89 DEGREES")
continue
}
if elevation < 1 {
fmt.Println("MINIMUM ELEVATION IS 1 DEGREE")
continue
}
shots += 1
if shots < 6 {
B2 := 2 * elevation / 57.3
shotImpact := int(float64(gunRange) * math.Sin(B2))
shotProximity := int(targetDistance - shotImpact)
if math.Abs(float64(shotProximity)) < 100 { // hit
fmt.Printf("*** TARGET DESTROYED *** %d ROUNDS OF AMMUNITION EXPENDED.\n", shots)
S1 += shots
if killedEnemies == 4 {
fmt.Printf("\n\nTOTAL ROUNDS EXPENDED WERE: %d\n", S1)
if S1 > 18 {
print("BETTER GO BACK TO FORT SILL FOR REFRESHER TRAINING!")
return
} else {
print("NICE SHOOTING !!")
return
}
} else {
killedEnemies += 1
fmt.Println("\nTHE FORWARD OBSERVER HAS SIGHTED MORE ENEMY ACTIVITY...")
break
}
} else { // missed
if shotProximity > 100 {
fmt.Printf("SHORT OF TARGET BY %d YARDS.\n", int(math.Abs(float64(shotProximity))))
} else {
fmt.Printf("OVER TARGET BY %d YARDS.\n", int(math.Abs(float64(shotProximity))))
}
}
} else {
fmt.Print("\nBOOM !!!! YOU HAVE JUST BEEN DESTROYED BY THE ENEMY.\n\n\n")
fmt.Println("BETTER GO BACK TO FORT SILL FOR REFRESHER TRAINING!")
return
}
}
}
}
func main() {
rand.Seed(time.Now().UnixNano())
scanner := bufio.NewScanner(os.Stdin)
printIntro()
for {
play()
fmt.Print("TRY AGAIN (Y OR N)? ")
scanner.Scan()
if strings.ToUpper(scanner.Text())[0:1] != "Y" {
fmt.Println("\nOK. RETURN TO BASE CAMP.")
break
}
}
}
@@ -108,7 +108,7 @@
900 PRINT "A FANTASTIC PERFORMANCE!!! CHARLEMANGE, DISRAELI, AND"
905 PRINT "JEFFERSON COMBINED COULD NOT HAVE DONE BETTER!":GOTO 990
940 PRINT "YOUR HEAVY-HANDED PERFORMANCE SMACKS OF NERO AND IVAN IV."
945 PRINT "THE PEOPLE (REMIANING) FIND YOU AN UNPLEASANT RULER, AND,"
945 PRINT "THE PEOPLE (REMAINING) FIND YOU AN UNPLEASANT RULER, AND,"
950 PRINT "FRANKLY, HATE YOUR GUTS!!":GOTO 990
960 PRINT "YOUR PERFORMANCE COULD HAVE BEEN SOMEWHAT BETTER, BUT"
965 PRINT "REALLY WASN'T TOO BAD AT ALL. ";INT(P*.8*RND(1));"PEOPLE"
+240
View File
@@ -0,0 +1,240 @@
package main
import (
"bufio"
"fmt"
"os"
"strings"
"time"
)
type PROBLEM_TYPE int8
const (
SEX PROBLEM_TYPE = iota
HEALTH
MONEY
JOB
UKNOWN
)
func getYesOrNo() (bool, bool, string) {
scanner := bufio.NewScanner(os.Stdin)
scanner.Scan()
if strings.ToUpper(scanner.Text()) == "YES" {
return true, true, scanner.Text()
} else if strings.ToUpper(scanner.Text()) == "NO" {
return true, false, scanner.Text()
} else {
return false, false, scanner.Text()
}
}
func printTntro() {
fmt.Println(" HELLO")
fmt.Println(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY")
fmt.Print("\n\n\n")
fmt.Println("HELLO. MY NAME IS CREATIVE COMPUTER.")
fmt.Println("\nWHAT'S YOUR NAME?")
}
func askEnjoyQuestion(user string) {
fmt.Printf("HI THERE %s, ARE YOU ENJOYING YOURSELF HERE?\n", user)
for {
valid, value, msg := getYesOrNo()
if valid {
if value {
fmt.Printf("I'M GLAD TO HEAR THAT, %s.\n", user)
fmt.Println()
} else {
fmt.Printf("OH, I'M SORRY TO HEAR THAT, %s. MAYBE WE CAN\n", user)
fmt.Println("BRIGHTEN UP YOUR VISIT A BIT.")
}
break
} else {
fmt.Printf("%s, I DON'T UNDERSTAND YOUR ANSWER OF '%s'.\n", user, msg)
fmt.Println("PLEASE ANSWER 'YES' OR 'NO'. DO YOU LIKE IT HERE?")
}
}
}
func promptForProblems(user string) PROBLEM_TYPE {
scanner := bufio.NewScanner(os.Stdin)
fmt.Println()
fmt.Printf("SAY %s, I CAN SOLVE ALL KINDS OF PROBLEMS EXCEPT\n", user)
fmt.Println("THOSE DEALING WITH GREECE. WHAT KIND OF PROBLEMS DO")
fmt.Println("YOU HAVE? (ANSWER SEX, HEALTH, MONEY, OR JOB)")
for {
scanner.Scan()
switch strings.ToUpper(scanner.Text()) {
case "SEX":
return SEX
case "HEALTH":
return HEALTH
case "MONEY":
return MONEY
case "JOB":
return JOB
default:
return UKNOWN
}
}
}
func promptTooMuchOrTooLittle() (bool, bool) {
scanner := bufio.NewScanner(os.Stdin)
scanner.Scan()
if strings.ToUpper(scanner.Text()) == "TOO MUCH" {
return true, true
} else if strings.ToUpper(scanner.Text()) == "TOO LITTLE" {
return true, false
} else {
return false, false
}
}
func solveSexProblem(user string) {
fmt.Println("IS YOUR PROBLEM TOO MUCH OR TOO LITTLE?")
for {
valid, tooMuch := promptTooMuchOrTooLittle()
if valid {
if tooMuch {
fmt.Println("YOU CALL THAT A PROBLEM?!! I SHOULD HAVE SUCH PROBLEMS!")
fmt.Printf("IF IT BOTHERS YOU, %s, TAKE A COLD SHOWER.\n", user)
} else {
fmt.Printf("WHY ARE YOU HERE IN SUFFERN, %s? YOU SHOULD BE\n", user)
fmt.Println("IN TOKYO OR NEW YORK OR AMSTERDAM OR SOMEPLACE WITH SOME")
fmt.Println("REAL ACTION.")
}
return
} else {
fmt.Printf("DON'T GET ALL SHOOK, %s, JUST ANSWER THE QUESTION\n", user)
fmt.Println("WITH 'TOO MUCH' OR 'TOO LITTLE'. WHICH IS IT?")
}
}
}
func solveHealthProblem(user string) {
fmt.Printf("MY ADVICE TO YOU %s IS:\n", user)
fmt.Println(" 1. TAKE TWO ASPRIN")
fmt.Println(" 2. DRINK PLENTY OF FLUIDS (ORANGE JUICE, NOT BEER!)")
fmt.Println(" 3. GO TO BED (ALONE)")
}
func solveMoneyProblem(user string) {
fmt.Printf("SORRY, %s, I'M BROKE TOO. WHY DON'T YOU SELL\n", user)
fmt.Println("ENCYCLOPEADIAS OR MARRY SOMEONE RICH OR STOP EATING")
fmt.Println("SO YOU WON'T NEED SO MUCH MONEY?")
}
func solveJobProblem(user string) {
fmt.Printf("I CAN SYMPATHIZE WITH YOU %s. I HAVE TO WORK\n", user)
fmt.Println("VERY LONG HOURS FOR NO PAY -- AND SOME OF MY BOSSES")
fmt.Printf("REALLY BEAT ON MY KEYBOARD. MY ADVICE TO YOU, %s,\n", user)
fmt.Println("IS TO OPEN A RETAIL COMPUTER STORE. IT'S GREAT FUN.")
}
func askQuestionLoop(user string) {
for {
problem := promptForProblems(user)
switch problem {
case SEX:
solveSexProblem(user)
case HEALTH:
solveHealthProblem(user)
case MONEY:
solveMoneyProblem(user)
case JOB:
solveJobProblem(user)
case UKNOWN:
fmt.Printf("OH %s, YOUR ANSWER IS GREEK TO ME.\n", user)
}
for {
fmt.Println()
fmt.Printf("ANY MORE PROBLEMS YOU WANT SOLVED, %s?\n", user)
valid, value, _ := getYesOrNo()
if valid {
if value {
fmt.Println("WHAT KIND (SEX, MONEY, HEALTH, JOB)")
break
} else {
return
}
}
fmt.Printf("JUST A SIMPLE 'YES' OR 'NO' PLEASE, %s\n", user)
}
}
}
func goodbyeUnhappy(user string) {
fmt.Println()
fmt.Printf("TAKE A WALK, %s.\n", user)
fmt.Println()
fmt.Println()
}
func goodbyeHappy(user string) {
fmt.Printf("NICE MEETING YOU %s, HAVE A NICE DAY.\n", user)
}
func askForFee(user string) {
fmt.Println()
fmt.Printf("THAT WILL BE $5.00 FOR THE ADVICE, %s.\n", user)
fmt.Println("PLEASE LEAVE THE MONEY ON THE TERMINAL.")
time.Sleep(4 * time.Second)
fmt.Print("\n\n\n")
fmt.Println("DID YOU LEAVE THE MONEY?")
for {
valid, value, msg := getYesOrNo()
if valid {
if value {
fmt.Printf("HEY, %s, YOU LEFT NO MONEY AT ALL!\n", user)
fmt.Println("YOU ARE CHEATING ME OUT OF MY HARD-EARNED LIVING.")
fmt.Println()
fmt.Printf("WHAT A RIP OFF, %s!!!\n", user)
fmt.Println()
} else {
fmt.Printf("THAT'S HONEST, %s, BUT HOW DO YOU EXPECT\n", user)
fmt.Println("ME TO GO ON WITH MY PSYCHOLOGY STUDIES IF MY PATIENTS")
fmt.Println("DON'T PAY THEIR BILLS?")
}
return
} else {
fmt.Printf("YOUR ANSWER OF '%s' CONFUSES ME, %s.\n", msg, user)
fmt.Println("PLEASE RESPOND WITH 'YES' or 'NO'.")
}
}
}
func main() {
scanner := bufio.NewScanner(os.Stdin)
printTntro()
scanner.Scan()
userName := scanner.Text()
fmt.Println()
askEnjoyQuestion(userName)
askQuestionLoop(userName)
askForFee(userName)
if false {
goodbyeHappy(userName) // unreachable
} else {
goodbyeUnhappy(userName)
}
}
@@ -0,0 +1,77 @@
package main
import (
"bufio"
"fmt"
"math/rand"
"os"
"strconv"
"strings"
"time"
)
const MAX_ATTEMPTS = 6
func printIntro() {
fmt.Println("HI LO")
fmt.Println("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY")
fmt.Println("\n\n\nTHIS IS THE GAME OF HI LO.")
fmt.Println("\nYOU WILL HAVE 6 TRIES TO GUESS THE AMOUNT OF MONEY IN THE")
fmt.Println("HI LO JACKPOT, WHICH IS BETWEEN 1 AND 100 DOLLARS. IF YOU")
fmt.Println("GUESS THE AMOUNT, YOU WIN ALL THE MONEY IN THE JACKPOT!")
fmt.Println("THEN YOU GET ANOTHER CHANCE TO WIN MORE MONEY. HOWEVER,")
fmt.Println("IF YOU DO NOT GUESS THE AMOUNT, THE GAME ENDS.")
fmt.Println()
fmt.Println()
}
func main() {
rand.Seed(time.Now().UnixNano())
scanner := bufio.NewScanner(os.Stdin)
printIntro()
totalWinnings := 0
for {
fmt.Println()
secret := rand.Intn(1000) + 1
guessedCorrectly := false
for attempt := 0; attempt < MAX_ATTEMPTS; attempt++ {
fmt.Println("YOUR GUESS?")
scanner.Scan()
guess, err := strconv.Atoi(scanner.Text())
if err != nil {
fmt.Println("INVALID INPUT")
}
if guess == secret {
fmt.Printf("GOT IT!!!!!!!!!! YOU WIN %d DOLLARS.\n", secret)
guessedCorrectly = true
break
} else if guess > secret {
fmt.Println("YOUR GUESS IS TOO HIGH.")
} else {
fmt.Println("YOUR GUESS IS TOO LOW.")
}
}
if guessedCorrectly {
totalWinnings += secret
fmt.Printf("YOUR TOTAL WINNINGS ARE NOW $%d.\n", totalWinnings)
} else {
fmt.Printf("YOU BLEW IT...TOO BAD...THE NUMBER WAS %d\n", secret)
}
fmt.Println()
fmt.Println("PLAYAGAIN (YES OR NO)?")
scanner.Scan()
if strings.ToUpper(scanner.Text())[0:1] != "Y" {
break
}
}
fmt.Println("\nSO LONG. HOPE YOU ENJOYED YOURSELF!!!")
}
@@ -0,0 +1,3 @@
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
Conversion to [C++17](https://en.wikipedia.org/wiki/C%2B%2B17)
@@ -0,0 +1,21 @@
#include <iostream> // std::cout, std::endl
#include <string> // std::string(size_t n, char c)
#include <cmath> // std::sin(double x)
int main()
{
std::cout << std::string(30, ' ') << "SINE WAVE" << std::endl;
std::cout << std::string(15, ' ') << "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY" << std::endl;
std::cout << std::string(5, '\n');
bool b = true;
for (double t = 0.0; t <= 40.0; t += 0.25)
{
int a = int(26 + 25 * std::sin(t));
std::cout << std::string(a, ' ') << (b ? "CREATIVE" : "COMPUTING") << std::endl;
b = !b;
}
return 0;
}
+11 -12
View File
@@ -1,4 +1,4 @@
use std::ffi::{OsString, OsStr};
use std::ffi::OsStr;
use std::{fs, io};
use std::fs::metadata;
use std::path::{Path, PathBuf};
@@ -8,8 +8,6 @@ use std::path::{Path, PathBuf};
* @author Anthony Rubick
*/
//DATA
const ROOT_DIR: &str = "../../";
const LANGUAGES: [(&str,&str); 10] = [ //first element of tuple is the language name, second element is the file extension
@@ -25,13 +23,19 @@ const LANGUAGES: [(&str,&str); 10] = [ //first element of tuple is the language
("vbnet", "vb")
];
const OUTPUT_PATH: &str = "../../todo.md";
//const INGORE: [&str;5] = ["../../.git","../../.vscode","../../00_Utilities","../../buildJvm","../../node_modules"]; //folders to ignore
fn main() {
//DATA
let mut root_folders:Vec<PathBuf>;
let mut output_string: String = String::new();
let format_game_first: bool;
let ingore: [PathBuf;5] = [
PathBuf::from(r"../../.git"),
PathBuf::from(r"../../.github"),
PathBuf::from(r"../../00_Alternate_Languages"),
PathBuf::from(r"../../00_Utilities"),
PathBuf::from(r"../../00_Common"),
]; //folders to ignore
//print welcome message
println!("
@@ -66,15 +70,10 @@ fn main() {
//for all folders, search for the languages and extensions
root_folders = root_folders.into_iter().filter(|path| {
match fs::read_dir(path) {
Err(why) => {println!("! {:?}", why.kind()); false},
Ok(paths) => {
paths.into_iter().filter(|f| metadata(f.as_ref().unwrap().path()).unwrap().is_dir()) //filter to only folders
.filter_map( |path| path.ok() ) //extract only the DirEntries
.any(|f| LANGUAGES.iter().any(|tup| OsString::from(tup.1).eq_ignore_ascii_case(f.file_name()))) //filter out ones that don't contain folders with the language names
}
}
//not one of the ignored folders
!ingore.contains(path)
}).collect();
root_folders.sort();
//create todo list
if format_game_first {
+181
View File
@@ -0,0 +1,181 @@
--
-- Animal.lua
--
-- maintain a flat table/list of all the known animals
local animals = {
"FISH",
"BIRD"
}
-- store the questions as a binary tree with each node having a
-- "y" or "n" branch
-- if the node has a member named "a" it's an answer, with an index
-- into the animals list.
-- Otherwise, it's a question that leads to more nodes.
local questionTree = {
q = "DOES IT SWIM",
y = { a = 1 },
n = { a = 2 }
}
-- print the given prompt string and then wait for input
-- loops until a non-empty input is given
-- returns the input as an upper-case string
function askPrompt(promptString)
local answered = false
local a
while (not answered) do
print(promptString)
a = io.read()
a = string.upper(a)
if (string.len(a) > 0) then
answered = true
end
end
return a
end
-- print the given prompt string and then wait for the
-- user to enter a string beginning with "Y" or "N"
function askYesOrNo(promptString)
local a
while ((a ~= "Y") and (a ~= "N")) do
a = askPrompt(promptString)
a = a:sub(1,1)
end
return a
end
-- prints the introductory text from the original BASIC program
function printIntro()
print(string.format("%32s", " ") .. "ANIMAL")
print(string.format("%15s", " ") .. "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY")
print()
print()
print()
print("PLAY 'GUESS THE ANIMAL'")
print("THINK OF AN ANIMAL AND THE COMPUTER WILL TRY TO GUESS IT.")
print()
end
-- prints the animals known in the source list
function listKnownAnimals()
print()
print("ANIMALS I ALREADY KNOW ARE:")
local x
local item
for x = 1,#animals do
-- use string.format to space each animal in a 12-character-wide "cell"
item = string.format("%-12s", animals[x])
-- io.write() works like print(), but doesn't automatically add a carriage return/newline
io.write(item)
-- every fifth item, start a new line
if ((x % 5) == 0) then
io.write("\n")
end
end
print()
print()
end
-- Prompts the user for info about the animal they were thinking of, then
-- uses that to add a new branch to the tree
-- curNode: the node in the tree where the computer made a wrong guess
-- branch: the answer the user gave to curNode's question
function addAnimalToTree(curNode, branch)
local newAnimal
local curResponse = curNode[branch]
local guessedIndex = curResponse.a
local guessedAnimal = animals[guessedIndex]
local newQuestion, newAnswer, newIndex
local newNode
newAnimal = askPrompt("THE ANIMAL YOU WERE THINKING OF WAS A ?")
newQuestion = askPrompt("PLEASE TYPE IN A QUESTION THAT WOULD DISTINGUISH A "..
tostring(newAnimal).." FROM A "..tostring(guessedAnimal))
newAnswer = askYesOrNo("FOR A "..tostring(newAnimal).." THE ANSWER WOULD BE?")
-- add the new animal to the master list at the end, and
-- save off its index in the list
table.insert(animals, newAnimal)
newIndex = #animals
-- create a new node for the question we just learned
newNode = {}
newNode.q = newQuestion
if (newAnswer == "Y") then
newNode.y = { a = newIndex }
newNode.n = { a = guessedIndex }
else
newNode.y = { a = guessedIndex }
newNode.n = { a = newIndex }
end
-- replace the previous answer with our new node
curNode[branch] = newNode
end
-- Starts at the root of the question tree and asks questions about
-- the user's animal until the computer hits an "a" answer node and tries
-- to make a guess
function askAboutAnimal()
local curNode = questionTree
local finished = false
local response, responseIndex
local nextNode, animalName
while (not finished) do
response = askYesOrNo(curNode.q .. "?")
-- convert the response "Y" or "N" to the lowercase "y" or "n" that we use to name our branches
branch = string.lower(response)
nextNode = curNode[branch]
-- is the next node an answer node, or another question?
if (nextNode.a ~= nil) then
-- it's an answer, so make a guess
animalName = animals[nextNode.a]
response = askYesOrNo("IS IT A "..tostring(animalName).."?")
if (response == "Y") then
-- we got the correct answer, so prompt for a new animal
print()
print("WHY NOT TRY ANOTHER ANIMAL?")
else
-- incorrect answer, so add a new entry at this point in the tree
addAnimalToTree(curNode, branch)
end
-- whether we were right or wrong, we're finished with this round
finished = true
else
-- it's another question, so advance down the tree
curNode = nextNode
end
end
end
-- MAIN CONTROL SECTION
printIntro()
-- loop forever until the player requests an exit by entering a blank line
local exitRequested = false
local answer
while (not exitRequested) do
print("ARE YOU THINKING OF AN ANIMAL?")
answer = io.read()
answer = string.upper(answer)
if (string.len(answer) == 0) then
exitRequested = true
elseif (answer:sub(1,4) == "LIST") then
listKnownAnimals()
elseif (answer:sub(1,1) == "Y") then
askAboutAnimal()
end
end
+150
View File
@@ -0,0 +1,150 @@
#!/usr/bin/perl
# Banner program in Perl
# Translated by Kevin Brannen (kbrannen)
use strict;
use warnings;
sub print_lines
{
my $lines = shift;
print "\n" x $lines;
}
# each letter is made of 7 slices (or rows);
# the initial & unused 0 is to allow for Perl arrays being 0-based
# but allow the algorithm to be 1-based (like Basic arrays);
# the numbers are essentially the dots/columns per slice in powers of 2.
my %data = (
" " => [ 0, 0, 0, 0, 0, 0, 0, 0 ],
"." => [ 0, 1, 1, 129, 449, 129, 1, 1 ],
"!" => [ 0, 1, 1, 1, 384, 1, 1, 1 ],
"=" => [ 0, 41, 41, 41, 41, 41, 41, 41 ],
"?" => [ 0, 5, 3, 2, 354, 18, 11, 5 ],
"*" => [ 0, 69, 41, 17, 512, 17, 41, 69 ],
"0" => [ 0, 57, 69, 131, 258, 131, 69, 57 ],
"1" => [ 0, 0, 0, 261, 259, 512, 257, 257 ],
"2" => [ 0, 261, 387, 322, 290, 274, 267, 261 ],
"3" => [ 0, 66, 130, 258, 274, 266, 150, 100 ],
"4" => [ 0, 33, 49, 41, 37, 35, 512, 33 ],
"5" => [ 0, 160, 274, 274, 274, 274, 274, 226 ],
"6" => [ 0, 194, 291, 293, 297, 305, 289, 193 ],
"7" => [ 0, 258, 130, 66, 34, 18, 10, 8 ],
"8" => [ 0, 69, 171, 274, 274, 274, 171, 69 ],
"9" => [ 0, 263, 138, 74, 42, 26, 10, 7 ],
"A" => [ 0, 505, 37, 35, 34, 35, 37, 505 ],
"B" => [ 0, 512, 274, 274, 274, 274, 274, 239 ],
"C" => [ 0, 125, 131, 258, 258, 258, 131, 69 ],
"D" => [ 0, 512, 258, 258, 258, 258, 131, 125 ],
"E" => [ 0, 512, 274, 274, 274, 274, 258, 258 ],
"F" => [ 0, 512, 18, 18, 18, 18, 2, 2 ],
"G" => [ 0, 125, 131, 258, 258, 290, 163, 101 ],
"H" => [ 0, 512, 17, 17, 17, 17, 17, 512 ],
"I" => [ 0, 258, 258, 258, 512, 258, 258, 258 ],
"J" => [ 0, 65, 129, 257, 257, 257, 129, 128 ],
"K" => [ 0, 512, 17, 17, 41, 69, 131, 258 ],
"L" => [ 0, 512, 257, 257, 257, 257, 257, 257 ],
"M" => [ 0, 512, 7, 13, 25, 13, 7, 512 ],
"N" => [ 0, 512, 7, 9, 17, 33, 193, 512 ],
"O" => [ 0, 125, 131, 258, 258, 258, 131, 125 ],
"P" => [ 0, 512, 18, 18, 18, 18, 18, 15 ],
"Q" => [ 0, 125, 131, 258, 258, 322, 131, 381 ],
"R" => [ 0, 512, 18, 18, 50, 82, 146, 271 ],
"S" => [ 0, 69, 139, 274, 274, 274, 163, 69 ],
"T" => [ 0, 2, 2, 2, 512, 2, 2, 2 ],
"U" => [ 0, 128, 129, 257, 257, 257, 129, 128 ],
"V" => [ 0, 64, 65, 129, 257, 129, 65, 64 ],
"W" => [ 0, 256, 257, 129, 65, 129, 257, 256 ],
"X" => [ 0, 388, 69, 41, 17, 41, 69, 388 ],
"Y" => [ 0, 8, 9, 17, 481, 17, 9, 8 ],
"Z" => [ 0, 386, 322, 290, 274, 266, 262, 260 ],
);
my ($horz, $vert, $center, $char, $msg) = (0, 0, '', '', '');
# get args to run with
while ($horz < 1)
{
print "HORIZONTAL (1 or more): ";
chomp($horz = <>);
$horz = int($horz);
}
while ($vert < 1)
{
print "VERTICAL (1 or more): ";
chomp($vert = <>);
$vert = int($vert);
}
print "CENTERED (Y/N): ";
chomp($center = <>);
$center = ($center =~ m/^Y/i) ? 1 : 0;
# note you can enter multiple chars and the program will do the right thing
# thanks to the length() calls below, which was in the original Basic
print "CHARACTER TO PRINT (TYPE 'ALL' IF YOU WANT CHARACTER BEING PRINTED): ";
chomp($char = uc(<>));
while (!$msg)
{
print "STATEMENT: ";
chomp($msg = uc(<>));
}
print "SET PAGE TO PRINT, HIT RETURN WHEN READY";
$_ = <>;
print_lines(2 * $horz);
# print the message
for my $letter ( split(//, $msg) )
{
if (!exists($data{$letter}))
{
die "Cannot use letter '$letter'!";
}
my @s = @{$data{$letter}};
#if ($letter eq " ") { print_lines(7 * $horz); next; }
my $print_letter = ($char eq "ALL") ? $letter : $char;
for my $slice (1 .. 7)
{
my (@j, @f);
for (my $k = 8; $k >= 0; $k--)
{
if (2**$k < $s[$slice])
{
$j[9 - $k] = 1;
$s[$slice] = $s[$slice] - 2**$k;
if ($s[$slice] == 1)
{
$f[$slice] = 9 - $k;
}
}
else
{
$j[9 - $k] = 0;
}
}
for my $t1 (1 .. $horz)
{
print " " x int((63 - 4.5 * $vert) * $center / (length($print_letter)) + 1);
for my $b (1 .. (defined($f[$slice]) ? $f[$slice] : 0))
{
my $str = $j[$b] ? $print_letter : (" " x length($print_letter));
print $str for (1 .. $vert);
}
print "\n";
}
}
# space between letters
print_lines(2 * $horz);
}
# while in the original code, this seems pretty excessive
#print_lines(75);
exit(0);
+18
View File
@@ -1,3 +1,21 @@
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
Conversion to [Perl](https://www.perl.org/)
There are two version of the code here, a "faithful" translation (basketball-orig.pl) and
a "modern" translation (basketball.pl). The main difference between the 2 are is that the
faithful translation has 3 GOTOs in it while the modern version has no GOTO. I have added
a "TIME" print when the score is shown so the Clock is visible. Halftime is at "50" and
end of game is at 100 (per the Basic code).
The 3 GOTOs in the faitful version are because of the way the original code jumped into
the "middle of logic" that has no obivious way to avoid ... that I can see, at least while
still maintaining something of the look and structure of the original Basic.
The modern version avoided the GOTOs by restructuring the program in the 2 "play()" subs.
Despite the change, this should play the same way as the faithful version.
All of the percentages remain the same. If writing this from scratch, we really should
have only a single play() sub which uses the same code for both teams, which would also
make the game more fair ... but that wasn't done so the percent edge to Darmouth has been
maintained here.
+415
View File
@@ -0,0 +1,415 @@
#!/usr/bin/perl
# Basketball program in Perl
# This is fairly faithful translation from the original Basic.
# This becomes apparent because there are actually 3 GOTOs still present
# because of the way the original code jumped into the "middle of logic"
# that has no obivious way to avoid ... that I can see.
# For better structure and no GOTOs, see the other version of this program.
# 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")
{
$Player = 0;
get_your_shot();
dartmouth_play();
}
else
{
opponent_play();
}
if ($Timer >= 100)
{
check_end_game();
last if (!$DoPlay);
$Timer = 93;
$ConTeam = center_jump();
}
}
exit(0);
###############################################################
sub dartmouth_play
{
if ($ShotType == 1 || $ShotType == 2)
{
$Timer++;
if ($Timer == 50)
{
end_first_half();
return;
}
if ($Timer == 92)
{
two_min_left();
}
print "JUMP SHOT\n";
if (rand(1) <= 0.341 * $Defense / 8)
{
print "SHOT IS GOOD.\n";
dartmouth_score();
$ConTeam = "opp";
return;
}
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";
$ConTeam = "opp";
return;
}
print "DARTMOUTH CONTROLS THE REBOUND.\n";
if (rand(1) <= 0.4) { goto L1300; }
if ($Defense == 6)
{
if (rand(1) <= 0.6)
{
print "PASS STOLEN BY $Opponent, EASY LAYUP.\n";
opp_score();
$ConTeam = "dart"; return;
return;
}
}
print "BALL PASSED BACK TO YOU.\n";
$ConTeam = "dart";
return;
}
if (rand(1) <= 0.782*$Defense/8)
{
print "SHOT IS BLOCKED. BALL CONTROLLED BY "; # no NL
if (rand(1) > 0.5)
{
print "$Opponent.\n";
$ConTeam = "opp";
return;
}
else
{
print "DARTMOUTH.\n";
$ConTeam = "dart";
return;
}
}
if (rand(1) > 0.843*$Defense/8)
{
print "CHARGING FOUL. DARTMOUTH LOSES BALL.\n";
$ConTeam = "opp";
return;
}
else
{
print "SHOOTER IS FOULED. TWO SHOTS.\n";
foul_shooting();
$ConTeam = "opp";
return;
}
}
L1300:
while (1)
{
$Timer++;
if ($Timer == 50)
{
end_first_half();
return;
}
if ($Timer == 92) { two_min_left(); }
if ($ShotType == 0)
{
get_defense();
return;
}
print '', ($ShotType > 3 ? "SET SHOT." : "LAY UP."), "\n";
if (7 / $Defense * rand(1) <= 0.4)
{
print "SHOT IS GOOD. TWO POINTS.\n";
dartmouth_score();
$ConTeam = "opp";
return;
}
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";
$ConTeam = "opp";
return;
}
print "DARTMOUTH CONTROLS THE REBOUND.\n";
next if (rand(1) <= 0.4);
print "BALL PASSED BACK TO YOU.\n";
$ConTeam = "dart";
return;
}
if (7 / $Defense * rand(1) <= 0.875)
{
print "SHOOTER FOULED. TWO SHOTS.\n";
foul_shooting();
$ConTeam = "opp";
return;
}
if (7 / $Defense * rand(1) <= 0.925)
{
print "SHOT BLOCKED. $Opponent\'S BALL.\n";
$ConTeam = "opp";
return;
}
print "CHARGING FOUL. DARTMOUTH LOSES THE BALL.\n";
$ConTeam = "opp";
return;
}
}
sub get_defense
{
$Defense = 0;
while ($Defense < 6 || $Defense > 7.5)
{
print "YOUR NEW DEFENSIVE ALLIGNMENT IS (6, 6.5, 7. 7.5): ";
chomp($Defense = <>);
($Defense) =~ m/(\d(\.\d)?)/;
}
}
sub opponent_play
{
$Player = 1;
$Timer++;
if ($Timer == 50)
{
end_first_half();
$ConTeam = center_jump();
return;
}
print "\n";
while (1)
{
my $shot = 10.0 / 4 * rand(1) + 1;
if ($shot <= 2.0)
{
print "JUMP SHOT.\n";
if (8.0 / $Defense * rand(1) <= 0.35)
{
print "SHOT IS GOOD.\n";
opp_score();
$ConTeam = "dart";
return;
}
if (8.0 / $Defense * rand(1) <= 0.75)
{
print "SHOT IS OFF RIM.\n";
L3110:
if ($Defense / 6.0 * rand(1) <= 0.5)
{
print "DARTMOUTH CONTROLS THE REBOUND.\n";
$ConTeam = "dart";
return;
}
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;
}
}
if (rand(1) <= 0.5)
{
print "PASS BACK TO $Opponent GUARD.\n";
$ConTeam = "opp";
return;
}
goto L3500;
}
if (8.0 / $Defense * rand(1) <= 0.9)
{
print "PLAYER FOULED. TWO SHOTS.\n";
foul_shooting();
$ConTeam = "dart";
return;
}
print "OFFENSIVE FOUL. DARTMOUTH'S BALL.\n";
$ConTeam = "dart";
return;
}
L3500:
print ($shot > 3 ? "SET SHOT.\n" : "LAY UP.\n");
if (7.0 / $Defense * rand(1) > 0.413)
{
print "SHOT IS MISSED.\n";
{
no warnings;
goto L3110;
}
}
else
{
print "SHOT IS GOOD.\n";
opp_score();
$ConTeam = "dart";
return;
}
}
}
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";
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();
}
+393
View File
@@ -0,0 +1,393 @@
#!/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();
}
+3
View File
@@ -1,3 +1,6 @@
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
Conversion to [Perl](https://www.perl.org/)
Added feature so that if "TIME" value is "0" then it will quit,
so you don't have to hit Control-C. Also added a little error checking of the input.
+97
View File
@@ -0,0 +1,97 @@
#!/usr/bin/perl
# Bounce program in Perl
# Translated by Kevin Brannen (kbrannen)
use strict;
use warnings;
print "\n";
print " " x 31,"BOUNCE\n";
print " " x 15, "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n";
print "\n\n\n";
print "THIS SIMULATION LETS YOU SPECIFY THE INITIAL VELOCITY\n";
print "OF A BALL THROWN STRAIGHT UP, AND THE COEFFICIENT OF\n";
print "ELASTICITY OF THE BALL. PLEASE USE A DECIMAL FRACTION\n";
print "COEFFICIENCY (LESS THAN 1).\n\n";
print "YOU ALSO SPECIFY THE TIME INCREMENT TO BE USED IN\n";
print "'STROBING' THE BALL'S FLIGHT (TRY .1 INITIALLY).\n\n";
# deal with basic's tab() for line positioning
# line = line string we're starting with
# pos = position to start writing
# s = string to write
# returns the resultant string, which might not have been changed
sub line_tab
{
my ($line, $pos, $s) = @_;
my $len = length($line);
# if curser is past position, do nothing
if ($len <= $pos) { $line .= " " x ($pos - $len) . $s; }
return $line;
}
while (1)
{
my @T; # time slice?
my $time_inc; # time increment, probably in fractions of seconds
my $velocity; # velocity in feet/sec
my $coeff_elas; # coeeficent of elasticity
my $line_pos; # position on line
my $S1 # duration in full seconds?
# get input
print "TIME INCREMENT (SEC, 0=QUIT): "; chomp($time_inc = <>);
last if ($time_inc == 0);
print "VELOCITY (FPS): "; chomp($velocity = <>);
print "COEFFICIENT: "; chomp($coeff_elas = <>);
if ($coeff_elas >= 1.0 || $coeff_elas <= 0)
{
print "COEFFICIENT MUST BE > 0 AND < 1.0\n\n\n";
next;
}
print "\nFEET\n";
$S1 = int(70.0 / ($velocity / (16.0 * $time_inc)));
for my $i (1 .. $S1)
{
$T[$i] = $velocity * $coeff_elas ** ($i - 1) / 16.0;
}
# draw graph
for (my $height=int(-16.0 * ($velocity / 32.0) ** 2.0 + $velocity ** 2.0 / 32.0 + .5) ; $height >= 0 ; $height -= .5)
{
if (int($height) == $height) { print sprintf("%2d", $height); }
else { print " "; }
$line_pos = 0;
my $curr_line = "";
for my $i (1 .. $S1)
{
my $time;
for ($time=0 ; $time <= $T[$i] ; $time += $time_inc)
{
$line_pos += $time_inc;
if (abs($height - (.5 * (-32) * $time ** 2.0 + $velocity * $coeff_elas ** ($i - 1) * $time)) <= .25)
{
$curr_line = line_tab($curr_line, ($line_pos / $time_inc), "0");
}
}
$time = ($T[$i + 1] // 0) / 2; # we can reach 1 past the end, use 0 if that happens
last if (-16.0 * $time ** 2.0 + $velocity * $coeff_elas ** ($i - 1) * $time < $height);
}
print "$curr_line\n";
}
# draw scale
print " .";
print "." x (int($line_pos + 1) / $time_inc + 1), "\n";
print " 0";
my $curr_line = "";
for my $i (1 .. int($line_pos + .9995))
{
$curr_line = line_tab($curr_line, int($i / $time_inc), $i);
}
print "$curr_line\n";
print " " x (int($line_pos + 1) / (2 * $time_inc) - 2), "SECONDS\n\n";
}
+19
View File
@@ -1,3 +1,22 @@
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
Conversion to [Perl](https://www.perl.org/)
###Bowling program in Perl
Run normally, this is a fairly faithful translation of the Basic game.
The only real differences are a few trivial fix-ups on the prints to make it
look better, and the player/frame/ball line was put before the "get the ball
going" line to make it more obvious who's turn it is.
However, if you run it with "-a" on the command line, it will go into
"advanced" mode, which means that "." is used to show pin down and "!" for
pin up, current running scores are shown at the end of each frame, and the
scoring also looks more normal at the end. This is all done because I think it
looks better and I wanted to see a score. Having a flag says you can play
whichever version of the game you like.
Note, the original code doesn't do the 10th frame correctly, in that it will
never do more than 2 balls, so the best score you can get is a 290.
This is true in both modes. That being said, it will always give you a mediocre
game; I don't think I've ever seen a score over 140.
+254
View File
@@ -0,0 +1,254 @@
#!/usr/bin/perl
# Bowling program in Perl
# Run normally, this is a fairly faithful translation of the Basic game.
# The only real differences are a few trivial fix-ups on the prints to make it
# look better, and the player/frame/ball line was put before the "get the ball
# going" line to make it more obvious who's turn it is.
#
# However, if you run it with "-a" on the command line, it will go into
# 'advanced' mode, which means that "." is used to show pin down and "!" for
# pin up, current running scores are shown at the end of each frame, and the
# scoring also looks more normal at the end. This is all done because I think it
# looks better and I wanted to see a score. Having a flag says you can play
# whichever version of the game you like.
#
# Note, the original code doesn't do the 10th frame correctly, in that it will
# never do more than 2 balls, so the best score you can get is a 290.
# This is true in both modes. That being said, it will always give you a mediocre game.
# Translated by Kevin Brannen (kbrannen)
use strict;
use warnings;
print "\n";
print " " x 34, "BASKETBALL\n";
print " " x 15, "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n";
# globals
my @C; # pin position matraix?
my @Scores; # scores: [player num][frame][ball] # ball3 is end-result, ball4 is frame score (advanced mode)
my $Answer; # get answers
my $Num_players; # number of players
my $Advanced = 0; # flag, 1 to use advanced code, 0 for original code
my $char_down = '0'; # char to show pin is down
my $char_up = '+'; # char to show pin is standing
if ($ARGV[0] && $ARGV[0] eq "-a")
{
shift;
$Advanced = 1;
$char_down = '.';
$char_up = '!';
}
print "WELCOME TO THE ALLEY\n";
print "BRING YOUR FRIENDS\n";
print "OKAY LET'S FIRST GET ACQUAINTED\n\n";
print "SEE THE INSTRUCTIONS (Y/N): ";
chomp($Answer = uc(<>));
if ($Answer eq "Y")
{
print "THE GAME OF BOWLING TAKES MIND AND SKILL. DURING THE GAME\n";
print "THE COMPUTER WILL KEEP SCORE.YOU MAY COMPETE WITH\n";
print "OTHER PLAYERS[UP TO FOUR]. YOU WILL BE PLAYING TEN FRAMES\n";
print "ON THE PIN DIAGRAM 'O' MEANS THE PIN IS DOWN...'+' MEANS THE\n";
print "PIN IS STANDING. AFTER THE GAME THE COMPUTER WILL SHOW YOUR SCORES.\n";
}
do {
print "FIRST OF ALL...HOW MANY ARE PLAYING (1-4): ";
$Num_players = int(<>);
} while ($Num_players < 1 || $Num_players > 4);
print "\nVERY GOOD...\n";
while (1)
{
# reset all scores
for my $p (1 .. $Num_players) # players
{
for my $f (1 .. 10) # frames
{
for my $b (1 .. 3) # balls
{
$Scores[$p][$f][$b] = 0;
}
}
}
# play the game
for my $frame (1 .. 10) # frame
{
for my $curr_player (1 .. $Num_players) # player
{
my $last_pins=0; # pins down for last ball
my $ball=1; # ball number, 1 or 2
my $end_result=0; # result at end of turn: 3=strike, 2=spare, 1=pins-left
for my $i (1 .. 15) { $C[$i] = 0 }
while (1) # another ball
{
# ARK BALL GENERATOR USING MOD '15' SYSTEM
my $K=0;
my $curr_pins=0; # pins down for this ball
for my $i (1 .. 20)
{
my $x = int(rand(1) * 100);
my $j;
for ($j=1 ; $j <= 10 ; $j++)
{
last if ($x < 15 * $j);
}
$C[15 * $j - $x] = 1;
}
# ARK PIN DIAGRAM
print "PLAYER: $curr_player FRAME: $frame BALL: $ball\n";
print "PRESS ENTER TO GET THE BALL GOING.";
$Answer = <>; # not used, just need an enter
for my $i (0 .. 3)
{
print "\n";
print " " x $i; # avoid the TAB(), just shift each row over for the triangle
for my $j (1 .. 4 - $i)
{
$K++;
print ($C[$K] == 1 ? " $char_down" : " $char_up");
}
}
print "\n";
# ARK ROLL ANALYSIS
for my $i (1 .. 10)
{
$curr_pins += $C[$i];
}
if ($curr_pins - $last_pins == 0)
{
print "GUTTER!!\n";
}
if ($ball == 1 && $curr_pins == 10)
{
print "STRIKE!!!!!\a\a\a\a\n"; # \a is for bell
$end_result = 3;
}
elsif ($ball == 2 && $curr_pins == 10)
{
print "SPARE!!!!\n";
$end_result = 2;
}
elsif ($ball == 2 && $curr_pins < 10)
{
if ($Advanced) { print 10 - $curr_pins, " PENS LEFT!!!\n"; }
else { print "ERROR!!!\n"; }
$end_result = 1;
}
if ($ball == 1 && $curr_pins < 10)
{
print "ROLL YOUR 2ND BALL\n";
}
print "\n";
# ARK STORAGE OF THE SCORES
if ($Advanced) { $Scores[$curr_player][$frame][$ball] = $curr_pins - $last_pins; }
else { $Scores[$curr_player][$frame][$ball] = $curr_pins; }
if ($ball == 1)
{
$ball = 2;
$last_pins = $curr_pins;
if ($end_result == 3) # strike, no more rolls, goto last
{
$Scores[$curr_player][$frame][$ball] = $curr_pins;
}
else
{
$Scores[$curr_player][$frame][$ball] = $curr_pins - $last_pins;
next if ($end_result == 0); # next roll
}
}
last;
}
$Scores[$curr_player][$frame][3] = $end_result;
} # next player
if ($Advanced)
{
print "Scores:\n";
for my $p (1 .. $Num_players)
{
my $total = calc_score($p);
print "\tPlayer $p: $total\n";
}
print "\n";
}
} # next frame
# end of game, show full scoreboard
show_scoreboard();
print "DO YOU WANT ANOTHER GAME (Y/N): ";
chomp($Answer = uc(<>));
print "\n";
last if ($Answer ne "Y");
}
exit(0);
sub show_scoreboard
{
print "FRAMES\n";
for my $i (1 .. 10)
{
print " $i ";
}
print "\n";
my @results = ( "-", ".", "/", "X" );
for my $p (1 .. $Num_players)
{
print "Player $p\n" if ($Advanced);
my $ball_max = ($Advanced ? 4 : 3);
for my $b (1 .. $ball_max)
{
for my $f (1 .. 10)
{
if ($b != 3) { print sprintf("%2d ", $Scores[$p][$f][$b]); }
else { print sprintf("%2s ", $results[$Scores[$p][$f][$b]]); }
}
print "\n";
}
print "\n";
}
}
sub calc_score
{
my $player = shift;
my $total = 0;
for my $frame (1 .. 10)
{
my $score = 0;
if ($frame == 10 || $Scores[$player][$frame][3] == 1) # pins
{
$score = $Scores[$player][$frame][1] + $Scores[$player][$frame][2];
}
elsif ($Scores[$player][$frame][3] == 2) # spare
{
$score = 10 + $Scores[$player][$frame+1][1];
}
elsif ($Scores[$player][$frame][3] == 3) # strike
{
$score = 10 + $Scores[$player][$frame+1][1];
if ($Scores[$player][$frame+1][1] == 10)
{
$score += ($frame < 9 ? $Scores[$player][$frame+2][1] : $Scores[$player][$frame+1][2]);
}
else
{
$score += $Scores[$player][$frame+1][2];
}
}
$Scores[$player][$frame][4] = $score;
$total += $score;
}
return $total;
}
+252
View File
@@ -0,0 +1,252 @@
#!/usr/bin/perl
# Boxing program in Perl
# Required extensive restructuring to remove all of the GOTO's.
# Translated by Kevin Brannen (kbrannen)
use strict;
use warnings;
# globals
my $Opp_won = 0; # num rounds opponent has won
my $You_won = 0; # num rounds you have won
my $Opp_name = ""; # opponent name
my $Your_name = ""; # your name
my $Your_best = 0; # your best punch
my $Your_worst = 0; # your worst punch
my $Opp_best; # opponent best punch
my $Opp_worst; # opponent worst punch
my $Opp_damage; # opponent damage ?
my $Your_damage; # your damage ?
sub get_punch
{
my $prompt = shift;
my $p;
while (1)
{
print "$prompt: ";
chomp($p = int(<>));
last if ($p >= 1 && $p <= 4);
print "DIFFERENT PUNCHES ARE: (1) FULL SWING; (2) HOOK; (3) UPPERCUT; (4) JAB.\n";
}
return $p;
}
print "\n";
print " " x 33, "BOXING\n";
print " " x 15, "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n";
print "BOXING OLYMPIC STYLE (3 ROUNDS -- 2 OUT OF 3 WINS)\n\n";
print "WHAT IS YOUR OPPONENT'S NAME: ";
chomp($Opp_name = <>);
print "INPUT YOUR MAN'S NAME: ";
chomp($Your_name = <>);
print "DIFFERENT PUNCHES ARE: (1) FULL SWING; (2) HOOK; (3) UPPERCUT; (4) JAB.\n";
$Your_best = get_punch("WHAT IS YOUR MANS BEST");
$Your_worst = get_punch("WHAT IS HIS VULNERABILITY");
do {
$Opp_best = int(4*rand(1)+1);
$Opp_worst = int(4*rand(1)+1);
} while ($Opp_best == $Opp_worst);
print "$Opp_name\'S ADVANTAGE IS $Opp_best AND VULNERABILITY IS SECRET.\n\n";
for my $R (1 .. 3) # rounds
{
last if ($Opp_won >= 2 || $You_won >= 2);
$Opp_damage = 0;
$Your_damage = 0;
print "ROUND $R BEGINS...\n";
for my $R1 (1 .. 7) # 7 events per round?
{
if (int(10*rand(1)+1) <= 5)
{
my $your_punch = get_punch("$Your_name\'S PUNCH");
$Opp_damage += 2 if ($your_punch == $Your_best);
if ($your_punch == 1) { punch1(); }
elsif ($your_punch == 2) { punch2(); }
elsif ($your_punch == 3) { punch3(); }
else { punch4(); }
next;
}
my $Opp_punch = int(4*rand(1)+1);
$Your_damage += 2 if ($Opp_punch == $Opp_best);
if ($Opp_punch == 1) { opp1(); }
elsif ($Opp_punch == 2) { opp2(); }
elsif ($Opp_punch == 3) { opp3(); }
else { opp4(); }
}
if ($Opp_damage > $Your_damage)
{
print "\n$Your_name WINS ROUND $R\n\n";
$You_won++;
}
else
{
print "\n$Opp_name WINS ROUND $R\n\n";
$Opp_won++;
}
}
if ($Opp_won >= 2)
{
done("$Opp_name WINS (NICE GOING, $Opp_name).");
}
#else # if ($You_won >= 2)
done("$Your_name AMAZINGLY WINS!!");
###################################################
sub done
{
my $msg = shift;
print $msg;
print "\n\nAND NOW GOODBYE FROM THE OLYMPIC ARENA.\n\n";
exit(0);
}
sub punch1
{
# $your_punch == 1, full swing
print "$Your_name SWINGS AND ";
if ($Opp_worst == 4 || int(30*rand(1)+1) < 10)
{
print "HE CONNECTS!\n";
if ($Opp_damage > 35)
{
done("$Opp_name IS KNOCKED COLD AND $Your_name IS THE WINNER AND CHAMP! ");
}
$Opp_damage += 15;
}
else
{
print "HE MISSES\n";
print "\n\n" if ($Opp_damage != 1);
}
}
sub punch2
{
# $your_punch == 2, hook
print "$Your_name GIVES THE HOOK... ";
if ($Opp_worst == 2)
{
$Opp_damage += 7;
return;
}
if (int(2*rand(1)+1) == 1)
{
print "BUT IT'S BLOCKED!!!!!!!!!!!!!\n";
}
else
{
print "CONNECTS...\n";
$Opp_damage += 7;
}
}
sub punch3
{
# $your_punch == 3, uppercut
print "$Your_name TRIES AN UPPERCUT ";
if ($Opp_worst == 3 || int(100*rand(1)+1) < 51)
{
print "AND HE CONNECTS!\n";
$Opp_damage += 4;
}
else
{
print "AND IT'S BLOCKED (LUCKY BLOCK!)\n";
}
}
sub punch4
{
# $your_punch == 4, jab
print "$Your_name JABS AT $Opp_name\'S HEAD ";
if ($Opp_worst == 4 || (int(8*rand(1)+1)) >= 4)
{
$Opp_damage += 3;
print "\n";
}
else
{
print "IT'S BLOCKED.\n";
}
}
sub opp1
{
# opp_punch == 1
print "$Opp_name TAKES A FULL SWING AND ";
if ($Your_worst == 1 || int(60*rand(1)+1) < 30)
{
print " POW!!!!! HE HITS HIM RIGHT IN THE FACE!\n";
if ($Your_damage > 35)
{
done("$Your_name IS KNOCKED COLD AND $Opp_name IS THE WINNER AND CHAMP!");
}
$Your_damage += 15;
}
else
{
print " IT'S BLOCKED!\n";
}
}
sub opp2
{
# opp_punch == 2
print "$Opp_name GETS $Your_name IN THE JAW (OUCH!)\n";
$Your_damage += 7;
print "....AND AGAIN!\n";
$Your_damage += 5;
if ($Your_damage > 35)
{
done("$Your_name IS KNOCKED COLD AND $Opp_name IS THE WINNER AND CHAMP!");
}
print "\n";
# 2 continues into opp_punch == 3
opp3();
}
sub opp3()
{
# opp_punch == 3
print "$Your_name IS ATTACKED BY AN UPPERCUT (OH,OH)...\n";
if ($Your_worst != 3 && int(200*rand(1)+1) > 75)
{
print " BLOCKS AND HITS $Opp_name WITH A HOOK.\n";
$Opp_damage += 5;
}
else
{
print "AND $Opp_name CONNECTS...\n";
$Your_damage += 8;
}
}
sub opp4
{
# opp_punch == 4
print "$Opp_name JABS AND ";
if ($Your_worst == 4)
{
$Your_damage += 5;
}
elsif (int(7*rand(1)+1) > 4)
{
print " BLOOD SPILLS !!!\n";
$Your_damage += 5;
}
else
{
print "IT'S BLOCKED!\n";
}
}
+2
View File
@@ -27,3 +27,5 @@ http://www.vintage-basic.net/games.html
#### Porting Notes
(please note any difficulties or challenges in porting here)
- There is a fundamental assumption in the pre-fight subroutine at line 1610, that the Picadores and Toreadores are more likely to do a bad job (and possibly get killed) with a low-quality bull. This appears to be a mistake in the original code, but should be retained.
+356
View File
@@ -0,0 +1,356 @@
package bullfight
import bullfight.Yorn.*
import kotlin.random.Random
import kotlin.system.exitProcess
private val Boolean.asInteger get() = if (this) 1 else 2
private val Float.squared: Float
get() = this * this
val fna: Boolean get() = RandomNumbers.nextBoolean()
enum class Quality(private val typeName: String) {
Superb("SUPERB"),
Good("GOOD"),
Fair("FAIR"),
Poor("POOR"),
Awful("AWFUL");
override fun toString() = typeName
val level get() = (ordinal + 1).toFloat()
}
enum class BullDeath(val factor: Float) {
Alive(1f), Dead(2f);
}
var l = 1f
lateinit var bullQuality: Quality
var momentOfTruth = false
var picadoresSuccess = 0f
var toreadoresSuccess = 0f
var passNumber = 0f
var honor = 0f
var bullDeath = BullDeath.Alive
interface RandomNumberSource {
fun nextBoolean(): Boolean
fun nextInt(from: Int, until: Int): Int
fun nextFloat(): Float
}
object RandomNumbers : RandomNumberSource {
override fun nextBoolean() = Random.nextBoolean()
override fun nextInt(from: Int, until: Int) = Random.nextInt(from, until)
override fun nextFloat() = Random.nextFloat()
}
fun main() {
intro()
instructions()
bullDeath = BullDeath.Alive
honor = 1f
bullQuality = Quality.values()[RandomNumbers.nextInt(1, 6)]
println("YOU HAVE DRAWN A $bullQuality BULL.")
when (bullQuality) {
Quality.Superb -> println("GOOD LUCK. YOU'LL NEED IT.")
Quality.Awful -> println("YOU'RE LUCKY.")
else -> Unit
}
picadoresSuccess = fight(FirstAct.picadores)
toreadoresSuccess = fight(FirstAct.toreadores)
println()
println()
var gored: Boolean
gameLoop@ do {
passNumber++
println("PASS NUMBER ${passNumber.toInt()}")
gored = if (passNumber >= 3) {
print("HERE COMES THE BULL. TRY FOR A KILL")
killAttempt("CAPE MOVE")
} else {
println("THE BULL IS CHARGING AT YOU! YOU ARE THE MATADOR--")
print("DO YOU WANT TO KILL THE BULL")
killAttempt("WHAT MOVE DO YOU MAKE WITH THE CAPE")
}
if (!gored) {
val move = restrictedInput(
values = Cape.values(),
errorMessage = "DON'T PANIC, YOU IDIOT! PUT DOWN A CORRECT NUMBER"
)
val m = when (move) {
Cape.Veronica -> 3f
Cape.Outside -> 2f
Cape.Swirl -> 0.5f
}
l += m
val f =
(6 - bullQuality.level + m / 10f) * RandomNumbers.nextFloat() / ((picadoresSuccess + toreadoresSuccess + passNumber / 10f) * 5f)
if (f < 0.51)
continue
}
println("THE BULL HAS GORED YOU!")
goreLoop@ do {
when (fna) {
false -> {
println("YOU ARE DEAD.")
honor = 1.5f
gameResult()
}
true -> {
println("YOU ARE STILL ALIVE.")
println()
print("DO YOU RUN FROM THE RING")
when (Yorn.input()) {
YES -> {
println("COWARD")
honor = 0f
}
NO -> {
println("YOU ARE BRAVE. STUPID, BUT BRAVE.")
when (fna) {
true -> {
honor = 2f
continue@gameLoop
}
false -> {
println("YOU ARE GORED AGAIN!")
continue@goreLoop
}
}
}
}
}
}
} while (true)
} while (true)
}
fun fnd() = 4.5 +
l / 6 -
(picadoresSuccess + toreadoresSuccess) * 2.5 +
4 * honor +
2 * bullDeath.factor -
passNumber.squared / 120f -
bullQuality.level
fun fnc() = fnd() * RandomNumbers.nextFloat()
private fun killAttempt(capeMessage: String): Boolean {
when (Yorn.input()) {
YES ->
when (momentOfTruth()) {
KillResult.Success -> gameResult()
KillResult.Fail -> return true
}
NO ->
print(capeMessage)
}
return false
}
private fun gameResult() {
println()
println()
if (honor == 0f) {
println(
"""
THE CROWD BOOS FOR TEN MINUTES. IF YOU EVER DARE TO SHOW
YOUR FACE IN A RING AGAIN, THEY SWEAR THEY WILL KILL YOU--
UNLESS THE BULL DOES FIRST.
""".trimIndent()
)
} else {
if (honor == 2f)
println("THE CROWD CHEERS WILDLY!")
else
if (bullDeath == BullDeath.Dead) {
println("THE CROWD CHEERS!")
println()
}
println("THE CROWD AWARDS YOU")
if (fnc() < 2.4)
println("NOTHING AT ALL.")
else if (fnc() < 4.9)
println("ONE EAR OF THE BULL.")
else
if (fnc() < 7.4)
println("BOTH EARS OF THE BULL!")
else
println("OLE! YOU ARE 'MUY HOMBRE'!! OLE! OLE!")
println()
}
println()
println("ADIOS")
println()
println()
println()
exitProcess(0)
}
enum class KillResult { Success, Fail }
fun momentOfTruth(): KillResult {
momentOfTruth = true
print(
"""
IT IS THE MOMENT OF TRUTH.
HOW DO YOU WANT TO KILL THE BULL
""".trimIndent()
)
val k =
(6 - bullQuality.level) * 10 * RandomNumbers.nextFloat() / ((picadoresSuccess + toreadoresSuccess) * 5 * passNumber)
val chance = when (stdInput(KillMethod.values())) {
KillMethod.OverHorns -> .8
KillMethod.Chest -> .2
null -> {
println("YOU PANICKED. THE BULL GORED YOU.")
return KillResult.Fail
}
}
return if (k <= chance) {
println("YOU KILLED THE BULL!")
bullDeath = BullDeath.Dead
KillResult.Success
} else {
println("THE BULL HAS GORED YOU!")
KillResult.Fail
}
}
interface InputOption {
val input: String
}
enum class Cape(override val input: String) : InputOption {
Veronica("0"),
Outside("1"),
Swirl("2"),
}
enum class KillMethod(override val input: String) : InputOption {
OverHorns("4"),
Chest("5"),
}
private fun <T : InputOption> restrictedInput(values: Array<T>, errorMessage: String): T {
do {
stdInput(values)?.let { return it }
println(errorMessage)
} while (true)
}
private fun <T : InputOption> stdInput(values: Array<T>): T? {
print("? ")
val z1 = readln()
return values.firstOrNull { z1 == it.input }
}
enum class Yorn(override val input: String) : InputOption {
YES("YES"), NO("NO");
companion object {
fun input(): Yorn {
return restrictedInput(values(), "YES OR NO")
}
}
}
enum class FirstAct(val str: String) {
picadores("PICADORES"), toreadores("TOREADORES");
override fun toString() = str
}
fun fight(firstAct: FirstAct): Float {
val b = 3.0 / bullQuality.level * RandomNumbers.nextFloat()
val firstActQuality = when {
b < .37 -> Quality.Awful
b < .5 -> Quality.Poor
b < .63 -> Quality.Fair
b < .87 -> Quality.Good
else -> Quality.Superb
}
val c = firstActQuality.level / 10f
val t = firstActQuality.level
println("THE $firstAct DID A $firstActQuality JOB.")
if (t >= 4f) {
if (t == 5f) {
if (firstAct != FirstAct.toreadores) {
println("${fna.asInteger} OF THE HORSES OF THE $firstAct KILLED.")
}
println("${fna.asInteger} OF THE $firstAct KILLED.")
} else {
println(
when (fna) {
true -> "ONE OF THE $firstAct WAS KILLED."
false -> "NO $firstAct WERE KILLED."
}
)
}
}
println()
return c
}
private fun instructions() {
print("DO YOU WANT INSTRUCTIONS? ")
if (readln().trim() != "NO") {
println("HELLO, ALL YOU BLOODLOVERS AND AFICIONADOS.")
println("HERE IS YOUR BIG CHANCE TO KILL A BULL.")
println()
println("ON EACH PASS OF THE BULL, YOU MAY TRY")
println("0 - VERONICA (DANGEROUS INSIDE MOVE OF THE CAPE)")
println("1 - LESS DANGEROUS OUTSIDE MOVE OF THE CAPE")
println("2 - ORDINARY SWIRL OF THE CAPE.")
println()
println("INSTEAD OF THE ABOVE, YOU MAY TRY TO KILL THE BULL")
println("ON ANY TURN: 4 (OVER THE HORNS), 5 (IN THE CHEST).")
println("BUT IF I WERE YOU,")
println("I WOULDN'T TRY IT BEFORE THE SEVENTH PASS.")
println()
println("THE CROWD WILL DETERMINE WHAT AWARD YOU DESERVE")
println("(POSTHUMOUSLY IF NECESSARY).")
println("THE BRAVER YOU ARE, THE BETTER THE AWARD YOU RECEIVE.")
println()
println("THE BETTER THE JOB THE PICADORES AND TOREADORES DO,")
println("THE BETTER YOUR CHANCES ARE.")
}
repeat(2) {
println()
}
}
fun intro() {
println(" ".repeat(34) + "BULL")
println(" ".repeat(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY")
println()
println()
println()
}
+8
View File
@@ -0,0 +1,8 @@
[package]
name = "rust"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
+3
View File
@@ -0,0 +1,3 @@
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
Conversion to [Rust](https://www.rust-lang.org/) by [Uğur Küpeli](https://github.com/ugurkupeli)
+152
View File
@@ -0,0 +1,152 @@
use std::io::stdin;
const WIDTH: usize = 64;
const DAYS_WIDTH: usize = WIDTH / 8;
const MONTH_WIDTH: usize = WIDTH - (DAYS_WIDTH * 2);
const DAY_NUMS_WIDTH: usize = WIDTH / 7;
const DAYS: [&str; 7] = [
"SUNDAY",
"MONDAY",
"TUESDAY",
"WEDNESDAY",
"THURSDAY",
"FRIDAY",
"SATURDAY",
];
fn main() {
println!("\n\t\t CALENDAR");
println!("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n");
let (starting_day, leap_year) = prompt();
let (months, total_days) = get_months_and_days(leap_year);
let mut days_passed = 0;
let mut current_day_index = DAYS.iter().position(|d| *d == starting_day).unwrap();
for (month, days) in months {
print_header(month, days_passed, total_days - days_passed);
print_days(&mut current_day_index, days);
days_passed += days as u16;
println!("\n");
}
}
fn prompt() -> (String, bool) {
let mut day = String::new();
loop {
println!("\nFirst day of the year?");
if let Ok(_) = stdin().read_line(&mut day) {
day = day.trim().to_uppercase();
if DAYS.contains(&day.as_str()) {
break;
} else {
day.clear();
}
}
}
let mut leap = false;
loop {
println!("Is this a leap year?");
let mut input = String::new();
if let Ok(_) = stdin().read_line(&mut input) {
match input.to_uppercase().trim() {
"Y" | "YES" => {
leap = true;
break;
}
"N" | "NO" => break,
_ => (),
}
}
}
println!();
(day, leap)
}
fn get_months_and_days(leap_year: bool) -> (Vec<(String, u8)>, u16) {
let months = [
"JANUARY",
"FEBUARY",
"MARCH",
"APRIL",
"MAY",
"JUNE",
"JULY",
"AUGUST",
"SEPTEMBER",
"OCTOBER",
"NOVEMBER",
"DECEMBER",
];
let mut months_with_days = Vec::new();
let mut total_days: u16 = 0;
for (i, month) in months.iter().enumerate() {
let days = if i == 1 {
if leap_year {
29u8
} else {
28
}
} else if if i < 7 { (i % 2) == 0 } else { (i % 2) != 0 } {
31
} else {
30
};
total_days += days as u16;
months_with_days.push((month.to_string(), days));
}
(months_with_days, total_days)
}
fn print_between(s: String, w: usize, star: bool) {
let s = format!(" {s} ");
if star {
print!("{:*^w$}", s);
return;
}
print!("{:^w$}", s);
}
fn print_header(month: String, days_passed: u16, days_left: u16) {
print_between(days_passed.to_string(), DAYS_WIDTH, true);
print_between(month.to_string(), MONTH_WIDTH, true);
print_between(days_left.to_string(), DAYS_WIDTH, true);
println!();
for d in DAYS {
let d = d.chars().nth(0).unwrap();
print_between(d.to_string(), DAY_NUMS_WIDTH, false);
}
println!();
println!("{:*>WIDTH$}", "");
}
fn print_days(current_day_index: &mut usize, days: u8) {
let mut current_date = 1u8;
print!("{:>w$}", " ", w = DAY_NUMS_WIDTH * *current_day_index);
for _ in 1..=days {
print_between(current_date.to_string(), DAY_NUMS_WIDTH, false);
if ((*current_day_index + 1) % 7) == 0 {
*current_day_index = 0;
println!();
} else {
*current_day_index += 1;
}
current_date += 1;
}
}
+2
View File
@@ -17,5 +17,7 @@ http://www.vintage-basic.net/games.html
(please note any difficulties or challenges in porting here)
There is a type in the original Basic, "...DECIDE **WHO** MUCH WATER..." should be "DECIDE **HOW** MUCH WATER"
#### External Links
- C: https://github.com/ericfischer/basic-computer-games/blob/main/24%20Chemist/c/chemist.c
+9
View File
@@ -0,0 +1,9 @@
[package]
name = "rust"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rand = "0.8.5"
+3
View File
@@ -0,0 +1,3 @@
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
Conversion to [Rust](https://www.rust-lang.org/) by Anthony Rubick [AnthonyMichaelTDM](https://github.com/AnthonyMichaelTDM)
+158
View File
@@ -0,0 +1,158 @@
/*
lib.rs contains all the logic of the program
*/
use rand::{Rng, prelude::thread_rng}; //rng
use std::error::Error; //better errors
use std::io::{self, Write}; //io interactions
use std::{str::FromStr, fmt::Display}; //traits
//DATA
/// handles setup for the game
pub struct Config {
}
impl Config {
/// creates and returns a new Config from user input
pub fn new() -> Result<Config, Box<dyn Error>> {
//DATA
let config: Config = Config {
};
//return new config
return Ok(config);
}
}
/// run the program
pub fn run(_config: &Config) -> Result<(), Box<dyn Error>> {
//DATA
let mut rng = thread_rng();
let mut lives: i8 = 9;
let mut amount_of_acid:i8;
let mut guess:f32;
let mut answer:f32;
let mut error:f32;
//Game loop
loop {
//initialize variables
amount_of_acid = rng.gen_range(1..50);
answer = 7.0 * (amount_of_acid as f32/3.0);
//print starting message / conditions
println!();
//get guess
guess = loop {
match get_number_from_input(&format!("{} Liters of Kryptocyanic acid. How much water? ", amount_of_acid),0.0,-1.0) {
Ok(num) => break num,
Err(err) => {
eprintln!("{}",err);
continue;
},
}
};
//calculate error
error = (answer as f32 - guess).abs() / guess;
println!("answer: {} | error: {}%", answer,error*100.);
//check guess against answer
if error > 0.05 { //error > 5%
println!(" Sizzle! You may have just been desalinated into a blob");
println!(" of quivering protoplasm!");
//update lives
lives -= 1;
if lives <= 0 {
println!(" Your 9 lives are used, but you will be long remembered for");
println!(" your contributions to the field of comic book chemistry.");
break;
}
else {
println!(" However, you may try again with another life.")
}
} else {
println!(" Good job! You may breathe now, but don't inhale the fumes!");
println!();
}
}
//return to main
Ok(())
}
/// gets a string from user input
fn get_string_from_user_input(prompt: &str) -> Result<String, Box<dyn Error>> {
//DATA
let mut raw_input = String::new();
//print prompt
print!("{}", prompt);
//make sure it's printed before getting input
io::stdout().flush().expect("couldn't flush stdout");
//read user input from standard input, and store it to raw_input, then return it or an error as needed
raw_input.clear(); //clear input
match io::stdin().read_line(&mut raw_input) {
Ok(_num_bytes_read) => return Ok(String::from(raw_input.trim())),
Err(err) => return Err(format!("ERROR: CANNOT READ INPUT!: {}", err).into()),
}
}
/// generic function to get a number from the passed string (user input)
/// pass a min lower than the max to have minimum and maximum bounds
/// pass a min higher than the max to only have a minimum bound
/// pass a min equal to the max to only have a maximum bound
///
/// Errors:
/// no number on user input
fn get_number_from_input<T:Display + PartialOrd + FromStr>(prompt: &str, min:T, max:T) -> Result<T, Box<dyn Error>> {
//DATA
let raw_input: String;
let processed_input: String;
//input loop
raw_input = loop {
match get_string_from_user_input(prompt) {
Ok(input) => break input,
Err(e) => {
eprintln!("{}",e);
continue;
},
}
};
//filter out non-numeric characters from user input
processed_input = raw_input.chars().filter(|c| c.is_numeric()).collect();
//from input, try to read a number
match processed_input.trim().parse() {
Ok(i) => {
//what bounds must the input fall into
if min < max { //have a min and max bound: [min,max]
if i >= min && i <= max {//is input valid, within bounds
return Ok(i); //exit the loop with the value i, returning it
} else { //print error message specific to this case
return Err(format!("ONLY BETWEEN {} AND {}, PLEASE!", min, max).into());
}
} else if min > max { //only a min bound: [min, infinity)
if i >= min {
return Ok(i);
} else {
return Err(format!("NO LESS THAN {}, PLEASE!", min).into());
}
} else { //only a max bound: (-infinity, max]
if i <= max {
return Ok(i);
} else {
return Err(format!("NO MORE THAN {}, PLEASE!", max).into());
}
}
},
Err(_e) => return Err(format!("Error: couldn't find a valid number in {}",raw_input).into()),
}
}
+46
View File
@@ -0,0 +1,46 @@
use std::process;//allows for some better error handling
mod lib; //allows access to lib.rs
use lib::Config;
/// main function
/// responsibilities:
/// - Calling the command line logic with the argument values
/// - Setting up any other configuration
/// - Calling a run function in lib.rs
/// - Handling the error if run returns an error
fn main() {
//greet user
welcome();
// set up other configuration
let mut config = Config::new().unwrap_or_else(|err| {
eprintln!("Problem configuring program: {}", err);
process::exit(1);
});
// run the program
if let Err(e) = lib::run(&mut config) {
eprintln!("Application Error: {}", e); //use the eprintln! macro to output to standard error
process::exit(1); //exit the program with an error code
}
//end of program
println!("THANKS FOR PLAYING!");
}
/// print the welcome message
fn welcome() {
println!("
Chemist
CREATIVE COMPUTING MORRISTOWN, NEW JERSEY
The fictitious chemical kryptocyanic acid can only be
diluted by the ratio of 7 parts water to 3 parts acid.
If any other ratio is attempted, the acid becomes unstable
and soon explodes. Given the amount of acid, you must
decide how much water to add for dilution. If you miss
you face the consequences.
");
}
+22 -1
View File
@@ -1,3 +1,24 @@
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
Conversion to [Lua](https://www.lua.org/)
Conversion to [Lua](https://www.lua.org/) by Alex Conconi
---
### Lua porting notes
- I did not like the old Western movie language style in the game introduction
and decided to tone it down, even if this deviates from the original BASIC
version.
- The `craps_game` function contains the main game logic: it
- prints the game credits and presents the intro question;
- asks for the end result and computes the original numer;
- calls `explain_solution` to print the various steps of the computation;
- presents the outro question and prints a `bolt` if necessary.
- Added basic input validation to accept only valid integers for numeric input.
- Minor formatting edits (lowercase, punctuation).
- Any answer to a "yes or no" question is regarded as "yes" if the input line
starts with 'y' or 'Y', else no.
+121
View File
@@ -0,0 +1,121 @@
--[[
Chief
From: BASIC Computer Games (1978)
Edited by David H. Ahl
In the words of the program author, John Graham, “CHIEF is designed to
give people (mostly kids) practice in the four operations (addition,
multiplication, subtraction, and division).
It does this while giving people some fun. And then, if the people are
wrong, it shows them how they should have done it.
CHIEF was written by John Graham of Upper Brookville, New York.
Lua port by Alex Conconi, 2022.
]]--
--- Helper function for tabulating messages.
local function space(n) return string.rep(" ", n) end
--- Generates a multi-line string representing a lightning bolt
local function bolt()
local bolt_lines = {}
for n = 29, 21, -1 do
table.insert(bolt_lines, space(n) .. "x x")
end
table.insert(bolt_lines, space(20) .. "x xxx")
table.insert(bolt_lines, space(19) .. "x x")
table.insert(bolt_lines, space(18) .. "xx x")
for n = 19, 12, -1 do
table.insert(bolt_lines, space(n) .. "x x")
end
table.insert(bolt_lines, space(11) .. "xx")
table.insert(bolt_lines, space(10) .. "x")
table.insert(bolt_lines, space(9) .. "*\n")
table.insert(bolt_lines, string.rep("#", 25) .. "\n")
return table.concat(bolt_lines, "\n")
end
--- Print the prompt and read a yes/no answer from stdin.
local function ask_yes_or_no(prompt)
io.stdout:write(prompt .. " ")
local answer = string.lower(io.stdin:read("*l"))
-- any line starting with a 'y' or 'Y' is considered a 'yes'
return answer:sub(1, 1) == "y"
end
--- Print the prompt and read a valid number from stdin.
local function ask_number(prompt)
io.stdout:write(prompt .. " ")
while true do
local n = tonumber(io.stdin:read("*l"))
if n then
return n
else
print("Enter a valid number.")
end
end
end
--- Explain the solution to persuade the player.
local function explain_solution()
local k = ask_number("What was your original number?")
-- For clarity we kept the same variable names of the original BASIC version
local f = k + 3
local g = f / 5
local h = g * 8
local i = h / 5 + 5
local j = i - 1
print("So you think you're so smart, eh?")
print("Now watch.")
print(k .. " plus 3 equals " .. f .. ". This divided by 5 equals " .. g .. ";")
print("this times 8 equals " .. h .. ". If we divide by 5 and add 5,")
print("we get " .. i .. ", which, minus 1, equals " .. j .. ".")
end
--- Main game function.
local function chief_game()
--- Print game introduction and challenge
print(space(29) .. "Chief")
print(space(14) .. "Creative Computing Morristown, New Jersey\n\n")
print("I am Chief Numbers Freek, the great math god.")
if not ask_yes_or_no("Are you ready to take the test you called me out for?") then
print("Shut up, wise tongue.")
end
-- Print how to obtain the end result.
print(" Take a number and add 3. Divide this number by 5 and")
print("multiply by 8. Divide by 5 and add the same. Subtract 1.")
-- Ask the result end and reverse calculate the original number.
local end_result = ask_number(" What do you have?")
local original_number = (end_result + 1 - 5) * 5 / 8 * 5 - 3
-- If it is an integer we do not want to print any zero decimals.
local int_part, dec_part = math.modf(original_number)
if dec_part == 0 then original_number = int_part end
-- If the player challenges the answer, print the explanation.
if not ask_yes_or_no("I bet your number was " .. original_number .. ". Am I right?") then
explain_solution()
-- If the player does not accept the explanation, zap them.
if not ask_yes_or_no("Now do you believe me?") then
print("YOU HAVE MADE ME MAD!!!")
print("THERE MUST BE A GREAT LIGHTNING BOLT!\n\n")
print(bolt())
print("I hope you believe me now, for your sake!!")
end
end
end
--- Run the game.
chief_game()
+202
View File
@@ -0,0 +1,202 @@
#!/usr/bin/perl
# Combat program in Perl
# Translated by Kevin Brannen (kbrannen)
use strict;
use warnings;
# globals
my $User_army;
my $User_navy;
my $User_AF;
my $Comp_army = 30000;
my $Comp_navy = 20000;
my $Comp_AF = 22000;
my $Attack_type;
my $Attack_num;
print "\n";
print " " x 33, "COMBAT\n";
print " " x 15, "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n";
print "I AM AT WAR WITH YOU.\nWE HAVE 72000 SOLDIERS APIECE.\n\n";
do {
print "DISTRIBUTE YOUR FORCES.\n";
print "\tME\t YOU\n";
print "ARMY\t$Comp_army\t";
chomp($User_army = <>);
print "NAVY\t$Comp_navy\t";
chomp($User_navy = <>);
print "A. F.\t$Comp_AF\t";
chomp($User_AF = <>);
} while ($User_army + $User_navy + $User_AF > 72000);
do {
print "YOU ATTACK FIRST. TYPE (1) FOR ARMY; (2) FOR NAVY;\n";
print "AND (3) FOR AIR FORCE.\n";
chomp($Attack_num = <>);
} while ($Attack_type < 1 && $Attack_type > 3);
do {
print "HOW MANY MEN\n";
chomp($Attack_type = <>);
} while ($Attack_type < 0
|| ($Attack_num == 1 && $Attack_type > $User_army)
|| ($Attack_num == 2 && $Attack_type > $User_navy)
|| ($Attack_num == 3 && $Attack_type > $User_AF));
if ($Attack_num == 1)
{
if ($Attack_type<$User_army/3)
{
print "YOU LOST $Attack_type MEN FROM YOUR ARMY.\n";
$User_army = int($User_army-$Attack_type);
}
if ($Attack_type<2*$User_army/3)
{
print "YOU LOST ", int($Attack_type/3), " MEN, BUT I LOST ", int(2*$Comp_army/3), "\n";
$User_army = int($User_army-$Attack_type/3);
$Comp_army = int(2*$Comp_army/3);
}
else
{
s270();
}
}
elsif ($Attack_num == 2)
{
if ($Attack_type < $Comp_navy/3)
{
print "YOUR ATTACK WAS STOPPED!\n";
$User_navy = int($User_navy-$Attack_type);
}
if ($Attack_type < 2*$Comp_navy/3)
{
print "YOU DESTROYED ", int(2*$Comp_navy/3), " OF MY ARMY.\n";
$Comp_navy = int(2*$Comp_navy/3);
}
else
{
s270();
}
}
else # $Attack_num == 3
{
if ($Attack_type < $User_AF/3)
{
print "YOUR ATTACK WAS WIPED OUT.\n";
$User_AF = int($User_AF-$Attack_type);
}
if ($Attack_type < 2*$User_AF/3)
{
print "WE HAD A DOGFIGHT. YOU WON - AND FINISHED YOUR MISSION.\n";
$Comp_army = int(2*$Comp_army/3);
$Comp_navy = int($Comp_navy/3);
$Comp_AF = int($Comp_AF/3);
}
else
{
print "YOU WIPED OUT ONE OF MY ARMY PATROLS, BUT I DESTROYED\n";
print "TWO NAVY BASES AND BOMBED THREE ARMY BASES.\n";
$User_army = int($User_army/4);
$User_navy = int($User_navy/3);
$User_AF = int(2*$User_AF/3);
}
}
print "\n\tYOU\tME\n";
print "ARMY\t$User_army\t$Comp_army\n";
print "NAVY\t$User_navy\t$Comp_navy\n";
print "A. F.\t$User_AF\t$Comp_AF\n";
do {
print "WHAT IS YOUR NEXT MOVE?\n";
print "ARMY=1 NAVY=2 AIR FORCE=3\n";
chomp($Attack_type = <>);
} while ($Attack_type < 1 && $Attack_type > 3);
do {
print "HOW MANY MEN\n";
chomp($Attack_num = <>);
} while ($Attack_num < 0
|| ($Attack_type == 1 && $Attack_num > $User_army)
|| ($Attack_type == 2 && $Attack_num > $User_navy)
|| ($Attack_type == 3 && $Attack_num > $User_AF));
if ($Attack_num == 1)
{
if ($Attack_num < $Comp_army/2)
{
print "I WIPED OUT YOUR ATTACK!\n";
$User_army -= $Attack_num;
}
else
{
print "YOU DESTROYED MY ARMY!\n";
$Comp_army = 0;
}
}
elsif ($Attack_num == 2)
{
if ($Attack_num < $Comp_navy/2)
{
print "I SUNK TWO OF YOUR BATTLESHIPS, AND MY AIR FORCE\n";
print "WIPED OUT YOUR UNGAURDED CAPITOL.\n";
$User_army /= 4;
$User_navy /= 2;
}
else
{
print "YOUR NAVY SHOT DOWN THREE OF MY XIII PLANES,\n";
print "AND SUNK THREE BATTLESHIPS.\n";
$Comp_AF = 2*$Comp_AF/3;
$Comp_navy /= 2;
}
}
else # $Attack_num == 3
{
if ($Attack_num > $Comp_AF/2)
{
print "MY NAVY AND AIR FORCE IN A COMBINED ATTACK LEFT\n";
print "YOUR COUNTRY IN SHAMBLES.\n";
$User_army /= 3;
$User_navy /= 3;
$User_AF /= 3;
}
else
{
print "ONE OF YOUR PLANES CRASHED INTO MY HOUSE. I AM DEAD.\n";
print "MY COUNTRY FELL APART.\n";
$Comp_army = $Comp_navy = $Comp_AF = 0;
}
}
print "\nFROM THE RESULTS OF BOTH OF YOUR ATTACKS,\n";
my $total_user = $User_army+$User_navy+$User_AF;
my $total_comp = $Comp_army+$Comp_navy+$Comp_AF;
if ($total_user > 3/2*($total_comp))
{
print "YOU WON, OH! SHUCKS!!!!\n";
}
elsif ($total_user < 2/3*($total_comp))
{
print "YOU LOST-I CONQUERED YOUR COUNTRY. IT SERVES YOU\n";
print "RIGHT FOR PLAYING THIS STUPID GAME!!!\n";
}
else
{
print "THE TREATY OF PARIS CONCLUDED THAT WE TAKE OUR\n";
print "RESPECTIVE COUNTRIES AND LIVE IN PEACE.\n";
}
print "\n";
exit(0);
#######################################################
sub s270
{
print "YOU SUNK ONE OF MY PATROL BOATS, BUT I WIPED OUT TWO\n";
print "OF YOUR AIR FORCE BASES AND 3 ARMY BASES.\n";
$User_army = int($User_army/3);
$User_AF = int($User_AF/3);
$Comp_navy = int(2*$Comp_navy/3);
}
+15 -1
View File
@@ -1,3 +1,17 @@
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
Conversion to [Lua](https://www.lua.org/)
Conversion to [Lua](https://www.lua.org/) by Alex Conconi
---
### Lua porting notes
- The `craps_main` function contains the main game loop, which iteratively
plays craps rounds by calling `play_round` and tracks winnings and losings.
- Replaced the original routine that tries to scramble the random number
generator with a proper seed initializer in Lua: `math.randomseed(os.time())`
(as advised in the general porting notes).
- Added basic input validation to accept only positive integers for the
wager and the answer to the "If you want to play again print 5" question.
- "If you want to play again print 5 if not print 2" reads a bit odd but
we decided to leave it as is and stay true to the BASIC original version.
+149
View File
@@ -0,0 +1,149 @@
--[[
Craps
From: BASIC Computer Games (1978)
Edited by David H. Ahl
This game simulates the games of craps played according to standard
Nevada craps table rules. That is:
1. A 7 or 11 on the first roll wins
2. A 2, 3, or 12 on the first roll loses
3. Any other number rolled becomes your "point." You continue to roll;
if you get your point you win. If you roll a 7, you lose and the dice
change hands when this happens.
This version of craps was modified by Steve North of Creative Computing.
It is based on an original which appeared one day one a computer at DEC.
Lua port by Alex Conconi, 2022
--]]
--- Throw two dice and return their sum.
local function throw_dice()
return math.random(1, 6) + math.random(1, 6)
end
--- Print prompt and read a number > 0 from stdin.
local function input_number(prompt)
while true do
io.write(prompt)
local number = tonumber(io.stdin:read("*l"))
if number and number > 0 then
return number
else
print("Please enter a number greater than zero.")
end
end
end
--- Print custom balance message depending on balance value
local function print_balance(balance, under_msg, ahead_msg, even_msg)
if balance < 0 then
print(under_msg)
elseif balance > 0 then
print(ahead_msg)
else
print(even_msg)
end
end
--- Play a round and return winnings or losings.
local function play_round()
-- Input the wager
local wager = input_number("Input the amount of your wager: ")
-- Roll the die for the first time.
print("I will now throw the dice")
local first_roll = throw_dice()
-- A 7 or 11 on the first roll wins.
if first_roll == 7 or first_roll == 11 then
print(string.format("%d - natural.... a winner!!!!", first_roll))
print(string.format("%d pays even money, you win %d dollars", first_roll, wager))
return wager
end
-- A 2, 3, or 12 on the first roll loses.
if first_roll == 2 or first_roll == 3 or first_roll == 12 then
if first_roll == 2 then
-- Special 'you lose' message for 'snake eyes'
print(string.format("%d - snake eyes.... you lose.", first_roll))
else
-- Default 'you lose' message
print(string.format("%d - craps.... you lose.", first_roll))
end
print(string.format("You lose %d dollars", wager))
return -wager
end
-- Any other number rolled becomes the "point".
-- Continue to roll until rolling a 7 or point.
print(string.format("%d is the point. I will roll again", first_roll))
while true do
local second_roll = throw_dice()
if second_roll == first_roll then
-- Player gets point and wins
print(string.format("%d - a winner.........congrats!!!!!!!!", first_roll))
print(string.format("%d at 2 to 1 odds pays you...let me see... %d dollars", first_roll, 2 * wager))
return 2 * wager
end
if second_roll == 7 then
-- Player rolls a 7 and loses
print(string.format("%d - craps. You lose.", second_roll))
print(string.format("You lose $ %d", wager))
return -wager
end
-- Continue to roll
print(string.format("%d - no point. I will roll again", second_roll))
end
end
--- Main game function.
local function craps_main()
-- Print the introduction to the game
print(string.rep(" ", 32) .. "Craps")
print(string.rep(" ", 14) .. "Creative Computing Morristown, New Jersey\n\n")
print("2,3,12 are losers; 4,5,6,8,9,10 are points; 7,11 are natural winners.")
-- Initialize random number generator seed
math.randomseed(os.time())
-- Initialize balance to track winnings and losings
local balance = 0
-- Main game loop
local keep_playing = true
while keep_playing do
-- Play a round
balance = balance + play_round()
-- If player's answer is 5, then stop playing
keep_playing = (input_number("If you want to play again print 5 if not print 2: ") == 5)
-- Print an update on winnings or losings
print_balance(
balance,
string.format("You are now under $%d", -balance),
string.format("You are now ahead $%d", balance),
"You are now even at 0"
)
end
-- Game over, print the goodbye message
print_balance(
balance,
"Too bad, you are in the hole. Come again.",
"Congratulations---you came out a winner. Come again.",
"Congratulations---you came out even, not bad for an amateur"
)
end
--- Run the game.
craps_main()
+14 -1
View File
@@ -1,3 +1,16 @@
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
Conversion to [Lua](https://www.lua.org/)
Conversion to [Lua](https://www.lua.org/) by Alex Conconi
---
### Porting notes for Lua
- This is a straightfoward port with only minor modifications for input
validation and text formatting.
- The "Try again?" question accepts 'y', 'yes', 'n', 'no' (case insensitive),
whereas the original BASIC version defaults to no unless 'YES' is typed.
- The "How many rolls?" question presents a more user friendly message
in case of invalid input.
+112
View File
@@ -0,0 +1,112 @@
--[[
Dice
From: BASIC Computer Games (1978)
Edited by David H. Ahl
"Not exactly a game, this program simulates rolling
a pair of dice a large number of times and prints out
the frequency distribution. You simply input the
number of rolls. It is interesting to see how many
rolls are necessary to approach the theoretical
distribution:
2 1/36 2.7777...%
3 2/36 5.5555...%
4 3/36 8.3333...%
etc.
"Daniel Freidus wrote this program while in the
seventh grade at Harrison Jr-Sr High School,
Harrison, New York."
Lua port by Alex Conconi, 2022.
]]--
local function print_intro()
print("\n" .. string.rep(" ", 19) .. "Dice")
print("Creative Computing Morristown, New Jersey\n\n")
print("This program simulates the rolling of a")
print("pair of dice.")
print("You enter the number of times you want the computer to")
print("'roll' the dice. Watch out, very large numbers take")
print("a long time. In particular, numbers over 5000.")
end
local function ask_how_many_rolls()
while true do
-- Print prompt and read a valid number from stdin
print("\nHow many rolls?")
local num_rolls = tonumber(io.stdin:read("*l"))
if num_rolls then
return num_rolls
else
print("Please enter a valid number.")
end
end
end
local function ask_try_again()
while true do
-- Print prompt and read a yes/no answer from stdin,
-- accepting only 'yes', 'y', 'no' or 'n' (case insensitive)
print("\nTry again? ([y]es / [n]o)")
local answer = string.lower(io.stdin:read("*l"))
if answer == "yes" or answer == "y" then
return true
elseif answer == "no" or answer == "n" then
return false
else
print("Please answer '[y]es' or '[n]o'.")
end
end
end
local function roll_dice(num_rolls)
-- Initialize a table to track counts of roll outcomes
local counts = {}
for i=2, 12 do
counts[i] = 0
end
-- Roll the dice num_rolls times and update outcomes counts accordingly
for _=1, num_rolls do
local roll_total = math.random(1, 6) + math.random(1, 6)
counts[roll_total] = counts[roll_total] + 1
end
return counts
end
local function print_results(counts)
print("\nTotal Spots Number of Times")
for roll_total, count in pairs(counts) do
print(string.format(" %-14d%d", roll_total, count))
end
end
local function dice_main()
print_intro()
-- initialize the random number generator
math.randomseed(os.time())
-- main game loop
local keep_playing = true
while keep_playing do
local num_rolls = ask_how_many_rolls()
local counts = roll_dice(num_rolls)
print_results(counts)
keep_playing = ask_try_again()
end
end
dice_main()
+125
View File
@@ -0,0 +1,125 @@
#!/usr/bin/perl
# Digits program in Perl
# Translated by Kevin Brannen (kbrannen)
use strict;
use warnings;
# globals
my $Answer;
print "\n";
print " " x 33, "DIGITS";
print " " x 15, "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n";
print "THIS IS A GAME OF GUESSING.\n";
print "FOR INSTRUCTIONS, TYPE '1', ELSE TYPE '0': ";
chomp($Answer = <>);
if ($Answer == 1)
{
print "\nPLEASE TAKE A PIECE OF PAPER AND WRITE DOWN\n";
print "THE DIGITS '0', '1', OR '2' THIRTY TIMES AT RANDOM.\n";
print "ARRANGE THEM IN THREE LINES OF TEN DIGITS EACH.\n";
print "I WILL ASK FOR THEN TEN AT A TIME.\n";
print "I WILL ALWAYS GUESS THEM FIRST AND THEN LOOK AT YOUR\n";
print "NEXT NUMBER TO SEE IF I WAS RIGHT. BY PURE LUCK,\n";
print "I OUGHT TO BE RIGHT TEN TIMES. BUT I HOPE TO DO BETTER\n";
print "THAN THAT. *****\n\n\n";
}
my ($A, $B, $C) = (0, 1, 3);
my (@M, @K, @L); # DIM M(26,2),K(2,2),L(8,2)
while (1)
{
for my $i (0 .. 26) { for my $j (0 .. 2) { $M[$i][$j] = 1; } }
for my $i (0 .. 2) { for my $j (0 .. 2) { $K[$i][$j] = 9; } }
for my $i (0 .. 8) { for my $j (0 .. 2) { $L[$i][$j] = 3; } }
$L[0][0] = $L[4][1] = $L[8][2] = 2;
my $Z = 26;
my $Z1 = 8;
my $Z2 = 2;
my $X = 0;
my @N;
for my $T (1 .. 3)
{
my $have_input = 0;
while (!$have_input)
{
$have_input = 1;
print "\nTEN NUMBERS, PLEASE: ";
chomp($Answer = <>);
$Answer = "0 " . $Answer; # need to be 1-based, so prepend a throw-away value for [0]
@N = split(/\s+/, $Answer);
for my $i (1 .. 10)
{
if (!defined($N[$i]) || ($N[$i] != 0 && $N[$i] != 1 && $N[$i] != 2))
{
print "ONLY USE THE DIGITS '0', '1', OR '2'.\n";
print "LET'S TRY AGAIN.";
$have_input = 0;
last;
}
}
}
print "\nMY GUESS\tYOUR NO.\tRESULT\tNO. RIGHT\n\n";
for my $U (1 .. 10)
{
my $num = $N[$U];
my $S = 0;
my $G;
for my $J (0 .. 2)
{
my $S1 = $A * $K[$Z2][$J] + $B * $L[$Z1][$J] + $C * $M[$Z][$J];
next if ($S > $S1);
if ($S >= $S1)
{
next if (rand(1) < .5);
}
$S = $S1;
$G = $J;
} # NEXT J
print " $G\t\t$N[$U]\t\t";
if ($G == $N[$U])
{
$X++;
print "RIGHT\t$X\n";
$M[$Z][$num]++;
$L[$Z1][$num]++;
$K[$Z2][$num]++;
$Z -= int($Z / 9) * 9;
$Z = 3 * $Z + $N[$U];
}
else
{
print "WRONG\t$X\n";
}
$Z1 = $Z - int($Z / 9) * 9;
$Z2 = $N[$U];
} # NEXT U
} # NEXT T
print "\n";
if ($X == 10)
{
print "I GUESSED EXACTLY 1/3 OF YOUR NUMBERS.\n";
print "IT'S A TIE GAME.\n";
}
elsif ($X > 10)
{
print "I GUESSED MORE THAN 1/3, OR $X, OF YOUR NUMBERS.\n";
print "I WIN.\a\a\a\a\a\a\a\a\a\a"
}
else
{
print "I GUESSED LESS THAN 1/3, OR $X, OF YOUR NUMBERS.\n";
print "YOU BEAT ME. CONGRATULATIONS *****\n";
}
print "\nDO YOU WANT TO TRY AGAIN (1 FOR YES, 0 FOR NO): ";
chomp($Answer = <>);
last if ($Answer != 1);
}
print "\nTHANKS FOR THE GAME.\n";
+124
View File
@@ -0,0 +1,124 @@
#!/usr/bin/perl
# Flip Flop program in Perl
# Translated by Kevin Brannen (kbrannen)
use strict;
use warnings;
use Math::Trig;
print "\n";
print " " x 32, "FLIPFLOP";
print " " x 15, "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n";
# *** CREATED BY MICHAEL CASS
print "THE OBJECT OF THIS PUZZLE IS TO CHANGE THIS:\n\n";
print "X X X X X X X X X X\n\n";
print "TO THIS:\n\n";
print "O O O O O O O O O O\n\n";
print "BY TYPING THE NUMBER CORRESPONDING TO THE POSITION OF THE\n";
print "LETTER ON SOME NUMBERS, ONE POSITION WILL CHANGE, ON\n";
print "OTHERS, TWO WILL CHANGE. TO RESET LINE TO ALL X'S, TYPE 0\n";
print "(ZERO) AND TO START OVER IN THE MIDDLE OF A GAME, TYPE \n";
print "11 (ELEVEN).\n\n";
sub initialize
{
my @a;
print "1 2 3 4 5 6 7 8 9 10\n";
print "X X X X X X X X X X\n";
for my $i (0 .. 10) { $a[$i] = "X"; } # make sure [0] has a value just in case
return @a;
}
while (1)
{
my $Q = rand(1);
my $C = 0;
print "HERE IS THE STARTING LINE OF X'S.\n\n";
my @A = initialize();
while (1)
{
my $M = 0;
my $N;
while (1)
{
print "\nINPUT THE NUMBER: ";
chomp($N = <>);
if ($N != int($N) || $N < 0 || $N > 11)
{
print "ILLEGAL ENTRY--TRY AGAIN.\n";
next;
}
last;
}
if ($N == 11) # start a new game
{
print "\n\n";
last;
}
if ($N == 0) # reset line
{
@A = initialize();
next;
}
if ($M != $N)
{
$M = $N;
$A[$N] = ($A[$N] eq "O") ? "X" : "O";
while ($M == $N)
{
my $R = tan($Q + $N / $Q - $N) - sin($Q / $N) + 336 * sin(8 * $N);
$N = $R - int($R);
$N = int(10 * $N);
if ($A[$N] eq "O")
{
$A[$N] = "X";
next;
}
$A[$N] = "O";
last; # GOTO 610
$A[$N] = "X";
}
}
else
{
if ($A[$N] ne "O") { $A[$N] = "O"; }
while ($M == $N)
{
my $R = .592 * (1 / tan($Q / $N + $Q)) / sin( $N * 2 + $Q) - cos($N);
$N = $R - int($R);
$N = int(10 * $N);
if ($A[$N] eq "O")
{
$A[$N] = "X";
next;
}
$A[$N] = "O";
last;
}
}
print "1 2 3 4 5 6 7 8 9 10\n";
for my $i (1 .. 10) { print "$A[$i] "; }
print "\n";
$C++;
my $i;
for ($i=1 ; $i <= 10 ; $i++) {
last if ($A[$i] ne "O");
}
if ($i == 11)
{
if ($C <= 12) { print "VERY GOOD. YOU GUESSED IT IN ONLY $C GUESSES.\n"; }
else { print "TRY HARDER NEXT TIME. IT TOOK YOU $C GUESSES.\n"; }
last;
}
}
print "DO YOU WANT TO TRY ANOTHER PUZZLE (Y/N): ";
$_ = <>;
print "\n";
last if (m/^n/i);
}
+2
View File
@@ -1,3 +1,5 @@
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
Conversion to [Perl](https://www.perl.org/)
You can answer yes/no questions in lower case if desired.
+265
View File
@@ -0,0 +1,265 @@
#!/usr/bin/perl
# Fur Trader program in Perl
# Translated by Kevin Brannen (kbrannen)
use strict;
use warnings;
# globals
my @Pelts = (qw(0 MINK BEAVER ERMINE FOX ));
my $Num_pelts = 4;
my @Quantity; # how many of each fur
my $Money;
my $Max_pelts = 190;
my $Ermine_price; # like we have @Pelts and @Quantity we could have @Prices
my $Beaver_price; # then have 4 constants as index into the arrays to avoid
my $Fox_price; # the magic numbers 1-4, or better have a array of objects (really a hash)
my $Mink_price; # with the 3 keys (name, number, price), but well keep it
# with 4 vars like the basic program did
print "\n";
print " " x 31, "FUR TRADER\n";
print " " x 15, "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n";
init();
while (1)
{
my $ans = get_yesno();
last if ($ans ne "YES");
$Ermine_price = new_price(.15, 0.95);
$Beaver_price = new_price(.25, 1.00);
print "\nYOU HAVE \$$Money SAVINGS.\n";
print "AND $Max_pelts FURS TO BEGIN THE EXPEDITION.\n";
print "\nYOUR $Max_pelts FURS ARE DISTRIBUTED AMONG THE FOLLOWING\n";
print "KINDS OF PELTS: MINK, BEAVER, ERMINE AND FOX.\n";
reset_furs();
my $total = 0;
for my $j ( 1 .. $Num_pelts)
{
print "\nHOW MANY $Pelts[$j] PELTS DO YOU HAVE? ";
chomp(my $ans = <>);
$Quantity[$j] = int($ans);
$total += $Quantity[$j];
}
if ($total > $Max_pelts)
{
print "\nYOU MAY NOT HAVE THAT MANY FURS.\n";
print "DO NOT TRY TO CHEAT. I CAN ADD.\n";
print "YOU MUST START AGAIN.\n";
init();
next;
}
print "\nYOU MAY TRADE YOUR FURS AT FORT 1, FORT 2,\n";
print "OR FORT 3. FORT 1 IS FORT HOCHELAGA (MONTREAL)\n";
print "AND IS UNDER THE PROTECTION OF THE FRENCH ARMY.\n";
print "FORT 2 IS FORT STADACONA (QUEBEC) AND IS UNDER THE\n";
print "PROTECTION OF THE FRENCH ARMY. HOWEVER, YOU MUST\n";
print "MAKE A PORTAGE AND CROSS THE LACHINE RAPIDS.\n";
print "FORT 3 IS FORT NEW YORK AND IS UNDER DUTCH CONTROL.\n";
print "YOU MUST CROSS THROUGH IROQUOIS LAND.\n";
my $done = 0;
while (!$done)
{
$ans = 0;
while ($ans < 1 || $ans > 3)
{
no warnings; # in case user enters alpha chars, then int() will return 0 with no warnings
print "ANSWER 1, 2, OR 3: ";
$ans = int(<>);
}
# returns 0 if they want to go somewhere else;
# or returns the old basic line number to show what to do
if ($ans == 1) { $done = fort1(); }
elsif ($ans == 2) { $done = fort2(); }
elsif ($ans == 3) { $done = fort3(); }
}
if ($done == 1410)
{
print "YOUR BEAVER SOLD FOR \$", $Beaver_price * $Quantity[2], "\t";
}
if ($done <= 1414)
{
print "YOUR FOX SOLD FOR \$", $Fox_price * $Quantity[4], "\n";
print "YOUR ERMINE SOLD FOR \$", $Ermine_price * $Quantity[3], "\t";
print "YOUR MINK SOLD FOR \$", $Mink_price * $Quantity[1], "\n";
}
# 1418 is always done
$Money += $Mink_price * $Quantity[1] + $Beaver_price * $Quantity[2] + $Ermine_price * $Quantity[3] + $Fox_price * $Quantity[4];
print "\nYOU NOW HAVE \$$Money INCLUDING YOUR PREVIOUS SAVINGS\n";
print "\nDO YOU WANT TO TRADE FURS NEXT YEAR? ";
}
exit(0);
###############################################################
sub init
{
print "YOU ARE THE LEADER OF A FRENCH FUR TRADING EXPEDITION IN\n";
print "1776 LEAVING THE LAKE ONTARIO AREA TO SELL FURS AND GET\n";
print "SUPPLIES FOR THE NEXT YEAR. YOU HAVE A CHOICE OF THREE\n";
print "FORTS AT WHICH YOU MAY TRADE. THE COST OF SUPPLIES\n";
print "AND THE AMOUNT YOU RECEIVE FOR YOUR FURS WILL DEPEND\n";
print "ON THE FORT THAT YOU CHOOSE.\n";
$Money = 600;
print "DO YOU WISH TO TRADE FURS?\n";
}
sub new_price
{
my ($base, $factor) = @_;
return int(($base * rand(1) + $factor) * 100 + .5) / 100;
}
sub supplies_fs
{
print "SUPPLIES AT FORT STADACONA COST \$125.00.\n";
print "YOUR TRAVEL EXPENSES TO STADACONA WERE \$15.00.\n";
}
sub supplies_ny
{
print "SUPPLIES AT NEW YORK COST \$80.00.\n";
print "YOUR TRAVEL EXPENSES TO NEW YORK WERE \$25.00.\n";
}
sub reset_furs
{
for my $j (1 .. $Num_pelts) { $Quantity[$j] = 0; }
}
sub get_yesno
{
my $ans;
print "ANSWER YES OR NO: ";
chomp($ans = uc(<>));
return $ans;
}
sub trade_elsewhere
{
print "DO YOU WANT TO TRADE AT ANOTHER FORT? ";
my $ans = get_yesno();
return $ans;
}
sub fort1
{
print "\nYOU HAVE CHOSEN THE EASIEST ROUTE. HOWEVER, THE FORT\n";
print "IS FAR FROM ANY SEAPORT. THE VALUE\n";
print "YOU RECEIVE FOR YOUR FURS WILL BE LOW AND THE COST\n";
print "OF SUPPLIES HIGHER THAN AT FORTS STADACONA OR NEW YORK.\n";
my $ans = trade_elsewhere();
if ($ans eq "YES") { return 0; }
$Money -= 160;
$Mink_price = new_price(.2, .7 );
$Ermine_price = new_price(.2, .65);
$Beaver_price = new_price(.2, .75);
$Fox_price = new_price(.2, .8 );
print "\nSUPPLIES AT FORT HOCHELAGA COST \$150.00.\n";
print "YOUR TRAVEL EXPENSES TO HOCHELAGA WERE \$10.00.\n";
return 1410;
}
sub fort2
{
print "\nYOU HAVE CHOSEN A HARD ROUTE. IT IS, IN COMPARSION,\n";
print "HARDER THAN THE ROUTE TO HOCHELAGA BUT EASIER THAN\n";
print "THE ROUTE TO NEW YORK. YOU WILL RECEIVE AN AVERAGE VALUE\n";
print "FOR YOUR FURS AND THE COST OF YOUR SUPPLIES WILL BE AVERAGE.\n";
my $ans = trade_elsewhere();
if ($ans eq "YES") { return 0; }
$Money -= 140;
print "\n";
$Mink_price = new_price(.3, .85);
$Ermine_price = new_price(.15, .8);
$Beaver_price = new_price(.2, .9);
my $P = int(10 * rand(1)) + 1;
if ($P <= 2)
{
$Quantity[2] = 0;
print "YOUR BEAVER WERE TOO HEAVY TO CARRY ACROSS\n";
print "THE PORTAGE. YOU HAD TO LEAVE THE PELTS, BUT FOUND\n";
print "THEM STOLEN WHEN YOU RETURNED.\n";
supplies_fs();
return 1414;
}
elsif ($P <= 6)
{
print "YOU ARRIVED SAFELY AT FORT STADACONA.\n";
supplies_fs();
}
elsif ($P <= 8)
{
reset_furs();
print "YOUR CANOE UPSET IN THE LACHINE RAPIDS. YOU\n";
print "LOST ALL YOUR FURS.\n";
supplies_fs();
return 1418;
}
elsif ($P <= 10)
{
$Quantity[4] = 0;
print "YOUR FOX PELTS WERE NOT CURED PROPERLY.\n";
print "NO ONE WILL BUY THEM.\n";
supplies_fs();
}
return 1410;
}
sub fort3
{
print "\nYOU HAVE CHOSEN THE MOST DIFFICULT ROUTE. AT\n";
print "FORT NEW YORK YOU WILL RECEIVE THE HIGHEST VALUE\n";
print "FOR YOUR FURS. THE COST OF YOUR SUPPLIES\n";
print "WILL BE LOWER THAN AT ALL THE OTHER FORTS.\n";
my $ans = trade_elsewhere();
if ($ans eq "YES") { return 0; }
$Money -= 105;
print "\n";
$Mink_price = new_price(.15, 1.05);
$Fox_price = new_price(.25, 1.1);
$Fox_price = new_price(.25, 1.1);
my $P = int(10 * rand(1)) + 1;
if ($P <= 2)
{
print "YOU WERE ATTACKED BY A PARTY OF IROQUOIS.\n";
print "ALL PEOPLE IN YOUR TRADING GROUP WERE\n";
print "KILLED. THIS ENDS THE GAME.\n";
exit(0);
}
elsif ($P <= 6)
{
print "YOU WERE LUCKY. YOU ARRIVED SAFELY\n";
print "AT FORT NEW YORK.\n";
supplies_ny();
}
elsif ($P <= 8)
{
reset_furs();
print "YOU NARROWLY ESCAPED AN IROQUOIS RAIDING PARTY.\n";
print "HOWEVER, YOU HAD TO LEAVE ALL YOUR FURS BEHIND.\n";
supplies_ny();
return 1418;
}
elsif ($P <= 10)
{
$Beaver_price /= 2;
$Mink_price /= 2;
print "YOUR MINK AND BEAVER WERE DAMAGED ON YOUR TRIP.\n";
print "YOU RECEIVE ONLY HALF THE CURRENT PRICE FOR THESE FURS.\n";
supplies_ny();
}
return 1410;
}
+81
View File
@@ -0,0 +1,81 @@
#!/usr/bin/perl
# Gunner program in Perl
# Required extensive restructuring to remove all of the GOTO's.
# Translated by Kevin Brannen (kbrannen)
use strict;
use warnings;
# globals
my $Max_range = int(40000*rand(1)+20000);
my $Total_shots = 0;
my $Games = 0;
print "\n";
print " " x 30, "GUNNER\n";
print " " x 15, "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n";
print "YOU ARE THE OFFICER-IN-CHARGE, GIVING ORDERS TO A GUN\n";
print "CREW, TELLING THEM THE DEGREES OF ELEVATION YOU ESTIMATE\n";
print "WILL PLACE A PROJECTILE ON TARGET. A HIT WITHIN 100 YARDS\n";
print "OF THE TARGET WILL DESTROY IT.\n\n";
print "MAXIMUM RANGE OF YOUR GUN IS $Max_range YARDS.\n\n";
GAME: while (1)
{
my $target_dist = int($Max_range * (.1 + .8 * rand(1)));
my $shots = 0;
print "DISTANCE TO THE TARGET IS $target_dist YARDS.\n\n";
while (1)
{
my $elevation = get_elevation(); # in degrees
$shots++;
my $dist = int($target_dist - ($Max_range * sin(2 * $elevation / 57.3)));
if (abs($dist) < 100)
{
print "*** TARGET DESTROYED *** $shots ROUNDS OF AMMUNITION EXPENDED.\n";
$Total_shots += $shots;
if ($Games++ == 4)
{
print "\n\nTOTAL ROUNDS EXPENDED WERE: $Total_shots\n";
if ($Total_shots > 18) { print "BETTER GO BACK TO FORT SILL FOR REFRESHER TRAINING!\n"; }
else { print "NICE SHOOTING !!\n"; }
last;
}
print "\nTHE FORWARD OBSERVER HAS SIGHTED MORE ENEMY ACTIVITY...\n";
next GAME;
}
if ($dist > 100) { print "SHORT OF TARGET BY ", abs($dist)," YARDS.\n"; }
else { print "OVER TARGET BY ", abs($dist), " YARDS.\n"; }
if ($shots >= 5)
{
print "\nBOOM !!!! YOU HAVE JUST BEEN DESTROYED BY THE ENEMY.\n\n\n\n";
print "BETTER GO BACK TO FORT SILL FOR REFRESHER TRAINING!\n";
last;
}
}
print "\nTRY AGAIN (Y OR N): ";
chomp(my $ans=uc(<>));
if ($ans ne "Y") { last; }
else { $Games = 0; $Total_shots = 0; }
}
print "\nOK. RETURN TO BASE CAMP.\n";
####################################
sub get_elevation
{
my $elevation;
while (1)
{
print "\nELEVATION: ";
chomp($elevation = <>);
if ($elevation > 89) { print "MAXIMUM ELEVATION IS 89 DEGREES.\n"; }
elsif ($elevation < 1) { print "MINIMUM ELEVATION IS ONE DEGREE.\n"; }
else { return $elevation; }
}
}
+1 -1
View File
@@ -133,7 +133,7 @@ namespace Hammurabi
break;
case PerformanceRating.Bad:
Console.WriteLine("YOUR HEAVY-HANDED PERFORMANCE SMACKS OF NERO AND IVAN IV.");
Console.WriteLine("THE PEOPLE (REMIANING) FIND YOU AN UNPLEASANT RULER, AND,");
Console.WriteLine("THE PEOPLE (REMAINING) FIND YOU AN UNPLEASANT RULER, AND,");
Console.WriteLine("FRANKLY, HATE YOUR GUTS!!");
break;
case PerformanceRating.Ok:
+1 -1
View File
@@ -108,7 +108,7 @@
900 PRINT "A FANTASTIC PERFORMANCE!!! CHARLEMANGE, DISRAELI, AND"
905 PRINT "JEFFERSON COMBINED COULD NOT HAVE DONE BETTER!":GOTO 990
940 PRINT "YOUR HEAVY-HANDED PERFORMANCE SMACKS OF NERO AND IVAN IV."
945 PRINT "THE PEOPLE (REMIANING) FIND YOU AN UNPLEASANT RULER, AND,"
945 PRINT "THE PEOPLE (REMAINING) FIND YOU AN UNPLEASANT RULER, AND,"
950 PRINT "FRANKLY, HATE YOUR GUTS!!":GOTO 990
960 PRINT "YOUR PERFORMANCE COULD HAVE BEEN SOMEWHAT BETTER, BUT"
965 PRINT "REALLY WASN'T TOO BAD AT ALL. ";INT(P*.8*RND(1));"PEOPLE"
+1 -1
View File
@@ -233,7 +233,7 @@ async function main()
print("ALSO BEEN DECLARED NATIONAL FINK!!!!\n");
} else if (p1 > 10 || l < 9) {
print("YOUR HEAVY-HANDED PERFORMANCE SMACKS OF NERO AND IVAN IV.\n");
print("THE PEOPLE (REMIANING) FIND YOU AN UNPLEASANT RULER, AND,\n");
print("THE PEOPLE (REMAINING) FIND YOU AN UNPLEASANT RULER, AND,\n");
print("FRANKLY, HATE YOUR GUTS!!\n");
} else if (p1 > 3 || l < 10) {
print("YOUR PERFORMANCE COULD HAVE BEEN SOMEWHAT BETTER, BUT\n");
+1 -1
View File
@@ -212,7 +212,7 @@ def main() -> None:
national_fink()
elif P1 > 10 or L < 9:
print("YOUR HEAVY-HANDED PERFORMANCE SMACKS OF NERO AND IVAN IV.")
print("THE PEOPLE (REMIANING) FIND YOU AN UNPLEASANT RULER, AND,")
print("THE PEOPLE (REMAINING) FIND YOU AN UNPLEASANT RULER, AND,")
print("FRANKLY, HATE YOUR GUTS!!")
elif P1 > 3 or L < 10:
print("YOUR PERFORMANCE COULD HAVE BEEN SOMEWHAT BETTER, BUT")
+156
View File
@@ -0,0 +1,156 @@
-- HELLO
--
-- Converted from BASIC to Lua by Recanman
local function tab(space)
local str = ""
for _ = space, 1, -1 do
str = str .. " "
end
return str
end
-- reused from Bagels.lua
function getInput(prompt)
io.write(prompt)
io.flush()
local input = io.read("l")
if not input then --- test for EOF
print("GOODBYE")
os.exit(0)
end
return input
end
print(tab(33) .. "HELLO\n")
print(tab(15) .. "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n")
print("\n")
print("\n")
print("\n")
print("HELLO. MY NAME IS CREATIVE COMPUTER.\n")
print("\n")
print("\n")
print("WHAT'S YOUR NAME")
local ns = getInput("? ")
print("\n")
print("HI THERE, " .. ns .. ", ARE YOU ENJOYING YOURSELF HERE")
while true do
local bs = getInput("? ")
print("\n")
if bs == "YES" then
print("I'M GLAD TO HEAR THAT, " .. ns .. ".\n")
print("\n")
break
elseif bs == "NO" then
print("OH, I'M SORRY TO HEAR THAT, " .. ns .. ". MAYBE WE CAN\n")
print("BRIGHTEN UP YOUR VISIT A BIT.\n")
break
else
print("PLEASE ANSWER 'YES' OR 'NO'. DO YOU LIKE IT HERE")
end
end
local function main()
print("\n")
print("SAY, " .. ns .. ", I CAN SOLVED ALL KINDS OF PROBLEMS EXCEPT\n")
print("THOSE DEALING WITH GREECE. WHAT KIND OF PROBLEMS DO\n")
print("YOU HAVE (ANSWER SEX, HEALTH, MONEY, OR JOB)")
while true do
local cs = getInput("? ")
print("\n")
if cs ~= "SEX" and cs ~= "HEALTH" and cs ~= "MONEY" and cs ~= "JOB" then
print("OH, " .. ns .. ", YOUR ANSWER OF " .. cs .. " IS GREEK TO ME.\n")
elseif cs == "JOB" then
print("I CAN SYMPATHIZE WITH YOU " .. ns .. ". I HAVE TO WORK\n")
print("VERY LONG HOURS FOR NO PAY -- AND SOME OF MY BOSSES\n")
print("REALLY BEAT ON MY KEYBOARD. MY ADVICE TO YOU, " .. ns .. ",\n")
print("IS TO OPEN A RETAIL COMPUTER STORE. IT'S GREAT FUN.\n")
elseif cs == "MONEY" then
print("SORRY, " .. ns .. ", I'M BROKE TOO. WHY DON'T YOU SELL\n")
print("ENCYCLOPEADIAS OR MARRY SOMEONE RICH OR STOP EATING\n")
print("SO YOU WON'T NEED SO MUCH MONEY?\n")
elseif cs == "HEALTH" then
print("MY ADVICE TO YOU " .. ns .. " IS:\n")
print(tab(5) .. "1. TAKE TWO ASPRIN\n")
print(tab(5) .. "2. DRINK PLENTY OF FLUIDS (ORANGE JUICE, NOT BEER!)\n")
print(tab(5) .. "3. GO TO BED (ALONE)\n")
elseif cs == "SEX" then
print("IS YOUR PROBLEM TOO MUCH OR TOO LITTLE")
while true do
local ds = getInput("? ")
print("\n")
if ds == "TOO MUCH" then
print("YOU CALL THAT A PROBLEM?!! I SHOULD HAVE SUCH PROBLEMS!\n")
print("IF IT BOTHERS YOU, " .. ns .. ", TAKE A COLD SHOWER.\n")
break
elseif ds == "TOO LITTLE" then
print("WHY ARE YOU HERE IN SUFFERN, " .. ns .. "? YOU SHOULD BE\n")
print("IN TOKYO OR NEW YORK OR AMSTERDAM OR SOMEPLACE WITH SOME\n")
print("REAL ACTION.\n")
break
else
print("DON'T GET ALL SHOOK, " .. ns .. ", JUST ANSWER THE QUESTION\n")
print("WITH 'TOO MUCH' OR 'TOO LITTLE'. WHICH IS IT")
end
end
end
print("\n")
print("ANY MORE PROBLEMS YOU WANT SOLVED, " .. ns)
local es = getInput("? ")
if es == "YES" then
print("WHAT KIND (SEX, MONEY, HEALTH, JOB)")
elseif es == "NO" then
print("THAT WILL BE $5.00 FOR THE ADVICE, " .. ns .. ".\n")
print("PLEASE LEAVE THE MONEY ON THE TERMINAL.\n")
print("\n")
print("\n")
print("\n")
while true do
print("DID YOU LEAVE THE MONEY")
local gs = getInput("? ")
print("\n")
if gs == "YES" then
print("HEY, " .. ns .. "??? YOU LEFT NO MONEY AT ALL!\n")
print("YOU ARE CHEATING ME OUT OF MY HARD-EARNED LIVING.\n")
print("\n")
print("WHAT A RIP OFF, " .. ns .. "!!!\n")
print("\n")
break
elseif gs == "NO" then
print("THAT'S HONEST, " .. ns .. ", BUT HOW DO YOU EXPECT\n")
print("ME TO GO ON WITH MY PSYCHOLOGY STUDIES IF MY PATIENT\n")
print("DON'T PAY THEIR BILLS?\n")
break
else
print("YOUR ANSWER OF '" .. gs .. "' CONFUSES ME, " .. ns .. ".\n")
print("PLEASE RESPOND WITH 'YES' OR 'NO'.\n")
end
end
break
end
end
print("\n")
print("TAKE A WALK, " .. ns .. ".\n")
print("\n")
print("\n")
end
main()
+14 -2
View File
@@ -1,10 +1,10 @@
## King
This is one of the most comprehensive, difficult, and interesting games. (If youve never played one of these games, start with HAMMURABI.)
This is one of the most comprehensive, difficult, and interesting games. (If you've never played one of these games, start with HAMMURABI.)
In this game, you are Premier of Setats Detinu, a small communist island 30 by 70 miles long. Your job is to decide upon the budget of your country and distribute money to your country from the communal treasury.
The money system is Rollods; each person needs 100 Rallods per year to survive. Your countrys income comes from farm produce and tourists visiting your magnificent forests, hunting, fishing, etc. Part of your land is farm land but it also has an excellent mineral content and may be sold to foreign industry for strip mining. Industry import and support their own workers. Crops cost between 10 and 15 Rallods per square mile to plant, cultivate, and harvest. Your goal is to complete an eight-year term of office without major mishap. A word of warning: it isnt easy!
The money system is Rollods; each person needs 100 Rallods per year to survive. Your country's income comes from farm produce and tourists visiting your magnificent forests, hunting, fishing, etc. Part of your land is farm land but it also has an excellent mineral content and may be sold to foreign industry for strip mining. Industry import and support their own workers. Crops cost between 10 and 15 Rallods per square mile to plant, cultivate, and harvest. Your goal is to complete an eight-year term of office without major mishap. A word of warning: it isn't easy!
The author of this program is James A. Storer who wrote it while a student at Lexington High School.
@@ -66,3 +66,15 @@ On basic line 1997 it is:
but it should be:
1997 PRINT " AND 1,000 SQ. MILES OF FOREST LAND."
### Bug 4
On basic line 1310 we see this:
1310 IF C=0 THEN 1324
1320 PRINT "OF ";INT(J);"SQ. MILES PLANTED,";
1324 ...
but it should probably be:
1310 IF J=0 THEN 1324
+133
View File
@@ -0,0 +1,133 @@
namespace King;
internal class Country
{
private const int InitialLand = 1000;
private readonly IReadWrite _io;
private readonly IRandom _random;
private float _rallods;
private float _countrymen;
private float _foreigners;
private float _arableLand;
private float _industryLand;
public Country(IReadWrite io, IRandom random)
: this(
io,
random,
(int)(60000 + random.NextFloat(1000) - random.NextFloat(1000)),
(int)(500 + random.NextFloat(10) - random.NextFloat(10)),
0,
InitialLand)
{
}
public Country(IReadWrite io, IRandom random, float rallods, float countrymen, float foreigners, float land)
{
_io = io;
_random = random;
_rallods = rallods;
_countrymen = countrymen;
_foreigners = foreigners;
_arableLand = land;
}
public string GetStatus(int landValue, int plantingCost)
=> Resource.Status(_rallods, _countrymen, _foreigners, _arableLand, landValue, plantingCost);
public float Countrymen => _countrymen;
public float Workers => _foreigners;
public bool HasWorkers => _foreigners > 0;
private float FarmLand => _arableLand;
public bool HasRallods => _rallods > 0;
public float Rallods => _rallods;
public float IndustryLand => InitialLand - _arableLand;
public int PreviousTourismIncome { get; private set; }
public bool SellLand(int landValue, out float landSold)
{
if (_io.TryReadValue(
SellLandPrompt,
out landSold,
new ValidityTest(v => v <= FarmLand, () => SellLandError(FarmLand))))
{
_arableLand = (int)(_arableLand - landSold);
_rallods = (int)(_rallods + landSold * landValue);
return true;
}
return false;
}
public bool DistributeRallods(out float rallodsGiven)
{
if (_io.TryReadValue(
GiveRallodsPrompt,
out rallodsGiven,
new ValidityTest(v => v <= _rallods, () => GiveRallodsError(_rallods))))
{
_rallods = (int)(_rallods - rallodsGiven);
return true;
}
return false;
}
public bool PlantLand(int plantingCost, out float landPlanted)
{
if (_io.TryReadValue(
PlantLandPrompt,
out landPlanted,
new ValidityTest(v => v <= _countrymen * 2, PlantLandError1),
new ValidityTest(v => v <= FarmLand, PlantLandError2(FarmLand)),
new ValidityTest(v => v * plantingCost <= _rallods, PlantLandError3(_rallods))))
{
_rallods -= (int)(landPlanted * plantingCost);
return true;
}
return false;
}
public bool ControlPollution(out float rallodsSpent)
{
if (_io.TryReadValue(
PollutionPrompt,
out rallodsSpent,
new ValidityTest(v => v <= _rallods, () => PollutionError(_rallods))))
{
_rallods = (int)(_rallods - rallodsSpent);
return true;
}
return false;
}
public bool TrySpend(float amount, float landValue)
{
if (_rallods >= amount)
{
_rallods -= amount;
return true;
}
_arableLand = (int)(_arableLand - (int)(amount - _rallods) / landValue);
_rallods = 0;
return false;
}
public void RemoveTheDead(int deaths) => _countrymen = (int)(_countrymen - deaths);
public void Migration(int migration) => _countrymen = (int)(_countrymen + migration);
public void AddWorkers(int newWorkers) => _foreigners = (int)(_foreigners + newWorkers);
public void SellCrops(int income) => _rallods = (int)(_rallods + income);
public void EntertainTourists(int income)
{
PreviousTourismIncome = income;
_rallods = (int)(_rallods + income);
}
}
+47
View File
@@ -0,0 +1,47 @@
namespace King;
internal class Game
{
const int TermOfOffice = 8;
private readonly IReadWrite _io;
private readonly IRandom _random;
public Game(IReadWrite io, IRandom random)
{
_io = io;
_random = random;
}
public void Play()
{
_io.Write(Title);
var reign = SetUpReign();
if (reign != null)
{
while (reign.PlayYear());
}
_io.WriteLine();
_io.WriteLine();
}
private Reign? SetUpReign()
{
var response = _io.ReadString(InstructionsPrompt).ToUpper();
if (response.Equals("Again", StringComparison.InvariantCultureIgnoreCase))
{
return _io.TryReadGameData(_random, out var reign) ? reign : null;
}
if (!response.StartsWith("N", StringComparison.InvariantCultureIgnoreCase))
{
_io.Write(InstructionsText(TermOfOffice));
}
_io.WriteLine();
return new Reign(_io, _random);
}
}
+61
View File
@@ -0,0 +1,61 @@
using System.Diagnostics.CodeAnalysis;
using static King.Resources.Resource;
namespace King;
internal static class IOExtensions
{
internal static bool TryReadGameData(this IReadWrite io, IRandom random, [NotNullWhen(true)] out Reign? reign)
{
if (io.TryReadValue(SavedYearsPrompt, v => v < Reign.MaxTerm, SavedYearsError(Reign.MaxTerm), out var years) &&
io.TryReadValue(SavedTreasuryPrompt, out var rallods) &&
io.TryReadValue(SavedCountrymenPrompt, out var countrymen) &&
io.TryReadValue(SavedWorkersPrompt, out var workers) &&
io.TryReadValue(SavedLandPrompt, v => v is > 1000 and <= 2000, SavedLandError, out var land))
{
reign = new Reign(io, random, new Country(io, random, rallods, countrymen, workers, land), years + 1);
return true;
}
reign = default;
return false;
}
internal static bool TryReadValue(this IReadWrite io, string prompt, out float value, params ValidityTest[] tests)
{
while (true)
{
var response = value = io.ReadNumber(prompt);
if (response == 0) { return false; }
if (tests.All(test => test.IsValid(response, io))) { return true; }
}
}
internal static bool TryReadValue(this IReadWrite io, string prompt, out float value)
=> io.TryReadValue(prompt, _ => true, "", out value);
internal static bool TryReadValue(
this IReadWrite io,
string prompt,
Predicate<float> isValid,
string error,
out float value)
=> io.TryReadValue(prompt, isValid, () => error, out value);
internal static bool TryReadValue(
this IReadWrite io,
string prompt,
Predicate<float> isValid,
Func<string> getError,
out float value)
{
while (true)
{
value = io.ReadNumber(prompt);
if (value < 0) { return false; }
if (isValid(value)) { return true; }
io.Write(getError());
}
}
}
+8
View File
@@ -6,4 +6,12 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="Resources/*.txt" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\00_Common\dotnet\Games.Common\Games.Common.csproj" />
</ItemGroup>
</Project>
+7
View File
@@ -0,0 +1,7 @@
global using Games.Common.IO;
global using Games.Common.Randomness;
global using King.Resources;
global using static King.Resources.Resource;
using King;
new Game(new ConsoleIO(), new RandomNumberGenerator()).Play();
+45
View File
@@ -0,0 +1,45 @@
namespace King;
internal class Reign
{
public const int MaxTerm = 8;
private readonly IReadWrite _io;
private readonly IRandom _random;
private readonly Country _country;
private float _yearNumber;
public Reign(IReadWrite io, IRandom random)
: this(io, random, new Country(io, random), 1)
{
}
public Reign(IReadWrite io, IRandom random, Country country, float year)
{
_io = io;
_random = random;
_country = country;
_yearNumber = year;
}
public bool PlayYear()
{
var year = new Year(_country, _random, _io);
_io.Write(year.Status);
var result = year.GetPlayerActions() ?? year.EvaluateResults() ?? IsAtEndOfTerm();
if (result.IsGameOver)
{
_io.WriteLine(result.Message);
return false;
}
return true;
}
private Result IsAtEndOfTerm()
=> _yearNumber == MaxTerm
? Result.GameOver(EndCongratulations(MaxTerm))
: Result.Continue;
}
@@ -0,0 +1 @@
{0} countrymen died of carbon-monoxide and dust inhalation
@@ -0,0 +1 @@
{0} countrymen died of starvation
+1
View File
@@ -0,0 +1 @@
{0} countrymen left the island.
+3
View File
@@ -0,0 +1,3 @@
also had your left eye gouged out!
;have also gained a very bad reputation.
;have also been declared national fink.
@@ -0,0 +1,10 @@
Congratulations!!!!!!!!!!!!!!!!!!
You have successfully completed your {0} year term
of office. You were, of course, extremely lucky, but
nevertheless, it's quite an achievement. Goodbye and good
luck - you'll probably need it if you're the type that
plays this game.
@@ -0,0 +1,3 @@
You have been thrown out of office and are now
residing in prison.;
You have been assassinated.
@@ -0,0 +1,7 @@
The number of foreign workers has exceeded the number
of countrymen. As a minority, they have revolted and
taken over the country.
{0}
+5
View File
@@ -0,0 +1,5 @@
{0} countrymen died in one year!!!!!
due to this extreme mismanagement, you have not only
been impeached and thrown out of office, but you
{1}
@@ -0,0 +1,7 @@
Money was left over in the treasury which you did
not spend. As a result, some of your countrymen died
of starvation. The public is enraged and you have
been forced to resign.
@@ -0,0 +1,7 @@
Over one third of the population has died since you
were elected to office. The people (remaining)
hate your guts.
{0}
@@ -0,0 +1 @@
You were forced to spend {0} rallods on funeral expenses
@@ -0,0 +1 @@
Think again. You've only got {0} rallods in the treasury.
@@ -0,0 +1 @@
How many rallods will you distribute among your countrymen
+4
View File
@@ -0,0 +1,4 @@
Goodbye.
(If you wish to continue this game at a later date, answer
'again' when asked if you want instructions at the start
of the game).
+2
View File
@@ -0,0 +1,2 @@
you harvested {0} sq. miles of crops.
{1}making {2} rallods.
@@ -0,0 +1 @@
(Due to increased air and water pollution from foreign industry.)
+1
View File
@@ -0,0 +1 @@
{0} countrymen came to the island.
@@ -0,0 +1 @@
Do you want instructions
@@ -0,0 +1,17 @@
Congratulations! You've just been elected Premier of Setats
Detinu, a small communist island 30 by 70 miles long. Your
job is to decide upon the country's budget and distribute
money to your countrymen from the communal treasury.
The money system is rallods, and each person needs 100
rallods per year to survive. Your country's income comes
from farm produce and tourists visiting your magnificent
forests, hunting, fishing, etc. Half your land if farm land
which also has an excellent mineral content and may be sold
to foreign industry (strip mining) who import and support
their own workers. Crops cost between 10 and 15 rallods per
square mile to plant.
Your goal is to complete your {0} year term of office.
Good luck!
+1
View File
@@ -0,0 +1 @@
Of {0} sq. miles planted,
@@ -0,0 +1 @@
Sorry, but each countryman can only plant 2 sq. miles.
@@ -0,0 +1 @@
Sorry, but you've only {0} sq. miles of farm land.
@@ -0,0 +1 @@
Think again, You've only {0} rallods left in the treasury.
@@ -0,0 +1 @@
How many square miles do you wish to plant
@@ -0,0 +1 @@
Think again. You only have {0} rallods remaining.
@@ -0,0 +1 @@
How many rallods do you wish to spend on pollution control
+112
View File
@@ -0,0 +1,112 @@
using System.Reflection;
using System.Runtime.CompilerServices;
namespace King.Resources;
internal static class Resource
{
private static bool _sellLandErrorShown;
public static Stream Title => GetStream();
public static string InstructionsPrompt => GetString();
public static string InstructionsText(int years) => string.Format(GetString(), years);
public static string Status(
float rallods,
float countrymen,
float workers,
float land,
float landValue,
float plantingCost)
=> string.Format(
workers == 0 ? StatusWithWorkers : StatusSansWorkers,
rallods,
(int)countrymen,
(int)workers,
(int)land,
landValue,
plantingCost);
private static string StatusWithWorkers => GetString();
private static string StatusSansWorkers => GetString();
public static string SellLandPrompt => GetString();
public static string SellLandError(float farmLand)
{
var error = string.Format(GetString(), farmLand, _sellLandErrorShown ? "" : SellLandErrorReason);
_sellLandErrorShown = true;
return error;
}
private static string SellLandErrorReason => GetString();
public static string GiveRallodsPrompt => GetString();
public static string GiveRallodsError(float rallods) => string.Format(GetString(), rallods);
public static string PlantLandPrompt => GetString();
public static string PlantLandError1 => GetString();
public static string PlantLandError2(float farmLand) => string.Format(GetString(), farmLand);
public static string PlantLandError3(float rallods) => string.Format(GetString(), rallods);
public static string PollutionPrompt => GetString();
public static string PollutionError(float rallods) => string.Format(GetString(), rallods);
public static string DeathsStarvation(float deaths) => string.Format(GetString(), (int)deaths);
public static string DeathsPollution(int deaths) => string.Format(GetString(), deaths);
public static string FuneralExpenses(int expenses) => string.Format(GetString(), expenses);
public static string InsufficientReserves => GetString();
public static string WorkerMigration(int newWorkers) => string.Format(GetString(), newWorkers);
public static string Migration(int migration)
=> string.Format(migration < 0 ? Emigration : Immigration, Math.Abs(migration));
public static string Emigration => GetString();
public static string Immigration => GetString();
public static string LandPlanted(float landPlanted)
=> landPlanted > 0 ? string.Format(GetString(), (int)landPlanted) : "";
public static string Harvest(int yield, int income, bool hasIndustry)
=> string.Format(GetString(), yield, HarvestReason(hasIndustry), income);
private static string HarvestReason(bool hasIndustry) => hasIndustry ? GetString() : "";
public static string TourismEarnings(int income) => string.Format(GetString(), income);
public static string TourismDecrease(IRandom random) => string.Format(GetString(), TourismReason(random));
private static string TourismReason(IRandom random) => GetStrings()[random.Next(5)];
private static string EndAlso(IRandom random)
=> random.Next(10) switch
{
<= 3 => GetStrings()[0],
<= 6 => GetStrings()[1],
_ => GetStrings()[2]
};
public static string EndCongratulations(int termLength) => string.Format(GetString(), termLength);
private static string EndConsequences(IRandom random) => GetStrings()[random.Next(2)];
public static string EndForeignWorkers(IRandom random) => string.Format(GetString(), EndConsequences(random));
public static string EndManyDead(int deaths, IRandom random) => string.Format(GetString(), deaths, EndAlso(random));
public static string EndMoneyLeftOver() => GetString();
public static string EndOneThirdDead(IRandom random) => string.Format(GetString(), EndConsequences(random));
public static string SavedYearsPrompt => GetString();
public static string SavedYearsError(int years) => string.Format(GetString(), years);
public static string SavedTreasuryPrompt => GetString();
public static string SavedCountrymenPrompt => GetString();
public static string SavedWorkersPrompt => GetString();
public static string SavedLandPrompt => GetString();
public static string SavedLandError => GetString();
public static string Goodbye => GetString();
private static string[] GetStrings([CallerMemberName] string? name = null) => GetString(name).Split(';');
private static string GetString([CallerMemberName] string? name = null)
{
using var stream = GetStream(name);
using var reader = new StreamReader(stream);
return reader.ReadToEnd();
}
private static Stream GetStream([CallerMemberName] string? name = null) =>
Assembly.GetExecutingAssembly().GetManifestResourceStream($"{typeof(Resource).Namespace}.{name}.txt")
?? throw new Exception($"Could not find embedded resource stream '{name}'.");
}
@@ -0,0 +1 @@
How many countrymen
@@ -0,0 +1,2 @@
Come on, you started with 1000 sq. miles of farm land
and 10,000 sq. miles of forest land

Some files were not shown because too many files have changed in this diff Show More