diff --git a/00_Alternate_Languages/01_Acey_Ducey/MiniScript/README.md b/00_Alternate_Languages/01_Acey_Ducey/MiniScript/README.md new file mode 100644 index 00000000..a15b86d9 --- /dev/null +++ b/00_Alternate_Languages/01_Acey_Ducey/MiniScript/README.md @@ -0,0 +1,16 @@ +Original source downloaded from [Vintage Basic](http://www.vintage-basic.net/games.html). + +Conversion to [MiniScript](https://miniscript.org). + +Ways to play: + +1. Command-Line MiniScript: +Download for your system from https://miniscript.org/cmdline/, install, and then run the program with a command such as: + + miniscript aceyducey.ms + +2. Mini Micro: +Download Mini Micro from https://miniscript.org/MiniMicro/, launch, and then click the top disk slot and chose "Mount Folder..." Select the folder containing the BASIC program. Then, at the Mini Micro command prompt, enter: + + load "aceyducey" + run diff --git a/00_Alternate_Languages/01_Acey_Ducey/MiniScript/aceyducey.ms b/00_Alternate_Languages/01_Acey_Ducey/MiniScript/aceyducey.ms new file mode 100644 index 00000000..c00684ce --- /dev/null +++ b/00_Alternate_Languages/01_Acey_Ducey/MiniScript/aceyducey.ms @@ -0,0 +1,59 @@ +print " "*26 + "Acey Ducey Card Game" +print " "*15 + "Creative Computing Morristown, New Jersey" +print +print +print "Acey-ducey is played in the following manner." +print "The dealer (computer) deals two cards face up." +print "You have an option to bet or not bet depending" +print "on whether or not you feel the card will have" +print "a value between the first two." +print "If you do not want to bet, input a 0." + +cards = range(2,10) + ["Jack", "Queen", "King", "Ace"] + +while true + money = 100 + + while true + print "You now have " + money + " dollars." + print + print "Here are your next two cards:" + while true + A = floor(rnd * cards.len) + B = floor(rnd * cards.len) + if B > A then break + end while + print cards[A] + print cards[B] + bet = input("What is your bet? ").val + while bet > money + print "Sorry, my friend, but you bet too much." + print "You have only " + money + " dollars to bet." + bet = input("What is your bet? ").val + end while + if bet == 0 then + print "Chicken!!" + continue + end if + C = floor(rnd * cards.len) + print cards[C] + + if C <= A or C >= B then + print "Sorry, you lose." + money -= bet + if money <= 0 then break + else + print "You win!!!" + money += bet + end if + end while + + print + print + print "Sorry, friend, but you blew your wad." + print; print + again = input("Try again (yes or no)? ").lower + if again and again[0] == "n" then break +end while + +print "O.K., hope you had fun!" \ No newline at end of file diff --git a/00_Alternate_Languages/02_Amazing/MiniScript/README.md b/00_Alternate_Languages/02_Amazing/MiniScript/README.md new file mode 100644 index 00000000..a93e33d1 --- /dev/null +++ b/00_Alternate_Languages/02_Amazing/MiniScript/README.md @@ -0,0 +1,18 @@ +Original source downloaded from [Vintage Basic](http://www.vintage-basic.net/games.html). + +Conversion to [MiniScript](https://miniscript.org). + +Ways to play: + +1. Command-Line MiniScript: +Download for your system from https://miniscript.org/cmdline/, install, and then run the program with a command such as: + + miniscript amazing.ms + +Note that because this program imports "listUtil", you will need to have a the standard MiniScript libraries somewhere in your import path. + +2. Mini Micro: +Download Mini Micro from https://miniscript.org/MiniMicro/, launch, and then click the top disk slot and chose "Mount Folder..." Select the folder containing the BASIC program. Then, at the Mini Micro command prompt, enter: + + load "amazing" + run diff --git a/00_Alternate_Languages/02_Amazing/MiniScript/amazing.ms b/00_Alternate_Languages/02_Amazing/MiniScript/amazing.ms new file mode 100644 index 00000000..3c358979 --- /dev/null +++ b/00_Alternate_Languages/02_Amazing/MiniScript/amazing.ms @@ -0,0 +1,108 @@ +import "listUtil" +print " "*28 + "Amazing Program" +print " "*15 + "Creative Computing Morristown, New Jersey" +print; print; print; print +while true + inp = input("What and your width and length? ") + inp = inp.replace(",", " ") + fields = inp.split + h = fields[0].val; v = fields[-1].val + if h > 1 and v > 1 then break + print "Meaningless dimensions. Try again." +end while + +// order: keeps track of the order in which each cell was +// visited as we built the maze. 0 means not explored yet. Indexed in [column][row] order. +// (This is W in the original BASIC program.) +order = list.init2d(h,v, 0) + +// walls: keeps track of the walls below and to the right of each cell: +// 0: walls below and to the right +// 1: wall to the right +// 2: wall below +// 3: neither wall +// (This is V in the original BASIC program.) +// Note that a wall to the right can be removed from a +// valid entry by adding 2; a wall below can be removed +// by adding 1. +walls = list.init2d(h,v, 0) +print +print +print +print + +// pick an exit at the top of the maze, +// and print the maze top +x = floor(rnd * h) +for i in range(0, h-1) + if i == x then print ". ","" else print ".--","" +end for +print "." + +// walk from our starting position (by the exit) around +// the maze, clearing a wall on each step +c = 1 // current step number +order[x][0] = c; c += 1 +r = x; s = 0 // [r][s] is our current position in the maze +while true + // collect the set of directions we can move in + dirs = [] + if r > 0 and order[r-1][s] == 0 then dirs.push "left" + if s > 0 and order[r][s-1] == 0 then dirs.push "up" + if r+1 < h and order[r+1][s] == 0 then dirs.push "right" + if s+1 < v and order[r][s+1] == 0 then dirs.push "down" + if not dirs then + //print "Uh-oh, I'm stuck at " + r + "," + s + // couldn't find any directions for this cell; + // find the next already-explored cell + while true + r += 1 + if r >= h then + r = 0 + s += 1 + if s >= v then s = 0 + end if + if order[r][s] != 0 then break + end while + continue + end if + + // pick a random available direction; move there, + // clearing the wall in between and updating order + d = dirs.any + if d == "left" then + walls[r-1][s] += 2 + r = r-1 + else if d == "up" then + walls[r][s-1] += 1 + s = s-1 + else if d == "right" then + walls[r][s] += 2 + r = r+1 + else if d == "down" then + walls[r][s] += 1 + s = s+1 + end if + + //print "At step " + c + ", at " + r + "," + s + order[r][s] = c + c += 1 + if c > h*v then break +end while + +// pick an exit at the bottom of the maze +x = floor(rnd * h) +walls[x][v-1] += 1 + +// print the (rest of the) maze +for j in range(0, v-1) + print "I", "" + for i in range(0, h-1) + if walls[i][j] < 2 then print " I", "" else print " ", "" + end for + print + for i in range(0, h-1) + if walls[i][j] % 2 == 0 then print ":--", "" else print ": ", "" + end for + print "." +end for diff --git a/00_Alternate_Languages/03_Animal/MiniScript/README.md b/00_Alternate_Languages/03_Animal/MiniScript/README.md new file mode 100644 index 00000000..cb7892f6 --- /dev/null +++ b/00_Alternate_Languages/03_Animal/MiniScript/README.md @@ -0,0 +1,16 @@ +Original source downloaded from [Vintage Basic](http://www.vintage-basic.net/games.html). + +Conversion to [MiniScript](https://miniscript.org). + +Ways to play: + +1. Command-Line MiniScript: +Download for your system from https://miniscript.org/cmdline/, install, and then run the program with a command such as: + + miniscript animal.ms + +2. Mini Micro: +Download Mini Micro from https://miniscript.org/MiniMicro/, launch, and then click the top disk slot and chose "Mount Folder..." Select the folder containing the BASIC program. Then, at the Mini Micro command prompt, enter: + + load "animal" + run diff --git a/00_Alternate_Languages/03_Animal/MiniScript/animal.ms b/00_Alternate_Languages/03_Animal/MiniScript/animal.ms new file mode 100644 index 00000000..5aafdddb --- /dev/null +++ b/00_Alternate_Languages/03_Animal/MiniScript/animal.ms @@ -0,0 +1,90 @@ +print " "*32 + "Animal" +print " "*15 + "Creative Computing Morristown, New Jersey" +print; print; print +print "Play 'Guess the Animal'" +print +print "Think of an animal and the computer will try to guess it." +print + +// Ask a yes/no question, and return "Y" or "N". +getYesNo = function(prompt) + while true + inp = input(prompt + "? ").upper + if inp and (inp[0] == "Y" or inp[0] == "N") then return inp[0] + print "Please answer Yes or No." + end while +end function + +// Our data is stored as a list of little maps. +// Answers have only an "answer" key. +// Questions have a "question" key, plus "ifYes" and "ifNo" +// keys which map to the index of the next question or answer. +data = [ + {"question":"Does it swim", "ifYes":1, "ifNo":2}, + {"answer":"fish"}, + {"answer":"bird"}] + +// List all known animals. +listKnown = function + print; print "Animals I already know are:" + for item in data + if item.hasIndex("answer") then print (item.answer + " "*17)[:17], "" + end for + print; print +end function + +// Ask the question at curIndex, and handle the user's response. +doQuestion = function + q = data[curIndex] + if getYesNo(q.question) == "Y" then + globals.curIndex = q.ifYes + else + globals.curIndex = q.ifNo + end if +end function + +// Check the answer at curIndex. If incorrect, get a new question +// to put at that point in our data. +checkAnswer = function + node = data[curIndex] + inp = getYesNo("Is it a " + node.answer) + if inp == "Y" then + print "Why not try another animal?" + else + actual = input("The animal you were thinking of was a? ").lower + print "Please type in a question that would distinguish a" + print actual + " from a " + node.answer + q = {} + q.question = input + q.question = q.question[0].upper + q.question[1:] - "?" + data[curIndex] = q + k = data.len + data.push node // old answer at index k + data.push {"answer":actual} // new answer at index k+1 + if getYesNo("For a " + actual + " the answer would be") == "Y" then + data[curIndex].ifYes = k+1 + data[curIndex].ifNo = k + else + data[curIndex].ifNo = k+1 + data[curIndex].ifYes = k + end if + end if +end function + +// Main loop. (Press Control-C to break.) +while true + while true + inp = input("Are you thinking of an animal? ").upper + if inp == "LIST" then listKnown + if inp and inp[0] == "Y" then break + end while + curIndex = 0 + while true + if data[curIndex].hasIndex("question") then + doQuestion + else + checkAnswer + break + end if + end while +end while diff --git a/00_Alternate_Languages/04_Awari/MiniScript/README.md b/00_Alternate_Languages/04_Awari/MiniScript/README.md new file mode 100644 index 00000000..269d1215 --- /dev/null +++ b/00_Alternate_Languages/04_Awari/MiniScript/README.md @@ -0,0 +1,16 @@ +Original source downloaded from [Vintage Basic](http://www.vintage-basic.net/games.html). + +Conversion to [MiniScript](https://miniscript.org). + +Ways to play: + +1. Command-Line MiniScript: +Download for your system from https://miniscript.org/cmdline/, install, and then run the program with a command such as: + + miniscript awari.ms + +2. Mini Micro: +Download Mini Micro from https://miniscript.org/MiniMicro/, launch, and then click the top disk slot and chose "Mount Folder..." Select the folder containing the BASIC program. Then, at the Mini Micro command prompt, enter: + + load "awari" + run diff --git a/00_Alternate_Languages/04_Awari/MiniScript/awari.ms b/00_Alternate_Languages/04_Awari/MiniScript/awari.ms new file mode 100644 index 00000000..e01c2d6c --- /dev/null +++ b/00_Alternate_Languages/04_Awari/MiniScript/awari.ms @@ -0,0 +1,146 @@ +print " "*34 + "Awari" +print " "*15 + "Creative Computing Morristown, New Jersey" + +// Keep a list of the opening moves (up to 8) of previously lost or drawn games. +// These will be used to penalize repeating the same moves again. +badGames = [] + +printQty = function(qty) + print (" " + qty)[-2:], " " +end function + +printBoard = function + print; print " ", "" + for i in range(12, 7); printQty board[i]; end for + print; printQty board[13] + print " " * 6, ""; printQty board[6] + print; print " ", "" + for i in range(0, 5); printQty board[i]; end for + print; print +end function + +// Redistribute the stones starting at position. +// If the last one ends by itself, opposite some nonzero +// stones on the other side, then capture them into homePos. +// Return true if the last stone ended at homePos, false otherwise. +moveStones = function(board, position, homePos) + p = board[position]; board[position] = 0 + while p + position = (position + 1) % 14 + board[position] += 1 + p -= 1 + end while + if board[position] == 1 and position != 6 and position != 13 and board[12-position] then + board[homePos] += board[12-position] + 1 + board[position] = 0 + board[12-position] = 0 + end if + globals.gameOver = board[0:6].sum == 0 or board[7:13].sum == 0 + return position == homePos +end function + +// Get the player move. Note that the player inputs their move as a number +// from 1-6, but we return it as an actual board position index 0-6. +getPlayerMove = function(prompt="Your move") + while true + pos = input(prompt + "? ").val + if 0 < pos < 7 and board[pos-1] then return pos - 1 + print "Illegal move." + end while +end function + +getComputerMove = function + // Copy the board for safekeeping + boardCopy = board[:] + bestScore = -99; bestMove = 0 + for j in range(7, 12) + if board[j] == 0 then continue // can't move from an empty spot + // suppose we move at position j... + moveStones board, j, 13 + // consider each possible response the player could make + bestPlayerScore = 0 + for i in range(0, 5) + if board[i] == 0 then continue + landPos = board[i] + i // figure the landing position + score = floor(landPos / 14); landPos %= 14 + if board[landPos] == 0 and landPos != 6 and landPos != 13 then + score += board[12 - landPos] // points for capturing stones + end if + if score > bestPlayerScore then bestPlayerScore = score + end for + // figure our own score as our points, minus player points, minus best player score + ourScore = board[13] - board[6] - bestPlayerScore + if gameMoves.len < 8 then + // subtract 2 points if current series of moves is in our bad-games list + proposed = gameMoves + [j] + for badGame in badGames + if badGame[:proposed.len] == proposed then ourScore -= 2 + end for + end if + if ourScore > bestScore then + bestScore = ourScore + bestMove = j + end if + // restore the board + globals.board = boardCopy[:] + end for + print char(42+bestMove) // (labels computer spots as 1-6 from right to left) + return bestMove +end function + +// The game is over when either side has 0 stones left. +isGameOver = function + return board[0:6].sum == 0 or board[7:13].sum == 0 +end function + +// Play one game to completion. +playOneGame = function + // The board is represented as a list of 13 numbers. + // Position 6 is the player's home; 13 is the computer's home. + globals.board = [3]*14; board[13] = 0; board[6] = 0 + // Also keep a list of the moves in the current game + globals.gameMoves = [] + print; print + while true + // Player's turn + printBoard + pos = getPlayerMove + gameMoves.push pos + if moveStones(board, pos, 6) then + if gameOver then break + printBoard + pos = getPlayerMove("Again") + gameMoves.push pos + moveStones board, pos, 6 + end if + if gameOver then break + // Computer's turn + printBoard; print "My move is ", "" + pos = getComputerMove + gameMoves.push pos + if moveStones(board, pos, 13) then + if gameOver then break + printBoard; print "...followed by ", "" + pos = getComputerMove + gameMoves.push pos + moveStones board, pos, 13 + end if + if gameOver then break + end while + printBoard + print; print "GAME OVER" + delta = board[6] - board[13] + if delta < 0 then + print "I win by " + (-delta) + " points" + return + end if + if delta == 0 then print "Drawn game" else print "You win by " + delta + " points" + if gameMoves.len > 8 then gameMoves = gameMoves[:8] + if badGames.indexOf(gameMoves) == null then badGames.push gameMoves +end function + +// Main loop +while true + playOneGame + print; print +end while diff --git a/01_Acey_Ducey/README.md b/01_Acey_Ducey/README.md index 26856f71..0fabfb08 100644 --- a/01_Acey_Ducey/README.md +++ b/01_Acey_Ducey/README.md @@ -15,10 +15,13 @@ As published in Basic Computer Games (1978): Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html +#### Known Bugs + +- Entering a negative bet allows you to gain arbitrarily large amounts of money upon losing the round. #### Porting Notes -(please note any difficulties or challenges in porting here) +- The assignment `N = 100` in line 100 has no effect; variable `N` is not used anywhere else in the program. #### External Links - Common Lisp: https://github.com/koalahedron/lisp-computer-games/blob/master/01%20Acey%20Ducey/common-lisp/acey-deucy.lisp diff --git a/02_Amazing/README.md b/02_Amazing/README.md index b53cbbf5..b8e4b9b4 100644 --- a/02_Amazing/README.md +++ b/02_Amazing/README.md @@ -13,6 +13,10 @@ As published in Basic Computer Games (1978): Downloaded from Vintage Basic at http://www.vintage-basic.net/games.html +#### Known Bugs + +- The input dimensions are checked for values of 1, but not for values of 0 or less. Such inputs will cause the program to break. + #### Porting Notes **2022-01-04:** patched original source in [#400](https://github.com/coding-horror/basic-computer-games/pull/400) to fix a minor bug where a generated maze may be missing an exit, particularly at small maze sizes.