Added MiniScript version of 23_Checkers.

This commit is contained in:
JoeStrout
2023-07-26 15:07:15 -07:00
parent f98fffc19f
commit 01e1cc964a
3 changed files with 261 additions and 1 deletions

View File

@@ -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 checkers.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 "checkers"
run

View File

@@ -0,0 +1,243 @@
print " "*32 + "Checkers"
print " "*15 + "Creative Computing Morristown, New Jersey"
print; print; print
print "This is the game of Checkers. The computer is X,"
print "and you are O. The computer will move first."
print "Squares are referred to by a coordinate system."
print "(0,0) is the lower left corner"
print "(0,7) is the upper left corner"
print "(7,0) is the lower right corner"
print "(7,7) is the upper right corner"
print "The computer will type '+TO' when you have another"
print "jump. Type two negative numbers if you cannot jump."
print; print; print
input "(Press Return.)"; print // (give player a chance to read)
// The board. Pieces are represented by numeric values:
// - 0 = empty square
// - -1,-2 = computer (X) (-1 for regular piece, -2 for king)
// - 1,2 = human (O) (1 for regular piece, 2 for king)
// Board is indexed by [x][y], so we have to initialize it sideways:
board = [
[ 1, 0, 1, 0, 0, 0, -1, 0],
[ 0, 1, 0, 0, 0, -1, 0, -1],
[ 1, 0, 1, 0, 0, 0, -1, 0],
[ 0, 1, 0, 0, 0, -1, 0, -1],
[ 1, 0, 1, 0, 0, 0, -1, 0],
[ 0, 1, 0, 0, 0, -1, 0, -1],
[ 1, 0, 1, 0, 0, 0, -1, 0],
[ 0, 1, 0, 0, 0, -1, 0, -1]]
// Function to print the board
printBoard = function
for y in range(7, 0)
for x in range(0, 7)
// We print by indexing with the board entry (-2 to 2) into a list
// of possible representations. Remember that in MiniScript, a
// negative index counts from the end.
print [". ", "O ", "O*", "X*", "X "][board[x][y]], " "
end for
print; print
end for
end function
// Function to get x,y coordinates from the player.
// This is written to allow the two numbers to be
// separated by any combination of ',' and ' '.
// Returns input as [x,y].
inputPosition = function(prompt, requiredPieceSign, allowCancel=false)
while true
ans = input(prompt + "? ").replace(",", " ").split
if ans.len < 2 then
print "Enter two coordinates, for example: 4 0"
continue
end if
x = val(ans[0])
y = val(ans[-1])
if x < 0 and y < 0 and allowCancel then
return [x, y]
else if x < 0 or x > 7 or y < 0 or y > 7 then
print "Coordinates must be in the range 0-7"
else if x%2 != y%2 then
print "Invalid coordinates (both must be odd, or both even)"
else if sign(board[x][y]) != requiredPieceSign then
print "Invalid coordinates"
else
return [x, y]
end if
end while
end function
// Evaluate a potential (computer) move.
evalMove = function(fromX, fromY, toX, toY)
score = 0
// +2 if it promotes this piece
if toY == 0 and board[fromX][fromY] == -1 then score += 2
// +5 if it jumps an opponent's piece
if abs(fromY-toY) == 2 then score += 5
// -2 if the piece is moving away from the top boundary
if fromY == 7 then score -= 2
// +1 for putting the piece against a vertical boundary
if toX == 0 or toX == 7 then score += 1
// check neighboring pieces of the target position
for c in [-1, 1]
if toX+c < 0 or toX+c > 7 or toY-1 < 0 then continue
// +1 for each adjacent friendly piece
if board[toX+c][toY-1] < 0 then score += 1
// -1 for each opponent piece that could now jump this one
if toX-c >= 0 and toX-c <= 7 and toY+1 <= 7 and board[toX+c][toY-1] > 0 and (
board[toX-c][toY+1] == 0 or (toX-c == fromX and toY+1 == fromY)) then score -= 2
end for
return score
end function
// Consider a possible (computer) move, including whether it's even valid.
// Return it or the previous best, whichever is better.
consider = function(fromX, fromY, toX, toY, previousBest)
// make sure it's within the bounds of the board
if toX < 0 or toX > 7 or toY < 0 or toY > 7 then return previousBest
// if it's an opponent's piece, consider jumping it instead
dx = toX - fromX
if board[toX][toY] > 0 and abs(dx) == 1 then
dy = toY - fromY
return consider(fromX, fromY, fromX + dx*2, fromY + dy*2, previousBest)
end if
// if it's a jump, make sure it's over an opponent piece
if abs(dx) == 2 then
midX = (fromX + toX)/2; midY = (fromY + toY)/2
if board[midX][midY] < 1 then return previousBest
end if
// make sure the destination is empty
if board[toX][toY] then return previousBest
// all checks passed; score it, and return whichever is better
rating = evalMove(fromX, fromY, toX, toY)
if not previousBest or rating > previousBest.rating then
newBest = {}
newBest.fromX = fromX; newBest.fromY = fromY
newBest.toX = toX; newBest.toY = toY
newBest.rating = rating
return newBest
else
return previousBest
end if
end function
// Do the computer's turn
doComputerTurn = function
// For each square on the board containing one of my pieces, consider
// possible moves and keep the best one so far. Start with a step
// size of 1 (ordinary move), but if we jump, then keep jumping.
stepSize = 1
while true
bestMove = null
for x in range(0, 7)
for y in range(0, 7)
if board[x][y] >= 0 then continue // not my piece
move = {}
move.fromPos = [x,y]
// Consider forward moves; if it's a king, also consider backward moves
for dx in [-stepSize, stepSize]
move.toPos = [dx, -stepSize]
bestMove = consider(x, y, x+dx, y-stepSize, bestMove)
if board[x][y] == -2 then bestMove = consider(x, y, x+dx, y+stepSize, bestMove)
end for
end for
end for
if not bestMove then
// No valid move -- if step size is still 1, this means we
// couldn't find ANY move on our turn, and we have lost.
// Otherwise, we're done.
if stepSize == 1 then
globals.gameOver = true
globals.winner = 1
end if
break
end if
// Do the move, and stop if we did not jump.
if stepSize == 1 then
print "From " + bestMove.fromX + " " + bestMove.fromY, ""
end if
print " to " + bestMove.toX + " " + bestMove.toY, ""
movePiece bestMove.fromX, bestMove.fromY, bestMove.toX, bestMove.toY
if abs(bestMove.toX - bestMove.fromX) == 1 then break
stepSize = 2
end while
print
end function
// Move one piece (including captures and crowning
movePiece = function(fromX, fromY, toX, toY)
piece = board[fromX][fromY]
board[toX][toY] = piece
board[fromX][fromY] = 0
// capture piece jumped over
if abs(toX - fromX) == 2 then
board[(fromX+toX)/2][(fromY+toY)/2] = 0
end if
// crown (make into a king) a piece that reaches the back row
if (toY == 7 and piece > 0) or (toY == 0 and piece < 0) then
board[toX][toY] = 2 * sign(piece)
end if
end function
// Handle the player's move.
doPlayerTurn = function
fromPos = inputPosition("From", 1, true)
fromX = fromPos[0]; fromY = fromPos[1]
if fromX < 0 then
// Player concedes the game.
globals.gameOver = true
globals.winner = -1
return
end if
while true
toPos = inputPosition("To", 0)
toX = toPos[0]; toY = toPos[1]
dist = abs(toX - fromX)
if dist <= 2 and abs(toY - fromY) == dist then break
end while
while true
// Make the move, and continue as long as we have a jump
movePiece fromX, fromY, toX, toY
if dist != 2 then break
// Prompt for another move, allowing a cancel (negative input).
fromX = toX; fromY = toX
toPos = inputPosition("+To", 0, true)
if toPos[0] < 0 or toPos[1] < 0 then break
toX = toPos[0]; toY = toPos[1]
end while
// If piece has reached the end of the board, crown this piece
if toY == 7 then board[toX][toY] = 2
end function
// Main loop.
gameOver = false
while not gameOver
doComputerTurn
if gameOver then break
printBoard
doPlayerTurn
if gameOver then break
printBoard
end while
print
if winner > 0 then print "You win." else print "I win."

View File

@@ -24,5 +24,6 @@ should be more readable.
- If the computer moves a checker to the bottom row, it promotes, but
leaves the original checker in place. (See line 1240)
- Human players may move non-kings as if they were kings. (See lines 1590 to 1810)
- Human players are not required to jump if it is possible.
- Human players are not required to jump if it is possible, and may make a number
other illegal moves (jumping their own pieces, jumping empty squares, etc.).
- Curious writing to "I" variable without ever reading it. (See lines 1700 and 1806)