alvaro

Members
  • Content count

    7780
  • Joined

  • Last visited

Community Reputation

21247 Excellent

1 Follower

About alvaro

  • Rank
    Contributor

Personal Information

  • Interests
    Art
    Audio
    Programming

Recent Profile Visitors

37882 profile views
  1. Blind Poker Artificial Neural Network

    The whole setup seems like a non-starter to me. How can you have those 208 inputs? If your game is anything like the poker I know, your agent will not have knowledge of the complete game state, so it shouldn't be given the complete game state as input. Start by thinking what information the agent really knows about and what actions are available. Then figure out how to provide the input to the ANN and how to get the output. For instance, if you list the hand so far as a sequence of events, you can feed those events to an RNN and then use a softmax output layer with a probability distribution over the possible actions. Once you have a reasonable ANN architecture, you need to train it. If you have access to a database of human games, it would be a good idea to start by doing supervised learning to try to predict what the human will do next. You can also train it by reinforcement learning, but that's usually harder, particularly in an adversarial setting like this. I have some half-baked ideas on how to do it, but it wouldn't be trivial.
  2. It's probably a good idea to think of your game design as if it were a board game, where you are using tokens to represent the goods, so you are forced to use small integers. Typical ways to break ties in board games involve some sort of turn order, so cities are sorted by some criterion (distance to London, size, foundation date...) and then if there is a remainder of 2 after integer division, the top 2 cities get an additional token. If you don't want this mechanic to affect the game much, make the number of tokens large, so a difference of 1 token won't matter. It's probably not good to obsess over making things exact.
  3. First of all, if your general code structure is working for you, I wouldn't go out of my way to change it, although there are alternatives you could experiment with. One class with massive state, of which there is a single instance that everyone has a reference or pointer to is indistinguishable from a large collection of global variables, and has exactly the same problems (e.g., it's hard to determine correctness because any part of the code could be changing the global state). If you don't use inheritance much, I consider that a good sign. There are places where inheritance could make your life easier, but it's easy to overdo, and then the resulting code is very confusing and hard to follow.
  4. I would go with "3) Use rational numbers". If your numbers don't get out of whack and you can just use 64 bits for numerator and denominator, the code shouldn't be too bad.
  5. Rotating source vector to destination vector (2D)

    If you use complex numbers to represent points and vectors, so you think of (x,y) as the number x+y*i, you can think of rotations as unit-length complex numbers, like cos(alpha)+sin(alpha)*i. Applying a rotation is now just complex-number multiplication. In that language, the rotation that maps a current vector to a target vector is simply z = target / current. This might not be very satisfying because there is no notion of "shortest". The way mathematicians think of rotations, they are not things that happen progressively over time or anything like that, but just mappings that take an input vector and produce an output vector. If you want to recover a notion of "shortest", perhaps you are interested in limiting how much the current vector can change in one step. This code would do that: Complex limited_rotation(Complex current, Complex target, Complex max_rotation) { Complex z = target / current; // You may want to normalize z here if you can't guarantee that current and target have the same length if (z.real() > max_rotation.real()) return z; if (z.imag() > 0) return max_rotation; return conj(max_rotation); }
  6. Quadcopter simulation and PIDs

    What are the two forces involved? A PID that overshoots usually can be reigned in by tweaking the D term. You may need a smaller P term too.
  7. Real progress in AI requires a metric by which to evaluate progress. If you can define quantitatively how satisfied you are with the behavior of your agents, you can always tweak things to improve it. Otherwise, you'll be flying blind. What you describe is an open-ended project with ill-defined [if at all defined] goals. I don't believe this will lead anywhere. Hey, you asked.
  8. Resources to get good at math?

    If I had to come up with a formula for the rotation matrix you describe, I would probably start from the quaternion representation (axis-angle to quaternion is a fairly trivial formula, which is cos(theta/2)+sin(theta/2)*(u_x*i+u_y*j+u_z*k)) and then apply the rotation to (1,0,0), (0,1,0) and (0,0,1). That will give you the three columns of the matrix. It would probably take me like 10 or 20 minutes of computation.
  9. I watched the video on JPS+ and goal bounds. It's really interesting and I could probably reproduce it from the level of detail given in the talk, but it would be challenging.
  10. Resources to get good at math?

    I'm going to give you a different perspective, which may not be what you were looking for in this thread, but I want to put it out there anyway: Getting good at math is not about accumulating math knowledge, but about learning how to solve problems. When I use the word "problem" here I don't mean an exercise to verify that you understood and can immediately apply some math content you just learned. I mean something closer to a real-life situation, where it's not easy to see initially what the path to a solution might look like, you explore some, you find some patterns, you hypothesize and solve intermediate problems... Here's a good example: "We have 100 lockers, initially all closed, numbered 1 to 100. 100 people are going to pass by the lockers, and they are labelled 1 to a 100. Person 1 will visit all the lockers; person 2 will visit only the even lockers; person 3 will visit only the lockers whose numbers are multiples of 3; etc. When a person visits a locker, it changes its state; so if the locker was open they will close it, and if it was closed they will open it. So to be clear, person 1 will open all the lockers; person 2 will close all the even lockers and leave the odd ones open; person 3 will close locker 3 (because it was open), open locker 6 (because it was closed), etc. After all 100 people have pass by the lockers, how many of them will be open?" You only learn to solve such problems by practicing. Give it a try, and don't be frustrated if you don't get very far. There are spoilers later in this paragraph, so I recommend you stop reading now and try it. Try to simulate the situation by hand, perhaps substituting 100 by a more manageable number like 10. Perhaps you'll observe some pattern so now you just need to prove it. Or you'll find some way to reformulate the problem in simpler terms, something about how many divisors a number has. Maybe you will explore a few numbers in light of this reformulation and you'll learn how the divisors can be paired together in some natural way. Finally, you'll understand the problem in some new, more informative way, which will allow you to crack it. I don't know very many resources that teach this skill. There is a classic book by Pólya called "How to Solve It", which is a good place to start. There are websites with collections of problems, like Project Euler . Or perhaps you can find training materials for Math Olympiad. One point of view on math education is that all the algebra, geometry, combinatorics, etc. that we go through in school is just a collection of classic situations where we can hone our problem-solving skills. Once you get good at solving problems, any math content you learn becomes a tool in your belt, and having a good collection of tools allows you to solve more problems, or solve them more easily. But just teaching the content without actually solving problems is like giving someone a tool box and pretending they can now fix anything.
  11. C++ Well-defined shifts

    I for one think this is a good idea. I would like to be able to shift something to the left some number of times as a way to divide it by a power of 2. If I shift by too much, the result should be 0 (at least for unsigned integer types). The current C++ rules are written so shifts can be translated to machine-code shifts, and those have semantics that made the hardware easy to implement (usually several decades ago). There are natural semantics for shifts with any number of bits, and it would be good to have them available. A similar "feature" of C++ that bothers me even more is the rules on integer modulo and division when it comes to signs. a % b should always return a number in the interval [0, abs(b)), and a / b should round down. The fact that 7 % 10 and -3 % 10 can be different boggles the mind. The whole point of arithmetic modulo 10 is that you should not see any difference between numbers that are a multiple of 10 apart. Just ask your mathematician friends.
  12. If you can get an ear-clipping algorithm to work, try it. If that's not fast enough for your purpose, try something fancier. For instance, CGAL has functions for partitioning a polygon into convex polygons, and then triangulating those is trivial: http://doc.cgal.org/latest/Partition_2/index.html
  13. That's closer, but I don't know what me is, or what SetAngles does. It probably doesn't take that much to turn what you posted into a complete C++ program that we can try.
  14. I am not sure what you mean by those quaternions that are specified using only two numbers. At the very least you need three, and you have to be more descriptive that "[x: 35.21, y: 181.58]" if you want me to understand what you are saying. Just demonstrate your last post with the exact code you are using. I'll try to reproduce the results and see if I can figure out where the confusing is coming from.
  15. I don't think the issue has to do with the matrix representation, and it certainly doesn't seem to be gimbal lock to me. Have you tried multiplying the matrices the other way around? me.rotation = CreateRotation( 5.0, 0.0, 0.0 ) * me.rotation;