Sunday 27 July 2008

AYO in SCALA

Have I mentioned that I'm on a mission to take on all the ideas I've ever had and make something of each one? Well I've suddenly realized that life is toooo short. In any case, here's another one of those childish dreams I used to have - to write an implementation of a local 9ja game.

I'll obviously have to blog some more about this largely untested code and the scala implementation that I've come up with but here's the source code any way...

If you are geekie (I have a friend that thinks I'm a geek... imagine!) enuf though, you could try out the code (it currently has only a command line interface but I plan to have a web based interface - lift, sweet or jsf are the prime suspects - sometime)

Tomorrow, hopefully, I'll be able to go through the code...

One important thing though is that this code is largely based on this bcc page


package ayo;

object Game {
def nextPlayer(player:Int) = (player+1)%2
def playerHoles(player:Int, holes:List[Int]) = if (player==0) holes.slice(0, 6) else holes.slice(6, 12)
def canMove(player:Int, holes:List[Int]) = playerHoles(player,holes).filter(x => x>0).length > 0
def isValidMove1(player:Int, position:Int) = (player==0 && position<6) player="="1">5)
def nextPos(pos:Int) = (pos+1)%12
def previousPos(pos:Int) = (pos+11)%12

def move1(player:Int, pos:Int, holes:List[Int]):Tuple2[Int, List[Int]] =
if(!isValidMove1(player:Int, pos:Int))
(pos, Nil)
else{
val nuHoles:List[Int] = {for(i <- 0 until holes.length) yield if(i==pos) 0 else holes(i)}.toList //prnt(nuHoles, Array("him", "her"), Array(0,0)) move2(player, nextPos(pos), holes(pos), nuHoles) } def move2(player:Int, pos:Int, stones:Int, holes:List[Int]):Tuple2[Int, List[Int]] = if(stones == 0 && (holes(previousPos(pos))<=1 || holes(previousPos(pos))==4)) (previousPos(pos), holes) else{ if(stones==0 && holes(previousPos(pos))>1){
val nuHoles = {for(i <- 0 until holes.length) yield if(i==previousPos(pos)) 0 else holes(i)}.toList //println("move2 type 1") //prnt(nuHoles, Array("him", "her"), Array(0,0)) move2(player, pos, holes(previousPos(pos)), nuHoles) }else{ val nuHoles = {for(i<-0 until holes.length) yield if(i==pos) holes(i)+1 else holes(i)}.toList //println("move2 type 2") //prnt(nuHoles, Array("him", "her"), Array(0,0)) move2(player, nextPos(pos), stones-1, nuHoles) } } def prnt(holes:List[Int], names:Array[String], stones:Array[Int]){ print("\n|") playerHoles(1, holes).reverse.foreach(x => print("\t"+x+"\t|"))
print(" "+names(1)+": "+stones(1)+"\n|")
playerHoles(0, holes).foreach(x => print("\t"+x+"\t|"))
print(" "+names(0)+": "+stones(0)+"\n")
}

def cleanup(player:Int, end:Int, holes:List[Int]):Tuple3[Int, Int, List[Int]] = {
var playerCount = if (holes(end)==4) 4 else 0
val nuHoles = {for(i<-0 until holes.length) yield if(end==i && playerCount!=0) 0 else holes(i)}.toList playerCount += playerHoles(player, nuHoles).foldRight(0)((x,y)=>{ if(x==4) x+y else y})
val nextPlayerCount = playerHoles(nextPlayer(player), nuHoles).foldRight(0)((x,y)=>{ if(x==4) x+y else y})

if(player==0)
(playerCount, nextPlayerCount, nuHoles.map(x => if(4==x) 0 else x))
else
(nextPlayerCount, playerCount, nuHoles.map(x => if(4==x) 0 else x))
}

def main(args : Array[String]) : Unit = {
var holes = List(4,4,4,4,4,4,4,4,4,4,4,4)
var capturedStones = Array(0,0)
var names = Array("him", "her")
var turn = 0

while(canMove(turn, holes)){
println
prnt(holes, names, capturedStones)

print(names(turn)+": ")
val pos = readInt

if(isValidMove1(turn, pos)){
var result1 = move1(turn, pos, holes)
var result2 = cleanup(turn, result1._1, result1._2)

capturedStones(0) += result2._1
capturedStones(1) += result2._2
holes = result2._3
turn = nextPlayer(turn)
}
}
}
//while the player can move
//print out the the board
//get player's move
//if the move is invalid goto step 1
//cleanup the move and store the players stones as well as the list to start again

def junk:Unit = {
/*
println(canMove(1, holes))

println("move is valid, "+isValidMove1(0,5))
println(move1(0, 5, holes)._1)
println("move is valid, "+isValidMove1(1,6))
println(move1(1, 6, move1(0, 5, holes)._2)._2)

print(cleanup(0, 5, move1(0, 1, (move1(1, 6, move1(0, 5, holes)._2)._2))._2)._1)
*/
}
}




Just for kicks here's the result of running two steps (mirroring the example in the bbc link above)



| 4 | 4 | 4 | 4 | 4 | 4 | her: 0
| 4 | 4 | 4 | 4 | 4 | 4 | him: 0
him: 2


| 1 | 0 | 6 | 6 | 6 | 1 | her: 0
| 6 | 6 | 2 | 7 | 1 | 6 | him: 0
her: 11


| 1 | 1 | 7 | 7 | 0 | 2 | her: 4
| 1 | 8 | 0 | 8 | 2 | 7 | him: 0
him:

No comments: