My first PICO-8 game! What do you think?
(Edit: use Q for "O" key and X for the "X" key)
v6 - white splash, substr trick, smarter AI
Really good ! Battleship is one of my all-time favorite "puzzle" games for any console.
And there are many "Battleship" games out there.
Unless you are perfectly pleased with this one you might take a look at B&W Gameboy's version which gives you the option of launching a submarine to scan a 4x4 area and special missile launches which send a volley of 2 or more in the air at a time, yet you can only use them once per game.
My favorite Battleship game comes from the Android called, "Fleet Battle - Sea Battle" by Smuttlewerk Interactive. I like it because you are awarded medals according to your shooting and deduction prowess, so there is a type of "experience points" and player growth in it.
Two things you can be aware of. One is important.
The important one is when your opponent makes a hit they still do not know where the rest of the ship is.
You should not give your opponent the advantage of just pegging the remaining pips for that ship as that is unfair.
Instead, like the player they can only guess where the rest of this ship is. Now, if they make a successful hit and there are two or more vertical, then yes, perhaps continue shooting in that vertical direction until miss just like a player would. Then choose the opposite direction of the initial hit.
Likewise if it is a 2nd successful hit and the two are horizontal, perhaps continue shooting in that horizontal direction until miss just like a player would. Then choose the opposite direction of the initial hit.
The 2nd can make the game go faster and perhaps be more exciting is to allow the player or opponent to shoot AGAIN having hit any target or sinking any ship.
I have found the best way a player can play is to take a shot and then shoot outwards from there like you are moving the chess knight. Any of these moves for instance based on your initial shot:
 Up two, left one
 Up two, right one
 Up One, left two
 Up One, right two
 Down two, left one
 Down two, right one
 Down one, left two
 Down one, right two
Once you are down to opponent ships that are only 2-3 across, then change your tactic to cross-hatch the map, that is where Y is an even number and X is odd. Or Y is an odd number and X is even.
Also when the map is filled with misses, intelligently determine which single shot would cover the most map and territory for a possible hit on the opponent. Scan outward from that move and calculate the highest chance for a possible hit based upon that strategic and single shot.
Here is a STAR and FAVORITED.
Hope This Helps !
Yes, the AI is very simple right now. You can probably guess how it works after playing a few games, but basically it has two strategies:
For all past Hits, look at adjacent cells (up,down,left,right) and see if there is one we haven't shot at yet. If so, shoot it.
- If strategy #1 didn't find a cell to shoot, shoot randomly.
I'm thinking of adding a "momentum" vector to the AI so that if it makes two hits in a row, it will continue shooting in that direction. The chess-knight strategy is interesting... I will look into that.
The powerups idea (having radar / special missiles / etc) is cool too.
I'm really not sure what I want to do with PICO-8 long term... kinda just playing around with it right now as a hobby / learning experiment. I'm a JS dev by day, so making graphics / sprites / sound design is all new to me and a nice break from code-driven development.
I'm considering training a neural net to play battleship. But since it's not a perfect information game I can't just throw AlphaZero at it so I'm not sure how to formulate it. Also, I'd have to figure out how to get the result into pretty compact Lua code. But it is something to think about.
Here is the Gameboy version to give you an IDEA of it's AI as it shows how it searches. This also shows its special features like multiple missile launching and submarine scan the surface in a 4x4 field.
Gameboy games only have 16k SRAM so surely you can improve this in your coding, wmhilton.
It's important to note that this Gameboy version uses a screen of 8x8 instead of your 10x10.
Also, may I suggest your "splash" has some color in other than the foreground and background.
Here is a modified "Splash" that is easier to see on the map.
Click the [8x8] button viewed above and press CTRL-C to COPY the image. Back in PICO-8's image editor, press CTRL-V to paste and see it there.
If you favor the "chess knight" move, I would not actually "move" from the initial firing shot but determine all points valid from a chess knight to reach that new random point so the player doesn't immediately recognize it is movements from a knight.
And you might save that for an advanced level. Here are a few ideas.
EASY: shoot random, if hit, use method you use now with no intelligent "linking" of hits.
MEDIUM: Shoot in cross-hatch "X", if hit, use human method to find all pieces to ship, look for horizontally or vertically linked shots and continue to hit each new piece of player's ships.
HARD: Intelligently make shot based on remaining ships and their length. if hit give computer "advantage" of knowing where the ship is and peg each piece one at a time without once shooting in the water. This would be grossly unfair if either player or opponent could shoot AGAIN once hitting or sinking a ship so use sparingly.
You could make it so it would be possible for the player to win the HARD level but it won't happen easily. :)
. . .
You might also have text stating to the player which SHIP was hit so the player knows the remaining length of it. This is done in Smuttlewerk's version via top icons.
Notice also that Smuttlewerk's version has unusually sized ships. One is 3/4 of a + whereas the other bigger one is 2 across by 3 down in a diagonal slope. this is pretty advanced for the size and shape of a ship and I wouldn't expect you to do that as it definitely varies from the classic "Battleship."
Was looking at your code ...
print("a",2+(x+0)*8,y*8, color(cur.x, 0)) print("b",2+(x+1)*8,y*8, color(cur.x, 1)) print("c",2+(x+2)*8,y*8, color(cur.x, 2)) print("d",2+(x+3)*8,y*8, color(cur.x, 3)) print("e",2+(x+4)*8,y*8, color(cur.x, 4)) print("f",2+(x+5)*8,y*8, color(cur.x, 5)) print("g",2+(x+6)*8,y*8, color(cur.x, 6)) print("h",2+(x+7)*8,y*8, color(cur.x, 7)) print("i",2+(x+8)*8,y*8, color(cur.x, 8)) print("j",2+(x+9)*8,y*8, color(cur.x, 9)) print("1",2+(x-1)*8,(y+1)*8, color(cur.y, 0)) print("2",2+(x-1)*8,(y+2)*8, color(cur.y, 1)) print("3",2+(x-1)*8,(y+3)*8, color(cur.y, 2)) print("4",2+(x-1)*8,(y+4)*8, color(cur.y, 3)) print("5",2+(x-1)*8,(y+5)*8, color(cur.y, 4)) print("6",2+(x-1)*8,(y+6)*8, color(cur.y, 5)) print("7",2+(x-1)*8,(y+7)*8, color(cur.y, 6)) print("8",2+(x-1)*8,(y+8)*8, color(cur.y, 7)) print("9",2+(x-1)*8,(y+9)*8, color(cur.y, 8)) print("10",(x-1)*8-2,(y+10)*8, color(cur.y, 9))
This might save you on some tokens:
for i=0,9 do print(sub("abcdefghij",i+1,i+1),(x+i)*8,y*8,color(cur.x,i)) print(i,2+(x-1)*8,(y+i+1)*8,color(cur.y,i)) end
Whoop ! I messed up and you followed my buggy code. :)
Notice the vertical is 0-8 and suddenly 10. Might want to fix that.
You can see how effective it is for the player to use "knight" moves. The cross-hatch on the side is when there was only the submarine left and I started searching for it. as it's 2x1 the "knight" move is not the best way to find it.
I watched that Game Boy video. That is amazing. I like the cutscenes! I'm a loooong way from having the art ability to do that methinks. I'm very tempted to do the missiles-flying-from-the-top thing though. I feel like that's in my range. Plus it adds dramatic tension as you see the missile coming in a column but don't know which row it will stop on!
[Please log in to post a comment]