'Ashish MOD
'Sorry bplus, but modified your a code a little. ;)
'debuging, if there is AI error, then prints the change value along with state of AI SUB
_TITLE "Snake AI-1_5 SHARE change AS XY" 'b+ 2020-03-18 '2020-03-14 Snake AI-1 first post
'2020-03-16 Snake AI-1_1 there must be overlap of the snake somewhere! Aha!
'2020-03-17 Snake AI-1_2 fix the duplicate segment problem
' Now a new mystery, an ocassional flashing duplicate box
'2020-03-17 Install standard snake rules for testing brain evolving
' First setup XY type and rename and convert variables using XY type.
' 2nd Make snake brain and whole game only dependent sqrsX, sqrsY and sq for screen size
' Got it!!! the code ends with hangup head next to fruit with 99 (1 cell less that whole board)
' cells of snake length, no new place can be found for fruit, perfect finish and no duplicate
' cells! PLUS now can turn on a dime go up one colume and down the next in 2 key press.
' Now add autoPilot on -1 / off 0 toggle control, OK snake rules tested when human pilots snake.
' Help screen & independent speeds for human or AI.
'2020-03-18 "Snake AI-1_4 fix tester" The AI tester needs to save Head(x, y) in case the AI
' does not change the head(x, y) or tries to move it diagonally.
'2020-03-18 Snake AI-1_5 SHARE change AS XY
' DIM SHARE change AS XY or change.x, change.y replaces variables called dx, dy.
' I decided to switch over to human control if AI fails to return a proper change.
' AI must leave change.x, change.y ready for human to take over control which means my changing
' the code for toggling the autopilot and adding change.x, change.y updates in my snakeBrain SUB.
' Rewrite SnakeBrain using only change.X and change.Y now. A BEEP will indicate an AI error and
' signal control returned to human. This noted in Key Help part of screen.
'################ MOD by Ashish ######################
'Added my own AI. It took 3 hours xD
' Snakepit Dimensions: square size = sq, sqrsX = # of squares along x-axis and sqrsY squares down.
CONST sq
= 20, sqrsX
= 20, sqrsY
= 20, xmax
= sq
* sqrsX
, ymax
= sq
* sqrsY
' Usually used to give a point on 2D board a single name that has an X dimension and a Y dimension.
' SHARED variables for any version of SnakeBrain SUB to act as autoPilot for snake snake.
DIM SHARED change
AS XY
' directs the head direction through AI or Human DIM SHARED head
AS XY
' leads the way of the snake(body) through snakepit DIM SHARED snake
(1 TO sqrsX
* sqrsY
) AS XY
' whole snake, head is at index = sLen DIM SHARED fruit
AS XY
' as snake eats fruit it grows, object is to grow snake to fill snakepit
' SHARED for screenUpdate
'other data needed for program
help ' Key Menu
hSpeed = 3: aSpeed = 20 ' autopilot speed is independent of human control speed
restart: ' reinitialize
r
= .3 + RND * .7: g
= r
* .5 + RND * .3 - .15: b
= .5 * r
+ RND * .3 - .15 ' rnd pal color varsFOR i
= 1 TO sqrsX
* sqrsY
' enough colors for snake to fill snakepit pal
(i
) = _RGB32(84 + 64 * SIN(r
+ i
/ 2), 84 + 64 * SIN(g
+ i
/ 2), 104 * SIN(b
+ i
/ 2))head.X = sqrsX / 2 - 3: head.Y = sqrsY / 2 - 3 ' head start
fruit.X = sqrsX / 2 + 2: fruit.Y = sqrsY / 2 + 2 ' first fruit
sLen = 1 ' for starters snake is all head
snake(sLen).X = head.X: snake(sLen).Y = head.Y ' head is always at sLen end
autoPilot = 1 ' start snake body count
change.X = 0: change.Y = 1 ' head snake down board, Y direction of first fruit
LINE (0, 0)-(xmax
, ymax
), &HFF884422, BF
' clear snakepit IF sLen
= sqrsX
* sqrsY
- 1 THEN screenUpdate:
EXIT DO ' game is won! start another autoPilot = 1 - autoPilot ' it is now up to AI to keep change updated for human take over
ELSEIF KEY$
= "p" THEN ' pause toggle p starts pause p ends pause IF autoPilot
AND aSpeed
+ 5 < 400 THEN aSpeed
= aSpeed
+ 5 ' max autopilot speed is 400 !!! IF autoPilot
= 0 AND hSpeed
+ .5 < 10 THEN hSpeed
= hSpeed
+ .5 ' max human speed is 10 IF autoPilot
AND aSpeed
- 5 > 0 THEN aSpeed
= aSpeed
- 5 IF autoPilot
= 0 AND hSpeed
- .5 > 1 THEN hSpeed
= hSpeed
- .5
IF autoPilot
THEN ' who is piloting the snake?
saveChange.X = change.X: saveChange.Y = change.Y ' if AI screws up then human takes over
' PLUG-IN YOUR Snake Brain AI here
'=========================================================================== AI Auto Pilot
snakeBrain
'=========================================================================================
'check changes
IF ABS(change.X
) = 0 THEN ' must have diffence in y's IF ABS(change.Y
) <> 1 THEN autoPilot
= 0 ' error switch to human IF ABS(change.X
) <> 1 THEN autoPilot
= 0 ' error switch to human ELSE ' must have a 0 in either change.x or change.y but not both autoPilot = 0 ' error switch to human
'DEBUG
IF autoPilot
= 0 THEN ' switching control over to human restore change values change.X
= saveChange.X: change.Y
= saveChange.Y:
BEEP ' alert human
ELSE ' ======================================================================= human control change.X = 0: change.Y = -1
change.X = 0: change.Y = 1
change.X = 1: change.Y = 0
change.X = -1: change.Y = 0
head.X = head.X + change.X: head.Y = head.Y + change.Y ' OK human or AI have spoken
' ============================ check snake head with Rules: ===============================
' 1. Snakepit boundary check, snake hits wall, dies.
IF head.X
< 0 OR head.X
> sqrsX
- 1 OR head.Y
< 0 OR head.Y
> sqrsY
- 1 THEN
' 2. Snake eats body part, dies. This should kill snake if turn its head back on itself.
FOR i
= 1 TO sLen
' did head just crash into body? IF head.X
= snake
(i
).X
AND head.Y
= snake
(i
).Y
THEN
' 3. Eats Fruit and grows or just move every segment up 1 space.
IF (fruit.X
= head.X
AND fruit.Y
= head.Y
) THEN ' snake eats fruit sLen = sLen + 1
snake(sLen).X = head.X: snake(sLen).Y = head.Y ' assimilate fruit into head for new segment
fruit.X
= INT(RND * sqrsX
): fruit.Y
= INT(RND * sqrsY
): good
= -1 FOR i
= 1 TO sLen
' move the snake data down 1 dropping off last snake(i).X = snake(i + 1).X: snake(i).Y = snake(i + 1).Y
snake(sLen).X = head.X: snake(sLen).Y = head.Y ' and adding new head position
screenUpdate ' on with the show this is it!
_DELAY 3 ' win or loose, go again
SUB screenUpdate
' draw snake and fruit, overlap code debugger IF i
= sLen
THEN c~&
= &HFF000000 ELSE c~&
= pal
(sLen
- i
)
' overlap helps debug duplicate square drawing which indicates a flawed code
overlap(snake(i).X, snake(i).Y) = overlap(snake(i).X, snake(i).Y) + 1
LINE (snake
(i
).X
* sq
, snake
(i
).Y
* sq
)-STEP(sq
- 2, sq
- 2), c~&
, BF
IF overlap
(snake
(i
).X
, snake
(i
).Y
) > 1 THEN ' show visually where code flaws effect display LINE (snake
(i
).X
* sq
+ .25 * sq
, snake
(i
).Y
* sq
+ .25 * sq
)_
-STEP(.5 * sq
- 2, .5 * sq
- 2), &HFFFFFFFF, BF
LINE (fruit.X
* sq
, fruit.Y
* sq
)-STEP(sq
- 2, sq
- 2), _RGB32(255, 100, 255), BF
SUB snakeBrain
'>>>>>>>>>> B+ SNAKE BRAIN needs sqrsX to be even number <<<<<<<<<<<<<<<
'IF sqrsX MOD 2 = 1 THEN change.X = 0: change.Y = 0: EXIT SUB 'throw error for code check to
'' discover and switch to human control
'IF head.X = 0 AND head.Y = sqrsY - 1 THEN
' change.X = 0: change.Y = -1
'ELSEIF head.X MOD 2 = 0 AND head.Y <> 0 AND head.Y <> sqrsY - 1 THEN
' change.X = 0: change.Y = -1
'ELSEIF head.X MOD 2 = 0 AND head.Y = 0 AND head.Y <> sqrsY - 1 THEN
' change.X = 1: change.Y = 0
'ELSEIF head.X MOD 2 = 1 AND head.X <> sqrsX - 1 AND head.Y = sqrsY - 2 THEN
' change.X = 1: change.Y = 0
'ELSEIF head.X MOD 2 = 1 AND head.X <> sqrsX - 1 AND head.Y < sqrsY - 1 THEN
' change.X = 0: change.Y = 1
'ELSEIF head.X = sqrsX - 1 AND head.Y = sqrsY - 1 THEN
' change.X = -1: change.Y = 0
'ELSEIF head.Y = sqrsY - 1 AND head.X <> 0 THEN
' change.X = -1: change.Y = 0
'ELSEIF head.X MOD 2 = 1 AND head.Y = 0 AND head.Y <> sqrsY - 1 THEN
' change.X = 0: change.Y = 1
'ELSEIF head.X = sqrsX - 1 AND head.Y < sqrsY - 1 THEN
' change.X = 0: change.Y = 1
'END IF
DIM nx
, ny
, dx
, dy
'Ashish AI dx = fruit.X - head.X
dy = fruit.Y - head.Y
nx = snakeBodyExists(1)
ny = snakeBodyExists(2)
IF sLen
> 1 THEN 'collison at corners of square state$ = "corners"
IF change.X
= -1 THEN change.X
= 0: change.Y
= 1: decided
= 0:
EXIT SUB IF change.Y
= -1 THEN change.Y
= 0: change.X
= 1: decided
= 0:
EXIT SUB state$ = "corners"
IF change.X
= -1 THEN change.X
= 0: change.Y
= -1: decided
= 0:
EXIT SUB IF change.Y
= 1 THEN change.Y
= 0: change.X
= 1: decided
= 0: decided
= 0:
EXIT SUB state$ = "corners"
IF change.X
= 1 THEN change.X
= 0: change.Y
= 1: decided
= 0:
EXIT SUB IF change.Y
= -1 THEN change.Y
= 0: change.X
= -1: decided
= 0:
EXIT SUB state$ = "corners"
IF change.X
= 1 THEN change.X
= 0: change.Y
= -1: decided
= 0:
EXIT SUB IF change.Y
= 1 THEN change.Y
= 0: change.X
= -1: decided
= 0:
EXIT SUB IF decided
= 0 THEN 'collision with walls IF head.X
= sqrsX
- 1 OR head.X
= 0 THEN state$ = "walls"
change.Y = ny * -1: change.X = 0
decided = 1
state$ = "walls"
change.X = nx * -1: change.Y = 0
decided = 1
IF dx
= 0 THEN 'when fruit and head in same direction and motion in same axis state$ = "linear"
change.Y
= 1: change.X
= 0: decided
= 0:
EXIT SUB change.Y
= -1: change.X
= 0: decided
= 0:
EXIT SUB state$ = "linear"
change.X
= 1: change.Y
= 0: decided
= 0:
EXIT SUB change.X
= -1: change.Y
= 0: decided
= 0:
EXIT SUB
state$ = "common"
'common decision
state$
= "common ny=" + STR$(ny
) change.X = 0
state$
= "common cy=" + STR$(change.Y
) IF dy
> 0 AND ny
<> 1 THEN change.Y
= 1: change.X
= 0 IF dy
< 0 AND ny
<> -1 THEN change.Y
= -1: change.X
= 0 decided = 0
state$
= "common nx=" + STR$(nx
) change.Y = 0
state$
= "common cx=" + STR$(change.X
) IF dx
> 0 AND nx
<> 1 THEN change.X
= 1: change.Y
= 0 IF dx
< 0 AND nx
<> -1 THEN change.X
= -1: change.Y
= 0 decided = 0
state$ = "rand_common"
IF ABS(dx
) = ABS(dy
) THEN 'random choice will be made then, rest code is same as above state$
= "rand_common ny=" + STR$(ny
) change.X = 0
state$
= "rand_common cy=" + STR$(change.Y
) IF dy
> 0 AND ny
<> 1 THEN change.Y
= 1: change.X
= 0 IF dy
< 0 AND ny
<> -1 THEN change.Y
= -1: change.X
= 0 decided = 0
state$
= "rand_common nx=" + STR$(nx
) change.Y = 0
state$
= "rand_common cx=" + STR$(change.X
) IF dx
> 0 AND nx
<> 1 THEN change.X
= 1: change.Y
= 0 IF dx
< 0 AND nx
<> -1 THEN change.X
= -1: change.Y
= 0 decided = 0
'END IF
IF which%
= 1 THEN 'x-direction