im developing an online version of the board game go, a japanese game which players take it in turns to place their stone on the grid. When one players stones are surrounded by their opponents, they are destroyed.
This is the logic i cant get my head around how i would program. So far ive made the 2 player grid where all the stones placment are stored in an array. I will include a picture which will make it much clearer here
So as you can see, the grid shows that black has 2 white stones surrounded in which case they should be destoryed, note that it can be any number of surrounded stones but in this case its 2.
To the right you can also see the array of stones which i will use to check if a player has been surrounded. I tried to make some pysudo code but it was becoming a mess and way over complicated, is this task really that complicated? any adivice or logic behind how i would do this would be appriated so if anyone online has done something similar that would be good too. Im not even sure making an array like i have done is the best way in the end so if theres a better way please let me know
I would recommend a different data model--essentially a two-dimensional array, holding values of 0, +1, and -1, for empty, black, and white respectively. For purposes of your algorithm, maintain a parallel array of booleans for "has liberty".
Your algorithm will need to scan the board multiple times. Prior to the scan, set the "has liberty" flag for a location to false if and only if the location is occupied. On each scan, find all the cells with "has liberty" of true and mark the cell to the left, right, top, and bottom as "has liberty"; if the location is occupied, restrict this marking to adjacent locations of the same color. When nothing changes on the board after a scan, you are done. At that point, all the stones with "has liberty" remaining false are captured and should be removed.
This is a simple, inefficient algorithm. Go engines such as GNU go have much more sophisticated algorithms that involve keeping track of "chains" or "groups" of connected stones, with their number of liberties, and then update those as stones are played. If you are planning to write a go-playing program, you will be doing this calculation thousands or millions of times as you read out different sequences, so that kind of optimization will become crucial.
Note that you will need to do special casing for the situation known as "ko" and similar situations where a stone is played in a seemingly "captured" position but survives because it itself takes other stones. . If you simply place the stone taking the ko on the board, and run the above algorithm, then both the stone being taken and the stone just played will be considered to be captured, which is wrong. Therefore, you need a board-level variable for most recent stone, and consider that stone to always be in the "has liberty" state, with appropriate logic to handle illegal moves.
A general rough outline for the algorithm:
Determine all the spots adjacent to your white pieces (let's use white here for clarity):
create two buckets (arrays): white pieces to check, adjacent spots
take any white piece, put it into the white-pieces bucket
for all the white pieces in your white-pieces bucket, determine their adjacent spots (up, down, left, right)
if there's no white piece on that spot, put the spot into the adjacent-spots bucket
if there's a white piece on that spot, put it into the white-pieces bucket
repeat this process until your white-pieces bucket is empty (you have found all the white pieces in a group)
(make sure you deduplicate your buckets in the process so you're not running around in circles)
Check whether all of the adjacent spots are covered in black pieces.
There's a ton of optimisation that can be done that would make this algorithm much more complicated, and a professional Go program is much more complex than this, but it gets you started.
Related
I have been learning about neural networks and genetic algorithms, and to test my learning, have tried to make an AI that learns to play flappy bird:
I have left it running for at least 10 hours (overnight and longer), but the fittest member still fails to show any significant advancements in intelligence from when I began the simulation apart from avoiding the floor and ceilings.
The inputs are the rays (as you can see above) that act as sight lines, and the network is fed in their lengths, and the birds vertical velocity. It seems that the best bird is essentially ignoring all the sight lines except the horizontal one, and when it is very short, it is jumping.
The output is a number between 0 and 1, if the output is larger than 0.5, then the bird jumps.
There are 4 hidden layers, with 15 neurons each, with the input layer feeding forward to the first hidden layers, then the 1st hidden layer feeding forward to the 2nd one ... and the final hidden layer feeding forward to the output, the dna of a bird is an array of real numbers representing the weights of the neural networks, I have made another project using the same style of neural network, and genetic algorithm, in which ants had to travel to food, and it worked perfectly.
Here is the code: https://github.com/Karan0110/flappy-bird-ai
Please say in the comments if you need any additional information
Please can you say whether my method is flawed or not, as I am almost certain the code works correctly (I got from the previous working project).
I like your idea, but I suggest you change some things.
Don't use a network with a fixed structure. Look up Neural evolution of autgmenting topologies and rather implement it yourself, or use a library like neataptic.
I don't believe your network needs that many inputs. I believe 3-5 sensors (20-50° gaps) would be enough, since many of the input values seem to be very similar.
If you are not sure why exactly your project is not working try this:
Try view an image of your current best network. If the network doesn't take important sensors (like the velocity) into account, you'll see it instantly.
Make sure all of your sensors are working fine (looks fine in the image above) and be sure to nkrmalize the values in a meaningful way.
Check if the maximum & average score increases over time. If it doesn't your GA isn't working properly or your networ receives inputs that are not good enough to solve the problem.
One trick that helped me out a lot, is to keep the elite of the GA in a seperate array. Only replace elite networks if some other network has performed better than the elite. Keep the elite trough all the generations, so once your algorithm finds an extraordinarily good solution, it won't be lost in any future generation if nothing else performs better.
I using JasonDavies's Word Cloud for my project, but there is a problem that I using Persian[Farsi] Strings and my problem here that words have overlapping in Svg.
This is my project's output:
What happened to the Farsi words?
As explained on the About page for the project, the generator needs to retrieve the shape of a glyph to be able to compute where it is "safe" to put other words. The about page explains the process in much more detail, but here's what we care for:
Glyphs are rendered individually to a hidden <canvas> element.
Pixel data is retrieved
Bounding boxes are derived
The word cloud is generated.
Now, the critical insight is that in Western (and many other) scripts, glyphs don't change shape based on context often. Yes, there are such things as ligatures, but they are generally rare, and definitely not necessary for the script.
In Persian, however, the glyph shape will change based on context. For non-Persian readers, look at ی and س which, when combined, become یس. Yes, that last one is two glyphs!
The algorithm actually has no problem dealing with Persian characters, as you can see by hacking the demo on the about page, putting a breakpoint just after the d.code is generated, to be able to modify it:
Replacing it with 1740, which is the charCode for the first Persian glyph above, and letting the algorithm run, shows beautiful and perfectly correct bounding boxes around the glyph:
The issue is that when the word cloud is actually rendered, the glyph is placed in context and... changes shape. The generator doesn't know this, though, and continues to use the old bounding data to place other words, thus creating the overlapping you witnessed. In addition, there is probably also an issue around right-to-left handling of text, which certainly would not help.
I would encourage you to take this up the author of the generator directly. The project has a GitHub page: https://github.com/jasondavies/d3-cloud so opening an issue there (and maybe referring back to this answer) would help!
I will describe my problem using the attached image :
The green block is the starting position of my game entity. Next I'd like to move it to the position marked by the orange square. But at the same time, I assume that levitation is not possible or/& this block is a wall. In either case going there is not possible. So I need to figure out a way of finding the first available place (as close to the orange square as possible) for my entity to move (in this case it would be either the top of the grey column or point two rows beneath the orange square).
I have a 2d array describing the grid, where 1 is a wall and 0 is empty space.
data = [
[1,1,1,1,...],
[1,0,0,0,0,...],
[1,0,0,...],
...
]
I was thinking about solution in this way (where for example I can check at 1. if beneath my cell is floor and end the algo, or continue if not to cell 2.) but I can't think of a way of doing this efficiently (and easily).
Does anyone has any ideas how to tackle this ? I'm not really sure what algo should I ask google for :)
You are looking for Q-learning algorithms. This is a form of reinforcement learning. Here's one http://en.wikipedia.org/wiki/SARSA
Basically you run the simulation between source and destination multiple times and each time it gets close and closer to discovering the goal.
I think you can use Cellular Automata for your case, if it is worth the trouble. It is not AI per se, easy to implement and you can replace A* as well as the final position finding problem using one logic.
Consider the eight neighbourhood cells around the game entity. Each cell can be free or blocked (0 or 1). There will be 2^8 combinations of the neighbourhood, but you may or may not have to use that many rules for the CA.
Try looking into this: http://www.cs.sun.ac.za/rw711/2012term1/documents/CABehringPathPlanning.pdf
they implemented CA for path planning in robotics, you can tweak it to suit your need.
The advantage is, with proper rule set, your CA will terminate only when the game entity has reached the appropriate position around the goal (closest to the goal and not levitating).
You can also implement multiple rule sets on the system, thereby making it more robust.
I'm new to HTML5/Canvas/Game programming, but have been tinkering around with it after reading a couple of books. I THINK I have a fairly good idea of how things work out. This question asks several smaller questions, but in general is basically a "structural approach" question. I'm not expecting verbose responses, but hopefully small pointers here and there :) Here is a link to a non-scrolling, and currently rather boring Super Mario World.
Super Mario World Test
NOTE: Controls are Left/Right and Spacebar to jump. This is only setup for Firefox right now as I'm just learning.
Did I Do Something Wrong at This Point?
Currently I've just focused on how Mario runs and jumps, and think that I've gotten it down fairly okay. The coin box doesn't do anything and the background is just an image loaded in for looks. Here's my approach, please let me know if there is anything entirely wrong with this:
Allows Mario to jump by enacting on 2 Y velocities (Gravity and Jump variables)
Allows Mario to run by enacting on 1 velocity (Left or Right "Friction" + Acceleration)
Sprites are used and positioned according to keypress/keydown
I'm not sure if this is right, but I'm using a constructor function to build an object, then inside the main animation loop I'm calling the prototype.draw function for that object to update all variables and redraw the object.
I'm clearing the entire canvas each Frame
Should I be splitting this into more than just a draw function, like Mario.move()?
I've setup a GroundLevel and a JumpLevel variable to create 2 planes of gameplay. The JumpLevel is setup to allow for controlling how high Mario can jump on the fly. The 2 places would allow for the ground to rise like a hill - keeping the point at which Gravity overrules Mario's jumping force at the same distance from the ground.
For clarity sake, everything is separated into different JS files, but would obviously consolidate.
Moving Forward:
Now that I've finished setting up how Mario moves around (I think there are a couple other minor things I might do like mushroom up/down and shooting fireballs). I think I can figure that out, but I'm really lost when it comes to visualizing the following and how HTML5/Canvas can handle this easily:
Scrolling background (I've tried setting up Ground Tiles and using Screen Wrapping, but that seems to cause a lot of uneven issues since I was moving the tiles in the opposite direction. Unfortunately, since I'm trying to account for acceleration, this threw off the count and was causing gaps in the ground. I ditched this idea. Would a DIV beneath the canvas with a large background image be the best solution?
Enemies: Would I create enemies the same way and run a loop for collision detection on every enemy during each frame?
Background Boxes: I'm trying to allow Mario to stand on the boxes in the background, but am unsure how to approach this. I currently have boundaries setup for Mario to stay on the canvas, do I continue to expand these conditions to setup different boundaries based on the boxes? I can see that having several boxes on the screen and doing it this way would get kind of crazy, especially if I would be doing the same hit testing for enemies? I know I'm missing something here....
Level Movement: This is somewhat related. When the Right key is pressed, basically everything in the level needs to move to the left. Would I need to track out all positions of everything that could touch Mario (boxes for him to stand on and enemies for him to collide with) during every animation frame? This seems like it would get kind of inefficient?
Thanks to all! I'll keep this updated with results/solutions :)
Wow, okay. I really like your question because you've obviously done a lot of thinking on this, but partially because of that it's incredibly broad and conversational. You'd do better to find a forum to ask this question.
...That being said, I'm gonna answer the handful of points I'm qualified to, in no particular order. :)
Level Movement: That's a weird (read: inefficient) way to do it. I wouldn't do any calculations based on onscreen positions: track a canonical, camera-agnostic set of coordinates for everything in your level and update the visuals to match. This will stop you from running into weird niggling problems where framerate impacts what you can and can't walk through, or causing slower computers to let Mario run through enemies without being damaged sometimes. Tracking positions this way will incidentally fix a lot of your other problems.
You should absolutely be splitting this into multiple functions. Having movement code and rendering code in the same place is going to screw you, particularly by interacting malignantly with your update/refresh rate. It's going to essentially mean that every time the player does a tricky jump the game does more updates than usual which will make animation/hit detection/etc much less likely to be even.
Enemies: I'd suggest rolling this in with everything else. Do one hit-detection pass against everything, and if you hit something check to see what it was. You could try to optimize this by only checking any given entity against objects within 100 pixels of itself, but if you do it this way you'll need to run separate collision detection events for every enemy. Letting the enemies clip through each other would be computationally cheaper.
Edit: I'd like to clarify about my first point on 'level movement.' Essentially, what you don't want to do is move every entity onscreen every time the camera does, or to store all entity locations as offsets from the camera location (in which case you're still effectively having to move everything, every time the camera moves.)
Your ideal approach is to store your enemy, block, terrain locations with X/Y coordinates that are offset from the absolute top-left of the level (at the very beginning.) In order to render a frame, you'd do essentially this: (pseudocode because we're talking about a hypothetical level format!)
function GetVisible(x,width,level_entities_array) {
for (i = 0; i < count(level_array); i++){
if (level_entities_array[i][x] > x && level_entities_array[i][x] < x+width) {
visible_elements[] = level_entities_array[i][x];
}
}
return visible_elements;
}
Boom, you've got everything that should be inside the window. Now you subtract the camera's x offset from the entity's x location and ZAP, you've got its position on the canvas. Pose as a team, 'cause things just got real.
You'll note that I'm not bothering to cull on the Y axis. This can be rectified by extrapolation, which I'm guessing you can handle because you've made it this far. This will be necessary if you want to do any Mario-style vertical exploration.
Yes, I know my pseudocode looks like C# and JavaScript's unholy lovechild. I'm sorry, that's just how I roll at 11:30 at night. ;)
I'm trying to create a random maze generator in javascript.
There may already be working examples out there but I'm trying to solve this one myself (well, as much as possible)
The problem I'm having is my script only runs for a few blocks then stops.
I think the issue is with my understanding of the explanation I'm following (from this Wikipedia page http://en.wikipedia.org/wiki/Maze_generation_algorithm)
This algorithm is a randomized version of Prim's algorithm.
Start with a grid full of walls.
Pick a cell, mark it as part of the maze.Add the walls of the cell to the wall list.
While there are walls in the list:
Pick a random wall from the list. If the cell on the opposite side isn't in the maze yet:
Make the wall a passage and mark the cell on the opposite side as part of the maze.
Add the neighboring walls of the cell to the wall list.
If the cell on the opposite side already was in the maze, remove the wall from the list.
As I've hi-lighted my problem is with the opposite side part of this. Does this mean any adjacent cell that is in our wall list? Or does it mean something else?
I've tried it with adjacent cells and it ends up just blocking itself in.
Any idea's would be appreciated.
If I can get it working I'll post the code when it's done. Just as I said I want to get as far by myself before getting help with a full solution.
A wall represents the connection between two different cells. When you add a wall to your wall list, it's because you are visiting a cell that will be part of your maze, so when it refers to the opposite one it means the cell 'behind' that wall, where a passage would lead to if that wall was not there.