Auto Racing
It been quite a while but I’d like to get back to writing my gaming blog. Let’s kick off with my obsession for the weekend, USAC Auto Racing. Let me be clear up front, this is not a good game. It’s a sports simulation game in the old school sense. There is a card for each driver in the race with several charts. You pick how you a driving for that turn, either aggressive, neutral, or conservative, then roll a D12, look it up on the chart and move that number or turns. There are also charts for various trouble situations you can get into and a pit stop chart. You line up the cars and start rolling. Eventually there will be a huge wreck that takes a bunch of cars out of the race. My copy of the game came with cards from the 1980 Indy 500. A dedicated user on BoardGameGeek has been creating cards for recent races and I decided to run a game this weekend with the 2007 cards. After two days of on and off play I’m a little more than halfway through the race and 12 of the 33 cars are out of the race. It’s a fun and mindless way to spend some gaming time on Indy 500 weekend.
Monopoly was my son’s idea. Casandra and I played along for a while but MAN is Monopoly a long game.
Each week I’ll go through my games played and provide some commentary. Ask me about any of these games for more information.
Ascension 2 games: Still slowing down and still losing. Ugh.
Magic: The Gathering 3 games: These were against an AI program called Magarena. It plays a pretty good game.
Can’t Stop 8 games: I’ve been writing about my iPad app. Can’t Stop is a fantastic dice game up there with Liar’s Dice. Great design and fast and fun to play.
Battleship Galaxies 1 game: Quick write up here. Fun light-er weight space combat game. I’m looking forward to giving it another go with some more of the rules.
Blood Bowl: Team Manager - The Card Game 1 game: Finally got this to the table with the board game crowd at work. It went over pretty well. We only got two out of five rounds in at lunch but I think now that we know the rules we could get a full game in. Very fun with a great theme.
Mage Knight Board Game 1 game: My first win in the solo game BUT, I played with a smaller map and easier cities. A fantastic adventure game and I’m learning more about different strategies each time I play.
Monopoly Revolutions 1 game: Cory request and I’ve been wanting to give it another try. Wow is Monopoly a long game. We were playing it straight, auctioning off the properties and no Free Parking bonus. But still an hour-and-a-half later and there were only six houses on the board. We called it a night.
I put the finishing touches on the game today. Here is the code in case you want to give it a go in Codea. I learned Lua three days ago to get into Codea so I make no claims about how elegant the code is! I’m not sure if there is anything to really learn from this code but the game does work and is fun to play. Rules at http://en.wikipedia.org/wiki/Can’t_Stop_(board_game)
-- Can't Stop
-- Mike Houser
-- Use this function to perform your initial setup
function setup()
max=700
spacing=116
transx=260
dice={0,0,0,0}
kChoosePlayers = 1
kTurnStart = 2
kDiceRolled = 3
kSpotsPicked = 4
kBusted = 5
kGameOver = 6
gamestate = kChoosePlayers
playerrect = {{80,350,160,430},{80,250,160,330},{80,150,160,230},{80,50,160,130}}
playercolor = {{0,0,255,255},{255,0,0,255},{0,255,0,255},{255,255,0,255}}
offmult = 10
offset = {{-1,-1},{1,1},{1,-1},{-1,1}}
numplayers = 0
currentplayer = 0
displayMode(FULLSCREEN)
fontSize(32)
textMode(CENTER)
columnsfilled={false,false,false,false,false,false,false,false,false,false,false,false}
legalnums = {false,false,false,false,false,false,false,false,false,false,false,false}
columnrects = {}
markers = {0,0,0,0,0,0,0,0,0,0,0,0}
spotrects = {}
board = {}
setupSpots()
end
function setupSpots()
spots = 1
for x = spacing+4, max, spacing do
spotrects[spots+1] = {}
spotrects[13-spots] = {}
for i = 1, spots*2, 1 do
centerx = (x / (spots*2+1))*i
centery = ((x / (spots*2+1))*i) + (max-x)
spotrects[spots + 1][i] = {centerx+transx,centery,20,20}
spotrects[13 - spots][i] = {centery+transx,centerx,20,20}
end
spots = spots + 1
end
end
function setupBoard()
for i = 1,numplayers,1 do
board[i] = {}
for j = 2,7,1 do
board[i][j] = {}
board[i][14-j] = {}
for k = 1,((j-1)*2)+1,1 do
table.insert(board[i][j],false)
if j ~= 7 then
table.insert(board[i][14-j],false)
end
end
end
end
end
function rollDice()
for i = 1,4,1 do
dice[i]=math.random(1,6)
end
gamestate = kDiceRolled
legalnums = {false,false,false,false,false,false,false,false,false,false,false,false}
if not columnsfilled[dice[1]+dice[2]] then
if numMarkers() < 3 or markers[dice[1]+dice[2]] > 0 then
legalnums[dice[1]+dice[2]] = true
end
end
if not columnsfilled[dice[3]+dice[4]] then
if numMarkers() < 3 or markers[dice[3]+dice[4]] > 0 then
legalnums[dice[3]+dice[4]] = true
end
end
if not columnsfilled[dice[1]+dice[3]] then
if numMarkers() < 3 or markers[dice[1]+dice[3]] > 0 then
legalnums[dice[1]+dice[3]] = true
end
end
if not columnsfilled[dice[2]+dice[4]] then
if numMarkers() < 3 or markers[dice[2]+dice[4]] > 0 then
legalnums[dice[2]+dice[4]] = true
end
end
if not columnsfilled[dice[1]+dice[4]] then
if numMarkers() < 3 or markers[dice[1]+dice[4]] > 0 then
legalnums[dice[1]+dice[4]] = true
end
end
if not columnsfilled[dice[2]+dice[3]] then
if numMarkers() < 3 or markers[dice[2]+dice[3]] > 0 then
legalnums[dice[2]+dice[3]] = true
end
end
numlegalnums = 0
for i=2,12,1 do
if legalnums[i] then
numlegalnums = numlegalnums + 1
break
end
end
if numlegalnums == 0 then
gamestate = kBusted
end
end
function numMarkers()
num = 0
for i = 2,12,1 do
if markers[i] > 0 then
num = num + 1
end
end
return num
end
function topColumn(col)
if col < 8 then
return ((col-1)*2)+1
else
return ((13-col)*2)+1
end
end
function columnPositionWithMarkers(column)
if markers[column] > 0 then
return markers[column]
else
for i = #board[currentplayer][column],1,-1 do
if board[currentplayer][column][i] then
return i
end
end
return 0
end
end
function isGameOver()
numCols = 0
for i=2,7,1 do
if board[currentplayer][i][((i-1)*2)+1] then
numCols = numCols + 1
end
if i ~= 7 then
if board[currentplayer][14 - i][((i-1)*2)+1] then
numCols = numCols + 1
end
end
end
return numCols >= 3
end
function pullBackOverColumns()
for i = 2,7,1 do
if markers[i] > ((i-1)*2)+1 then
markers[i] = ((i-1)*2)+1
end
if markers[14-i] > ((i-1)*2)+1 then
markers[14-i] = ((i-1)*2)+1
end
end
end
function lockBoard()
for i = 2,12,1 do
if markers[i] > 0 then
if markers[i] < topColumn(i) then
for j = 1,markers[i]-1,1 do
board[currentplayer][i][j] = false
end
board[currentplayer][i][markers[i]] = true
else
columnsfilled[i] = true
board[currentplayer][i][topColumn(i)] = true
for j = 1,topColumn(i)-1,1 do
for player = 1,numplayers,1 do
board[player][i][j] = false
end
end
end
end
end
end
function columnHit(col)
markers[col] = columnPositionWithMarkers(col) + 1
if dice[1] + dice[2] == col then
if not columnsfilled[dice[3] + dice[4]] then
if numMarkers() < 3 or markers[dice[3] + dice[4]] > 0 then
markers[dice[3] + dice[4]] = columnPositionWithMarkers(dice[3] + dice[4]) + 1
end
end
elseif dice[1] + dice[3] == col then
if not columnsfilled[dice[2] + dice[4]] then
if numMarkers() < 3 or markers[dice[2] + dice[4]] > 0 then
markers[dice[2] + dice[4]] = columnPositionWithMarkers(dice[2] + dice[4]) + 1
end
end
elseif dice[1] + dice[4] == col then
if not columnsfilled[dice[2] + dice[3]] then
if numMarkers() < 3 or markers[dice[2] + dice[3]] > 0 then
markers[dice[2] + dice[3]] = columnPositionWithMarkers(dice[2] + dice[3]) + 1
end
end
elseif dice[2] + dice[3] == col then
if not columnsfilled[dice[1] + dice[4]] then
if numMarkers() < 3 or markers[dice[1] + dice[4]] > 0 then
markers[dice[1] + dice[4]] = columnPositionWithMarkers(dice[1] + dice[4]) + 1
end
end
elseif dice[2] + dice[4] == col then
if not columnsfilled[dice[1] + dice[3]] then
if numMarkers() < 3 or markers[dice[1] + dice[3]] > 0 then
markers[dice[1] + dice[3]] = columnPositionWithMarkers(dice[1] + dice[3]) + 1
end
end
elseif dice[3] + dice[4] == col then
if not columnsfilled[dice[1] + dice[2]] then
if numMarkers() < 3 or markers[dice[1] + dice[2]] > 0 then
markers[dice[1] + dice[2]] = columnPositionWithMarkers(dice[1] + dice[2]) + 1
end
end
end
pullBackOverColumns()
legalnums = {false,false,false,false,false,false,false,false,false,false,false,false}
gamestate = kSpotsPicked
end
function stopHit()
lockBoard()
markers = {0,0,0,0,0,0,0,0,0,0,0,0}
if isGameOver() then
gamestate = kGameOver
else
currentplayer = currentplayer + 1
if currentplayer > numplayers then
currentplayer = 1
end
gamestate = kTurnStart
dice = {0,0,0,0}
end
end
function bustHit()
currentplayer = currentplayer + 1
if currentplayer > numplayers then
currentplayer = 1
end
markers = {0,0,0,0,0,0,0,0,0,0,0,0}
gamestate = kTurnStart
dice = {0,0,0,0}
end
function touched(touch)
if touch.state ~= ENDED then
return
end
if gamestate == kChoosePlayers then
for i = 1,4,1 do
if touch.x > playerrect[i][1] and touch.x < playerrect[i][3] then
if touch.y > playerrect[i][2] and touch.y < playerrect[i][4] then
numplayers = i
currentplayer = 1
gamestate = kTurnStart
setupBoard()
markers = {0,0,0,0,0,0,0,0,0,0,0,0}
break
end
end
end
elseif gamestate == kTurnStart or gamestate == kSpotsPicked then
if touch.x > 0 and touch.x < 230 then
if touch.y > 530 and touch.y < 720 then
rollDice()
end
end
if gamestate == kSpotsPicked then
if touch.x > 55 and touch.x < 182 then
if touch.y > 461 and touch.y < 530 then
stopHit()
end
end
end
elseif gamestate == kBusted then
if touch.x > 55 and touch.x < 182 then
if touch.y > 461 and touch.y < 530 then
bustHit()
end
end
elseif gamestate == kGameOver then
if touch.x > 55 and touch.x < 182 then
if touch.y > 461 and touch.y < 530 then
setup()
end
end
elseif gamestate == kDiceRolled then
for i = 2,12,1 do
if legalnums[i] then
if touch.x > columnrects[i][1] and touch.x < columnrects[i][1] + columnrects[i][3] then
if touch.y > columnrects[i][2] and touch.y < columnrects[i][2] + columnrects[i][4] then
columnHit(i)
end
end
end
end
end
end
-- This function gets called once every frame
function draw()
background(0, 0, 0, 255)
strokeWidth(5)
stroke(255, 255, 255, 255)
fill(0, 0, 0, 255)
ellipseMode(CENTER)
-- draw board
if gamestate > kChoosePlayers then
spots = 1
for x = spacing+4, max, spacing do
fill(0, 0, 0, 255)
stroke(255, 255, 255, 255)
for player = 1,numplayers,1 do
if board[player][spots+1][topColumn(spots+1)] then
stroke(playercolor[player][1],playercolor[player][2], playercolor[player][3], playercolor[player][4])
end
end
line(x+transx,max,0+transx,max-x)
stroke(255, 255, 255, 255)
for player = 1,numplayers,1 do
if board[player][13-spots][topColumn(13-spots)] then
stroke(playercolor[player][1],playercolor[player][2], playercolor[player][3], playercolor[player][4])
end
end
line(max+transx,x,transx+(max-x),0)
stroke(255, 255, 255, 255)
for i = 2,12,1 do
for j = 1, #spotrects[i], 1 do
stroke(255, 255, 255, 255)
fill(0, 0, 0, 255)
for player = 1,numplayers,1 do
if board[player][i][topColumn(i)] then
stroke(playercolor[player][1],playercolor[player][2], playercolor[player][3], playercolor[player][4])
end
end
ellipse(spotrects[i][j][1],spotrects[i][j][2],spotrects[i][j][3], spotrects[i][j][4])
if markers[i] == j then
fill(255, 255, 255, 0)
stroke(167, 157, 157, 255)
rect(spotrects[i][j][1] - 19,spotrects[i][j][2] - 19,spotrects[i][j][3] + 20, spotrects[i][j][4] + 20)
end
for player = 1,numplayers,1 do
if board[player][i][j] then
fill(playercolor[player][1],playercolor[player][2], playercolor[player][3], playercolor[player][4])
stroke(playercolor[player][1],playercolor[player][2], playercolor[player][3], playercolor[player][4])
ellipse(spotrects[i][j][1] + offset[player][1]*offmult,spotrects[i][j][2] + offset[player][2]*offmult,25,25)
end
end
end
end
font("Arial-BoldMT")
fill(255, 255, 255, 255)
for player = 1,numplayers,1 do
if board[player][spots+1][topColumn(spots+1)] then
fill(playercolor[player][1],playercolor[player][2], playercolor[player][3], playercolor[player][4])
end
end
text(tostring(spots+1),x+transx+30,max+30)
columnrects[spots+1] = {x+transx+6,max+5,50,50}
if legalnums[spots+1] then
fill(255, 255, 255, 255)
stroke(255, 255, 255, 255)
rect(x+transx+6,max+5,50,50)
fill(0, 0, 0, 255)
text(tostring(spots+1),x+transx+30,max+30)
end
if markers[spots+1] == (spots*2)+1 then
fill(255, 0, 0, 0)
stroke(167, 157, 157, 255)
rect(x+transx+6,max+5,50,50)
end
fill(255, 255, 255, 255)
for player = 1,numplayers,1 do
if board[player][13-spots][topColumn(13-spots)] then
fill(playercolor[player][1],playercolor[player][2], playercolor[player][3], playercolor[player][4])
end
end
text(tostring(13-spots),max+30+transx,x+30)
columnrects[13-spots] = {max+6+transx,x+6,50,50}
if legalnums[13-spots] then
fill(255, 255, 255, 255)
stroke(255, 255, 255, 255)
rect(max+6+transx,x+6,50,50)
fill(0, 0, 0, 255)
text(tostring(13-spots),max+30+transx,x+30)
end
if markers[13-spots] == (spots*2)+1 then
fill(255, 255, 255, 0)
stroke(167, 157, 157, 255)
rect(max+6+transx,x+6,50,50)
end
spots = spots + 1
end
--draw dice
stroke(252, 252, 252, 255)
fill(182, 175, 175, 255)
rect(30,650,80,80)
rect(130,650,80,80)
rect(30,550,80,80)
rect(130,550,80,80)
fill(255, 255, 255, 255)
if dice[1] > 0 then
text(tostring(dice[1]),70,690)
text(tostring(dice[2]),170, 690)
text(tostring(dice[3]),70,590)
text(tostring(dice[4]),170,590)
end
for i=1,numplayers,1 do
if gamestate == kGameOver then
if i == currentplayer then
drawplayer(i)
end
else
drawplayer(i)
end
end
if gamestate == kSpotsPicked then
drawStopSign()
elseif gamestate == kBusted then
drawBusted()
elseif gamestate == kGameOver then
drawNewGame()
end
else
strokeWidth(5)
fill(255, 255, 255, 255)
font("Arial-BoldItalicMT")
text("Choose # of Players",159,468)
for i=1,4,1 do
drawplayer(i)
end
end
end
function drawplayer(player)
stroke(playercolor[player][1], playercolor[player][2], playercolor[player][3], playercolor[player][4])
if player == currentplayer then
fill(0, 0, 0, 255)
rect(playerrect[player][1]-10, playerrect[player][2]-10, 100, 100)
end
fill(playercolor[player][1], playercolor[player][2], playercolor[player][3], playercolor[player][4])
rect(playerrect[player][1], playerrect[player][2], 80, 80)
if player < 4 then
fill(255, 255, 255, 255)
else
fill(0, 0, 0, 255)
end
font("Arial-BoldMT")
text(tostring(player), playerrect[player][1] + 40, playerrect[player][2] + 40)
if player == currentplayer then
fill(0, 0, 0, 0)
stroke(157, 157, 157, 255)
if numMarkers() < 1 then
rect(playerrect[player][1] - 40, playerrect[player][2] + 64, 25, 25)
end
if numMarkers() < 2 then
rect(playerrect[player][1] - 40, playerrect[player][2] + 28, 25, 25)
end
if numMarkers() < 3 then
rect(playerrect[player][1] - 40, playerrect[player][2] - 8, 25, 25)
end
end
end
function drawStopSign()
stroke(255, 0, 0, 255)
fill(255, 0, 0, 255)
rect(55,461,127,69)
font("Arial-BoldMT")
fill(255, 255, 255, 255)
text("STOP",121,494)
end
function drawBusted()
stroke(255, 0, 0, 255)
fill(255, 0, 0, 0)
rect(55,461,127,69)
font("Arial-BoldMT")
fill(255, 255, 255, 255)
text("BUST",121,494)
end
function drawNewGame()
stroke(255, 255, 255, 255)
fill(255, 0, 0, 0)
rect(55,461,127,69)
font("Arial-BoldMT")
fill(255, 255, 255, 255)
text("WIN!",121,494)
end
Can’t Stop app finished in two days! Codea is amazing. I started not knowing Lua and in two days have a working iPad game.
I’m tired of waiting for a Can’t Stop app to appear on the App Store and I’ve been wanting to play with Codea for a while so I’m going to do it. I’ll post some screen shots and short blurbs on the development along the way.
Can’t Stop is a classic dice game of pushing your luck from the great designer Sid Sackson and I’ve been playing on yucata.de. It would be a great, quick game on the iPad. I’m not going to worry about AI until I get the game working as I want to play with my kids.
The first issue is learning Lua - which turns out to be pretty straightforward. Some interesting syntax choices but every language has those. I like that the table construct handles both the list and dictionary functionality from Python. I wrote some simple command-line programs and then dove into Codea yesterday and this morning. I knew I was hooked when I got the board drawn in less than an hour.

At that point I stopped and started to think through the various game states that the game could be in and moved to programming the first which is choosing the number of players.

That’s where I am. The program is 108 lines long and it’s off to a fun start.