----------------------------------- bugzpodder Sun Jun 01, 2003 9:31 pm Summer AI Challenge ----------------------------------- this is better than "just make any game you want" cuz we have an objective and in the end we can actually have real tournaments and so forth. I propose a challenge of snakes game. basically we have an NxN board, and we have some players at random starting locations. for each move you are given the position of the board, and you have to decide which way to go: North, East, South, West. then which ever direction you've chosen, that square will be occupied by you. you lose if you move into a square thats preoccupied (a wall, yourself, someone else). now coordination, we have basically two choices: stdout or turing. stdout will mean like languages such as C++,Java,Pascal can be used. its hard to connect AI made for stdout with AI made in turing. i think i better stick to turing cuz everyone here knows turing, and if you know C++ you can always convert it to turing. i'll write up the engine when exams are over. it'll be really fun, we did this in stage 2. if you *really* want to use C++ stick a message here. i'll run a competition at end of august or something. the basic format is make a class (if you havent made one before, dont worry, i'll write an example up and all you gotta do is modify the main procedure) ----------------------------------- Martin Sun Jun 01, 2003 9:33 pm ----------------------------------- It's a 1:1 move ratio right? ----------------------------------- bugzpodder Mon Jun 02, 2003 7:35 am ----------------------------------- yes. ----------------------------------- Martin Mon Jun 02, 2003 7:40 am ----------------------------------- Alright, just a couple more questions. First of all, are there walls anywhere or just on the borders? And secondly, how do we do this so that it allows for the other player to move? ----------------------------------- bugzpodder Mon Jun 02, 2003 4:22 pm ----------------------------------- my original plan was to have walls on the sides only but now i changed my mind. it would be *VERY* interesting to have some walls in the middle of the board (i can code up a map editor also hehe), or even randomly generated walls (maybe symmetrical, maybe asymmetrical)!! and as to the move sequences, the players will be named in some (maybe random) order such that player 1 gets to move first, then player 2 and so on. or maybe i'll decide simutaneous moves, but then its hard to predict if two players will get crashed into each other. but this is always an option ----------------------------------- Catalyst Mon Jun 02, 2003 4:31 pm ----------------------------------- sounds very interesting im in for sure ----------------------------------- bugzpodder Mon Jun 02, 2003 4:43 pm ----------------------------------- i'll have sample codes up very soon. in fact i am working on them right now. ----------------------------------- Tony Mon Jun 02, 2003 5:27 pm ----------------------------------- yeah, I wanted to have some AI challange. It would be really cool to host an AI turnament. I'm going to be in too. Though it would be nice if more people participated. ----------------------------------- bugzpodder Mon Jun 02, 2003 6:20 pm ----------------------------------- well, we'll see how this one turns out. a simple AI shouldnt even take long to code. 2 days is almost sufficient, but this engine is going to take me a while, depending on if i am busy. i say probably before exams it will be done so you guys can test your AIs. you cant stop me from using C++ type arrays, comments and semicolons. so bite me here is a sample AI code that you can use. read the instructions inside look at later posts for updated code if you have any questions/comment/concerns feel free to let me know ----------------------------------- bugzpodder Mon Jun 02, 2003 8:02 pm ----------------------------------- btw i added a function AIName in the code above so I could possibly use that for a rating system. ----------------------------------- Martin Mon Jun 02, 2003 8:13 pm ----------------------------------- You'd have to be careful about randomly placed walls...wouldn't be too fair if somebody started surrounded. Another cool idea would be to run the ai's through our little maze generator ;) ----------------------------------- Tony Mon Jun 02, 2003 9:45 pm ----------------------------------- wouldn't be much of a point then... You'd have to specify thing kind of thing in mission statment (cant expect open field AI to run through maze) and then each program just finds the longest path and follows it... ----------------------------------- bugzpodder Mon Jun 02, 2003 9:50 pm ----------------------------------- i am not talking about a lot of walls, just a few. if they are randomly generated, they could be randomly placed blocks. or else they will be symmetrical about the center of the field so no one gets an advantage ----------------------------------- Tony Mon Jun 02, 2003 10:00 pm ----------------------------------- I think for it to be completely fair, starting positions should be random, but symetrical, and walls should also be symetrical along the same axis. ----------------------------------- bugzpodder Mon Jun 02, 2003 10:05 pm ----------------------------------- even when there is no walls in the middle of the game, you still cant guarentee it to be "fair" maybe some algorithms like to be closer with an opponent and some algorithms would be better off starting away from others. some maybe be better closer ot the walls some may like the center more. so its hard to be "fair" and only random is really fair. ----------------------------------- bugzpodder Mon Jun 02, 2003 10:06 pm ----------------------------------- a good AI should deal with a lot of situations, at least i would think so. ----------------------------------- Tony Tue Jun 03, 2003 10:10 am ----------------------------------- yeah... and you could determine your relative starting position and execute different strategies if you'd like 8) ----------------------------------- bugzpodder Tue Jun 03, 2003 8:12 pm ----------------------------------- i am trying to write the snake engine and i am stuck on some problems. i want to have easy access of everyone's AI (ie store the pointers in an array) but stupid turing cant handle this. so in the end, i will probably put the whole engine into the SampleAI. but for now I'll leave it be. anyone have other bright ideas? ----------------------------------- Catalyst Tue Jun 03, 2003 8:34 pm ----------------------------------- what type of pointers are you talking about (to store in the array) cpp or turing? ----------------------------------- bugzpodder Tue Jun 03, 2003 8:56 pm ----------------------------------- turing. everyone is going to have seperate classes and i am trying to find a way to combine everything. here is the *NEW* samplesnake code, which i added one line of label 0: and the engine, which allows you to test your own AI. its not finalized. the simpliest way to use it is to not modify the name of the SampleSnakeAI and just modify the Think() procedure in it. look at later posts for updated code look at later posts for updated code ----------------------------------- Catalyst Tue Jun 03, 2003 9:19 pm ----------------------------------- i like the ; and () :D u could write a generic class and have the users classes overide the base (like virtual functions) class using deferred or you could have the functions and procedure outside the program and brought in using parameters to the class ----------------------------------- bugzpodder Tue Jun 03, 2003 9:27 pm ----------------------------------- well these things sound promising i am going to try it in the next few days. anywayz here is a screen shot of my AI, based on the one i made in stage 2 (the 2nd zig-zag one, its my trademark ;)). the main part was only 10 lines ;) http://www.compsci.ca/bbs/download.php?id=296 http://www.compsci.ca/bbs/files/tmp2.JPG ----------------------------------- Catalyst Tue Jun 03, 2003 9:30 pm ----------------------------------- ur sample ai stops after a few turns ----------------------------------- Catalyst Tue Jun 03, 2003 9:33 pm ----------------------------------- nvr mind, didnt know they turned on themselves ----------------------------------- Tony Tue Jun 03, 2003 9:38 pm ----------------------------------- thats because his sample AI moves randomly... so it crashes into itself and stops ----------------------------------- bugzpodder Tue Jun 03, 2003 9:52 pm ----------------------------------- well i hurriedly made these things so everyone could start making their AI and use the program to test it out. let me know when you've made something. ----------------------------------- Catalyst Tue Jun 03, 2003 11:35 pm ----------------------------------- edit: see below ----------------------------------- bugzpodder Wed Jun 04, 2003 7:43 am ----------------------------------- dead link. ----------------------------------- Catalyst Wed Jun 04, 2003 2:52 pm ----------------------------------- two ai's i tried out new algo: http://www.angelfire.com/alt/catalyst0/snakes2.JPG old algo: http://www.angelfire.com/alt/catalyst0/snakes.JPG ----------------------------------- bugzpodder Wed Jun 04, 2003 5:07 pm ----------------------------------- i like the ; and () :D u could write a generic class and have the users classes overide the base (like virtual functions) class using deferred or you could have the functions and procedure outside the program and brought in using parameters to the class I basically want something that without modifying my code, I could specify which AIs to use. or if thats not possible then i need to at least have the pointers/functions stored in an array so i could loop through them in my code. i am not interested in having seperate calls to each AI using their name. anyone? ----------------------------------- PaddyLong Wed Jun 04, 2003 5:07 pm ----------------------------------- from what I found from trying this, your values for north and south are backwards.. ----------------------------------- bugzpodder Wed Jun 04, 2003 5:08 pm ----------------------------------- i like the ; and () :D u could write a generic class and have the users classes overide the base (like virtual functions) class using deferred or you could have the functions and procedure outside the program and brought in using parameters to the class I basically want something that without modifying my code, I could specify which AIs to use. or if thats not possible then i need to at least have the pointers/functions stored in an array so i could loop through them in my code. i am not interested in having seperate calls to each AI using their name. anyone? ----------------------------------- bugzpodder Wed Jun 04, 2003 5:13 pm ----------------------------------- i can think of one way, is where we can have compiled programs and I'll use Sys.Exec to execute the programs, which will read in a file and output to a file. but then again, i think turing does not way the command executed by Sys.Exec to finish and goes on, right? ----------------------------------- bugzpodder Wed Jun 04, 2003 5:15 pm ----------------------------------- from what I found from trying this, your values for north and south are backwards.. i dont think so. 0,0 is at the top left corner. ----------------------------------- Catalyst Wed Jun 04, 2003 5:19 pm ----------------------------------- you can have the users load their Think funcs into a generic class oh, and in turing bottom-right is 0,0 ----------------------------------- PaddyLong Wed Jun 04, 2003 5:26 pm ----------------------------------- I think what catalyst suggested is probably the best way. oh yeah, you can have an array of pointers to classes which I think you said you couldn't in a previous post... ex... var classarray : array 1 .. 4 of ^someclass for q:1..4 new classarray (q) end for so just have like a Snake or Player class that has their X, Y position as well as their current direction then for the think function, just pass up the X, Y positions of the other players as a parameter (probably need to have getPos functions in the Snake class that just results the X and Y position - this is so that cou can actually fill this array that you are passing to the think function with the data from all of the Snake objects) ----------------------------------- bugzpodder Wed Jun 04, 2003 5:33 pm ----------------------------------- Catalyst, could you give an simple example? PaddyLong, I am well aware of that. but since every AI have a *different* class name, then it is impossible to do what you suggested, since I want an array of pointers to *different classes*. inheritance/implementation of classes still results a different class (ie a class of different name) and therefore i cant put them in an array, at least i dont think. a run-time solution is even more impossible, since now i have to basically replace class names with strings. ----------------------------------- PaddyLong Wed Jun 04, 2003 5:45 pm ----------------------------------- lol I just figured out what you were talking about... wasn't thinking of how each of the things wouldn't have its unique AI if they all were one class what is the maximum number of AI's you plan to have competing at once? Like are you going to do it as a sort of tournament ladder or just have everyone in on a big free for all? ----------------------------------- bugzpodder Wed Jun 04, 2003 5:50 pm ----------------------------------- i'd like to have a big free for all but looks like that its not really possible unless manually modify the Engine for all AIs. which is not good. but pointers, boiled on to the end, are really only integers/addresses. i was wondering if i could exploit this fact so i could at least have an areaay of pointers to different classes ----------------------------------- PaddyLong Wed Jun 04, 2003 5:59 pm ----------------------------------- maybe... but each class might take up a different amount of memory and so you might not be able to ----------------------------------- bugzpodder Wed Jun 04, 2003 6:00 pm ----------------------------------- pointers are not classes, they are merely pointers, that stores an address (just a simple integer) of a memory. at least thats how it works in C++ ----------------------------------- PaddyLong Wed Jun 04, 2003 6:12 pm ----------------------------------- yeah I know what pointers are... but liek you might not just be able to guess where the addresses of the different classes are based on what the address of a given class is ----------------------------------- bugzpodder Wed Jun 04, 2003 6:18 pm ----------------------------------- i have no idea what you mean by "guessing" in C++ you dont need to guess, just declare it and you have the address (i mean, you either know the address or you dont, you cant "guess"). cept turing wont let you do this... ----------------------------------- PaddyLong Wed Jun 04, 2003 6:19 pm ----------------------------------- nm, I now udnerstadn what you were talking about by having an array of pointers ----------------------------------- bugzpodder Wed Jun 04, 2003 6:27 pm ----------------------------------- got it, turing use pointer to "anyclass" to do this. but i still have to modify my program each time i want to use a class of different name. anyone know how to avoid this? ----------------------------------- bugzpodder Wed Jun 04, 2003 7:07 pm ----------------------------------- we'll see how this works out. if all else fails, i'd have to go with C++. ----------------------------------- Catalyst Wed Jun 04, 2003 7:08 pm ----------------------------------- I dont think this can be done with fcns but im not sure you should be able to workaround using a proc tho proc blank end blank class AIDemo export Load, Think var Think : proc blank proc Load (proc f) Think := f end Load end AIDemo var demo : ^AIDemo new demo proc RThree put "It Works" end RThree demo -> Load (RThree) for i : 1 .. 2 demo -> Think end for just loadup the instances then they can be run thru the array ----------------------------------- bugzpodder Wed Jun 04, 2003 7:58 pm ----------------------------------- then i guess it isnt as different as this. anywayz here is the newest version of code where i've made use of inheritance to solve this problem. there will probably be no further changes made to the BaseAI. the only thing you should be changing is the include file name and the stuff in the Reset procedure (class name) for your own Class /*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 (); here is a sample of the AI /* ************************************************************** * AI Name: SampleAI * * Coder: Bugz Podder * ************************************************************** */ class SampleSnakeAI inherit BaseSnakeAI body fcn AIName():string result "SampleAI" end AIName body fcn Think () : int /*This is your main AI, do whatever you want*/ if GAME_TYPE = 0 then /* Turn-Based */ result Rand.Int (1, 4) elsif GAME_TYPE = 1 then /* Real-Time */ result Rand.Int (1, 4) end if end Think end SampleSnakeAI ----------------------------------- Catalyst Sat Jun 07, 2003 3:51 pm ----------------------------------- this would be cool if it ran over the net ----------------------------------- Martin Sat Jun 07, 2003 7:50 pm ----------------------------------- Apparently the net module works a bunch better now, so we might be able to. ----------------------------------- PaddyLong Sat Jun 07, 2003 8:04 pm ----------------------------------- can we add functions to our class? just ones for checking things for our AI ... like boolean ones to see if something more than a basic if statement is true ----------------------------------- bugzpodder Sun Jun 08, 2003 1:18 pm ----------------------------------- of course, you can add anything you'd like. net module ehh, i'll take a look at that. ----------------------------------- bugzpodder Thu Aug 07, 2003 8:47 pm ----------------------------------- My AI and the engine (i dont know if its the same as as posted b4) anyways to use your own engine, you have to change two places in the code (Thats what i mean when i said in the other post, the problem was) one place is a bunch of replace codes, and one place is a bunch of pointer declaration. just change the class name to your own class. or you can do a search and replace (search for FunAI) ----------------------------------- Catalyst Thu Aug 07, 2003 9:56 pm ----------------------------------- heres the one i coded some of the code is unecessary im not gonna edit it now ----------------------------------- PaddyLong Fri Aug 08, 2003 1:19 pm ----------------------------------- here's my snake ai