• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.

Wizuriel

Members
  • Content count

    15
  • Joined

  • Last visited

Community Reputation

150 Neutral

About Wizuriel

  • Rank
    Member
  1. Sorry for kind of necroing this, but I just managed to get negamax working (correctly) and while my program is still slow (3-5min a turn), it's still a huge improvement over my 1hour initial time. Still trying to cut back on my A* searches and find general improvements, but a working copy has been put up at: http://thetaraday.somee.com/Games?id=7 and wanted to thank everyone here for the help.
  2. Ahoy. So after some painful months and much help from people in [url="http://www.gamedev.net/topic/630517-designing-ai-for-quoridor/"]this thread[/url] I know have AI for my quoridor game that appears to play right and only takes 3-5min to make a turn (still working on it). Meanwhile my next big thing would be going from C# and a consol application to actually putting in on my website. Originally my plan was just to rewrite everything in Javascript, but yeah I really don't want to do that unless it really is the best way. My other thought would be to just use a ton of AJAX to communicate how the game is going from the backend to javascript on the front end to display the results, but been finding so far that has been very messy trying to communicate my objects to JS. So was hoping people might have some suggestions
  3. edit: wish I could delete this post. Going try and re do the search by scratch and hope I get a better result this time
  4. Did you do any optimization to get those numbers? My depth 2 on the starting position is exploring about 17k nodes taking about 46 seconds to do so :S
  5. [quote name='alvaro' timestamp='1346871685' post='4976942'] [quote name='Wizuriel' timestamp='1346870816' post='4976938'] Right now everything I do used dynamic memory allocation and truth be told my classes aren't memory efficient (especially for debugging I like tracking some extra information to make sure stuff is working), but would that really be the difference between you're alpha beta pruning taking seconds and mine taking hours? [/quote] Of course, you might have a bug somewhere. But needless memory allocation can easily result in a factor of 100 slowdown. The problem is that everything in an alpha-beta searcher is part of the "inner loop", in some sense. Keeping an eye on performance is very important in this context. I'll add some node counts to my code so we can compare mine and yours and see if I am just getting more nodes per second. It could be that I am also visiting many fewer nodes than you are, which would probably indicate a problem with your alpha-beta implementation. [/quote] Would be appreciated. Going off my code using standard board and players starting in the middle P1) initial position has 131 children. Assume player 1 moves P2) initial position (based off player 1 moving) has 131 children P1) First child from the 131 children returns 132 more children P2) P2's first child also has 132 children This first branch assumes both players are just moving directly towards their desired goal So yeah I should find a way that you can't move backwards for the children (by backwards I mean to a position already done by one of the earlier children). Easiest way I can think of would be to have each view have a link back to it's parents and make sure the new view is not equal to any of the parents. Would the extra memory usage be worth the less nodes to view?
  6. [quote name='alvaro' timestamp='1346856164' post='4976835'] Make sure you are not doing any dynamic memory allocation at all. I don't know how feasible this is with languages like C# and Java, but in C or C++ it's fairly straight forward. [/quote] Right now everything I do used dynamic memory allocation and truth be told my classes aren't memory efficient (especially for debugging I like tracking some extra information to make sure stuff is working), but would that really be the difference between you're alpha beta pruning taking seconds and mine taking hours?
  7. Can you check if the friendly unit blocking your path is on your goal square? If so report back that you reached you're goal? Edit: or can you make friendly units push other friendly units out of the way?
  8. Now I'm really curious what I did wrong for mine to take hours to do depth 4 searching. I've tried shrinking the board down to 5x5 with fewer walls to test it and I'm positive my algorithms are all working correctly (if not quickly). In a nutshell what I do is send the current view to my function. -Try to move pawn each direction (check if way is blocked by a wall, if not you can move, if the node your moving has the opponent I get his move directions and add then to yours (since opponent square won't see your piece as his it returns that your square is not valid so doesn't infinite loop). -Try to place wall on each square -When placing a wall I check that it doesn't hit another wall or go between a wall (My wall pieces have a start and end point making it pretty easy to tell the difference between 1 wall and between 2 walls which would be legal) -If wall position doesn't hit a wall do A* search on both player and opponent. I do this until I find a path for each of them (so min of once per pawn, max of board length), if both still have exits the wall is good. run all those children in the alpha beta function
  9. Huzzah just got the alpha beta working (at least to the best I can debug/see) [img]http://public.gamedev.net//public/style_emoticons/default/biggrin.png[/img] I gave up on negamax and just used a more traditional alpha/beta look. I don't think my program is slow because of the pathing. When I generate children each wall place requires pathing to be called a min of twice (once per each player till it can find a path to one of their goal spaces). My getchildren routine is doing that in a fraction of a second. I think my programs slow speed is just the amount of states it needs to explore and evaluate (also probably doesn't help for debugging it I kept links to each state to help debug, good think memory is cheap [img]http://public.gamedev.net//public/style_emoticons/default/biggrin.png[/img]). Unfortunately even if my opponent just moves that can also reflect my best position. It is possible because of wall placements that player 1 can't place a wall to block player 2 without also increasing player 1's path. After player 2 has moved x squares though it is possible that you can now place a wall to increase just player 2's time despite both players following their optimal path. Though now that I wrote all that I do think is player 1 path is shorter than player 2's path as long as both just move I shouldn't have to reevaluate player 1's positions. Unfortunately would need to still do so for player 2 :S edit: Updated code [source lang="csharp"] public static List<BoardView> GetBestMove(BoardView myview, int depth, int color) { var bestMoves = new List<BoardView>(); double highestScore = int.MinValue; double tmpScore; List<BoardView> validmoves = new List<BoardView>(); //getting all valid children based off the current players position validmoves.AddRange(myview.getChildren(color)); for (int x = 0; x < validmoves.Count; x++) { BoardView move = validmoves[x]; //doing minimax tree / negamax alpha beta pruning (tree?) for upcoming potential moves to evaluate how well this first move way //tmpScore = NegaMax(move, int.MinValue, int.MaxValue, depth - 1, -color, color); tmpScore = alphabeta(move, int.MinValue, int.MaxValue, depth - 1, -color, color); if (tmpScore > highestScore) { bestMoves.Clear(); bestMoves.Add(move); highestScore = tmpScore; } else if (tmpScore == highestScore) { move.board.myscore = highestScore; bestMoves.Add(move); } } return bestMoves; }[/source] Edit: Of course this one still doesn't show private static double alphabeta(BoardView myview, double alpha, double beta, int depth, int color, int originalplayer) { if (depth <= 0 || myview.currentplayer.checkWin()) { double score = myview.getScore(originalplayer); return score; } if (color != originalplayer) { double minscore = beta; List<BoardView> validmoves = new List<BoardView>(); validmoves.AddRange(myview.getChildren(color)); foreach (BoardView child in validmoves) { minscore = Math.Min(minscore, alphabeta(child, alpha, beta, depth-1, -color, originalplayer)); beta = minscore; if (alpha >= beta) return minscore; } return minscore ; } else { double maxscore = alpha; List<BoardView> validmoves = new List<BoardView>(); validmoves.AddRange(myview.getChildren(color)); foreach (BoardView child in validmoves) { maxscore = Math.Max(maxscore, alphabeta(child, alpha, beta, depth-1, -color, originalplayer)); if (alpha >= beta) { return maxscore; } } return maxscore; } } [source lang="csharp"] public class BoardView { public Board board { get; set; } public Player currentplayer { get; set; } public Player opponent { get; set; } public BoardView parent { get; set; } //makes a clone of an old view public BoardView(BoardView oldview) { parent = oldview; board = new Board(oldview.board); currentplayer = new Player(oldview.currentplayer); opponent = new Player(oldview.opponent); } //makes a new board view by combining 2 players and a board public BoardView(Board myboard, Player p1, Player p2) { board = new Board(myboard); currentplayer = new Player(p1); opponent = new Player(p2); } //swap the players public void swap() { Player temp = currentplayer; currentplayer = opponent; opponent = temp; } /* * returns a list of all avilable moves from a given view * color = 1 = current player * color = -1 = opponent */ public List<BoardView> getChildren(int color) { List<BoardView> children = new List<BoardView>(); Boolean swapped = false; /* * checking if the current player is what it should be according to the color call * If color = 1 player = 1 * if color = -1 player = 2 * if I swap here it changes this level not the children, so will need to swap again later (since I just want the children to move opposite the parents, not the current level to swap * who played) */ if (currentplayer.symbol != Global.getType(color)) { swapped = true; swap(); } //getting all movement views from the current player GameSpace myspace = board.grid[currentplayer.position]; List<GameSpace> movement = new List<GameSpace>(AStar.neighborsAndJumps(myspace, board, opponent.symbol)); foreach (GameSpace mymove in movement) { BoardView newReality = new BoardView(this); newReality.board.MovePawn(newReality.currentplayer.position, mymove.SQNum, newReality.currentplayer.symbol); newReality.currentplayer.position = mymove.SQNum; children.Add(newReality); } //if the current player has walls left, find all valid moves if (currentplayer.numberwalls > 0) { /* * 0 = horz walls * 1 = vertical walls */ for (int y = 0; y < 2; y++) { //go through and try a wall at every valid position for (int x = 0; x < board.grid.Count; x++) { int pos = 0; int temp = opponent.position; //finding where I should start the wall placement. If my goal[0] is > size (length of board) than it means I'm heading towards the back squares if (currentplayer.goal[0] >= Global.SIZE) { /* * opponent is moving to the front squares. Check if current player or opponent is closer to the goal. * If I'm closer start placing walls behind me, if opponent is closer place walls behind opponent */ if (currentplayer.position < opponent.position) temp = currentplayer.position; /* * starting at the far right of the row the opponent or current player are on (depending who is closer to the goal). Keep moving left checking each square for wall placement. * Hopefully this will quickly find a good spot to place a wall that slows the opponent and not me */ pos = (temp / Global.SIZE) * Global.SIZE + (Global.SIZE - 1) - x; if (pos < 0) pos += board.grid.Count; } else { //opponent is moving to the back squares if (currentplayer.position > opponent.position) temp = currentplayer.position; /* * starting at the far left of the row the opponent or current player are on (depending who is closer to the goal). Keep moving right checking each square for wall placement. * Hopefully this will quickly find a good spot to place a wall that slows the opponent and not me */ pos = (temp / Global.SIZE) * Global.SIZE + x; if (pos >= board.grid.Count) pos -= board.grid.Count; } BoardView newReality = new BoardView(this); if (y == 0) { //if true the wall has been placed and add it to the list of vald moves if (newReality.board.SetHorzWall(pos, newReality.currentplayer, newReality.opponent)) { children.Add(newReality); } } else { //if true the wall has been placed and add it to the list of vald moves if (newReality.board.SetVertWall(pos, newReality.currentplayer, newReality.opponent)) { children.Add(newReality); } } } } } /* * If I swapped above than undo the swap at the current level */ if (swapped) swap(); return children; } public double getScore(int color) { bool swapped = false; if (currentplayer.symbol != Global.getType(color)) { swapped = true; swap(); } double score = 0; //finding my shortest path to a goal List<GameSpace> mypath = new List<GameSpace>(board.findPath(true, currentplayer, opponent)); //finding opponents shortest path to a goal List<GameSpace> opppath = new List<GameSpace>(board.findPath(true, opponent, currentplayer)); score = 100 * (opppath.Count - 1 - mypath.Count) + currentplayer.numberwalls - opponent.numberwalls; if (swapped) swap(); return score; }[/source] edity 2: I'm not really understanding the killer heuristic, Right now I always start with movement towards the goal (followed by the rest since it is a short list) and for my wall placement I start by placing walls between my opponent and their goal in a way that won't block me. Is there anything else I can try with that?
  10. Okay so just not sure if I'm doing this right then. I'm trying to use negamax with alpha beta pruning to find my move. What I have so far getbestmove: This is the function I initially call to try and find my best move. I get all the possible moves based off the current players position. I than loop through them all and run them through the negamax function to evaluate how good of a placement they are. [source lang="csharp"] public static List<BoardView> GetBestMove(BoardView myview, int depth, int color) { var bestMoves = new List<BoardView>(); double highestScore = int.MinValue; double tmpScore; Boolean first = true; List<BoardView> validmoves = new List<BoardView>(); //getting all valid children based off the current players position validmoves.AddRange(myview.getChildren(color)); for (int x = 0; x < validmoves.Count; x++) { BoardView move = validmoves[x]; //doing minimax tree / negamax alpha beta pruning (tree?) for upcoming potential moves to evaluate how well this first move way if (first) { tmpScore = NegaMax(move, int.MinValue, int.MaxValue, depth, -color); first = false; } else tmpScore = NegaMax(move, highestScore, int.MaxValue, depth, -color); if (tmpScore > highestScore) { bestMoves.Clear(); bestMoves.Add(move); highestScore = tmpScore; } else if (tmpScore == highestScore) { move.board.myscore = highestScore; bestMoves.Add(move); } } return bestMoves; } [/source] [source lang="csharp"] private static double NegaMax(BoardView myview, double alpha, double beta, int depth, int color) { if (depth <= 0 || myview.currentplayer.checkWin()) return myview.getScore(); List<BoardView> validmoves = new List<BoardView>(); validmoves.AddRange(myview.getChildren(color)); foreach (BoardView child in validmoves) { double temp = -NegaMax(child, -beta, -alpha, depth - 1, -color); if (temp > alpha) alpha = temp; if (alpha >= beta) break; // cut-off } return alpha; } [/source] and my boardview class. This just pretty much holds the board and 2 players. The constructor takes either an old view or a board and 2 players. It than makes deep copies of the objects. swap: just swaps the current and opponent references getChildren: Returns a list of all possible plays based off the current players position on the board. It first checks for movement for the current player than wall positions. For wall positions it first checks if the current player is between the opponent and the goal and which direction the opponent is going. This should create 4 scenarions i) Opponent is going towards start of the board and I'm between my opponent and the goal spaces. The wall logic will start placing walls behind me going from my position > 0 ; maxsquare > position ii) Opponent is going towards start of board and I'm not between my opponent and the goal. Same thing as above but I start placing the walls behind the opponent iii & iv) same thing but replace start of board with end of board and the logic is position > maxsquare; 0 > position Getscore: I use an A* search to find the shortest path for me to a goal square and my opponent and his goal squares. The main weight is based off the distance to the goal with some weight on bad wall positions. While I don't think this equation is going get great defensive wall positions (see picture posted earlier in this thread). In theory moving away from the goal or bad wall placements should return bad scores resulting in those paths getting cut off. [source lang="csharp"] public class BoardView { public Board board { get; set; } public Player currentplayer { get; set; } public Player opponent { get; set; } //public BoardView parent { get; set; } //makes a clone of an old view public BoardView(BoardView oldview) { //parent = oldview; board = new Board(oldview.board); currentplayer = new Player(oldview.currentplayer); opponent = new Player(oldview.opponent); } //makes a new board view by combining 2 players and a board public BoardView(Board myboard, Player p1, Player p2) { board = new Board(myboard); currentplayer = new Player(p1); opponent = new Player(p2); } //swap the players public void swap() { Player temp = currentplayer; currentplayer = opponent; opponent = temp; } /* * returns a list of all avilable moves from a given view * color = 1 = current player * color = -1 = opponent */ public List<BoardView> getChildren(int color) { List<BoardView> children = new List<BoardView>(); //getting all movement views from the current player GameSpace myspace = board.grid[currentplayer.position]; List<GameSpace> movement = new List<GameSpace>(AStar.neighborsAndJumps(myspace, board, opponent.symbol)); if (currentplayer.symbol != Global.getType(color)) { myspace = board.grid[opponent.position]; movement = new List<GameSpace>(AStar.neighborsAndJumps(myspace, board, currentplayer.symbol)); } foreach (GameSpace mymove in movement) { BoardView newReality = new BoardView(this); if (newReality.currentplayer.symbol != Global.getType(color)) newReality.swap(); newReality.board.MovePawn(newReality.currentplayer.position, mymove.SQNum, newReality.currentplayer.symbol); newReality.currentplayer.position = mymove.SQNum; children.Add(newReality); } //if the current player has walls left, find all valid moves if (currentplayer.numberwalls > 0) { /* * 0 = horz walls * 1 = vertical walls */ for (int y = 0; y < 2; y++) { //go through and try a wall at every valid position for (int x = 0; x < board.grid.Count; x++) { int pos = 0; int temp = opponent.position; //finding where I should start the wall placement. If my goal[0] is > size (length of board) than it means I'm heading towards the back squares if (currentplayer.goal[0] >= Global.SIZE) { /* * opponent is moving to the front squares. Check if current player or opponent is closer to the goal. * If I'm closer start placing walls behind me, if opponent is closer place walls behind opponent */ if (currentplayer.position < opponent.position) temp = currentplayer.position; /* * starting at the far right of the row the opponent or current player are on (depending who is closer to the goal). Keep moving left checking each square for wall placement. * Hopefully this will quickly find a good spot to place a wall that slows the opponent and not me */ pos = (temp / Global.SIZE) * Global.SIZE + (Global.SIZE - 1) - x; if (pos < 0) pos += board.grid.Count; } else { //opponent is moving to the back squares if (currentplayer.position > opponent.position) temp = currentplayer.position; /* * starting at the far left of the row the opponent or current player are on (depending who is closer to the goal). Keep moving right checking each square for wall placement. * Hopefully this will quickly find a good spot to place a wall that slows the opponent and not me */ pos = (temp / Global.SIZE) * Global.SIZE + x; if (pos >= board.grid.Count) pos -= board.grid.Count; } BoardView newReality = new BoardView(this); if (newReality.currentplayer.symbol != Global.getType(color)) newReality.swap(); if (y == 0) { //if true the wall has been placed and add it to the list of vald moves if (newReality.board.SetHorzWall(pos, newReality.currentplayer, newReality.opponent)) { children.Add(newReality); } } else { //if true the wall has been placed and add it to the list of vald moves if (newReality.board.SetVertWall(pos, newReality.currentplayer, newReality.opponent)) { children.Add(newReality); } } } } } return children; } public double getScore() { double score = 0; //finding my shortest path to a goal List<GameSpace> mypath = new List<GameSpace>(board.findPath(true, currentplayer, opponent)); //finding opponents shortest path to a goal List<GameSpace> opppath = new List<GameSpace>(board.findPath(true, opponent, currentplayer)); score = 100 * (opppath.Count - mypath.Count) + currentplayer.numberwalls - opponent.numberwalls; return score; } [/source] Edit: For some reason my negamax function won't show right with the code tag [img]http://public.gamedev.net//public/style_emoticons/default/sad.png[/img] private static double NegaMax(BoardView myview, double alpha, double beta, int depth, int color) { if (depth <= 0 || myview.currentplayer.checkWin()) return myview.getScore(); List<BoardView> validmoves = new List<BoardView>(); validmoves.AddRange(myview.getChildren(color)); foreach (BoardView child in validmoves) { double temp = -NegaMax(child, -beta, -alpha, depth - 1, -color); if (temp > alpha) alpha = temp; if (alpha >= beta) break; // cut-off } return alpha; } edit 2: Found a bug when I was calling swap. Did more checking that swapping occurs at the right time. Man that getchild function is atrocious :S
  11. [quote name='jefferytitan' timestamp='1346620333' post='4975829'] Are you pruning the search space using common sense assumptions? For example, taking advantage of left/right reflection symmetry, ignoring illegal wall combinations, ignoring wall combinations which will never improve the situation, etc? And of course there's applying heuristics so you search the more likely options first, e.g. putting a wall behind the opponent is unlikely to help your cause. [/quote] I'm trying to [img]http://public.gamedev.net//public/style_emoticons/default/biggrin.png[/img] I do make sure all wall combinations are legal and my first children are always moving forward (followed by other movement options) since getting closer to the goal should always give a good score (I think). As for applying common sense to try and prune more wall options, that I'm not sure how to do. I am going through every valid move, because I couldn't think of a logical way to try and find good spots for defensive walls to help you. I'm literally starting at square zero, checking what walls I can place there and if it is legal making it a new child and going to the next square. Also you might be surprised how much putting a wall behind your opponent can help What I'm actually going try and see if it helps if make the computer just move on the first 3 turns. If they are both in the middle hopefully can prune some results faster as more walls are played instead of just movement. Yeah if no walls are placed and pawns just move you have 128 legal wall placements and 4 movement options.
  12. [quote name='IADaveMark' timestamp='1346445083' post='4975220'] Here's a thought... rather than forward searching (which can be a huge potential state space), do it like a planner and search backwards from the goal. [/quote] Not really sure how that would reduce the state space, but definitely need to find some way to do that. I followed alvaro's advice and did a Minimax tree with alpha beta pruning and at depth 3+ it is pretty slow on finding the next move. Though looking at the game each position can have something like 130 children :S
  13. I'm not too sure though how to evaluate the position for a minimax tree without it quickly growing out of control / taking forever. For an easy scenario: [img]http://thetaraday.somee.com/quoridor.png[/img] Player green should place the yellow wall, if he doesn't and just moves (following the yellow arrow since that is his closest path to the end) player blue will just place a wall in front of him forcing him to have to backtrack to the one path around that series of walls. In actual gameplay this can get more complex since your best action might be placing several walls trying to make a safe path to the goal instead of moving or trying to block your opponent. So right now the way I'm (or I was) looking at it would be: If my path is shorter (using A* and Manhattan distance [with some weight to try and avoid paths right beside 2 walls]) a) see if placing a wall defensively is a good idea (not sure how to do without brute force since the best position in this scenario won't be from the best paths [usually]) b) move If my path is longer -find my opponents best path -for each wall position on their best path try placing a wall and recalculate my best path and opponents -pick the one that gives the best results.
  14. Hello. I'm attempting to learn programming and web development and for my latest project I'm attempting to program the board game Quoridor. For those that don't know the game; basic idea is Quoridor is played on a 9x9 board, first pawn that reaches the opposite side of the board wins. During your turn you can either move or place a wall (you have 10 walls), each wall blocks 2 squares. So right now I have the an A* search that lets my AI finding the fastest path and I use the A* search to make sure no wall placed in illegal spots (an illegal wall would completely block a player from being able to reach the end). My problem is trying to do the wall placing AI. My first attempt was kind of a state machine. After 3 turns (so if both pawns move only they are at the middle of the board) I do a check which pawn is closer to their goal. If the player is closer I try putting a wall on every path of their best route (or the first best route that A* returns, I do check multiple ones but only return the first best one) and put the wall where the players movement is increased the most compared to how it affects the AI. If the AI is closer to the goal than I just get the AI to move. Now the problem with this is the AI kind of stupidly and quickly runs out of walls, and doesn't place them in the best spot (since It's just going off the best route, the walls don't line up right to really slow the player, its too direct). Also one of the biggest strategies in Quoridor is placing walls defensively so your opponent can't cut off your best path (something I have no idea how to even begin to code). So I'm now trying to think of a different way of approaching this problem. I'm kind of interested with trying a genetic algorithm / neural network to try and predict moves and act accordingly, but for the life of me I can't think how to condense the data down to even start to do that. So kind of hoping someone can point me in a better direction.
  15. Hello. I'm trying to create a reasonable simple hidden object (where is Waldo/Wally type game) and having some trouble creating a plan of action to create this. What I want to do is have a starmap and ask Users to find a specific Zodiac. When a user clicks a star it should shown to be clicked and once the user believes they have the right stars selected can submit it to check if they are right or not. My plan is to have a blank starmap and set it as the background image. I know I can use jquery to bind mouse clicks over the image. My idea than was to have a list of the correct pixle positions and check if the users click was within x radius of the right spot to verify they clicked a star. My problem is how to show the user clicked something. Right now the only way I can think of doing that is have a different image map of each star selected (plan is just to colour them in) and the rest of the map set as transparent and just overlap the background image with a selected star image (so as they keep getting overlapped the stars should be shown to be coloured in). In a nutshell my Pseudo code is [source lang="plain"] pick random zodiac. Set blank star map as background image do { if mouse click { send server the spot clicked check if spot is within X of any stars (list of correct positions) if user clicked a star highlight/deselect star //insert idea here how to highlight star } if user submits { check if right starts selected If true than game isDone if not inform user their selection is wrong } } while (isDone == false)[/source] So just wondering if this would be the best way to go, if there is a more efficient way?