/*Coded by Bugz Podder
Version 0.02 (look at version number to see if you have latest code!)
--Ver 0.02 if a player has no moves, the engine now takes care of it
--Ver 0.01 first official version
*/
randomize
View.Set ("graphics:550;550");
class BaseSnakeAI
/*
This is a sample AI for Bugz' Snake Game
for each move you have 4 directions, NORTH EAST SOUTH OR WEST
you lose if you attempts to go into a square that is not free (occupied by a wall or a snake)
Draws are possible.
in the beginning of the game, you are given the number of players, your player number, board size
the board state (could potentially have some walls in the middle but definately an outer wall,
location of all the players, as well as game type)
for each move you are given a list of updated positions (which the procedure
already took care of) as well as you are asked for a direction to go.
Real-Time game has one extra rule that Turned-Based doesnt have is if two snakes
attempts to go onto the same square at the same turn, both will *DIE*
what you *CANT* change
values for NORTH, EAST, SOUTH, WEST
the AIName, Reset and Move procedure's name as well as what they do
anythin else you can pretty much change, including variable names and so on.
*/
export Reset, Move, AIName;
const SOUTH := 1;
const EAST := 2;
const NORTH := 3;
const WEST := 4;
var NUM_PLAYERS, MY_NUMBER, BOARD_SIZE, GAME_TYPE : int;
var board : array 0 .. 251, 0 .. 251 of int;
var playerX, playerY : array 1 .. 50 of int;
var playerAlive : array 1 .. 50 of boolean;
/* your id number is MY_NUMBER, and playerX, playerY stores X and Y values of every player
playerAlive tells you if a player is alive. to access your info, such as your
current location, use playerX(MY_NUMBER) and playerY(MY_NUMBER)
board (i,j) has a value of -1 if its a wall, 0 if its empty, or 1..50 depending on the
player who occupied it
GAME_TYPE: - 0 if it is Turn-Based
- 1 if it is Real-Time
*/
deferred fcn AIName () : string
proc Reset (gtype : int, nump : int, mynum : int, size : int, brd : array 0 .. 251, 0 .. 251 of int,
Xcrd : array 1 .. 50 of int, Ycrd : array 1 .. 50 of int)
GAME_TYPE := gtype;
NUM_PLAYERS := nump;
MY_NUMBER := mynum;
BOARD_SIZE := size;
board := brd;
playerX := Xcrd;
playerY := Ycrd;
for i : 1 .. NUM_PLAYERS
playerAlive (i) := true;
end for
end Reset
deferred fcn Think () : int
fcn Move (dir : array 1 .. 50 of int) : int
for i : 1 .. NUM_PLAYERS
case dir (i) of
label 0 :
label 1 :
playerY (i) -= 1;
label 2 :
playerX (i) += 1;
label 3 :
playerY (i) += 1;
label 4 :
playerX (i) -= 1;
label :
playerAlive (i) := false;
end case
board (playerX (i), playerY (i)) := i;
end for
result Think ()
end Move
end BaseSnakeAI
include "SampleSnakeAI.t"
class SnakeEngine
import BaseSnakeAI, SampleSnakeAI
export Run, Reset
const SOUTH := 1;
const EAST := 2;
const NORTH := 3;
const WEST := 4;
const dir : array 1 .. 4, 0 .. 1 of int := init (0, -1, 1, 0, 0, 1, -1, 0);
var NUM_ALIVE, NUM_PLAYERS, BOARD_SIZE, GAME_TYPE, NUM_TURN, DELAY_TIME, OFFSET : int;
var board : array 0 .. 251, 0 .. 251 of int;
var playerX, playerY, playerDir, beginDir : array 1 .. 50 of int;
var playerAlive : array 1 .. 50 of boolean;
var ptr : array 1 .. 50 of ^BaseSnakeAI
proc Reset (nump, brdsize, gametype, delaytime : int)
NUM_PLAYERS := nump;
BOARD_SIZE := brdsize;
GAME_TYPE := gametype;
DELAY_TIME := delaytime;
OFFSET := 20;
%calculate offset
var ptr1 : ^SampleSnakeAI
var ptr2 : ^SampleSnakeAI
var ptr3 : ^SampleSnakeAI
var ptr4 : ^SampleSnakeAI
new ptr1
new ptr2
new ptr3
new ptr4
ptr (1) := ptr1;
ptr (2) := ptr2;
ptr (3) := ptr3;
ptr (4) := ptr4;
end Reset
fcn freesp (x, y : int) : int
var w := 0;
for i : 1 .. 4
if board (x + dir (i, 0), y + dir (i, 1)) = 0 then
w += 1;
end if
end for
result w
end freesp
proc Run ()
for i : 1 .. BOARD_SIZE
for j : 1 .. BOARD_SIZE
board (i, j) := 0;
end for
end for
for i : 0 .. BOARD_SIZE + 1
drawfillbox (i * 10 - 5 + OFFSET, -5 + OFFSET, i * 10 + 5 + OFFSET, 5 + OFFSET, black);
drawfillbox (-5 + OFFSET, i * 10 - 5 + OFFSET, 5 + OFFSET, i * 10 + 5 + OFFSET, black);
drawfillbox (i * 10 - 5 + OFFSET, (BOARD_SIZE + 1) * 10 - 5 + OFFSET, i * 10 + 5 + OFFSET, (BOARD_SIZE + 1) * 10 + 5 + OFFSET, black);
drawfillbox ((BOARD_SIZE + 1) * 10 - 5 + OFFSET, i * 10 - 5 + OFFSET, (BOARD_SIZE + 1) * 10 + 5 + OFFSET, i * 10 + 5 + OFFSET, black);
board (0, i) := -1;
board (i, 0) := -1;
board (i, BOARD_SIZE + 1) := -1;
board (BOARD_SIZE + 1, i) := -1;
end for
for i : 1 .. NUM_PLAYERS
var RandX, RandY : int
loop
RandX := Rand.Int (1, BOARD_SIZE);
RandY := Rand.Int (1, BOARD_SIZE);
exit when board (RandX, RandY) = 0
end loop
playerX (i) := RandX;
playerY (i) := RandY;
playerAlive (i) := true;
playerDir (i) := 0;
end for
for i : 1 .. NUM_PLAYERS
drawfillbox (playerX (i) * 10 - 5 + OFFSET, playerY (i) * 10 - 5 + OFFSET, playerX (i) * 10 + 5 + OFFSET, playerY (i) * 10 + 5 + OFFSET, i);
ptr (i) -> Reset (GAME_TYPE, NUM_PLAYERS, i, BOARD_SIZE, board, playerX, playerY)
end for
var move : int := 0;
NUM_ALIVE := NUM_PLAYERS;
NUM_TURN := 0;
var winner := -1;
loop
NUM_TURN += 1;
exit when NUM_ALIVE = 0
if NUM_ALIVE = 1 and winner = -1 then
for i : 1 .. NUM_PLAYERS
if playerAlive (i) then
winner := i;
end if
end for
end if
if GAME_TYPE = 0 then
beginDir := playerDir;
end if
for i : 1 .. NUM_PLAYERS
if playerAlive (i) = true then
if freesp (playerX (i), playerY (i)) = 0 then
playerAlive (i) := false;
playerDir (i) := -1;
NUM_ALIVE -= 1;
else
if GAME_TYPE = 0 then
move := ptr (i) -> Move (playerDir);
elsif GAME_TYPE = 1 then
move := ptr (i) -> Move (beginDir);
end if
playerDir (i) := move;
if move > 0 and move < 5 and board (playerX (i) + dir (move, 0), playerY (i) + dir (move, 1)) = 0 then
playerX (i) += dir (move, 0);
playerY (i) += dir (move, 1);
board (playerX (i), playerY (i)) := i;
drawfillbox (playerX (i) * 10 - 5 + OFFSET, playerY (i) * 10 - 5 + OFFSET, playerX (i) * 10 + 5 + OFFSET, playerY (i) * 10 + 5 + OFFSET, i);
if NUM_TURN > 1 then
drawline (playerX (i) * 10 + OFFSET, playerY (i) * 10 + OFFSET, (playerX (i) - dir (move, 0)) * 10 + OFFSET, (playerY (i) - dir (move, 1)) * 10 + OFFSET, black);
end if
delay (DELAY_TIME);
else
playerAlive (i) := false;
playerDir (i) := -1;
NUM_ALIVE -= 1;
end if
end if
end if
end for
end loop
if winner = -1 then
put "Tie game!";
else
put "Winner is " + ptr (winner) -> AIName ();
end if
end Run
end SnakeEngine
var x : ^SnakeEngine
new x
x -> Reset (4, 50, 0, 0); /* number of players, board size, game type (leave it at 0 for now), delay)*/
x -> Run ();
|