Tank Combat AI Planning Post

This is going to be a lot different from everything else I have done for this class. Everything before this has been simple enough that I could just make something that looks at the numbers and chooses the optimal play. Using a less concrete strategy and coordinating up to four tanks will require a much different approach. I have a few ideas, but implementing them will be much less straightforward than the previous projects.

The simplest idea I have is to just have each tank track the nearest tank and shoot at it. I already started this, and I have it to where I can tell tanks to shoot at a point, so this won’t be a big leap from there. This is the simplest strategy, and would pretty much just hope for the other AIs to simply perform worse than mine. This is also the most boring strategy to make, so I want to make something at least a little more complex. This will be my backup in case the other strategies don’t work out as well.

The way I make the tanks shoot at a target is fairly simple. After finding the path to the target, they check if the last point in the path is visible, and then when it is, stop following the path and start shooting at the target. I also added a bit of code to prevent tanks from shooting while their teammates are in front of them. This would be the bulk of this AI strategy, but with an extra bit to set the targets of each tank to the closest enemy tank.

Another strategy I came up with uses the mechanics in an interesting way. The strategy is to group up all of the tanks and travel in a pack, because tanks don’t collide with each other. The problem then is trying to shoot, so I thought about making each tank take turns peeking out ahead and shooting, then returning to the pack. This strategy has some benefits, like taking up less surface area to be shot from, but is mostly just something I thought would be funny to see. Unfortunately, I have found that the tanks seem to shoot from behind a little, because my tanks can shoot teammates that are overlapping and slightly behind them. This might make the strategy less effective, as peeking out would take more time and possibly be less efficient. I still want to try it out, even if it doesn’t work that well and is just something to bring out when I’m in the lead or something.

Some other strategies are basically just counter play to other strategies people might use. A counter to the stay still and shoot at the closest tank strategy would be to have a tank drive by and distract the enemy tanks, while the other tanks open fire. Even if the enemy tanks move while shooting and just drive at my tank, if they move predictably enough, I could use that to predict where to aim, because I can control where my distraction tank will go. This would require their tanks to drive pretty much exactly how I would expect, which is unlikely with all of the different pathfinding and steering strategies people might use.

Beyond higher level strategies, I will also probably implement more lower level improvements and optimizations. Things like aiming ahead of moving tanks, or improving my path smoothing, which still has a few issues. This would also include things like avoiding shooting my own tanks, which I already implemented. These types of improvements will help my tanks no matter what higher level strategy I am using.

Gin AI Postmortem

The AI I made worked pretty well. Adjusting the weights ended up being enough to make it win the tournament in class, without losing a match. It still followed the basic strategies I decided on early on, and didn’t use much prediction or tricks. It pretty much just played the numbers, and that was enough to win.

I believe a big part of the reason that my AI won is how other AIs played. I think most other people went with a more interactive and complicated strategy, involving trying to predict the other player’s moves and other similar strategies. I don’t think this helped as much as they expected, especially against my AI, which almost never picked up cards, meaning it rarely gave away information about its hands. My AI just played the cards and mostly ignored the other player, which helped it play consistently well against every other AI.

One thing that further proves this idea is something I found while adjusting the weights. I found that I could set every weight to zero except the weight for the value of cards, and it would still win against every other AI most of the time. With those weights, the AI would simply throw away the highest card in its hand that didn’t make a meld. To test this even more, I made a new AI that only added about 20 lines of code. It would pick up a discard if it made a meld, and then throw away the highest value card that was not in a meld. This is all that this new AI did, and it still beat every other AI most of the time. It even beat my AI a good amount of the time, but I think I had a slight edge.

Capstone Sprint 10

I didn’t get as much done on the game as I would have liked this week. Between getting a new computer and trying to make up for other things I missed from not having a computer for the last two weeks, I could not find as much time as I wanted to work on this project. I did manage to get team play working, so that will be something we can test this next week. I also should be in a better position to work on the game more in the future.

We now have team games and free for all, in two separate builds for the moment. They are in two scenes, so choosing which to play will be easy to pick from a menu in the future, just by loading one of the scenes. The layout is slightly different, and some variables are adjusted to prevent teammates from attacking each other and making the score based on the scores of both teammates.

Another thing I worked on was a moving camera. The camera now tracks the players and zooms in and out based on the distance between them. This makes the game feel less static and more interesting, because the screen isn’t constantly filled with stationary space. It isn’t perfect yet, and needs more testing, but it’s a start.

There were a few more mechanics I wanted to add this week but didn’t find the time for. I should be able to add them in this next week, now that I have less other things to worry about. I have my new computer with everything working, and plans for most of the new features.

Tank Movement Planning Post

Getting the tank to move through a maze shouldn’t be all that complicated. We have done pathfinding before, so the only new aspect is the actual process of navigating between points using the track system. This should be as simple as setting up a function to turn towards the point and then drive straight, so I don’t believe this will be an issue.

The first step is to make the tank drive to a point without pathfinding. I will do this by making the tank run one track slower in order to turn in that direction, towards aiming in the direction of the target. Once it is facing close enough to the target, it will run both tracks at full speed to drive straight. When it gets to the point it will stop.

The next step is to add pathfinding. I will use a flow field algorithm, because it is simple enough to implement and allows the most flexibility in moving towards the target. If a tank strays off the path for any reason, it can still use the same flow field to make it to the target without generating a new path. This won’t help much for the task of navigating a maze, because there won’t be any evasive or tactical measures necessary, but flow fields aren’t really any less efficient at solving mazes anyway. It will actually be more efficient than most other strategies if we have multiple tanks with the same target.

The last piece I want to add is path smoothing. I haven’t done it before, but it would help a lot to make the paths more direct and less grid based. It also allows things like slowing down around turns without much extra work. This will help with speed too by enabling the tanks to follow shorter paths with less turns.

This all together should enable the tanks to navigate a maze and reach the exit as quickly as possible, or at least fast enough. The biggest issue is hitting walls, because travelling by points is a little inconsistent with the big delay between inputs, and it’s hard to avoid walls along a narrow path without moving unnecessarily slow. I might add some obstacle avoidance to avoid walls if the tank gets too close.

Capstone Sprint 9

This week went better than the last. We figured out more of what to do with our game and I got started on a prototype. The biggest difference is moving from networked multiplayer to local with a single wide camera view of the whole game. Some of the systems I worked on last week still apply to the new design and mechanics, and I was able to use those in the new prototype. Most of the systems I have worked on for the hunting game do not apply to the new farming game, so those will likely not be used for this new project.

I got a lot of work done on the new prototype this week. I added the multiplayer, planting and growing, combat, respawning, and score systems, making the game playable with some of the major features present. The biggest missing mechanic is the trap and fence building system. You can currently cut down trees, but they do not add to a resource counter. I just have to add that, a system to reduce that number and add a fence/trap, and the mechanics for the fences and traps. The fences will just have a collision box and a certain number of hits to break. The traps will just have a hit box that tells the player to stay still for a certain amount of time. After this is added, we will finally have a prototype representative of the final game we want to make.

We have had a lot of trouble with our previous game concept because it was vague and under-developed. It was hard to work on because I couldn’t get a good idea of what the game was supposed to be. It didn’t help that what I could get of the concept did not sound fun to me, supposedly because it was not my type of game. That is not as big of an issue with the new game idea we have. I can contribute to the discussion of the game because it sounds fun to me, and I can understand the game better because I have been more engaged in the design of the game. I believe it is also a much more appropriately scoped game for this project.

Capstone Sprint 8

This was a rough week. I had a full schedule of tasks planned, then we changed the entire game and I had to implement an entirely new set of features. The biggest problem of this is trying to determine what the new game is supposed to be and how to implement the mechanics needed. After getting an idea, I was able to implement some basic functionality, but being at a tech demo level at this point is a bad sign. Regardless, I have an idea of what to do for this new game, and a start.

After working out what the new game was going to look like, I decided to implement the mechanics of planting and growing the plants at the center of the game play. The idea is to have a plot for plants that you can plant seeds in, then add water, and the plants will grow until that water runs out. You get more water from a well, and you can water your plants and leave them to do something else while they grow. You can only grow one plant of each type, and having a fully grown plant of each type wins you the game.

To accomplish this, I started with the watering and growing mechanic. You can click on a well with a watering can in hand, and it will gradually fill up in a couple seconds. You can then click on a plant, and the water will be transferred to the plant until the plant has max water or the watering can runs out. The plant will then grow for that amount of time times a multiplier. As the plant grows, its scale increases, showing that it is growing. When it reaches full size, the scale jumps a bit, showing that it reached full size. There is not yet a visual for how much water the can or plants have.

The other mechanic I added was planting seeds. You can get seeds from a seed box, which uses the same crafting menu the hunting game had, but with no ingredients. This works because your seed box is supposed to have an infinite number of your own seeds. You can then plant these seeds in a seed plot. This plot has 8 spaces, with each having a unique plant type. The plants are always there even before being planted, with a scale of zero. After being planted, the plant’s scale jumps up to the minimum, showing it is now there. The seed is taken from the player’s inventory, and the plant can now be watered. If you try to plant a seed that has already been planted, nothing happens.

Gin AI Code Report

I put the AI together similarly to how I planned it earlier. I put in ways of determining which cards had better chances of making a meld, and dumping the card with the least chance and the highest value. I also kept track of discards and opponent cards, to determine how valuable a card is to the other player. I wasn’t sure of the optimal balance between these strategies, so I gave them all weights set in the constructor so I could adjust it easily. This ended up being a good idea.

The first step is drawing. I always draw a card, unless the card in the discard gives me a meld or adds to a current meld in my hand. This seemed like the simplest strategy, and an effective one too. I didn’t think there was a point in picking up cards that give me a chance for melds in the future, because I could usually draw a card and have a chance of getting a meld immediately. Even if I couldn’t, there is still a good chance of getting a card that gets me closer to a meld, making both strategies even in that case. The other advantage is that even if I get closer to a meld, my opponent probably won’t drop any cards that would help me if they saw me picking up a card, so I would have to finish the meld with a draw from the deck anyway. It helps to not let the other player know my plan.

The next step is discarding. This step was actually made of several smaller steps. The first step was checking for big gin. Since we aren’t playing with actual big gin, I had to add a check for it and a way of dealing with it. I found that if you get big gin, there is always at least one card that you can discard and still get gin. I just go through my cards and find one that when discarded does just that. It’s unlikely, but I had to have some check for it otherwise my program would crash.

The next step is to check for cards that when discarded, would let me knock. If I find any cards that let me do that, I drop the card that will give me the lowest hand and knock. This isn’t that important, but helps get quick knocks. Any advantage I can get is welcome, especially if it isn’t that complicated or hard.

The real bulk of the process is choosing which card to discard. The first step is to find the value of each card in my hand. First, I make a copy of my hand, then remove all of the melds to find the deadwood. There is no point in discarding a card in a meld. After this, I check each card for its value in making future melds. If I pair with that card, I add the pair weight twice. I then look for the other cards that would finish the meld. If I find either of them in the discard or the other player’s hand, I subtract the pair weight for each. This means that if both cards are already known to be somewhere I can’t access, there is no benefit to this pair, and I am now back where I started. I do the same thing for runs, where if there are two available finishes to a run, I add the run weight twice, and once for only one available finish. I subtract the point value of the card times the value weight, making it more likely to drop higher cards.

The next step in this process is to find the value of the card to my opponent’s hand. I run the same process again, but for what I know of my opponent’s hand, multiplied by the opponent weight. This makes it less likely to drop cards that will likely help out my opponent. I then add this value to the other value, and discard the card with the lowest total value.

Passing cards was the simplest step. I just called my discard function and passed what it returned. I had to set the card to be tracked as in the opponent’s hand instead of the discard, but that was it.

I wasn’t sure what the value of each aspect was, so I set the meld weights to 1, the opponent weight to 1, and the value weight to .1, meaning that it would only ever break a tie. This worked alright for the dummy, and against the early AIs of some other students. I felt like this was good enough, and submitted my early AI like this.

This is where things start to get weird. Many people seemed to have trouble with the dummy, which just threw away high cards. With my weighting, mine worked pretty much the opposite way, keeping high cards as long as they start a meld in my hand. I lost most games against other people, but beat the dummy out of the tournament for everyone else. It made me think that if I just submitted the dummy, I would have a 50% chance of winning the tournament, because I would have to get a lucky win against the dummy and beat everyone else.

This obviously wouldn’t actually be a good strategy, but adjusting the weighting could make my AI play more like the dummy. I increased the value weight, and got better results the higher I went. Even with a value weight of 1, I still beat everyone I tested against, even the dummy. At this weight, I would throw away pairs if I had a single card a few points lower. I will try to find the best weight before the final tournament, because that is probably not the best strategy.

I could theoretically have it change the weights based on the score, because a higher weight prevents big losses, and a lower weight has a better chance of bigger wins. If I need to make a big comeback, I could switch to a higher weight and play for gins and undercuts for bonus points. Unfortunately, accessing the scores is not possible currently, so I couldn’t if I wanted to. It probably wouldn’t be that helpful anyway.

It’s funny that this is what I ended up doing, because my original strategy was to throw away high cards, even in pairs. I figured it couldn’t actually be a good strategy, and weighted my AI to play differently. It turned out to be far more effective.

Capstone Sprint 7

We made good progress this week. While we didn’t have many meetings, and the meetings we had were pretty short, we knew what we had to do and got to spend a lot of time working on it. I spent most of my time working on combat this week, with the rest of the time spent finishing up the equip system I started on last week.

I started this week with working on the equip/inventory system, because I still had some improvements to make. I reworked the equip mechanics first, because it still used an old system that was added for early prototyping. The player can now click a button in the inventory menu to equip almost any item, and click another button to add an item to a hotbar. For most objects, the hotbar equips the item, but some objects can be placed in the world, and the hotbar lets the player do that more easily too. With that, much of the basic functionality of the menus was finished, and I was able to move onto the next task.

After finishing with the menus for now, I moved on to implementing basic combat past shooting arrows at brainless zombies that couldn’t even fight back. I added a system for melee weapons for the player, using adjustable hitboxes, swing speeds, and damage values. After that, I added a health bar for the player and an attack for the enemy. The current only attack is a full 360 spin, with the tail having a hitbox. It uses this attack when the player is within a certain range, and can’t move while using this attack. It is mostly just a placeholder for attacks with animations, but I decided to have some fun with it. It didn’t take that long, and it makes the attack make visual sense for now, even without an animation.

Gin Rummy AI Planning Post

I am not very familiar with this game, and I had never played it before this week, so I wasn’t very sure what the strategy would be. I decided to give it a try, and I developed a simple strategy that seems to work ok. I basically just dumped high cards, got melds where I could, dumped the most useless cards when high cards were similar, and knocked at the earliest opportunity. My strategy was very simple and algorithmic, so it should directly translate into an AI, with the additional bonus of card counting.

The choice of whether to draw or pick from the discard pile seems very simple, at least for now. I always drew unless taking the discard gave me a meld or added onto one I already had. It didn’t seem worth it to take it to get closer to a meld, because there was still a low chance of drawing the last card needed, and I could usually draw to try to get a meld immediately. Maybe it would be worth it to take in some cases, especially because if the other player dropped it, they probably don’t have a match or run with it. They still could, especially if they have a card that would go with it but is already in another meld. They would also be less likely to drop a match or run for that card in the future if they are watching out for it, so that makes it even harder. Maybe I’ll change it later, but for now I will only pick up cards for a meld, and will draw in all other cases.

The way I discarded cards was mostly discarding high cards, so that will be how I start the AI. If the highest value deadwood card I have is not beginning a run or a match, that will be the first card to ditch, because holding onto it will not likely have any payoff later. If I have some high cards that start a meld and a slightly lower card with no value, it could be better to drop the lower card, because it still reduces score without losing an opportunity. If I have no cards close to a high pair or run, then I will just drop the high cards anyway. Dropping a pair of kings isn’t risky, because the other player would have to have a pair already to use it in a match, and then they would take the first king and I would not drop the second. After that, neither player would be able to make a match with that card, and I would just have to find melds of the lower cards I kept. This is a part I could see changing, because I don’t really know if that is the best choice, especially if everyone else’s AIs always drop high cards too. I’ll have to adjust it later if it doesn’t work out.

The thing the computer can do that I couldn’t is a card tracker that keeps track of where every known card is. This helps determine if cards are safe to drop and have better chances of being drawn. If a match or run of a card is in the discard, there is a lower chance of the other player having it, and a lower chance of drawing it from the deck. Both of these mean it is a better card to drop. If the other player has a run or match of a card, it would be a worse idea to drop it, because they could pick it up. This would help inform the last step whenever possible, and help decide which melds to try to go for.

Optimal play can only get you so far in a two player game like this, and some of it will come down to playing the other player instead of the game. I’m thinking about making the AI keep track of how the other player plays, and looking out for patterns such as always dropping high cards to take advantage of. If that is how they play, it would be a good idea to hold onto higher pairs for a bit, waiting for the other player to drop them. It would still be a good idea to drop them later, because if they aren’t dropping them, they probably already made a meld or just didn’t start with any. Adding this whole process would likely improve performance when it is used, and shouldn’t decrease it at all, because it would only activate upon noticing the other player using the strategy, instead of just assuming the strategy from the start. I will try to put this in if I have the time and feel the need.

I am not incredibly confident in any of these strategies, and it will probably be a good idea to test the alternatives to these to see which is better. It should be easy enough to make the AI adjustable, either by making it data driven or just adjusting the code quickly.

Capstone Sprint 4

This week went alright mostly. We planned on getting the three prototypes as close to QA-ready as we could, and went to QA with two of them. We took the Bar Fight game and the Glider game, and we’re working on the Hunting game for next time. I put in a lot of time getting the Bar Fight game ready for QA, and starting work on the Hunting game prototype.

The Bar Fight game did well at QA, with everyone who played it enjoying it. It did have some issues, like throwing objects not really being worth it in most cases. It wasn’t worth the difficulty in aiming, the loss of a weapon, and the damage reduction. The only slight use was for finishing people off when they had low health, but that alone was very satisfying. One fix for this would be to implement the vertical attack that should be much better for throwing. Because of a Unity input problem, the vertical attack didn’t work at QA. It probably wouldn’t matter much, because it currently isn’t all that useful for throwing. I do believe I found source of the Unity problem and can fix it for next time.

The Glider prototype didn’t do as well. Most people had issues controlling the glider, probably because the feedback is extremely confusing with the glider flipping constantly when holding any key. There was also no clear objective or end states. We did get some usable feedback on the art and settings, along with thoughts of the general idea of the game, so it wasn’t a complete loss. I will probably start helping on this prototype for next time, so the glider isn’t as much of a problem.

The last prototype is still a work in progress, and isn’t ready for QA yet. We have bow shooting and trapping mechanics, which can be used to kill extremely basic AIs. There is also an inventory system, including crafting new items using objects found in the world. This will hopefully be ready for QA next week, so we can complete what we need for the first challenge.

The last thing we need to figure out is what game we want to go forward with. I personally believe that the Bar Fight game is the strongest game idea we have currently. I think it is the most though out game idea we have, with the other two games still not being all that clear. I’m understanding the Hunting game better now, and I think I get the point, even if I still think it wouldn’t be all that fun of a game (in my opinion), and it seems a bit out of scope in art, design, and programming. With the glider game, I still don’t really know what it is. It has never really been more than a concept, and even the concept has changed quite a few times. It started out as a wing-suit racing game, then changed to gliders, and now it might be turning into a paper airplane game. The game might not be about gliding anymore, and maybe not even racing. The idea of the game went from fast, dangerous, downhill competitive flight racing, to some sort of casual plane flying through a paper forest, and who knows where it will go from there. It is hard to get behind an idea that keeps changing that much, especially as the programmer, because I don’t even know where to begin in making the game.