--Robert Knepher
--ROBOTIC PIGEONS LEAVE MESSES!
-- HANDLER
-- moveOK
-- DESCRIPTION
-- Returns TRUE / FALSE based on whether the indicated move is legal
-- INPUT VARIABLES
-- boardList, row, column
-- OUTPUT VARIABLES
-- TRUE / FALSE
on moveOK boardList, row, column
rowList = boardList[row]
thisItem = rowList[column]
if not (thisItem = ..EMPTY) then
return FALSE
end if
if (column > 1) then
-- Set startCol, check element to the left
startCol = column - 1
thisItem = rowList[startCol]
if not (thisItem = ..EMPTY) then
return TRUE
end if
else
startCol = column
end if
if (column < 8) then
-- Set endCol, check element to the right
endCol = column + 1
thisItem = rowList[endCol]
if not (thisItem = ..EMPTY) then
return TRUE
end if
else
endCol = column
end if
if (row > 1) then
-- Check upper row
rowList = boardList[row-1]
repeat with colIndex = startCol to endCol
thisItem = rowList[colIndex]
if not (thisItem = ..EMPTY) then
return TRUE
end if
end repeat
end if
if (row < 8) then
-- Check lower row
rowList = boardList[row+1]
repeat with colIndex = startCol to endCol
thisItem = rowList[colIndex]
if not (thisItem = ..EMPTY) then
return TRUE
end if
end repeat
end if
return FALSE
end
-- HANDLER
-- makeMove
-- DESCRIPTION
-- Returns a new board list based on the indicated move
-- INPUT VARIABLES
-- boardList, whoseTurn, row, column
-- OUTPUT VARIABLES
-- new board list
on makeMove boardList, whoseTurn, row, column
newList = duplicate (boardList)
rowList = newList[row]
rowList[column] = whoseTurn
-- Now traverse in 8 different directions to reverse any
-- needed values as a result of the move.
if (whoseTurn = ..cyborg) then
opponent = ..human
else
opponent = ..cyborg
end if
tweakMove (newList, ..UPPER_LEFT, whoseTurn, opponent, row, column)
tweakMove (newList, ..UP, whoseTurn, opponent, row, column)
tweakMove (newList, ..UPPER_RIGHT, whoseTurn, opponent, row, column)
tweakMove (newList, ..RIGHT, whoseTurn, opponent, row, column)
tweakMove (newList, ..LOWER_RIGHT, whoseTurn, opponent, row, column)
tweakMove (newList, ..DOWN, whoseTurn, opponent, row, column)
tweakMove (newList, ..LOWER_LEFT, whoseTurn, opponent, row, column)
tweakMove (newList, ..LEFT, whoseTurn, opponent, row, column)
return newList
end
on tweakMove boardList, direction, whoseTurn, opponent, row, column
-- Default values
rowIncrement = 1
colIncrement = 1
case direction of
..UPPER_LEFT,
..UP,
..UPPER_RIGHT:
rowIncrement = -1
..LEFT,
..RIGHT:
rowIncrement = 0
..LOWER_LEFT,
..DOWN,
..LOWER_RIGHT:
rowIncrement = 1
end case
case direction of
..UPPER_LEFT,
..LEFT,
..LOWER_LEFT:
colIncrement = -1
..UP,
..DOWN:
colIncrement = 0
..UPPER_RIGHT,
..RIGHT,
..LOWER_RIGHT:
colIncrement = 1
end case
rowIndex = row
colIndex = column
-- First check that there's a whoseTurn's token in the
-- direction we're searching
tokenFound = FALSE
repeat while TRUE
rowIndex = rowIndex + rowIncrement
if ((rowIndex < 1) or (rowIndex > 8)) then
exit repeat
end if
colIndex = colIndex + colIncrement
if ((colIndex < 1) or (colIndex > 8)) then
exit repeat
end if
rowList = boardList[rowIndex]
thisToken = rowList[colIndex]
if (thisToken = whoseTurn) then
tokenFound = TRUE
exit repeat
else if (thisToken = ..empty) then
exit
end if
end repeat
if (tokenFound = FALSE) then
exit
end if
repeat while TRUE
rowIndex = rowIndex + rowIncrement
if ((rowIndex < 1) or (rowIndex > 8)) then
exit repeat
end if
colIndex = colIndex + colIncrement
if ((colIndex < 1) or (colIndex > 8)) then
exit repeat
end if
rowList = boardList[rowIndex]
if (rowList[colIndex] = opponent) then
rowList[colIndex] = whoseTurn
else
exit repeat
end if
end repeat
end
---------------------------------------------------------------------
property pRow
property pColumn
property pScore
property pBoardList
-- HANDLER
-- new
-- DESCRIPTION
-- Creates the object, initializes variables
-- INPUT VARIABLES
-- boardList
-- list of 8 lists, representing the board
-- whoseTurn
-- symbol. possible values: ..CYBORG, ..USER
-- levelsToGo
-- integer >= 0, indicating the search depth
-- OUTPUT VARIABLES
-- [HANDLER]
-- reference to the object
on new me, boardList, whoseTurn, levelsToGo
-- We'll generate a list of property lists, each property list
-- containing the necessary details of each possible move.
-- Each property list has the following properties:
-- ..boardList, ..row, ..column
templateList = [..boardList: [], ..row: 0, ..column: 0]
listOfPLists = []
repeat with rowIndex = 1 to 8
repeat with colIndex = 1 to 8
if ( moveOK(boardList, rowIndex, colIndex) ) then
newPList = duplicate(templateList)
newPList.boardList = makeMove(boardList, whoseTurn, rowIndex, colIndex)
newPList.row = rowIndex
newPList.column = colIndex
append listOfPLists, newPList
end if
end repeat
end repeat
-- We've generated a list of possible moves. If no deeper searching is required,
-- set variables and exit
if (whoseTurn = ..CYBORG) then
-- We'll set pScore to the highest score found. Initialize to low value
pScore = -10000
else
-- We'll set pScore to the lowest score found. Initialize to high value
pScore = 10000
end if
if (levelsToGo = 0) then
repeat with pList in listOfPLists
thisScore = computeScore (pList.boardList)
if (((whoseTurn = ..CYBORG) and (thisScore > pScore)) or
((whoseTurn = ..human) and (thisScore < pScore))) then
pScore = thisScore
pBoardList = pList.boardList
pRow = pList.row
pColumn = pList.column
end if
end repeat
return me
end if
-- Deeper searching is required (levelsToGo > 0)
newLevels = levelsToGo - 1
if (whoseTurn = ..CYBORG) then
newTurn = ..USER
else
newTurn = ..CYBORG
end if
repeat with pList in listOfPLists
newChildObject =
new(script "Recursive Analyze Object", pList.boardList, newTurn, newLevels)
thisScore = getScore (newChildObject)
if (((whoseTurn = ..CYBORG) and (thisScore > pScore)) or
((whoseTurn = ..human) and (thisScore < pScore))) then
pScore = thisScore
pBoardList = pList.boardList
pRow = pList.row
pColumn = pList.column
end if
end repeat
return me
end
on getScore me
return pScore
end
on getBoardList me
return pBoardList
end
on getRow me
return pRow
end
on getColumn me
return pColumn
end
-----------------------------------------------------------------------
global gBoardList
global gSpriteList
on startmovie
gBoardList=
[[..empty,..empty,..empty,..empty,..empty,..empty,..empty,..empty],
[..empty,..empty,..empty,..empty,..empty,..empty,..empty,..empty],
[..empty,..empty,..empty,..empty,..empty,..empty,..empty,..empty],
[..empty,..empty,..empty,..cyborg, ..human, ..empty,..empty,..empty],
[..empty,..empty,..empty,..human, ..cyborg, ..empty,..empty,..empty],
[..empty,..empty,..empty,..empty,..empty,..empty,..empty,..empty],
[..empty,..empty,..empty,..empty,..empty,..empty,..empty,..empty],
[..empty,..empty,..empty,..empty,..empty,..empty,..empty,..empty]]
gSpriteList=
[[26, 27, 28, 29, 30, 31, 32, 33],
[35, 36, 37, 38, 39, 40, 41, 42],
[44, 45, 46, 47, 48, 49, 50, 51],
[53, 54, 55, 56, 57, 58, 59, 60],
[62, 63, 64, 65, 66, 67, 68, 69],
[71, 72, 73, 74, 75, 76, 77, 78],
[80, 81, 82, 83, 84, 85, 86, 87],
[89, 90, 91, 92, 93, 94, 95, 96]]
set the member of sprite 56 to "cyborg"
set the member of sprite 66 to "cyborg"
set the member of sprite 57 to "human"
set the member of sprite 65 to "human"
end
on updateSprites
repeat with rowIndex = 1 to 8
rowBoardList = gBoardList [rowIndex]
rowSpriteList = gSpriteList[rowIndex]
repeat with colIndex = 1 to 8
boardValue = rowBoardList [colIndex]
spriteNumber = rowSpriteList[colIndex]
case boardValue of
..empty:
sprite spriteNumber.member = member 2
..cyborg:
sprite spriteNumber.member = member "cyborg"
..human:
sprite spriteNumber.member = member "human"
end case
end repeat
end repeat
updateStage
end
---------------------------------------------------------------------------
global gBoardList
property pRow
property pColumn
-- HANDLER
-- getBehaviorDescription
-- DESCRIPTION
-- Provides a description that appears in the
-- bottom pane of the Behavior Inspector when the
-- behavior is selected.
-- INPUT VARIABLES
-- me
-- Sprite object that this behavior is attached to
-- OUTPUT VARIABLES
-- [HANDLER]
-- Behavior description string
on getBehaviorDescription me
return
"Riddle mouseDown behavior" & RETURN & RETURN &
"This behavior will attempt to make the user's move at the indicated " &
"square of the Riddle board. Human can choose the row and column." & RETURN & RETURN &
"PARAMETERS:" & RETURN &
"* Row (1 - 8)" & RETURN &
"* Column (1 - 8)"
end getBehaviorDescription
-- HANDLER
-- getBehaviorTooltip
-- DESCRIPTION
-- Provides a description that as a tooltip for the behavior
-- INPUT VARIABLES
-- me
-- Sprite object that this behavior is attached to
-- OUTPUT VARIABLES
-- [HANDLER]
-- Tooltip description string
on getBehaviorTooltip me
return
"Riddle mouseDown behavior. " &
"Performs processing when it's the user's turn to make a move."
end getBehaviorTooltip
-- HANDLER
-- getPropertyDescriptionList
-- DESCRIPTION
-- Provides a property list that is used by Director
-- to set the parameters of the behavior
-- INPUT VARIABLES
-- me
-- Sprite object that this behavior is attached to
-- OUTPUT VARIABLES
-- [HANDLER]
-- Property description list
on getPropertyDescriptionList me
return
[
..pRow:
[
..comment: "Row number",
..format: ..integer,
..range: [..min: 1, ..max: 8],
..default: 1
],
..pColumn:
[
..comment: "Column number",
..format: ..integer,
..range: [..min: 1, ..max: 8],
..default: 1
]
]
end getPropertyDescriptionList
-- HANDLER
-- mouseDown
-- DESCRIPTION
-- Performs processing when the user clicks on the sprite
-- INPUT VARIABLES
-- me
-- Sprite object that this behavior is attached to
-- OUTPUT VARIABLES
on mouseDown me
if not (moveOK (gBoardList, pRow, pColumn)) then
exit
end if
-- Do further processing
gBoardList = makeMove( gBoardList, ..human, pRow, pColumn )
newObject = new (script "Recursive Analyze Object", gBoardList, ..cyborg, 2)
gBoardList = getBoardList (newObject )
updateSprites
end