From 3b7e8befa3c75a9ac0aac03dc527c6637dd5fcd7 Mon Sep 17 00:00:00 2001 From: Sam Moore <matches@ucc.asn.au> Date: Sat, 28 Apr 2012 18:20:32 +0800 Subject: [PATCH] [PRELIMINARY ROUND 1] Credits: -------- celcius - David Gow (sulix) ramen - John Hodge (tpg) peternlewis - Peter N Lewis Samples: basic_python basic_cpp (NOT COMPETING) basic_java (NOT COMPETING) asmodeus vixen hunter All samples are provided by Sam Moore The preliminary round is worth 10%; scores in simulate.py have been weighted accordingly Good luck! --- agents/celsius/celsius.py | 539 ++++++ agents/celsius/info | 4 + agents/peternlewis/Makefile | 25 + agents/peternlewis/__MACOSX/._peternlewis | Bin 0 -> 229 bytes .../__MACOSX/peternlewis/._.DS_Store | Bin 0 -> 82 bytes .../__MACOSX/peternlewis/._Makefile | Bin 0 -> 171 bytes .../peternlewis/__MACOSX/peternlewis/._info | Bin 0 -> 229 bytes .../__MACOSX/peternlewis/._peternlewis.cpp | Bin 0 -> 167 bytes .../__MACOSX/peternlewis/._peternlewis.h | Bin 0 -> 171 bytes agents/peternlewis/info | 4 + agents/peternlewis/peternlewis | Bin 0 -> 159242 bytes agents/peternlewis/peternlewis.cpp | 1708 +++++++++++++++++ agents/peternlewis/peternlewis.h | 71 + agents/peternlewis/peternlewis.o | Bin 0 -> 268304 bytes agents/ramen/Makefile | 25 + agents/ramen/ai.c | 874 +++++++++ agents/ramen/ai_common.h | 108 ++ agents/ramen/db.c | 258 +++ agents/ramen/info | 4 + agents/ramen/interface.h | 70 + agents/ramen/main.c | 240 +++ judge/simulator/simulate.py | 2 +- 22 files changed, 3931 insertions(+), 1 deletion(-) create mode 100755 agents/celsius/celsius.py create mode 100644 agents/celsius/info create mode 100644 agents/peternlewis/Makefile create mode 100644 agents/peternlewis/__MACOSX/._peternlewis create mode 100644 agents/peternlewis/__MACOSX/peternlewis/._.DS_Store create mode 100644 agents/peternlewis/__MACOSX/peternlewis/._Makefile create mode 100644 agents/peternlewis/__MACOSX/peternlewis/._info create mode 100644 agents/peternlewis/__MACOSX/peternlewis/._peternlewis.cpp create mode 100644 agents/peternlewis/__MACOSX/peternlewis/._peternlewis.h create mode 100644 agents/peternlewis/info create mode 100755 agents/peternlewis/peternlewis create mode 100755 agents/peternlewis/peternlewis.cpp create mode 100755 agents/peternlewis/peternlewis.h create mode 100644 agents/peternlewis/peternlewis.o create mode 100644 agents/ramen/Makefile create mode 100644 agents/ramen/ai.c create mode 100644 agents/ramen/ai_common.h create mode 100644 agents/ramen/db.c create mode 100644 agents/ramen/info create mode 100644 agents/ramen/interface.h create mode 100644 agents/ramen/main.c diff --git a/agents/celsius/celsius.py b/agents/celsius/celsius.py new file mode 100755 index 0000000..cc71b90 --- /dev/null +++ b/agents/celsius/celsius.py @@ -0,0 +1,539 @@ +#!/usr/bin/python -u + +#NOTE: The -u option is required for unbuffered stdin/stdout. +# If stdin/stdout are buffered, the manager program will not recieve any messages and assume that the agent has timed out. + + +import sys +import random + +ranks = ['B','1','2','3','4','5','6','7','8','9','s','F', '?', '!', '+'] + +""" +The scaretable lists how `scary' pieces are to each other; pieces will move +in the least scary direction. +""" + +# B 1 2 3 4 5 6 7 8 9 s F ? ! + +scaretable = [[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], #B + [ 0, 0,-8,-8,-7,-6,-5,-4,-3,-2, 5,-9, 0,-7, 0], #1 + [ 0, 4, 0,-7,-6,-5,-4,-3,-2,-1,-2,-9,-3,-6, 0], #2 + [ 0, 4, 2, 0,-6,-5,-4,-3,-2,-1,-2,-9,-2,-5, 0], #3 + [ 0, 3, 2, 2, 0,-5,-4,-3,-2,-1,-2,-9,-1,-3, 0], #4 + [ 0, 3, 2, 2, 2, 0,-4,-3,-2,-1,-2,-9, 0,-2, 0], #5 + [ 0, 3, 2, 2, 2, 2, 0,-3,-2,-1,-2,-9, 1,-1, 0], #6 + [ 0, 3, 2, 2, 2, 2, 2, 0,-2,-1,-2,-9,-1, 0, 0], #7 + [-40, 3, 2, 2, 2, 2, 2, 2, 0,-2,-2,-9,-1, 1, 0], #8 + [ 0, 3, 2, 2, 2, 2, 2, 2, 2, 0,-2,-9,-2, 2, 0], #9 + [ 0, -5, 3, 3, 3, 3, 3, 3, 3, 3,-1,-9, 5, 3, 0], #s + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], #F + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], #? + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], #! + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]] #+ + +""" +The override table allows moves to be forced or prevented, thus ensuring +that sacrifices are not made. +""" +# B 1 2 3 4 5 6 7 8 9 s F ? ! + +overrides = [[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], #B + [ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,-1,-1, 0, 0, 1], #1 + [ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1, 0, 0, 1], #2 + [ 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,-1, 0, 0, 1], #3 + [ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,-1, 0, 0, 1], #4 + [ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,-1, 0, 0, 1], #5 + [ 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,-1, 0, 0, 1], #6 + [ 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,-1, 0, 0, 1], #7 + [-1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,-1, 0, 0, 1], #8 + [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,-1, 0, 0, 1], #9 + [ 1,-1, 1, 1, 1, 1, 1, 1, 1, 1,-1,-1, 0, 0, 1], #s + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], #F + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], #? + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], #! + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]] #+ + + +def is_integer(s): + """ Using exceptions for this feels... wrong...""" + try: + int(s) + return True + except ValueError: + return False + +def move(x, y, direction, multiplier): + """ Moves point (x,y) in direction, returns a pair """ + if direction == "UP": + return (x,y-multiplier) + elif direction == "DOWN": + return (x,y+multiplier) + elif direction == "LEFT": + return (x-multiplier, y) + elif direction == "RIGHT": + return (x+multiplier, y) + return (x,y) + + + +def oppositeColour(colour): + """ Returns the opposite colour to that given """ + if colour == "RED": + return "BLUE" + elif colour == "BLUE": + return "RED" + else: + return "NONE" + +class Piece: + """ Class representing a piece + Pieces have colour, rank and co-ordinates + """ + def __init__(self, colour, rank, x, y): + self.colour = colour + self.rank = rank + self.x = x + self.y = y + self.lastMoved = -1 + self.beenRevealed = False + self.positions = [(x, y)] + + + + self.heatmap = [] + self.turnCount = 0 + + def mobile(self): + return self.rank != 'F' and self.rank != 'B' and self.rank != '?' and self.rank != '+' + + def valuedRank(self): + if ranks.count(self.rank) > 0: + return len(ranks) - 2 - ranks.index(self.rank) + else: + return 0 + + def scariness(self, other): + scare = scaretable[ranks.index(self.rank)][ranks.index(other.rank)] + if scare > 0: + scare = scare * 1 + return scare + + def getOverride(self, other): + return overrides[ranks.index(self.rank)][ranks.index(other.rank)] + + def getHeatmap(self, x,y,w,h): + if (x < 0) or (x >= w) or (y < 0) or (y >= h): + return 10 + else: + return self.heatmap[x][y] + + def validSquare(self, x, y, width, height, board): + if x < 0: + return False + if y < 0: + return False + if x >= width: + return False + if y >= height: + return False + if board[x][y] != None and board[x][y].colour == self.colour: + return False + if board[x][y] != None and board[x][y].rank == '#': + return False + return True + + def generateHeatmap(self, width, height, board): + self.heatmap = [] + newmap = [] + for x in range(0,width): + self.heatmap.append([]) + newmap.append([]) + for y in range(0,height): + self.heatmap[x].append(0) + newmap[x].append(0) + if board[x][y] == None: + self.heatmap[x][y] = 0 + continue + if board[x][y].colour == self.colour: + if board[x][y].rank == 'F': + self.heatmap[x][y] = -5 # + self.valuedRank() # Defend our flag + else: + self.heatmap[x][y] = self.scariness(board[x][y]) + + # Make pieces prefer to stay where they are + #self.heatmap[self.x][self.y] = -0.5 + + for i in range(0,min(30,len(self.positions))): + p = self.positions[len(self.positions)-1-i] + if board[p[0]][p[1]] != None: + self.heatmap[p[0]][p[1]] += 0.2 * ((50 - i)/50) + + + + for n in range(0,8): + for x in range(0,width): + for y in range(0,height): + if self.heatmap[x][y] != 0: + newmap[x][y] = self.heatmap[x][y] + continue + newmap[x][y] = 0 #self.heatmap[x][y] * 0.2 + if self.validSquare(x-1,y,width,height,board): + newmap[x][y] += self.heatmap[x-1][y] * 0.2 + else: + newmap[x][y] += 0 #self.heatmap[x][y] * 0.1 + if self.validSquare(x+1,y,width,height,board): + newmap[x][y] += self.heatmap[x+1][y] * 0.2 + else: + newmap[x][y] += 0 #self.heatmap[x][y] * 0.1 + if self.validSquare(x,y-1,width,height,board): + newmap[x][y] += self.heatmap[x][y-1] * 0.2 + else: + newmap[x][y] += 0 #self.heatmap[x][y] * 0.1 + if self.validSquare(x,y+1,width,height,board): + newmap[x][y] += self.heatmap[x][y+1] * 0.2 + else: + newmap[x][y] += 0 #self.heatmap[x][y] * 0.1 + self.heatmap = newmap + + def debugPrintHeat(self,w,h): + """ For debug purposes only. Prints the board to stderr. + Does not indicate difference between allied and enemy pieces + Unknown (enemy) pieces are shown as '?' + """ + sys.stderr.write("Pos: " + str(self.x) + ", " + str(self.y) + " -- rank: " + str(self.rank) + "\n") + for y in range(0, h): + for x in range(0, w): + if (self.heatmap[x][y] - self.heatmap[self.x][self.y] > 0.0): + sys.stderr.write("O") + elif (self.heatmap[x][y] - self.heatmap[self.x][self.y] == 0.0): + sys.stderr.write("X") + elif (self.heatmap[x][y] - self.heatmap[self.x][self.y] < 0.0): + sys.stderr.write(".") + else: + sys.stderr.write(" ") + sys.stderr.write("\n") + sys.stderr.write("\n") + + + + +def valuedRank(rank): + if ranks.count(rank) > 0: + return len(ranks) - 2 - ranks.index(rank) + else: + return 0 + + + +class SulixAI: + """ + BasicAI class to play a game of stratego + Implements the protocol correctly. Stores the state of the board in self.board + Only makes random moves. + Override method "MakeMove" for more complex moves + """ + def __init__(self): + """ Constructs the BasicAI agent, and starts it playing the game """ + #sys.stderr.write("BasicAI __init__ here...\n"); + self.turn = 0 + self.board = [] + self.units = [] + self.enemyUnits = [] + + self.total_turns = 0 + + self.totalAllies = {'B':6,'1':1,'2':1,'3':2,'4':3,'5':4,'6':4,'7':4,'8':5,'9':8,'s':1,'F':1} + self.totalEnemies = {'B':6,'1':1,'2':1,'3':2,'4':3,'5':4,'6':4,'7':4,'8':5,'9':8,'s':1,'F':1} + self.hiddenEnemies = {'B':6,'1':1,'2':1,'3':2,'4':3,'5':4,'6':4,'7':4,'8':5,'9':8,'s':1,'F':1} + self.hiddenAllies = {'B':6,'1':1,'2':1,'3':2,'4':3,'5':4,'6':4,'7':4,'8':5,'9':8,'s':1,'F':1} + self.lastMoved = None + + + + def Setup(self): + """ Implements Setup part of protocol. Always uses the same setup. Override to create custom setups """ + #sys.stderr.write("BasicAI Setup here...\n"); + setup = sys.stdin.readline().split(' ') + if len(setup) != 4: + sys.stderr.write("BasicAI setup fails, expected 4 tokens, got " + str(len(setup)) + " "+str(setup) + "\n") + self.colour = setup[0] + self.opponentName = setup[1] + self.width = int(setup[2]) + self.height = int(setup[3]) + for x in range(0, self.width): + self.board.append([]) + for y in range(0, self.height): + self.board[x].append(None) + if self.colour == "RED": + print "FB8sB979B8\nBB99555583\n6724898974\nB314676699" + elif self.colour == "BLUE": + print "B314676699\n6724898974\nBB99555583\nFB8sB979B8" + return True + + def MoveCycle(self): + #sys.stderr.write("BasicAI MakeMove here...\n"); + if self.InterpretResult() == False or self.ReadBoard() == False or self.MakeMove() == False: + return False + self.turn += 1 + return self.InterpretResult() + + def MakeMove(self): + """ Randomly moves any moveable piece, or prints "NO_MOVE" if there are none """ + #TODO: Over-ride this function in base classes with more complex move behaviour + + #sys.stderr.write("Sulix's AI makes a move...\n") + #self.debugPrintBoard() + + if len(self.units) <= 0: + return False + + index = random.randint(0, len(self.units)-1) + startIndex = index + + directions = ("UP", "DOWN", "LEFT", "RIGHT") + bestdir = 0 + bestScare = 999 + bestpiece = None + while True: + piece = self.units[index] + + if piece != None and piece.mobile(): + dirIndex = random.randint(0, len(directions)-1) + startDirIndex = dirIndex + piece.generateHeatmap(self.width, self.height, self.board) + currentScary = piece.getHeatmap(piece.x, piece.y, self.width, self.height) * 0 + piece.turnCount*0 #Perhaps just look for the best move + piece.turnCount = piece.turnCount + 1 + while True: + #sys.stderr.write("Trying index " + str(dirIndex) + "\n") + p = move(piece.x, piece.y, directions[dirIndex],1) + if p[0] >= 0 and p[0] < self.width and p[1] >= 0 and p[1] < self.height: + target = self.board[p[0]][p[1]] + if target == None or (target.colour != piece.colour and target.colour != "NONE" and target.colour != "BOTH"): + scare = piece.getHeatmap(p[0], p[1],self.width, self.height) - currentScary + override = 0 + if target != None: + override = piece.getOverride(target) + + if (self.total_turns % 250 < 15) and (self.total_turns > 250): + scare += random.randint(0, 5) + + + if override == 1: + scare = 999 + elif override == -1: + piece.turnCount = 0 + print str(piece.x) + " " + str(piece.y) + " " + directions[dirIndex] + return True + + + + + if scare < bestScare: + bestdir = dirIndex + bestScare = scare + bestpiece = piece + + dirIndex = (dirIndex + 1) % len(directions) + if startDirIndex == dirIndex: + break + + + index = (index + 1) % len(self.units) + if startIndex == index: + if bestScare != 999: + bestpiece.turnCount = 0 + print str(bestpiece.x) + " " + str(bestpiece.y) + " "+directions[bestdir] +# bestpiece.debugPrintHeat(self.width, self.height) + return True + else: + print "SURRENDER" + return True + + + def ReadBoard(self): + """ Reads in the board. + On the very first turn, sets up the self.board structure + On subsequent turns, the board is simply read, but the self.board structure is not updated here. + """ + #sys.stderr.write("BasicAI ReadBoard here...\n"); + for y in range(0,self.height): + row = sys.stdin.readline().strip() + if len(row) < self.width: + sys.stderr.write("Row has length " + str(len(row)) + " vs " + str(self.width) + "\n") + return False + for x in range(0,self.width): + if self.turn == 0: + if row[x] == '.': + pass + elif row[x] == '#': + self.board[x][y] = Piece(oppositeColour(self.colour), '?',x,y) + self.enemyUnits.append(self.board[x][y]) + elif row[x] == '+': + self.board[x][y] = Piece("NONE", '+', x, y) + else: + self.board[x][y] = Piece(self.colour, row[x],x,y) + self.units.append(self.board[x][y]) + else: + pass + return True + + + def InterpretResult(self): + """ Interprets the result of a move, and updates the board. + The very first move is ignored. + On subsequent moves, the self.board structure is updated + """ + + self.total_turns = self.total_turns + 1 + + #sys.stderr.write("BasicAI InterpretResult here...\n") + result = sys.stdin.readline().split(' ') + #sys.stderr.write(" Read status line \"" + str(result) + "\"\n") + if self.turn == 0: + return True + + if result[0].strip() == "QUIT": #Make sure we exit when the manager tells us to! + return False + + if result[0].strip() == "NO_MOVE": #No move was made, don't need to update anything + return True + + if len(result) < 4: #Should be at least 4 tokens (X Y DIRECTION OUTCOME) in any other case + return False + + x = int(result[0].strip()) + y = int(result[1].strip()) + + + # The piece moved! It's not a bomb + if self.board[x][y].rank == '?': + self.board[x][y].rank = '!' + #sys.stderr.write(" Board position " + str(x) + " " + str(y) + " is OK!\n") + + direction = result[2].strip() + + multiplier = 1 + outcome = result[3].strip() + outIndex = 3 + if is_integer(outcome): + multiplier = int(outcome) + outcome = result[4].strip() + outIndex = 4 + + p = move(x,y,direction, multiplier) + + # It's a scout! I saw it move. + if multiplier > 1: + self.board[x][y].rank = '9' + + #Determine attacking piece + attacker = self.board[x][y] + self.board[x][y] = None + + if attacker == None: + return False + + lastMoved = attacker + + defender = self.board[p[0]][p[1]] + + #Update attacker's position (Don't overwrite the board yet though) + + attacker.x = p[0] + attacker.y = p[1] + attacker.positions.insert(0, (attacker.x, attacker.y)) + + + #Determine ranks of pieces if supplied + if len(result) >= outIndex + 3: + if defender == None: + return False + attacker.rank = result[outIndex+1].strip() + if attacker.beenRevealed == False: + if attacker.colour == self.colour: + self.hiddenAllies[attacker.rank] -= 1 + elif attacker.colour == oppositeColour(self.colour): + self.hiddenEnemies[attacker.rank] -= 1 + attacker.beenRevealed = True + defender.rank = result[outIndex+2].strip() + if defender.beenRevealed == False: + if defender.colour == self.colour: + self.hiddenAllies[defender.rank] -= 1 + elif defender.colour == oppositeColour(self.colour): + self.hiddenEnemies[defender.rank] -= 1 + + defender.beenRevealed = True + + + + if outcome == "OK": + self.board[p[0]][p[1]] = attacker + + elif outcome == "KILLS": + self.board[p[0]][p[1]] = attacker + + if defender.colour == self.colour: + self.totalAllies[defender.rank] -= 1 + self.units.remove(defender) + elif defender.colour == oppositeColour(self.colour): + self.totalEnemies[defender.rank] -= 1 + self.enemyUnits.remove(defender) + + elif outcome == "DIES": + if attacker.colour == self.colour: + self.totalAllies[attacker.rank] -= 1 + self.units.remove(attacker) + elif attacker.colour == oppositeColour(self.colour): + self.totalEnemies[attacker.rank] -= 1 + self.enemyUnits.remove(attacker) + + elif outcome == "BOTHDIE": + self.board[p[0]][p[1]] = None + + if defender.colour == self.colour: + self.totalAllies[defender.rank] -= 1 + self.units.remove(defender) + elif defender.colour == oppositeColour(self.colour): + self.totalEnemies[defender.rank] -= 1 + self.enemyUnits.remove(defender) + + if attacker.colour == self.colour: + self.totalAllies[attacker.rank] -= 1 + self.units.remove(attacker) + elif attacker.colour == oppositeColour(self.colour): + self.totalEnemies[attacker.rank] -= 1 + self.enemyUnits.remove(attacker) + + elif outcome == "FLAG": + #sys.stderr.write(" Game over!\n") + return False + elif outcome == "ILLEGAL": + #sys.stderr.write(" Illegal move!\n") + return False + else: + #sys.stderr.write(" Don't understand outcome \"" + outcome + "\"!\n"); + return False + + #sys.stderr.write(" Completed interpreting move!\n"); + return True + + + + def debugPrintBoard(self): + """ For debug purposes only. Prints the board to stderr. + Does not indicate difference between allied and enemy pieces + Unknown (enemy) pieces are shown as '?' + """ + for y in range(0, self.height): + for x in range(0, self.width): + if self.board[x][y] == None: + sys.stderr.write("."); + else: + sys.stderr.write(str(self.board[x][y].rank)); + sys.stderr.write("\n") + +if __name__ == "__main__": + sulixAI = SulixAI() + if sulixAI.Setup(): + while sulixAI.MoveCycle(): + pass + diff --git a/agents/celsius/info b/agents/celsius/info new file mode 100644 index 0000000..aedb008 --- /dev/null +++ b/agents/celsius/info @@ -0,0 +1,4 @@ +celsius.py +David Gow +python +Generates a heatmap of the board, and uses this to control pieces. diff --git a/agents/peternlewis/Makefile b/agents/peternlewis/Makefile new file mode 100644 index 0000000..e7e0bc1 --- /dev/null +++ b/agents/peternlewis/Makefile @@ -0,0 +1,25 @@ +#Makefile for basic_cpp +# Sample C++ Stratego AI +# UCC Programming Competition 2012 + +CPP = g++ -Wall -pedantic -g +OBJ = peternlewis.o + +BIN = peternlewis + +$(BIN) : $(OBJ) + $(CPP) -o $(BIN) $(OBJ) + +%.o : %.cpp %.h + $(CPP) -c $< + +clean : + $(RM) $(BIN) $(OBJ) $(LINKOBJ) + +#Cleans up all backup files +clean_full: + $(RM) $(BIN) $(OBJ) $(LINKOBJ) + $(RM) *.*~ + $(RM) *~ + + diff --git a/agents/peternlewis/__MACOSX/._peternlewis b/agents/peternlewis/__MACOSX/._peternlewis new file mode 100644 index 0000000000000000000000000000000000000000..633840e786bbae3b20ae2dbc8220e656a5c5d607 GIT binary patch literal 229 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDI}@n#?f@t*=Q5x_AdBnYYuq+<pU`=V)M zM2L$f=jZAr78K;9>J^qI7A5ADWagzZ6zUro7#Lccq?xChq^22K2PdW_7G+wSIa@dy qxVky%x;dH{=$e?g8R<GYIa=yE8XGw~niv~c7@E4(APj`)VgLXi{w9e4 literal 0 HcmV?d00001 diff --git a/agents/peternlewis/__MACOSX/peternlewis/._.DS_Store b/agents/peternlewis/__MACOSX/peternlewis/._.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..321346b56958ca49a4cec87e452fe5f048ea9c64 GIT binary patch literal 82 ucmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDI}u>uf-_(4F-09OIxU;zLoY6T$x literal 0 HcmV?d00001 diff --git a/agents/peternlewis/__MACOSX/peternlewis/._Makefile b/agents/peternlewis/__MACOSX/peternlewis/._Makefile new file mode 100644 index 0000000000000000000000000000000000000000..6adb72ec537e12b7d90a1ae5cb0b7773f90043a8 GIT binary patch literal 171 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDI}aU~Fg_^W}KA;dKz1VrNojv*mIP+5?U zIY7*hrkW8UE}op9tCv_%kdvwxl3G#XnwOlPl9`tdR1g~CrfXqsXl!C+Xl`j?0swGa B6-xjB literal 0 HcmV?d00001 diff --git a/agents/peternlewis/__MACOSX/peternlewis/._info b/agents/peternlewis/__MACOSX/peternlewis/._info new file mode 100644 index 0000000000000000000000000000000000000000..633840e786bbae3b20ae2dbc8220e656a5c5d607 GIT binary patch literal 229 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDI}@n#?f@t*=Q5x_AdBnYYuq+<pU`=V)M zM2L$f=jZAr78K;9>J^qI7A5ADWagzZ6zUro7#Lccq?xChq^22K2PdW_7G+wSIa@dy qxVky%x;dH{=$e?g8R<GYIa=yE8XGw~niv~c7@E4(APj`)VgLXi{w9e4 literal 0 HcmV?d00001 diff --git a/agents/peternlewis/__MACOSX/peternlewis/._peternlewis.cpp b/agents/peternlewis/__MACOSX/peternlewis/._peternlewis.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d2c90afbdcb16874f509659d3ca1c73eec0eab0c GIT binary patch literal 167 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDI}aVZdk_{)KqA;dKz#5vs4mB9hT!v-8f zLV}>;ARTjnm>W$UBSKs}IX_n~v7jI)RWBs9qQo^XIX@*cFCC~LH!(RguOz=X!`c7< DyVn<L literal 0 HcmV?d00001 diff --git a/agents/peternlewis/__MACOSX/peternlewis/._peternlewis.h b/agents/peternlewis/__MACOSX/peternlewis/._peternlewis.h new file mode 100644 index 0000000000000000000000000000000000000000..cb3e53ffa6ed2763c11ffc5db6908cf89641a892 GIT binary patch literal 171 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDI}aU~Fg_^W}KA;dKz#5vs4mB9hT!v-8f zLV}>;ARTjnm>*3YBSKs}IX_n~v7jI)RWBs9qQo^XIX@*cFCC~LG{jBU!rIW-#K_Rx H(!vA)5&IUi literal 0 HcmV?d00001 diff --git a/agents/peternlewis/info b/agents/peternlewis/info new file mode 100644 index 0000000..7b0886b --- /dev/null +++ b/agents/peternlewis/info @@ -0,0 +1,4 @@ +peternlewis +Peter N Lewis +C++ +Based on my MacTech 1997 cahellnge winning algorithm, updated only enough to comply with the UCC challenge API. diff --git a/agents/peternlewis/peternlewis b/agents/peternlewis/peternlewis new file mode 100755 index 0000000000000000000000000000000000000000..b63237ff14e5cb54a07d72dbb26686b7f7713725 GIT binary patch literal 159242 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 Hx9k50%yjQm literal 0 HcmV?d00001 diff --git a/agents/peternlewis/peternlewis.cpp b/agents/peternlewis/peternlewis.cpp new file mode 100755 index 0000000..b8666f7 --- /dev/null +++ b/agents/peternlewis/peternlewis.cpp @@ -0,0 +1,1708 @@ +#define ASSERTIONS 1 +#define DEBUG_RULES 0 +#define DEBUG 0 +#define SAVE_OUTPUT 1 + +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <cstdlib> +#include <iostream> +#include <iostream> +#include <fstream> +#include <sstream> +#include <vector> +#include <cassert> +#include <sstream> + +using namespace std; // two of two, yay! + +typedef bool Boolean; +typedef unsigned long UInt32; + +#include "peternlewis.h" + +const char *gPieceCharacters = kPieceCharacters; +#if SAVE_OUTPUT +ofstream gOutputFile; +#endif + +template <class T> +inline std::string to_string (const T& t) +{ + std::stringstream ss; + ss << t; + return ss.str(); +} + + +/* + Author: Peter N Lewis + + Originally: Submitted in 1997 to MacTech Programming Challenge and won. + <http://www.mactech.com/articles/mactech/Vol.13/13.11/Nov97Challenge/index.html> + + Assumptions: + Only time we spend thinking is counted against out 10 seconds (not time in GetMove/ReportMove) + + Method: + Basically we keep track of the board and what we know and what they know. + Each opponent piece has a bit map associated with it describing what pieces it could be. + As we see more pieces, the bit map is culled. If the piece moves, the bomb & flag bits are removed. + If we've seen all Scouts (for example), then the Scout bit is removed from all remaining pieces. + If all but one bit is remvoed, then we know what the piece is. + + At each turn, we simply apply a sequence of actions (listed below) and take the first action that works. + + It does very little in the way of lookahead (it plans out a path, but doesn't remember it and + doesn't take it to account any movement by the opposition) + + It keeps a CRC of recent board positions (since the last strike) and doesn't replay any boards + (we want to win, not draw!). + + If we exceed 10 seconds thinking time, we resign. Not that this is particularly likely, + in the games I tried, it spend less than half a second total. + + Optimizations: + None. + + Comment: + It actually plays a half decent game! The end game is not as good as I'd like, but time is up! +*/ + +/* +USE SPY + If our spy is next to their 1, kill it + +DEFEND AGAINST SPY + if we have seen the spy, ignore this case + + If an unknown piece is next to the 1, then + run, attack, have another piece attack, or ignore depending on a table + +ATTACK WEAKER + If a known piece is next to a weaker known piece, attack it + except if it places that piece in a dangerous location + +EXPLORE ATTACK + If a 6,7,9 is next to an unknown piece, attack it + +RETREAT + If a known piece is next to a stronger known piece, run away + (preferably towards something that can kill it + or if it's lowly, towards an unknown piece) + +SCOUT + Try advancing scouts rapidly + +ATTACK DISTANT + If a known piece is distant, but a clear path leads a slightly better piece towards it, advance the better piece + (includes miners) + +EXPLORE DISTANT + Try exploring (advance lowly pieces towards unknown pieces) + +ATTACK KNOWN WITH SAME DISTANT + If a known piece can be attacked by a known identical piece, attack it + +FIND FLAG + When few unmoved pieces remain, start assuming they are bombs/flags + +MOVE FORWARD + Move any piece we can forward + +MOVE + Move any piece we can + +RESIGN + Give up +*/ + +static void Output( string what ) +{ +#if SAVE_OUTPUT + gOutputFile << "<< " << what << "\n"; +#endif + cout << what << "\n"; +} + +static void SaveInput( string what ) +{ +#if SAVE_OUTPUT + gOutputFile << ">> " << what << "\n"; +#endif +} + +static void Log( string what ) +{ +#if SAVE_OUTPUT + gOutputFile << what << "\n"; +#endif + cerr << what << "\n"; +} + +static void Debug( string what ) +{ +#if SAVE_OUTPUT + gOutputFile << what << "\n"; +#endif +#if DEBUG + cerr << what << "\n"; +#endif +} + +static void Assert( short must, string what ) +{ + if ( !must ) { +#if ASSERTIONS + Log( string("Assert failed! ") + what + "\n" ); +#endif + } +} + +std::vector<string> gLineBuffer; + +enum { + kNoNothing = 0x00001FFE, + kStationaryBits = ((1 << kBomb) | (1 << kFlag)) +}; + +enum { + kRepeatedBoards = 1000 +}; + +typedef struct Square { + PlayerColor color; + PieceRank rank; + UInt32 possibilities; +} Square; + +typedef Square OurBoard[kBoardSize][kBoardSize]; + +typedef int Counts[kFlag+1]; + +typedef UInt32 BoardPossibilities[kBoardSize][kBoardSize]; + +typedef struct Storage { + OurBoard board; + Counts our_pieces; + Counts their_pieces; + Boolean do_getmove; + Boolean victory; + Square blankSquare; + PlayerColor playerColor; + PlayerColor theirColor; + BoardPossibilities dangers; + BoardPossibilities known_dangers; + UInt32 repeated_board[kRepeatedBoards]; + UInt32 repeated_board_count; +} Storage, *StoragePtr; + +static void DumpBoard( StoragePtr storage ) +{ +#if DEBUG + Debug( "DumpBoard:" ); + for ( int row = 0; row < kBoardSize; row++ ) { + string line; + for ( int col = 0; col < kBoardSize; col++ ) { + PieceRank rank = storage->board[row][col].rank; + if ( kMarshall <= rank && rank <= kFlag ) { + char left, right; + if ( storage->board[row][col].color == kRed ) { + left = '{'; + right = '}'; + } else { + left = '['; + right = ']'; + } + line += left; + line += gPieceCharacters[rank]; + line += right; + line += ' '; + } else { + line += ' '; + if ( rank == kEmpty ) { + line += '.'; + } else if ( rank == kWater ) { + line += '*'; + } else if ( rank == kMoved ) { + line += 'M'; + } else if ( rank == kAddForRankish ) { + line += '%'; + } else if ( rank == kUnknown ) { + line += '?'; + } else { + line += '@'; + } + line += ' '; + line += ' '; + } + } + Debug( line ); + } + Debug( "" ); +#endif +} + +static PieceRank HelperGetRank(char token) +{ + for ( unsigned int ii=0; ii <= strlen(gPieceCharacters); ++ii ) { + if (gPieceCharacters[ii] == token) { + return (PieceRank)(ii); + } + } + return kUnknown; +} + +/** + * Tokenise a string + */ +static int HelperTokenise(std::vector<string> & buffer, std::string & str, char split = ' ') +{ + buffer.clear(); + string token = ""; + for (unsigned int x = 0; x < str.size(); ++x) + { + if (str[x] == split && token.size() > 0) + { + buffer.push_back(token); + token = ""; + } + if (str[x] != split) + token += str[x]; + } + if (token.size() > 0) + buffer.push_back(token); + return buffer.size(); +} + +/** + * Convert string to integer + */ +static int HelperInteger(std::string & fromStr) +{ + stringstream s(fromStr); + int result = 0; + s >> result; + return result; +} + +/** + * Read in a line from stdin + */ +static void HelperReadLine() +{ + std::string buffer = ""; + for (char c = cin.get(); c != '\n' && cin.good(); c = cin.get()) { + buffer += c; + } + SaveInput( buffer ); + HelperTokenise( gLineBuffer, buffer ); + if ( gLineBuffer.size() == 0 ) { + Log( "No tokens on line" ); + exit( 99 ); + } + if ( gLineBuffer.size() == 0 ) { + Log( "No tokens on line" ); + exit( 99 ); + } + if ( gLineBuffer[0] == "QUIT" || gLineBuffer[0] == "NO_MOVE") { + Log( "QUIT token found" ); + exit( 99 ); + } +} + +static void HelperJunkLine( int lines = 1 ) +{ + while ( lines > 0 ) { + HelperReadLine(); + lines--; + } +} + +enum MoveOutcome { + kMR_OK, + kMR_Kills, + kMR_Dies, + kMR_BothDie +}; + +static void HelperReadMove( StoragePtr storage, PiecePosition& from, PiecePosition& to, MoveOutcome& result, PieceRank& attacker, PieceRank& defender ) +{ + HelperReadLine(); + if ( gLineBuffer.size() < 4 ) { + Log( "Less than 4 tokens" ); + exit( 99 ); + } + from.col = HelperInteger( gLineBuffer[0] ); + from.row = HelperInteger( gLineBuffer[1] ); + int move = HelperInteger( gLineBuffer[3] ); + if ( move == 0 ) { + gLineBuffer.insert( gLineBuffer.begin()+3, "1" ); + move = 1; + } + to = from; + std::string dir = gLineBuffer[2]; + if (dir == "UP") { + to.row -= move; + } else if (dir == "DOWN") { + to.row += move; + } else if (dir == "LEFT") { + to.col -= move; + } else if (dir == "RIGHT") { + to.col += move; + } else { + Log( "DIRECTION ERROR" ); + exit( 99 ); + } + attacker = kUnknown; + defender = kUnknown; + std::string res = gLineBuffer[4]; + if ( res == "ILLEGAL" ) { + Log( "Opponent (hopefully) made ILLEGAL move" ); + exit( 99 ); + } else if ( res == "OK" ) { + result = kMR_OK; + } else { + if ( res == "KILLS" ) { + result = kMR_Kills; + } else if ( res == "DIES" ) { + result = kMR_Dies; + } else if ( res == "BOTHDIE" ) { + result = kMR_BothDie; + } else { + Log( string("Unknown move result ") + res ); + exit( 99 ); + } + attacker = HelperGetRank( gLineBuffer[5][0] ); + defender = HelperGetRank( gLineBuffer[6][0] ); + } + +} + +#ifdef false + +static const char *board_setup_1[4] = { // 1 = Marshal, ..., 9 = Scout, : = Spy, ; = Bomb, < = Flag + "8;<;77;6;7", + "75;586896;", + "6989954893", + "943159:249", +}; + +static const char *bobs_board_setup[4] = { // 1 = Marshal, ..., 9 = Scout, : = Spy, ; = Bomb, < = Flag + "<8;645:1;6", + "8277984893", + ";;5756;7;8", + "9949359969", +}; + +#endif + +static const char *board_setup[4] = { // 1 = Marshal, ..., 9 = Scout, : = Spy, ; = Bomb, < = Flag +// "8;<;67;;77", + "8;<;67;7;7", + "48;3862;89", + "6359954865", + "997159:499", +}; + +static const char *start_piece_counts = "0112344458161"; + +static int dR[4] = { 1, 0, -1, 0 }; +static int dC[4] = { 0, -1, 0, 1 }; + +#if ASSERTIONS + +static void AssertValidBoard( StoragePtr storage ) +{ + int piece; + int count1 = 0; + int count2 = 0; + int row, col; + + for ( piece = kMarshall; piece <= kFlag; piece++ ) { + count1 += storage->their_pieces[piece]; + } + + for ( row = 0; row < kBoardSize; row++ ) { + for( col = 0; col < kBoardSize; col++ ) { + if ( storage->board[row][col].color == storage->theirColor + && storage->board[row][col].rank == kUnknown ) { + count2++; + } + } + } + + Assert( count1 == count2, "count1 == count2" ); +} + +#else + +#define AssertValidBoard( storage ) + +#endif + +static void PositionPieces( + StoragePtr storage, /* 1MB of preinitialized storage for your use */ + PlayerColor playerColor, /* you play red or blue, with red playing first */ + Board *theBoard /* provide the initial position of your pieces */ +) +{ + int row, our_row, their_row, col, board_col; + PlayerColor theirColor; + int piece; + Boolean reverse = (time( NULL ) & 1) != 0; + + Assert( strlen(board_setup[0]) == kBoardSize, "strlen(board_setup[0]) == kBoardSize" ); + Assert( strlen(board_setup[1]) == kBoardSize, "strlen(board_setup[1]) == kBoardSize" ); + Assert( strlen(board_setup[2]) == kBoardSize, "strlen(board_setup[2]) == kBoardSize" ); + Assert( strlen(board_setup[3]) == kBoardSize, "strlen(board_setup[3]) == kBoardSize" ); + + for ( row = 0; row <= 3; row++ ) { + if ( playerColor == kRed ) { + our_row = row; + their_row = (kBoardSize-1)-row; + theirColor = kBlue; + } else { + their_row = row; + our_row = (kBoardSize-1)-row; + theirColor = kRed; + } + for ( col = 0; col < 10; col++ ) { + board_col = reverse ? (kBoardSize-1) - col : col; + (*theBoard)[our_row][col].thePieceRank = (PieceRank) (board_setup[row][board_col] - '0'); + (*theBoard)[our_row][col].thePieceColor = playerColor; + + storage->board[our_row][col].color = playerColor; + storage->board[our_row][col].rank = (*theBoard)[our_row][col].thePieceRank; + storage->board[our_row][col].possibilities = kNoNothing; + + storage->board[their_row][col].color = theirColor; + storage->board[their_row][col].rank = kUnknown; + storage->board[their_row][col].possibilities = kNoNothing; + } + } + + for ( row = 4; row <= 5; row++ ) { + for( col = 0; col < kBoardSize; col++ ) { + storage->board[row][col].color = (PlayerColor)kNoColor; + storage->board[row][col].rank = (PieceRank) ((col/2 % 2 == 1) ? kWater : kEmpty); + storage->board[row][col].possibilities = 0; + } + } + + for ( piece = kMarshall; piece <= kFlag; piece++ ) { + storage->our_pieces[piece] = start_piece_counts[piece] - '0'; + storage->their_pieces[piece] = start_piece_counts[piece] - '0'; + } + + storage->do_getmove = (playerColor == kBlue); + storage->victory = false; + storage->blankSquare = storage->board[4][0]; + storage->playerColor = playerColor; + storage->theirColor = playerColor == kRed ? kBlue : kRed; + storage->repeated_board_count = 0; + + AssertValidBoard( storage ); +} + +static void Learn( StoragePtr storage, Boolean them, int row, int col, PieceRank rank ) +{ + Boolean gotall; + PlayerColor thiscolor; + int r, c; + + if ( storage->board[row][col].rank == kUnknown ) { + + if ( rank == kMoved ) { + UInt32 possibilities = storage->board[row][col].possibilities; + possibilities &= ~kStationaryBits; + + if ( (possibilities & (possibilities-1)) == 0 ) { // only one bit on! Now we know! + int newrank; + newrank = 0; + while ( (possibilities & 1) == 0 ) { + possibilities >>= 1; + newrank++; + } + rank = (PieceRank)newrank; + } else { + storage->board[row][col].possibilities = possibilities; + } + } + + if ( rank != kMoved ) { + storage->board[row][col].rank = rank; + storage->board[row][col].possibilities = (1 << rank); + if ( them ) { + gotall = --storage->their_pieces[rank] == 0; + } else { + gotall = --storage->our_pieces[rank] == 0; + } + if ( gotall ) { + thiscolor = storage->board[row][col].color; + for ( r = 0; r < kBoardSize; r++ ) { + for ( c = 0; c < kBoardSize; c++ ) { + if ( storage->board[r][c].rank == kUnknown + && storage->board[r][c].color == thiscolor ) { + UInt32 possibilities = storage->board[r][c].possibilities; + possibilities &= ~ (1 << rank); + storage->board[r][c].possibilities = possibilities; + if ( (possibilities & (possibilities-1)) == 0 ) { // only one bit on! + int newrank; + newrank = 0; + while ( (possibilities & 1) == 0 ) { + possibilities >>= 1; + newrank++; + } + Learn( storage, them, r, c, (PieceRank)newrank ); + } + } + } + } + } + } + } else { + Assert( rank == kMoved || storage->board[row][col].rank == rank, "rank == kMoved || storage->board[row][col].rank == rank" ); + } +} + +static void HandleTheirMove( StoragePtr storage, const PiecePosition moveFrom, const PiecePosition moveTo, Boolean moveStrike, const MoveResult moveResult ) +{ + Assert( moveResult.legalMove, "moveResult.legalMove" ); // They must have made a legal move or we would not be called + Assert( !moveResult.victory, "!moveResult.victory" ); // If they won we would not be called + if ( moveStrike ) { + Learn( storage, true, moveFrom.row, moveFrom.col, moveResult.rankOfAttacker.thePieceRank ); + Learn( storage, false, moveTo.row, moveTo.col, moveResult.rankOfDefender.thePieceRank ); + if ( moveResult.attackerRemoved && moveResult.defenderRemoved ) { + storage->board[moveFrom.row][moveFrom.col] = storage->blankSquare; + storage->board[moveTo.row][moveTo.col] = storage->blankSquare; + } else if ( moveResult.attackerRemoved ) { +// if ( storage->board[moveTo.row][moveTo.col].rank == kBomb ) { + storage->board[moveFrom.row][moveFrom.col] = storage->blankSquare; +// } else { +// storage->board[moveFrom.row][moveFrom.col] = storage->board[moveTo.row][moveTo.col]; +// storage->board[moveTo.row][moveTo.col] = storage->blankSquare; +// } + } else { + Assert( moveResult.defenderRemoved, "moveResult.defenderRemoved" ); + storage->board[moveTo.row][moveTo.col] = storage->board[moveFrom.row][moveFrom.col]; + storage->board[moveFrom.row][moveFrom.col] = storage->blankSquare; + } + } else { + storage->board[moveTo.row][moveTo.col] = storage->board[moveFrom.row][moveFrom.col]; + storage->board[moveFrom.row][moveFrom.col] = storage->blankSquare; + if ( abs(moveTo.row - moveFrom.row) + abs(moveTo.col - moveFrom.col) > 1 ) { + Learn( storage, true, moveTo.row, moveTo.col, kScout ); + } else { + Learn( storage, true, moveTo.row, moveTo.col, (PieceRank)kMoved ); + } + } + + AssertValidBoard( storage ); +} + +static Boolean FindPiece( StoragePtr storage, PlayerColor color, PieceRank rank, int *row, int *col ) +{ + int r, c; + + for ( r = 0; r < kBoardSize; r++ ) { + for( c = 0; c < kBoardSize; c++ ) { + if ( storage->board[r][c].color == color + && storage->board[r][c].rank == rank ) { + *row = r; + *col = c; + return true; + } + } + } + return false; +} + +static Boolean IsOnBoardWeak( int row, int col ) +{ + return 0 <= row && row < kBoardSize && 0 <= col && col < kBoardSize; +} + +static Boolean IsOnBoard( int row, int col ) +{ + if ( 0 <= row && row < kBoardSize && 0 <= col && col < kBoardSize ) { + if ( row <= 3 || row >= 6 ) { + return true; + } + if ( col <= 1 || col >= 8 ) { + return true; + } + if ( 4 <= col && col <= 5 ) { + return true; + } + } + return false; +} + +static Boolean IsColorPiece( StoragePtr storage, int row, int col, PlayerColor color ) +{ + Assert( IsOnBoardWeak( row, col ), "IsOnBoardWeak( row, col )" ); + return storage->board[row][col].color == color; +} + +static Boolean IsOurPiece( StoragePtr storage, int row, int col ) +{ + Assert( IsOnBoardWeak( row, col ), "IsOnBoardWeak( row, col )" ); + return storage->board[row][col].color == storage->playerColor; +} + +static Boolean IsTheirPiece( StoragePtr storage, int row, int col ) +{ + Assert( IsOnBoardWeak( row, col ), "IsOnBoardWeak( row, col )" ); + return storage->board[row][col].color == storage->theirColor; +} + +static Boolean IsUnknownPiece( StoragePtr storage, int row, int col ) +{ + Assert( IsOnBoardWeak( row, col ), "IsOnBoardWeak( row, col )" ); + return storage->board[row][col].rank == kUnknown; +} + +static Boolean IsRankPiece( StoragePtr storage, int row, int col, PieceRank rank ) +{ + Assert( IsOnBoardWeak( row, col ), "IsOnBoardWeak( row, col )" ); + return storage->board[row][col].rank == rank; +} + +static Boolean IsEmptySquare( StoragePtr storage, int row, int col ) +{ + Assert( IsOnBoardWeak( row, col ), "IsOnBoardWeak( row, col )" ); + return storage->board[row][col].rank == (PieceRank)kEmpty; +} + +static Boolean IsWaterSquare( StoragePtr storage, int row, int col ) +{ + Assert( IsOnBoardWeak( row, col ), "IsOnBoardWeak( row, col )" ); + return storage->board[row][col].rank == (PieceRank)kWater; +} + +static Boolean IsLowlyRank( PieceRank rank ) +{ + return kCaptain <= rank && rank <= kScout && rank != kMiner; +} + +static Boolean IsLowlyPiece( StoragePtr storage, int row, int col ) +{ + Assert( IsOnBoard( row, col ), "IsOnBoard( row, col )" ); + return IsLowlyRank( storage->board[row][col].rank ); +} + +static Boolean IsMovedPiece( StoragePtr storage, int row, int col ) +{ + Assert( IsOnBoard( row, col ), "IsOnBoard( row, col )" ); + return (storage->board[row][col].possibilities & kStationaryBits) == 0; +} + +static Boolean IsRevealedPiece( StoragePtr storage, int row, int col ) +{ + Assert( IsOnBoard( row, col ), "IsOnBoard( row, col )" ); + Assert( IsOurPiece( storage, row, col ), "IsOurPiece( storage, row, col )" ); + UInt32 possibilities = storage->board[row][col].possibilities; + return ( (possibilities & (possibilities-1)) == 0 ); +} + +static int CountAdjacentUnknownPieces( StoragePtr storage, PlayerColor color, int row, int col ) +{ + int d; + int unknowns = 0; + + for ( d = 0; d < 4; d++ ) { + int r = row + dR[d]; + int c = col + dC[d]; + + if ( IsOnBoard( r, c ) && IsColorPiece( storage, r, c, color ) && IsUnknownPiece( storage, r, c ) ) { + unknowns++; + } + } + + return unknowns; +} + +static const char *defend_spy_table = "RARROAOORARRRARRXAXAOAOOXAXAXAXA"; +// Run/Attack/Other/Nothing, >1 unknown:other:danger:moved + +static Boolean LowlyCanAttack( StoragePtr storage, int row, int col, int *otherRow, int *otherCol ) +{ + for ( int d = 0; d < 4; d++ ) { + int r = row + dR[d]; + int c = col + dC[d]; + + if ( IsOnBoard( r, c ) + && IsOurPiece( storage, r, c ) + && IsLowlyPiece( storage, r, c ) ) { + *otherRow = r; + *otherCol = c; + return true; + } + } + return false; +} + +static void UpdateDangerPossibilities( StoragePtr storage ) +{ + int row, col; + + for ( row = 0; row < kBoardSize; row++ ) { + for( col = 0; col < kBoardSize; col++ ) { + storage->dangers[row][col] = 0; + storage->known_dangers[row][col] = 0; + } + } + + for ( row = 0; row < kBoardSize; row++ ) { + for( col = 0; col < kBoardSize; col++ ) { + if ( IsTheirPiece( storage, row, col ) ) { + UInt32 possibilities = (storage->board[row][col].possibilities & ~kStationaryBits); + UInt32 known_possibilities = 0; + + if ( storage->board[row][col].rank != kUnknown ) { + known_possibilities = possibilities; + } + + for ( int d = 0; d < 4; d++ ) { + int r = row + dR[d]; + int c = col + dC[d]; + + if ( IsOnBoard( r, c ) ) { + storage->dangers[r][c] |= possibilities; + storage->known_dangers[r][c] |= known_possibilities; + } + } + + } + } + } + +} + +static UInt32 GetDangerPossibilities( StoragePtr storage, int row, int col ) +{ + Assert( IsOnBoard( row, col ), "IsOnBoard( row, col )" ); + return storage->dangers[row][col]; +} + +static Boolean PossibilitiesCouldKill( PieceRank rank, UInt32 possibilities ) +{ + if ( (possibilities & ~kStationaryBits) == 0 ) { + return false; + } + + switch ( rank ) { + case kFlag: + return true; + case kBomb: + return (possibilities & (1 << kMiner)) != 0; + case kMarshall: + return (possibilities & ((1 << kMarshall) + (1<< kSpy))) != 0; + default: + return (possibilities & ((1 << (rank+1)) - 1)) != 0; + } +} + +static Boolean PossibilitiesCouldKillSafely( PieceRank rank, UInt32 possibilities ) +{ + if ( (possibilities & ~kStationaryBits) == 0 ) { + return false; + } + + switch ( rank ) { + case kFlag: + return true; + case kBomb: + return (possibilities & (1 << kMiner)) != 0; + case kMarshall: + return (possibilities & ((1<< kSpy))) != 0; + default: + return (possibilities & ((1 << rank) - 1)) != 0; + } +} + +static Boolean WillKillPossibilities( PieceRank rank, UInt32 possibilities ) +{ + Assert( possibilities != 0, "possibilities != 0" ); + + switch ( rank ) { + case kFlag: + return false; + case kBomb: + return false; + case kMiner: + return (possibilities & ~((1 << kScout) + (1 << kBomb) + (1 << kFlag))) == 0; + case kSpy: + return (possibilities & ~(1 << kMarshall)) == 0; + default: + return (possibilities & (((1 << (rank + 1)) - 1) + (1 << kBomb))) == 0; + } +} + +static Boolean WillKillOrSuicidePossibilities( PieceRank rank, UInt32 possibilities ) +{ + Assert( possibilities != 0, "possibilities != 0" ); + + switch ( rank ) { + case kFlag: + return false; + case kBomb: + return false; + case kMiner: + return (possibilities & ~((1 << kScout) + (1 << kMiner) + (1 << kBomb) + (1 << kFlag))) == 0; + case kSpy: + return (possibilities & ~((1 << kMarshall) + (1 << kSpy))) == 0; + default: + return (possibilities & (((1 << rank) - 1) + (1 << kBomb))) == 0; + } +} + +static Boolean WillPossibilitiesKill( UInt32 possibilities, PieceRank rank ) +{ + Assert( possibilities != 0, "possibilities != 0" ); + possibilities &= ~kStationaryBits; + if ( possibilities == 0 ) { + return false; + } + + switch ( rank ) { + case kFlag: + return true; + case kBomb: + return possibilities == (1 << kMiner); + default: + return (possibilities & ~((1 << (rank+1))-1)) == 0; + } +} + +static Boolean FindSafeSquare( StoragePtr storage, int row, int col, int *safeRow, int *safeCol ) +{ + Assert( IsOnBoard( row, col ), "IsOnBoard( row, col )" ); + + PieceRank rank = storage->board[row][col].rank; + int doff = (storage->playerColor == kBlue ? 0 : 2); // Try backwards first + + for ( int d = 0; d < 4; d++ ) { + int dr = dR[(d + doff) % 4]; + int dc = dC[(d + doff) % 4]; + int r = row + dr; + int c = col + dc; + + while ( IsOnBoard( r, c ) && IsEmptySquare( storage, r, c ) ) { + if ( !PossibilitiesCouldKill( rank, GetDangerPossibilities( storage, r, c ) ) ) { + *safeRow = r; + *safeCol = c; + return true; + } + if ( rank != kScout ) { + break; + } + r += dr; + c += dc; + } + } + return false; +} + +static void CountEnemies( StoragePtr storage, int row, int col, int *knowns, int *unknowns ) +{ + *knowns = 0; + *unknowns = 0; + + for ( int d = 0; d < 4; d++ ) { + int r = row + dR[d]; + int c = col + dC[d]; + + if ( IsOnBoard( r, c ) && IsTheirPiece( storage, r, c ) ) { + if ( storage->board[r][c].rank == kUnknown ) { + *unknowns += 1; + } else { + *knowns += 1; + } + } + } +} + +/* +static Boolean CanRun( StoragePtr storage, int row, int col, int *runRow, int *runCol ) +{ + for ( int d = 0; d < 4; d++ ) { + int r = row + dR[(d + (storage->playerColor == kBlue ? 0 : 2)) % 4]; // Try backwards first + int c = col + dC[(d + (storage->playerColor == kBlue ? 0 : 2)) % 4]; + + if ( IsOnBoard( r, c ) && (storage->board[r][c].rank == kEmpty) ) { + *runRow = r; + *runCol = c; + return true; + } + } + return false; +} +*/ + +static Boolean FindSafePath( StoragePtr storage, Boolean very_safe, Boolean suicide_ok, int from_row, int from_col, int to_row, int to_col, int *best_path, int *first_row, int *first_col ) +{ + Assert( IsOurPiece( storage, from_row, from_col ), "IsOurPiece( storage, from_row, from_col )" ); + + PieceRank rank = storage->board[from_row][from_col].rank; + BoardPossibilities *dangers = very_safe ? &storage->dangers : &storage->known_dangers; + + if ( abs( from_row - to_row ) + abs( from_col - to_col ) > *best_path ) { + return false; + } + + if ( abs( from_row - to_row ) + abs( from_col - to_col ) == 1 ) { + *best_path = 0; + *first_row = to_row; + *first_col = to_col; + return true; + } + + int path_length_to[kBoardSize][kBoardSize]; + PiecePosition que[kBoardSize * kBoardSize]; + int que_start = 0; + int que_fin = 0; + int que_next_len = 0; + int current_len = 0; + int row, col; + + for ( row = 0; row < kBoardSize; row++ ) { + for( col = 0; col < kBoardSize; col++ ) { + path_length_to[row][col] = -1; + } + } + + que[que_fin].row = from_row; + que[que_fin].col = from_col; + path_length_to[from_row][from_col] = 0; + que_fin++; + que_next_len = que_fin; + + while ( que_fin > que_start ) { + row = que[que_start].row; + col = que[que_start].col; + que_start++; + + for ( int d = 0; d < 4; d++ ) { + int dr = dR[d]; + int dc = dC[d]; +// scout moves NYI + int r = row + dr; + int c = col + dc; + + if ( IsOnBoard( r, c ) && path_length_to[r][c] == -1 + && IsEmptySquare( storage, r, c ) ) { + if ( suicide_ok + ? !PossibilitiesCouldKillSafely( rank, (*dangers)[r][c] ) + : !PossibilitiesCouldKill( rank, (*dangers)[r][c] ) ) { + path_length_to[r][c] = current_len + 1; + if ( abs( to_row - r ) + abs( to_col - c ) == 1 ) { + *best_path = current_len + 1; + while ( current_len > 0 ) { + for ( int d = 0; d < 4; d++ ) { + int backr = r + dR[d]; + int backc = c + dC[d]; + + if ( path_length_to[backr][backc] == current_len ) { + r = backr; + c = backc; + break; + } + } + current_len--; + } + *first_row = r; + *first_col = c; + return true; + } + que[que_fin].row = r; + que[que_fin].col = c; + que_fin++; + } else { + path_length_to[r][c] = 1000; // Cant go here + } + } + } + + if ( que_start == que_next_len ) { + que_next_len = que_fin; + current_len++; + } + } + + return false; +} + +static UInt32 CalcBoardCRC( StoragePtr storage, int from_row, int from_col, int to_row, int to_col ) +{ + Assert( !IsOnBoard( from_row, from_col ) || IsOurPiece( storage, from_row, from_col ), "!IsOnBoard( from_row, from_col ) || IsOurPiece( storage, from_row, from_col )" ); + Assert( !IsOnBoard( to_row, to_col ) || IsEmptySquare( storage, to_row, to_col ), "!IsOnBoard( to_row, to_col ) || IsEmptySquare( storage, to_row, to_col )" ); + + UInt32 result = 0; + + int row, col; + int rankish; + + for ( row = 0; row < kBoardSize; row++ ) { + for( col = 0; col < kBoardSize; col++ ) { + if ( row == from_row && col == from_col ) { + rankish = 0; + } else if ( row == to_row && col == to_col ) { + rankish = storage->board[from_row][from_col].rank; + } else if ( IsEmptySquare( storage, row, col ) || IsWaterSquare( storage, row, col ) ) { + rankish = 0; + } else if ( IsOurPiece( storage, row, col ) ) { + rankish = storage->board[row][col].rank; + } else { + rankish = storage->board[row][col].rank + kAddForRankish; + } + result += rankish; // Hmm, not a very good CRC + result = result * 11 + (result >> 25); + } + } + + return result; +} + +static Boolean OKMove( StoragePtr storage, int from_row, int from_col, int to_row, int to_col ) +{ + if ( IsTheirPiece( storage, to_row, to_col ) ) { + return true; + } + + UInt32 crc = CalcBoardCRC( storage, from_row, from_col, to_row, to_col ); + for ( UInt32 i = 0; i < storage->repeated_board_count; i++ ) { + if ( crc == storage->repeated_board[i] ) { + return false; + } + } + return true; +} + +static void AppendRepeatedBoard( StoragePtr storage ) +{ + UInt32 crc = CalcBoardCRC( storage, -1, -1, -1, -1 ); + + if ( storage->repeated_board_count == kRepeatedBoards ) { + storage->repeated_board_count--; + memcpy( &storage->repeated_board[0], &storage->repeated_board[1], storage->repeated_board_count * sizeof(storage->repeated_board[0]) ); + } + storage->repeated_board[storage->repeated_board_count++] = crc; +} + +#if DEBUG_RULES + #define RETURN( x ) Log( x ); return +#else + #define RETURN( x ) return +#endif + +static void FigureOutOurMove( StoragePtr storage, PiecePosition *moveFrom, PiecePosition *moveTo ) +{ + int ourRow, ourCol, theirRow, theirCol, row, col, runRow, runCol; + int rowFirst = storage->playerColor == kRed ? 0 : kBoardSize - 1; + int rowLast = storage->playerColor == kRed ? kBoardSize - 1 : 0; + int rowAdd = storage->playerColor == kRed ? 1 : -1; + int bestUnknowns; + int bestPath; + int thisPath; + + UpdateDangerPossibilities( storage ); + +// USE SPY + if ( FindPiece( storage, storage->theirColor, kMarshall, &theirRow, &theirCol ) + && FindPiece( storage, storage->playerColor, kSpy, &ourRow, &ourCol ) + && abs( theirRow - ourRow ) + abs( theirCol - ourCol ) == 1 ) { + moveFrom->row = ourRow; + moveFrom->col = ourCol; + moveTo->row = theirRow; + moveTo->col = theirCol; + RETURN( "USE SPY" ); + } + +// DEFEND AGAINST SPY + if (storage->their_pieces[kSpy] > 0) { + if ( FindPiece( storage, storage->playerColor, kMarshall, &ourRow, &ourCol ) ) { + int unknowns = CountAdjacentUnknownPieces( storage, storage->theirColor, ourRow, ourCol ); + + if ( unknowns ) { + int base_index = 0; + Boolean canrun = FindSafeSquare( storage, ourRow, ourCol, &runRow, &runCol ); + if ( !canrun ) { + base_index += 16; + } + if ( unknowns > 1 ) { + base_index += 8; + } + + for ( int d = 0; d < 4; d++ ) { + int r = ourRow + dR[d]; + int c = ourCol + dC[d]; + int otherRow, otherCol; + + if ( IsOnBoard( r, c ) + && IsTheirPiece( storage, r, c ) + && IsUnknownPiece( storage, r, c ) ) { + int index = base_index; + if ( LowlyCanAttack( storage, r, c, &otherRow, &otherCol ) ) { + index += 4; + } + if ( CountAdjacentUnknownPieces( storage, storage->theirColor, r, c ) > 0 ) { + index += 2; + } + if ( IsMovedPiece( storage, r, c ) ) { + index += 1; + } + + if ( defend_spy_table[index] == 'A' ) { // Attack + moveFrom->row = ourRow; + moveFrom->col = ourCol; + moveTo->row = r; + moveTo->col = c; + RETURN( "DEFEND AGAINST SPY 1" ); + } else if ( defend_spy_table[index] == 'O' ) { // Attack + moveFrom->row = otherRow; + moveFrom->col = otherCol; + moveTo->row = r; + moveTo->col = c; + RETURN( "DEFEND AGAINST SPY 2" ); + } + } + } + + if ( canrun && OKMove( storage, ourRow, ourCol, runRow, runCol ) ) { + moveFrom->row = ourRow; + moveFrom->col = ourCol; + moveTo->row = runRow; + moveTo->col = runCol; + RETURN( "DEFEND AGAINST SPY 3" ); + } + // Give up! Next ruleÉ + } + } + } + +// ATTACK WEAKER + for ( row = rowFirst; 0 <= row && row < kBoardSize; row += rowAdd ) { + for( col = 0; col < kBoardSize; col++ ) { + if ( IsTheirPiece( storage, row, col ) ) { + UInt32 enemy = storage->board[row][col].possibilities; + UInt32 danger = GetDangerPossibilities( storage, row, col ); + + int bestDir = -1; + Boolean isBestRevealed = true; + PieceRank bestRank = kUnknown; + + for ( int d = 0; d < 4; d++ ) { + int r = row + dR[d]; + int c = col + dC[d]; + + if ( IsOnBoard( r, c ) && IsOurPiece( storage, r, c ) ) { + if ( !PossibilitiesCouldKill( storage->board[r][c].rank, danger ) ) { + if ( WillKillPossibilities( storage->board[r][c].rank, enemy ) ) { + Boolean thisRevealed = IsRevealedPiece( storage, r, c ); + if ( isBestRevealed || !thisRevealed ) { + if ( bestDir == -1 || (storage->board[r][c].rank > bestRank) ) { + bestDir = d; + bestRank = storage->board[r][c].rank; + isBestRevealed = thisRevealed; + } + } + } + } + } + } + if ( bestDir != -1 ) { + moveFrom->row = row + dR[bestDir]; + moveFrom->col = col + dC[bestDir]; + moveTo->row = row; + moveTo->col = col; + RETURN( "ATTACK WEAKER" ); + } + } + } + } + +// EXPLORE ATTACK + for ( int rnk = kScout; rnk >= kMarshall; rnk-- ) { + PieceRank rank = (PieceRank) rnk; + if ( IsLowlyRank( rank ) ) { + + for ( row = rowLast; 0 <= row && row < kBoardSize; row -= rowAdd ) { + for( col = 0; col < kBoardSize; col++ ) { + if ( IsOurPiece( storage, row, col ) + && IsRankPiece( storage, row, col, rank ) ) { + + for ( int d = 0; d < 4; d++ ) { + int r = row + dR[d]; + int c = col + dC[d]; + + if ( IsOnBoard( r, c ) + && IsTheirPiece( storage, r, c ) + && IsRankPiece( storage, r, c, kUnknown ) ) { + moveFrom->row = row; + moveFrom->col = col; + moveTo->row = r; + moveTo->col = c; + RETURN( "EXPLORE ATTACK" ); + } + } + } + } + } + + } + } + +// RETREAT + for ( row = rowLast; 0 <= row && row < kBoardSize; row -= rowAdd ) { + for( col = 0; col < kBoardSize; col++ ) { + if ( IsOurPiece( storage, row, col ) + && IsMovedPiece( storage, row, col ) ) { + + for ( int d = 0; d < 4; d++ ) { + int r = row + dR[d]; + int c = col + dC[d]; + + if ( IsOnBoard( r, c ) + && IsTheirPiece( storage, r, c ) + && WillPossibilitiesKill( storage->board[r][c].possibilities, storage->board[row][col].rank ) ) { + bestPath = 1000; + for ( int to_row = rowLast; 0 <= to_row && to_row < kBoardSize; to_row -= rowAdd ) { + for( int to_col = 0; to_col < kBoardSize; to_col++ ) { + thisPath = bestPath; + if ( IsTheirPiece( storage, to_row, to_col ) + && (IsRankPiece( storage, to_row, to_col, kUnknown ) + || WillKillPossibilities( storage->board[row][col].rank, storage->board[to_row][to_col].possibilities )) + && FindSafePath( storage, false, true, row, col, to_row, to_col, &thisPath, &runRow, &runCol ) + && OKMove( storage, row, col, runRow, runCol ) ) { + bestPath = thisPath; + moveFrom->row = row; + moveFrom->col = col; + moveTo->row = runRow; + moveTo->col = runCol; + } + } + } + if ( bestPath < 1000 ) { + RETURN( "RETREAT" ); + } + } + } + } + } + } + +// SCOUT + bestUnknowns = 0; + + for ( row = rowLast; 0 <= row && row < kBoardSize; row -= rowAdd ) { + for( col = 0; col < kBoardSize; col++ ) { + if ( IsOurPiece( storage, row, col ) + && IsRankPiece( storage, row, col, kScout ) ) { + for ( int d = 0; d < 4; d++ ) { + int r = row + dR[d]; + int c = col + dC[d]; + + while ( IsOnBoard( r, c ) && IsEmptySquare( storage, r, c ) ) { + + int knowns, unknowns; + CountEnemies( storage, r, c, &knowns, &unknowns ); + if ( knowns == 0 && unknowns > bestUnknowns && OKMove( storage, row, col, r, c ) ) { + bestUnknowns = unknowns; + ourRow = row; + ourCol = col; + runRow = r; + runCol = c; + } + r += dR[d]; + c += dC[d]; + } + } + } + } + } + + if ( bestUnknowns > 0 ) { + moveFrom->row = ourRow; + moveFrom->col = ourCol; + moveTo->row = runRow; + moveTo->col = runCol; + RETURN( "SCOUT" ); + } + +// ATTACK DISTANT + + bestPath = 1000; + + for ( row = rowFirst; 0 <= row && row < kBoardSize; row += rowAdd ) { + for( col = 0; col < kBoardSize; col++ ) { + if ( IsTheirPiece( storage, row, col ) ) { + UInt32 possibilities = storage->board[row][col].possibilities; + UInt32 danger = GetDangerPossibilities( storage, row, col ); + + if ( (possibilities & ((1 << kBomb) | (1 << kMarshall))) != ((1 << kBomb) | (1 << kMarshall)) ) { + for ( int r = rowFirst; 0 <= r && r < kBoardSize; r += rowAdd ) { + for( int c = 0; c < kBoardSize; c++ ) { + if ( IsOurPiece( storage, r, c ) ) { + if ( WillKillPossibilities( storage->board[r][c].rank, possibilities ) ) { + if ( storage->board[r][c].rank >= kCaptain || !PossibilitiesCouldKill( storage->board[r][c].rank, danger ) ) { + thisPath = bestPath; + if ( FindSafePath( storage, true, false, r, c, row, col, &thisPath, &runRow, &runCol ) ) { + if ( OKMove( storage, r, c, runRow, runCol ) ) { + bestPath = thisPath; + moveFrom->row = r; + moveFrom->col = c; + moveTo->row = runRow; + moveTo->col = runCol; + } + } + } + } + } + } + } + } + + } + } + } + + if ( bestPath < 1000 ) { + RETURN( "ATTACK DISTANT" ); + } + +// EXPLORE DISTANT + + bestPath = 1000; + + for ( row = rowFirst; 0 <= row && row < kBoardSize; row += rowAdd ) { + for( col = 0; col < kBoardSize; col++ ) { + if ( IsTheirPiece( storage, row, col ) && storage->board[row][col].rank == kUnknown ) { + + for ( int r = rowFirst; 0 <= r && r < kBoardSize; r += rowAdd ) { + for( int c = 0; c < kBoardSize; c++ ) { + if ( IsOurPiece( storage, r, c ) && IsLowlyPiece( storage, r, c ) ) { + thisPath = bestPath; + if ( FindSafePath( storage, false, true, r, c, row, col, &thisPath, &runRow, &runCol ) ) { + if ( OKMove( storage, r, c, runRow, runCol ) ) { + bestPath = thisPath; + moveFrom->row = r; + moveFrom->col = c; + moveTo->row = runRow; + moveTo->col = runCol; + } + } + } + } + } + + } + } + } + + if ( bestPath < 1000 ) { + RETURN( "EXPLORE DISTANT" ); + } + +// ATTACK KNOWN WITH SAME DISTANT + + bestPath = 1000; + + for ( row = rowFirst; 0 <= row && row < kBoardSize; row += rowAdd ) { + for( col = 0; col < kBoardSize; col++ ) { + if ( IsTheirPiece( storage, row, col ) ) { + UInt32 possibilities = storage->board[row][col].possibilities; + + if ( (possibilities & ((1 << kBomb) | (1 << kMarshall))) != ((1 << kBomb) | (1 << kMarshall)) ) { + for ( int r = rowFirst; 0 <= r && r < kBoardSize; r += rowAdd ) { + for( int c = 0; c < kBoardSize; c++ ) { + if ( IsOurPiece( storage, r, c ) ) { + if ( WillKillOrSuicidePossibilities( storage->board[r][c].rank, possibilities ) ) { + thisPath = bestPath; + if ( FindSafePath( storage, true, true, r, c, row, col, &thisPath, &runRow, &runCol ) ) { + if ( OKMove( storage, r, c, runRow, runCol ) ) { + bestPath = thisPath; + moveFrom->row = r; + moveFrom->col = c; + moveTo->row = runRow; + moveTo->col = runCol; + } + } + } + } + } + } + } + + } + } + } + + if ( bestPath < 1000 ) { + RETURN( "ATTACK KNOWN WITH SAME DISTANT" ); + } + +// FIND FLAG +// NYI + +// MOVE FORWARD + + for ( row = rowLast; 0 <= row && row < kBoardSize; row -= rowAdd ) { + for( col = 0; col < kBoardSize; col++ ) { + if ( IsOurPiece( storage, row, col ) ) { + PieceRank rank = storage->board[row][col].rank; + if ( rank != kBomb && rank != kFlag ) { + int r = row + rowAdd; + if ( IsOnBoard( r, col ) && !IsOurPiece( storage, r, col ) && OKMove( storage, row, col, r, col ) ) { + moveFrom->row = row; + moveFrom->col = col; + moveTo->row = r; + moveTo->col = col; + RETURN( "MOVE FORWARD" ); + } + } + } + } + } + +// MOVE + + for ( row = rowLast; 0 <= row && row < kBoardSize; row -= rowAdd ) { + for( col = 0; col < kBoardSize; col++ ) { + if ( IsOurPiece( storage, row, col ) ) { + PieceRank rank = storage->board[row][col].rank; + if ( rank != kBomb && rank != kFlag ) { + + for ( int d = 0; d < 4; d++ ) { + int r = row + dR[d]; + int c = col + dC[d]; + + if ( IsOnBoard( r, c ) && !IsOurPiece( storage, r, c ) && OKMove( storage, row, col, r, c ) ) { + moveFrom->row = row; + moveFrom->col = col; + moveTo->row = r; + moveTo->col = c; + RETURN( "MOVE" ); + } + } + } + } + } + } + +// RESIGN + moveFrom->row = -1; + moveFrom->col = -1; + moveTo->row = -1; + moveTo->col = -1; + RETURN( "RESIGN" ); + +} + +static void HandleOurMove( StoragePtr storage, PiecePosition moveFrom, PiecePosition moveTo, const MoveResult moveResult ) +{ + Boolean moveStrike; + + if ( IsOnBoard( moveTo.row, moveTo.col ) ) { + moveStrike = storage->board[moveTo.row][moveTo.col].color != kNoColor; + } else { + moveStrike = false; + } + + if ( moveResult.victory ) { // We Win! :-) + storage->victory = true; + } else if ( !moveResult.legalMove ) { // We Lose! :-( + } else { + if ( moveStrike ) { + storage->repeated_board_count = 0; + Learn( storage, true, moveTo.row, moveTo.col, moveResult.rankOfDefender.thePieceRank ); + Learn( storage, false, moveFrom.row, moveFrom.col, moveResult.rankOfAttacker.thePieceRank ); + + if ( moveResult.attackerRemoved && moveResult.defenderRemoved ) { + storage->board[moveFrom.row][moveFrom.col] = storage->blankSquare; + storage->board[moveTo.row][moveTo.col] = storage->blankSquare; + } else if ( moveResult.attackerRemoved ) { +// if ( storage->board[moveTo.row][moveTo.col].rank == kBomb ) { + storage->board[moveFrom.row][moveFrom.col] = storage->blankSquare; +// } else { +// storage->board[moveFrom.row][moveFrom.col] = storage->board[moveTo.row][moveTo.col]; +// storage->board[moveTo.row][moveTo.col] = storage->blankSquare; +// } + } else { + Assert( moveResult.defenderRemoved, "moveResult.defenderRemoved" ); + storage->board[moveTo.row][moveTo.col] = storage->board[moveFrom.row][moveFrom.col]; + storage->board[moveFrom.row][moveFrom.col] = storage->blankSquare; + } + + } else { + if ( abs( moveTo.row - moveFrom.row ) + abs( moveTo.col - moveFrom.col ) > 1 ) { + Assert( storage->board[moveFrom.row][moveFrom.col].rank == kScout, "storage->board[moveFrom.row][moveFrom.col].rank == kScout" ); + Learn( storage, false, moveFrom.row, moveFrom.col, kScout ); + } else { + Learn( storage, false, moveFrom.row, moveFrom.col, (PieceRank)kMoved ); + } + storage->board[moveTo.row][moveTo.col] = storage->board[moveFrom.row][moveFrom.col]; + storage->board[moveFrom.row][moveFrom.col] = storage->blankSquare; + } + AppendRepeatedBoard( storage ); + } + + AssertValidBoard( storage ); +} + +/* +Boolean MakeAMove( + StoragePtr storage, / * 1MB of storage from PositionPieces * / + PlayerColor playerColor, / * you play red or blue, with red playing first * / + GetOpponentMove *GetMove, / * callback used to find about opponents last move * / + ReportYourMove *ReportMove / * callback used to make a move * / +) +{ + if ( storage->do_getmove ) { + HandleTheirMove( storage, *GetMove ); + } + storage->do_getmove = true; + + HandleOurMove( storage, *ReportMove ); + + return storage->victory; +} +*/ + +// Code to map UCC Challenge to MacTech Challenge + +static PlayerColor ReadPlayerLine() +{ + HelperReadLine(); + + std::string colourStr = gLineBuffer[0]; + + if ( colourStr == "RED" ) { + return kRed; + } else if ( colourStr == "BLUE" ) { + return kBlue; + } else { + Log( string("What color? ") + colourStr ); + exit( 99 ); + } +} + +static PlayerColor OtherPlayerColor( PlayerColor player ) +{ + return (player == kRed) ? kBlue : kRed; +} + +int main(int argc, char ** argv) +{ + srand(time(NULL)); + cin.rdbuf()->pubsetbuf(NULL, 0); + cout.rdbuf()->pubsetbuf(NULL, 0); + cout.setf(std::ios::unitbuf); +#if SAVE_OUTPUT + gOutputFile.open( (string("/tmp/peternlewis-output-") + to_string(time( NULL )) + "-" + to_string(rand() & 0xFFFF) + ".log").c_str() ); + gOutputFile.setf(std::ios::unitbuf); +#endif + + Storage storage; + Board board; + + PlayerColor player = ReadPlayerLine(); + + PositionPieces( &storage, player, &board ); + if ( player == kRed ) { + for ( int r = 0; r <= 3; r++ ) { + string line; + for ( int c = 0; c < kBoardSize; c++ ) { + line += gPieceCharacters[board[r][c].thePieceRank]; + } + Output( line ); + } + } else { + for ( int r = kBoardSize - 4; r < kBoardSize; r++ ) { + string line; + for ( int c = 0; c < kBoardSize; c++ ) { + line += gPieceCharacters[board[r][c].thePieceRank]; + } + Output( line ); + } + } + + bool expectStart = (player == kRed); + while ( 1 ) { + Debug( "LOOP" ); + if ( expectStart ) { + HelperReadLine(); + expectStart = false; + } else { + PiecePosition from; + PiecePosition to; + MoveOutcome result; + PieceRank attacker; + PieceRank defender; + HelperReadMove( &storage, from, to, result, attacker, defender ); + Debug( to_string(from.col) + "," + to_string(from.row) + " -> " + to_string(to.col) + "," + to_string(to.row) ); + MoveResult moveResult; + moveResult.rankOfAttacker.thePieceRank = attacker; + moveResult.rankOfAttacker.thePieceColor = OtherPlayerColor( player ); + moveResult.rankOfDefender.thePieceRank = defender; + moveResult.rankOfDefender.thePieceColor = player; + moveResult.attackerRemoved = (result == kMR_Dies) || (result == kMR_BothDie); + moveResult.defenderRemoved = (result == kMR_Kills) || (result == kMR_BothDie); + moveResult.victory = false; + moveResult.legalMove = true; + HandleTheirMove( &storage, from, to, (result != kMR_OK), moveResult ); + } + HelperJunkLine( kBoardSize ); + DumpBoard( &storage ); + + PiecePosition moveFrom; + PiecePosition moveTo; + + FigureOutOurMove( &storage, &moveFrom, &moveTo ); + Debug( to_string(moveFrom.col) + ',' + to_string(moveFrom.row) + " -> " + to_string(moveTo.col) + ',' + to_string(moveTo.row) ); + if ( moveFrom.row < 0 ) { + Output( "SURRENDER" ); + exit(EXIT_SUCCESS); + } + std::string dir; + int move; + if ( moveTo.col > moveFrom.col ) { + dir = "RIGHT"; + move = moveTo.col - moveFrom.col; + } else if ( moveTo.col < moveFrom.col ) { + dir = "LEFT"; + move = moveFrom.col - moveTo.col; + } else if ( moveTo.row < moveFrom.row ) { + dir = "UP"; + move = moveFrom.row - moveTo.row; + } else if ( moveTo.row > moveFrom.row ) { + dir = "DOWN"; + move = moveTo.row - moveFrom.row; + } + Output( to_string(moveFrom.col) + ' ' + to_string(moveFrom.row) + ' ' + dir + ' ' + to_string(move) ); + { + PiecePosition from; + PiecePosition to; + MoveOutcome result; + PieceRank attacker; + PieceRank defender; + HelperReadMove( &storage, from, to, result, attacker, defender ); + MoveResult moveResult; + moveResult.rankOfAttacker.thePieceRank = attacker; + moveResult.rankOfAttacker.thePieceColor = player; + moveResult.rankOfDefender.thePieceRank = defender; + moveResult.rankOfDefender.thePieceColor = OtherPlayerColor( player ); + moveResult.attackerRemoved = (result == kMR_Dies) || (result == kMR_BothDie); + moveResult.defenderRemoved = (result == kMR_Kills) || (result == kMR_BothDie); + moveResult.victory = false; + moveResult.legalMove = true; + HandleOurMove( &storage, from, to, moveResult ); + DumpBoard( &storage ); + } + } + + exit(EXIT_SUCCESS); + return 0; +} diff --git a/agents/peternlewis/peternlewis.h b/agents/peternlewis/peternlewis.h new file mode 100755 index 0000000..9b12e8c --- /dev/null +++ b/agents/peternlewis/peternlewis.h @@ -0,0 +1,71 @@ +#ifndef __LL_CHALLENGE__ +#define __LL_CHALLENGE__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define kBoardSize 10 + +typedef enum { kUnknown=0, + kMarshall=1,kGeneral,kColonel,kMajor,kCaptain, + kLieutenant,kSergeant,kMiner,kScout,kSpy, + kBomb,kFlag, + + kEmpty, + kWater, + kMoved, // fake rank for moved pieces + kAddForRankish // add this in for enemies when calculating the CRC +} PieceRank; + +#define kPieceCharacters "0123456789sBF.+MA" + +typedef enum {kNoColor, kRed, kBlue} PlayerColor; + +typedef struct PieceType { + PieceRank thePieceRank; /* rank of a piece */ + PlayerColor thePieceColor; /* color of a piece */ +} PieceType; + +typedef PieceType Board[kBoardSize][kBoardSize]; +/* Used to provide test code with board configuration. Red starts + in rows 0..3, Blue starts in rows 6..9 */ +/* Squares [4][2], [4][3], [4][6], [4][7] and + [5][2], [5][3], [5][6], [5][7] are water and cannot + be occupied */ + +typedef struct PiecePosition { + long row; /* 0..9 */ + long col; /* 0..9 */ +} PiecePosition; + +typedef struct MoveResult { + PieceType rankOfAttacker; + /* after a strike, returns identity of attacker */ + PieceType rankOfDefender; + /* after a strike, returns identity of defender */ + Boolean attackerRemoved; + /* true after a strike against a piece of equal or greater rank, + or against a bomb when the attacker is not a Miner */ + Boolean defenderRemoved; + /* true after a strike by a piece of equal or greater rank, + or against a bomb when the attacker is a Miner, + or against a Marshall by a Spy */ + Boolean victory; + /* true after a strike against the Flag */ + Boolean legalMove; + /* true unless you + - move into an occupied square, or + - move or strike in a direction other than forward, backward, or sideways, or + - move more than one square (except Scouts), or + - move a Bomb or a Flag, + - move into Water, or + - strike a square not occupied by an opponent, or + - make any other illegal move */ +} MoveResult; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/agents/peternlewis/peternlewis.o b/agents/peternlewis/peternlewis.o new file mode 100644 index 0000000000000000000000000000000000000000..7654f1ac5aade64b88decebc935635d11429af8e GIT binary patch literal 268304 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�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 literal 0 HcmV?d00001 diff --git a/agents/ramen/Makefile b/agents/ramen/Makefile new file mode 100644 index 0000000..06068b3 --- /dev/null +++ b/agents/ramen/Makefile @@ -0,0 +1,25 @@ + +OBJ = main.o ai.o db.o +BIN = ../ramen + +CFLAGS = -Wall -Wextra -g -std=gnu99 +LINKFLAGS = -g -lm + +DEPFILES = $(OBJ:%=%.dep) + +.PHONY: all clean + +all: $(BIN) + +clean: + $(RM) $(BIN) $(OBJ) $(DEPFILES) + +$(BIN): $(OBJ) + $(CC) -o $@ $(OBJ) $(LINKFLAGS) + +%.o: %.c + $(CC) -o $@ -c $< $(CFLAGS) $(CPPFLAGS) + $(CPP) $(CPPFLAGS) $< -MM -o $@.dep + +-include $(DEPFILES) + diff --git a/agents/ramen/ai.c b/agents/ramen/ai.c new file mode 100644 index 0000000..6625d24 --- /dev/null +++ b/agents/ramen/ai.c @@ -0,0 +1,874 @@ +/* + * UCC 2012 Programming Competition Entry + * - "Ramen" + * + * By John Hodge [TPG] + */ +#define ENABLE_DEBUG 0 +#define SHOW_TARGET_MAP 0 +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <limits.h> +#include "interface.h" +#include "ai_common.h" + +// === CONSTANTS === +//! \brief Maximum recusion depth +#define MAX_SEARCH_DEPTH 5 + +//! \brief Threshold before repeat modifier is applied +#define REPEAT_THRESHOLD 3 +//! \brief Modifier applied to a repeated move +#define REPEAT_MOVE_MODIFY(score) do{score /= (giNumRepeatedMove <= 5 ? 2 : 10); score -= giNumRepeatedMove*10;}while(0); + +//! \brief Number of moves by this AI before the defensive modifier kicks in +#define DEFENSIVE_THRESHOLD 20 +//! \brief Modifier applied to offensive moves when > DEFENSIVE_THRESHOLD defensive moves have been done in a row +#define DEFENSIVE_MODIFY(score) do{score *= 1+(giTurnsSinceLastTake/15);}while(0) +/** + * \name AI move outcome scores + * \{ + */ +#define OC_LOSE -100 +#define OC_DRAW 0 +#define OC_UNK 40 +#define OC_WIN 100 +#define OC_FLAG 150 +/** + * \} + */ + +// === PROTOTYPES === +// - Wrapper and Initialisation +void AI_Initialise(enum eColours Colour, const char *Opponent); +void AI_HandleMove(int bMyMove, const tMove *Move); +void UpdateStates(const tMove *OpponentMove); +void AI_DoMove(tMove *MyMove); +// - Management +tPiece *GetPieceByPos(int X, int Y); +void MovePieceTo(tPiece *Piece, int X, int Y); +void UpdateRank(tPiece *Piece, char RankChar); +void PieceExposed(tPiece *Piece); +void RemovePiece(tPiece *Piece); +// -- AI Core + int GetBestMove(tPlayerStats *Attacker, tPlayerStats *Defender, tMove *Move, int Level); + int GetPositionScore(tPlayerStats *Attacker, tPlayerStats *Defender, int Level, int X, int Y, tPiece *Piece); + int GetScore(tPiece *This, tPiece *Target); + int GetRawScore(tPiece *This, tPiece *Target); +// -- Helpers +static inline int GetOutcome(int Attacker, int Defender); +static inline int ABS(int Val); +static inline int RANGE(int Min, int Val, int Max); + +// === GLOBALS === +enum eColours gMyColour; +tPiece gBlockPiece = {.Team = 2}; + int giGameStateSize; +tGameState *gpCurrentGameState; +BOOL gbFirstTurn = true; +//tPiece **gaBoardPieces; +const char *gsOpponentDbFilename; +// -- State variables to avoid deadlocking + int giNumRepeatedMove; + int giTurnsSinceLastTake; +tMove gLastMove; +tPiece *gLastMove_Target, *gLastMove_Piece; + +// === CODE === +void AI_Initialise(enum eColours Colour, const char *Opponent) +{ + gMyColour = Colour; + + // TODO: Get opponent filename + gsOpponentDbFilename = DB_GetOpponentFile(Opponent); + + // Select setup +// setup_id = rand() % 3; + int setup_id = 1; + switch( setup_id ) + { +// case 0: // Bomb-off (dick move) +// // 39 pieces, bombs blocking gates, high level pieces backing up +// { +// const char *setup[] = { +// "8.88979993\n", +// "6689995986\n", +// "F72434s174\n", +// "BB56BB55BB\n" +// }; +// if( Colour == COLOUR_RED ) +// for(int i = 0; i < 4; i ++ ) printf(setup[i]); +// else +// for(int i = 4; i --; ) printf(setup[i]); +// break; +// } + case 1: + { + const char *setup[] = { + "FB8sB479B8\n", + "BB31555583\n", + "6724898974\n", + "967B669999\n" + }; + if( Colour == COLOUR_RED ) + for(int i = 0; i < 4; i ++ ) printf(setup[i]); + else + for(int i = 4; i --; ) printf(setup[i]); + } + break ; + default: + exit(1); + } + + + giGameStateSize = sizeof(tGameState) + giBoardHeight*giBoardWidth*sizeof(tPieceRef); + gpCurrentGameState = calloc( giGameStateSize, 1 ); + gpCurrentGameState->Opponent.Colour = !Colour; + gpCurrentGameState->MyExposed.Colour = Colour; + gpCurrentGameState->MyActual.Colour = Colour; +// gaBoardPieces = calloc( giBoardHeight*giBoardWidth, sizeof(tPiece*) ); +} + +void AI_int_InitialiseBoardState(void) +{ + int piece_index = 0; + int my_piece_index = 0; + for( int y = 0; y < giBoardHeight; y ++ ) + { + for( int x = 0; x < giBoardWidth; x ++ ) + { + tPiece *p; + char b; + + b = gaBoardState[y*giBoardWidth+x]; + + if( b == '.' ) continue ; + if( b == '+' ) + { + gpCurrentGameState->BoardState[ y*giBoardWidth+x ].Team = 3; + continue ; + } + + if( b == '#' ) + { + if( piece_index >= N_PIECES ) { + piece_index ++; + continue ; + } + p = &gpCurrentGameState->Opponent.Pieces[piece_index++]; + p->Rank = RANK_UNKNOWN; + p->X = x; p->StartX = x; + p->Y = y; p->StartY = y; + p->bHasMoved = false; + p->Team = !gMyColour; + gpCurrentGameState->BoardState[ y*giBoardWidth+x ].Team = 2; + gpCurrentGameState->BoardState[ y*giBoardWidth+x ].Index = piece_index - 1; + DEBUG("Enemy at %i,%i", x, y); + } + else + { + if( my_piece_index >= N_PIECES ) { + my_piece_index ++; + continue ; + } + p = &gpCurrentGameState->MyActual.Pieces[my_piece_index++]; + p->X = x; + p->Y = y; + p->Team = gMyColour; + UpdateRank(p, b); + gpCurrentGameState->MyActual.nRanks[p->Rank] ++; + gpCurrentGameState->BoardState[ y*giBoardWidth+x ].Team = 1; + gpCurrentGameState->BoardState[ y*giBoardWidth+x ].Index = my_piece_index - 1; + } + + + } + } + gpCurrentGameState->Opponent.nPieces = piece_index; + if( piece_index > N_PIECES ) + DEBUG("GAH! Too many opposing pieces (%i > 40)", piece_index); + if( my_piece_index > N_PIECES ) + DEBUG("GAH! Too many of my pieces (%i > 40)", my_piece_index); + + // Catch for if I don't put enough pieces out (shouldn't happen) + while( my_piece_index < N_PIECES ) { + gpCurrentGameState->MyActual.Pieces[my_piece_index].bDead = true; + gpCurrentGameState->MyActual.Pieces[my_piece_index].Rank = RANK_UNKNOWN; + my_piece_index ++; + } + + // Load guesses at what each piece is + DB_LoadGuesses(gsOpponentDbFilename, !gMyColour); + gpCurrentGameState->Opponent.bGuessValid = true; +} + +void AI_HandleMove(int bMyMove, const tMove *Move) +{ + if( gbFirstTurn ) + { + gbFirstTurn = false; + + AI_int_InitialiseBoardState(); + + // Reverse the first move + if( Move->dir != DIR_INVAL ) + { + tPiece *p; + switch(Move->dir) + { + case DIR_INVAL: ASSERT(Move->dir != DIR_INVAL); break; + case DIR_LEFT: p = GetPieceByPos( Move->x-1, Move->y ); break ; + case DIR_RIGHT: p = GetPieceByPos( Move->x+1, Move->y ); break ; + case DIR_UP: p = GetPieceByPos( Move->x, Move->y-1 ); break ; + case DIR_DOWN: p = GetPieceByPos( Move->x, Move->y+1 ); break ; + } + MovePieceTo( p, Move->x, Move->y ); + p->StartX = Move->x; + p->StartY = Move->y; + } + } + + if(Move->result == RESULT_VICTORY) + { + // TODO: Distiguish between victory conditions? + // - Note flag location? + + // TODO: Save back initial board state + DB_WriteBackInitialState(gsOpponentDbFilename, !gMyColour, gpCurrentGameState->Opponent.Pieces); + } + + if( !bMyMove ) + { + if( Move->dir != DIR_INVAL ) + UpdateStates(Move); + } + else + { + tPiece *p = GetPieceByPos(Move->x, Move->y); + ASSERT(p); + + int newx = p->X, newy = p->Y; + switch(Move->dir) + { + case DIR_INVAL: break; + case DIR_LEFT: newx -= Move->dist; break; + case DIR_RIGHT: newx += Move->dist; break; + case DIR_UP: newy -= Move->dist; break; + case DIR_DOWN: newy += Move->dist; break; + } + tPiece *target = GetPieceByPos(newx, newy); + + switch(Move->result) + { + case RESULT_ILLEGAL: break; + case RESULT_INVAL: break; + case RESULT_OK: + MovePieceTo(p, newx, newy); + break; + case RESULT_KILL: + UpdateRank(target, Move->defender); + RemovePiece(target); + MovePieceTo(p, newx, newy); + PieceExposed(p); // TODO: Update oponent's view + giTurnsSinceLastTake = 0; + break; + case RESULT_DIES: + case RESULT_VICTORY: + UpdateRank(target, Move->defender); + PieceExposed(p); + RemovePiece(p); + giTurnsSinceLastTake = 0; + break; + case RESULT_BOTHDIE: + UpdateRank(target, Move->defender); + PieceExposed(p); + RemovePiece(p); + RemovePiece(target); + giTurnsSinceLastTake = 0; + break; + } + } +} + +void UpdateStates(const tMove *OpponentMove) +{ + // --- Get moved piece, update position --- + tPiece *moved_piece = GetPieceByPos(OpponentMove->x, OpponentMove->y); + // - Sanity + ASSERT( moved_piece ); + ASSERT( moved_piece->Team == !gMyColour ); + // - Only scouts can move multiple squares + if( moved_piece->Rank == RANK_UNKNOWN && OpponentMove->dist > 1 ) + UpdateRank(moved_piece, '9'); + // - Update position + int newx = moved_piece->X, newy = moved_piece->Y; + switch(OpponentMove->dir) + { + case DIR_INVAL: break; + case DIR_LEFT: newx -= OpponentMove->dist; break; + case DIR_RIGHT: newx += OpponentMove->dist; break; + case DIR_UP: newy -= OpponentMove->dist; break; + case DIR_DOWN: newy += OpponentMove->dist; break; + } + tPiece *my_piece = GetPieceByPos(newx, newy); + + // Check if one of my pieces has been taken + switch( OpponentMove->result ) + { + case RESULT_ILLEGAL: break; + case RESULT_INVAL: break; + case RESULT_OK: + MovePieceTo(moved_piece, newx, newy); + break; + case RESULT_KILL: + case RESULT_VICTORY: + UpdateRank(moved_piece, OpponentMove->attacker); + PieceExposed(my_piece); + RemovePiece(my_piece); + MovePieceTo(moved_piece, newx, newy); + break; + case RESULT_DIES: + UpdateRank(moved_piece, OpponentMove->attacker); + PieceExposed(my_piece); + RemovePiece(moved_piece); + break; + case RESULT_BOTHDIE: + UpdateRank(moved_piece, OpponentMove->attacker); + RemovePiece(moved_piece); + PieceExposed(my_piece); + RemovePiece(my_piece); + break; + } + + // Update rank if revealed + if( moved_piece->Rank == RANK_UNKNOWN ) + UpdateRank(moved_piece, gaBoardState[moved_piece->Y*giBoardWidth+moved_piece->X]); + + // - Update piece states + DEBUG("Updating piece states"); + for( int y = 0; y < giBoardHeight; y ++ ) + { + for( int x = 0; x < giBoardWidth; x ++ ) + { + char c = gaBoardState[y*giBoardWidth+x]; + if( c == '.' ) continue; + if( c == '+' ) continue; + tPiece *p = GetPieceByPos(x, y); + if(!p) DEBUG("c = %c", c); + ASSERT(p); + if( p->Team == gMyColour ) continue ; + if( p->Rank == RANK_UNKNOWN && c != '#' ) + UpdateRank(p, c); + } + } +} + +void AI_DoMove(tMove *MyMove) +{ +#if 1 + // Sanity checks + for( int i = 0; i < N_PIECES; i ++ ) + { + tPiece *p = &gpCurrentGameState->MyActual.Pieces[i]; + if(p->bDead) continue; + + if( p != GetPieceByPos(p->X, p->Y) ) { + DEBUG("Piece %p(%i,%i R%i) not at stated position", + p, p->X, p->Y, p->Rank); + } + } +#endif + + DEBUG("Deciding on move"); + GetBestMove(&gpCurrentGameState->MyActual, &gpCurrentGameState->Opponent, MyMove, 0); +} + +tPiece *GetPieceByPos(int X, int Y) +{ + tPieceRef *pr = &gpCurrentGameState->BoardState[Y*giBoardWidth+X]; + switch( pr->Team ) + { + case 0: return NULL; + case 1: return &gpCurrentGameState->MyActual.Pieces[ (int)pr->Index ]; + case 2: return &gpCurrentGameState->Opponent.Pieces[ (int)pr->Index ]; + case 3: return &gBlockPiece; + } + return NULL; +} + +void MovePieceTo(tPiece *Piece, int X, int Y) +{ + DEBUG("Moved %p(%i,%i) to (%i,%i)", + Piece, Piece->X, Piece->Y, X, Y); + + gpCurrentGameState->BoardState[Y*giBoardWidth + X] + = gpCurrentGameState->BoardState[Piece->Y*giBoardWidth + Piece->X]; + gpCurrentGameState->BoardState[Piece->Y*giBoardWidth + Piece->X].Team = 0; + + Piece->X = X; + Piece->Y = Y; + + if( !Piece->bHasMoved ) + { + if( Piece->Team == gMyColour ) + { + gpCurrentGameState->MyExposed.nMoved ++; + } + else + { + gpCurrentGameState->Opponent.nMoved ++; + } + } + + Piece->bHasMoved = true; +} + +void UpdateRank(tPiece *Piece, char RankChar) +{ + enum eRanks rank; + + rank = CharToRank(RankChar); + + if( Piece->Rank == rank ) + return ; + + if( Piece->Rank != RANK_UNKNOWN ) + { + if(Piece->Rank != rank ) + { + DEBUG("Rank of piece %p(%i,%i) has changed, was %i now %i", + Piece, Piece->X, Piece->Y, Piece->Rank, rank); + Piece->Rank = rank; + } + return ; + } + + if( Piece->Team == !gMyColour && rank != RANK_UNKNOWN ) + { + if( gpCurrentGameState->Opponent.nRanks[rank] >= MAX_RANK_COUNTS[rank] ) { + DEBUG("ERROR: Bookkeeping failed, >%i units of rank %i on board", + MAX_RANK_COUNTS[rank], rank); + } + DEBUG("Found a %i", rank); + gpCurrentGameState->Opponent.nRanks[rank] ++; + if( gpCurrentGameState->Opponent.nIdentified == gpCurrentGameState->Opponent.nPieces ) { + DEBUG("ERROR: Bookkeeping failed, >%i units identified", + gpCurrentGameState->Opponent.nPieces); + } + gpCurrentGameState->Opponent.nIdentified ++; + + if( Piece->GuessedRank != RANK_UNKNOWN && Piece->GuessedRank != rank ) + { + fprintf(stderr, "Assumption failed, saved %c != act %c", + cRANK_CHARS[Piece->GuessedRank], cRANK_CHARS[rank]); + gpCurrentGameState->Opponent.bGuessValid = false; + } + + } + Piece->Rank = rank; + if( Piece->Team == !gMyColour ) + { + // Expensive? What's that? + DB_WriteBackInitialState(gsOpponentDbFilename, !gMyColour, gpCurrentGameState->Opponent.Pieces); + } +} + +void PieceExposed(tPiece *Piece) +{ + ASSERT(Piece->Team == gMyColour); + if( Piece->bExposed == false ) + { + gpCurrentGameState->MyExposed.nRanks[Piece->Rank] ++; + gpCurrentGameState->MyExposed.nIdentified ++; + Piece->bExposed = true; + } +} + +/** + * \brief Remove a piece from the board + */ +void RemovePiece(tPiece *Piece) +{ + tPlayerStats *owner; + gpCurrentGameState->BoardState[Piece->Y*giBoardWidth + Piece->X].Team = 0; + if( Piece->Team == !gMyColour ) { + owner = &gpCurrentGameState->Opponent; + } + else { + owner = &gpCurrentGameState->MyExposed; + gpCurrentGameState->MyActual.nRanks[Piece->Rank] --; + } + owner->nKilledRanks[Piece->Rank] ++; + owner->nRanks[Piece->Rank] --; + owner->nIdentified --; + owner->nPieces --; + Piece->bDead = true; +} + +// ---------------------------------------------------------------------------- +// - AI Core +// ---------------------------------------------------------------------------- +#define TARGET_GRID_W 10 +#define TARGET_GRID_H 10 +#define TARGET_GRID_SIZE (TARGET_GRID_W*TARGET_GRID_H) +typedef struct sGridSlot { + tPiece *p; + char dist; + char complexity; + enum eDirections firstdir; + char firstdist; + char bDirect; +} tTargetGrid[TARGET_GRID_SIZE]; +int GetTargetsFrom(tPiece *Piece, tTargetGrid *grid) +{ + int n_targets; + + memset(*grid, 0, sizeof(*grid)); + + int cur_dist = 1; + int b_updates = 0; + + void _check_dir(struct sGridSlot *pgs, struct sGridSlot *gs, int x, int y, enum eDirections dir) + { + if( !gs ) return ; + if( gs->dist ) return ; + if( pgs->p ) return ; + + tPiece *p = GetPieceByPos(x, y); + if( p && (p == &gBlockPiece || p->Team == Piece->Team) ) + p = (void*)-1; + gs->dist = cur_dist + 1; + gs->p = p; + DEBUG("%p at %i,%i %i away", p, x, y, cur_dist); + if( pgs->firstdir == DIR_INVAL || (pgs->firstdir == dir && pgs->bDirect) ) { + gs->bDirect = 1; + gs->firstdir = dir; + gs->firstdist = pgs->firstdist + 1; + } + else { + gs->firstdist = pgs->firstdist; + gs->firstdir = pgs->firstdir; + gs->bDirect = 0; + } + b_updates = 1; + } + + (*grid)[ Piece->X + Piece->Y * TARGET_GRID_W ].dist = -1; + + do { + b_updates = 0; + for( int i = 0; i < TARGET_GRID_SIZE; i ++ ) + { + int x = i % TARGET_GRID_W; + int y = i / TARGET_GRID_H; + struct sGridSlot *gs = &(*grid)[i]; + + struct sGridSlot *gs_u = NULL, *gs_d = NULL; + struct sGridSlot *gs_l = NULL, *gs_r = NULL; + + if( !gs->dist ) continue ; + + // Get adjacent cells + if( y > 0 ) + gs_u = &(*grid)[i - TARGET_GRID_W]; + if( x > 0 ) + gs_l = &(*grid)[i - 1]; + if( y < TARGET_GRID_H - 1 ) + gs_d = &(*grid)[i + TARGET_GRID_W]; + if( x < TARGET_GRID_W - 1 ) + gs_r = &(*grid)[i + 1]; + + _check_dir(gs, gs_u, x, y-1, DIR_UP); + _check_dir(gs, gs_d, x, y+1, DIR_DOWN); + _check_dir(gs, gs_l, x-1, y, DIR_LEFT); + _check_dir(gs, gs_r, x+1, y, DIR_RIGHT); + } + + cur_dist ++; + } while(b_updates); + +#if SHOW_TARGET_MAP + fprintf(stderr, "%p Type %c\n", Piece, cRANK_CHARS[Piece->Rank]); + for( int i = 0; i < 10*10; i ++ ) + { + tPiece *np = (*grid)[i].p; + if( i == Piece->X + Piece->Y * TARGET_GRID_W ) + fprintf(stderr, "?"); + else if( (*grid)[i].dist == 0 ) + fprintf(stderr, "#"); // Unreachable + else if( !np ) + fprintf(stderr, " "); // Empty + else if( np == (void*)-1 ) + fprintf(stderr, "."); // My team/block + else + fprintf(stderr, "X"); // Viable target! + if( i % 10 == 9 ) + fprintf(stderr, "\n"); + } +#endif + + DEBUG("Getting targets"); + n_targets = 0; + for( int i = 0; i < TARGET_GRID_SIZE; i ++ ) + { + if( (*grid)[i].p == (void*)-1 ) + (*grid)[i].p = NULL; + if( (*grid)[i].p ) { + DEBUG("Target (%i,%i) %p %i dist", + i%10, i/10, (*grid)[i].p, (*grid)[i].dist); + (*grid)[i].dist -= 1; + n_targets ++; + } + } + + return n_targets; +} + +int GetBestMove(tPlayerStats *Attacker, tPlayerStats *Defender, tMove *Move, int Level) +{ + // Avoid infinite recursion + if( Level == MAX_SEARCH_DEPTH ) return 1; + + int best_score = INT_MIN; + tMove best_move; + tPiece *best_p = NULL; + tPiece *best_target = NULL; + tTargetGrid grid; + + // - Check possible moves + for( int i = 0; i < N_PIECES; i ++ ) + { + tPiece *p = &Attacker->Pieces[i]; + int p_score = 0; // Piece score + struct sGridSlot *bt_gs = NULL; + int bt_score; // Best target score + + // Dead, ignore + if( p->bDead ) + continue ; + // These cannot move + if( p->Rank == RANK_BOMB || p->Rank == RANK_FLAG ) + continue ; + + // Get what pieces are able to be attacked from this piece + int nt = GetTargetsFrom(p, &grid); + DEBUG("(%i,%i) %i targets", p->X, p->Y, nt); + if( nt <= 0 ) continue ; + + // Find the best target of those + for( int j = 0; j < TARGET_GRID_SIZE; j ++ ) + { + struct sGridSlot *gs = &grid[j]; + if( !gs->p ) continue ; + + int t_score = GetScore(p, gs->p); + +#if 1 + if( gs->p == gLastMove_Target && p == gLastMove_Piece && giNumRepeatedMove > REPEAT_THRESHOLD) + { + REPEAT_MOVE_MODIFY(t_score); + } +#endif + + // TODO: For scouts, use gs->complexity + // TODO: Don't use a linear relationship on distance + p_score += t_score / (gs->dist < 2 ? 1 : 2); + + // Best target + if( !bt_gs || t_score > bt_score ) { + bt_score = t_score; + bt_gs = gs; + } + } + + DEBUG("p_score = %i, bt_score = %i", p_score, bt_score); + + // Best move is towards that piece + if( best_move.dir == DIR_INVAL || best_score < p_score ) + { + best_move.dir = bt_gs->firstdir; + best_move.x = p->X; + best_move.y = p->Y; + best_move.dist = (p->Rank == RANK_SCOUT) ? bt_gs->firstdist : 1; + best_score = p_score; + best_p = p; + best_target = bt_gs->p; + } + } + + + if( Move ) + { + ASSERT(best_move.dir != DIR_INVAL); + *Move = best_move; + + if( ((Move->dir-1)^1) == gLastMove.dir-1 && Move->dist == gLastMove.dist + && Move->x == gLastMove.x && Move->y == gLastMove.y ) + { + giNumRepeatedMove ++; + DEBUG("Up to %i repititions", giNumRepeatedMove); + } + else + giNumRepeatedMove = 0; + + // TODO: Recurse once on this to determine what the other team will do + // Record that move, then check when the move is performed to see if we were right. + + gLastMove = *Move; + gLastMove_Target = best_target; + gLastMove_Piece = best_p; + giTurnsSinceLastTake ++; + } + + DEBUG("best_score = %i", best_score); + + return best_score; +} + +/** + * \brief + */ +int GetScore(tPiece *This, tPiece *Target) +{ + tPlayerStats *attacker, *defender; + int score; + + if( This->Team == gMyColour ) { + defender = &gpCurrentGameState->Opponent; + attacker = &gpCurrentGameState->MyExposed; + } + else { + attacker = &gpCurrentGameState->Opponent; + defender = &gpCurrentGameState->MyExposed; + } + + score = GetRawScore(This, Target); + + if( This->Team == gMyColour ) + { + switch( This->Rank ) + { + case RANK_MARSHAL: // Marshal has balls of steel if the spy and enemy marshal are dead + if( defender->nKilledRanks[RANK_MARSHAL] && defender->nKilledRanks[RANK_SPY] ) + score *= 2; + break; + case RANK_GENERAL: // General always attacks! + score *= 2; + break; + case RANK_SCOUT: + score = score * gpCurrentGameState->MyActual.nRanks[RANK_SCOUT] / MAX_RANK_COUNTS[RANK_SCOUT] + score; + break; + default: + break; + } + } + + return score; +} + +int GetRawScore(tPiece *This, tPiece *Target) +{ + tPlayerStats *this_team, *target_team; + + ASSERT( This->Team != Target->Team ); + + if( This->Team == gMyColour ) { + target_team = &gpCurrentGameState->Opponent; + this_team = &gpCurrentGameState->MyExposed; + } + else { + this_team = &gpCurrentGameState->Opponent; + target_team = &gpCurrentGameState->MyExposed; + } + + // Both ranks known, used fixed rules + if( This->Rank != RANK_UNKNOWN && Target->Rank != RANK_UNKNOWN ) + { + return GetOutcome(This->Rank, Target->Rank); + } + // If it's our move, and the guesses are valid, then use the guess + else if( This->Team == gMyColour + && gpCurrentGameState->Opponent.bGuessValid + && Target->GuessedRank != RANK_UNKNOWN + ) + { + return GetOutcome(This->Rank, Target->GuessedRank); + } + else + { + int sum = 0; + int max = Target->bHasMoved ? RANK_SPY : RANK_FLAG; + int count = 0; + + if( target_team->nIdentified >= target_team->nPieces ) { + DEBUG("%i >= %i, what the fsck", + target_team->nIdentified, target_team->nPieces); + } + ASSERT(target_team->nPieces > target_team->nIdentified); + + for( int i = RANK_MARSHAL; i <= max; i ++ ) + { + int n_unk = MAX_RANK_COUNTS[i] - (target_team->nRanks[i] + target_team->nKilledRanks[i]); + if( n_unk == 0 ) + continue ; + ASSERT( n_unk > 0 ); + + // TODO: Fiddle with outcome score depending on respective ranks + sum += n_unk * GetOutcome(This->Rank, i); + count += n_unk; + } + +// if( Target->bHasMoved ) +// sum /= target_team->nPieces - target_team->nMoved; +// else +// sum /= target_team->nPieces - target_team->nIdentified; + sum /= count; + + if( sum > OC_FLAG ) { + fprintf(stderr, "sum (%i) > OC_WIN (%i) -- nUnIdent=%i\n", + sum, OC_WIN, target_team->nPieces - target_team->nIdentified); + ASSERT( sum <= OC_FLAG ); + } + + return sum - ABS(sum) / 10; + } +} + +static inline int GetOutcome(int Attacker, int Defender) +{ + if( Attacker == 0 ) return OC_UNK; + if( Defender == 0 ) return OC_UNK; + + if( Defender == RANK_FLAG ) + return OC_FLAG; + + if( Attacker != RANK_MINER && Defender == RANK_BOMB ) + return OC_LOSE; + if( Attacker == RANK_MINER && Defender == RANK_BOMB ) + return OC_WIN; + + if( Attacker == RANK_SPY && Defender == RANK_MARSHAL ) + return OC_WIN; + + if( Attacker == Defender ) + return OC_DRAW; + + if( Attacker < Defender ) + return OC_WIN; + else + return OC_LOSE; +} + + +static inline int ABS(int Val) +{ + return Val < 0 ? -Val : Val; +} + +static inline int RANGE(int Min, int Val, int Max) +{ + return Min <= Val && Val <= Max; +} + diff --git a/agents/ramen/ai_common.h b/agents/ramen/ai_common.h new file mode 100644 index 0000000..0793659 --- /dev/null +++ b/agents/ramen/ai_common.h @@ -0,0 +1,108 @@ +/* + * UCC 2012 Programming Competition Entry + * - "Ramen" + * + * By John Hodge [TPG] + */ +#ifndef _AI_COMMON_H_ +#define _AI_COMMON_H_ + +#include "interface.h" + +#define N_PIECES 40 + +enum eRanks +{ + RANK_UNKNOWN, // 0 + RANK_MARSHAL, // 1 + RANK_GENERAL, // 2 + RANK_COLONEL, // 3 + RANK_MAJOR, // 4 + RANK_CAPTAIN, // 5 + RANK_LIEUTENANT,// 6 + RANK_SERGEANT, // 7 + RANK_MINER, // 8 + RANK_SCOUT, // 9 + RANK_SPY, // 10 + RANK_BOMB, // 11 + RANK_FLAG, // 12 + N_RANKS +}; +static const int MAX_RANK_COUNTS[N_RANKS] = { + 40, 1, 1, 2, 3, 4, 4, 4, 5, 8, 1, 6, 1 +}; +static const char cRANK_CHARS[N_RANKS] = "#123456789sBF"; +static inline enum eRanks CharToRank(char ch) +{ + switch(ch) + { + case '1': return RANK_MARSHAL; + case '2': return RANK_GENERAL; + case '3': return RANK_COLONEL; + case '4': return RANK_MAJOR; + case '5': return RANK_CAPTAIN; + case '6': return RANK_LIEUTENANT; + case '7': return RANK_SERGEANT; + case '8': return RANK_MINER; + case '9': return RANK_SCOUT; + case 's': return RANK_SPY; + case 'B': return RANK_BOMB; + case 'F': return RANK_FLAG; + case '#': return RANK_UNKNOWN; + default: + // Wut. Unkown + DEBUG("Unknown character '%c'", ch); + return RANK_UNKNOWN; + } +} + +/** + */ +typedef struct sPiece +{ + int X, Y; + BOOL bDead; + enum eRanks Rank; // -1 = unknown + BOOL bHasMoved; + enum eColours Team; + // TODO: Keep last moved + + BOOL bExposed; // Marks when the piece is known by the other team + + int StartX, StartY; // Used to save initial layout + enum eRanks GuessedRank; // Only used it bGuessValid is set +} tPiece; + +typedef struct sPlayerStats +{ + enum eColours Colour; + int nPieces; + int nMoved; + int nIdentified; + int nRanks[N_RANKS]; + int nKilledRanks[N_RANKS]; + tPiece Pieces[N_PIECES]; + BOOL bGuessValid; +} tPlayerStats; + +typedef struct sPieceRef +{ + char Index; // Index into tPlayerStats.Pieces + char Team; // 0 = Empty, 1 = Me, 2 = Opponent, 3 = Block +} tPieceRef; + +typedef struct sGameState +{ + tPlayerStats Opponent; + tPlayerStats MyExposed; + tPlayerStats MyActual; + tPieceRef BoardState[]; // +} tGameState; + +// --- Database +extern char *DB_GetOpponentFile(const char *Opponent); +extern void DB_LoadGuesses(const char *DBFile, enum eColours Colour); +extern void DB_WriteBackInitialState(const char *DBFile, enum eColours Colour, tPiece *Pieces); + +#endif + diff --git a/agents/ramen/db.c b/agents/ramen/db.c new file mode 100644 index 0000000..a62d44a --- /dev/null +++ b/agents/ramen/db.c @@ -0,0 +1,258 @@ +/* + * UCC 2012 Programming Competition Entry + * - "Ramen" + * + * By John Hodge [TPG] + */ +#include <stdio.h> +#include <stdlib.h> +#include "ai_common.h" +#include <stdint.h> +#include <string.h> + +#define TAG_BOARDSTATE 0x7342 + +typedef struct sTag +{ + uint16_t Tag; + uint16_t Length; +} tTag; + +typedef struct sSavedBoardState +{ + uint8_t W, H; + uint16_t Count; + char NormalisedBoard[]; +} tSavedBoardState; + +// === PROTOTYPES === +tSavedBoardState *DB_int_ReadState(FILE *fp, off_t *offset); +void DB_int_AppendTag(FILE *fp, uint16_t Tag, uint16_t Size, void *Data); + +// === CODE === +char *DB_GetOpponentFile(const char *Opponent) +{ + uint32_t checksum = 0; + + { + int ofs = 0; + const char *str = Opponent; + while( *str ) + { + checksum ^= *str << ofs; + str ++; + ofs += 5; + ofs %= 32 - 5; + } + } + + const char *filename = NULL; + int filenamelen = 0; + { + const char *last_slash = NULL; + const char *last_dot = NULL; + const char *str = Opponent; + while( *str ) + { + if(*str == '/') last_slash = str; + if(*str == '.') last_dot = str; + str ++; + } + filename = last_slash + 1; + if( last_slash > last_dot ) + filenamelen = str - filename; + else + filenamelen = last_dot - filename; + } + + int len = snprintf(NULL, 0, "%08x_%.*s.ramen", checksum, filenamelen, filename); + char *ret = malloc(len+1); + snprintf(ret, len+1, "%08x_%.*s.ramen", checksum, filenamelen, filename); +// fprintf(stderr, "DB File = '%s'\n", ret); + return ret; +} + +void DB_LoadGuesses(const char *DBFile, enum eColours Colour) +{ + FILE *fp; + off_t offset = 0; + tSavedBoardState *saved_board = NULL; + + fp = fopen(DBFile, "r+"); + if(!fp) return ; + + // Read board states, checking for a same state + while( (saved_board = DB_int_ReadState(fp, &offset)) ) + { + if( saved_board->W != giBoardWidth ) + continue ; + if( saved_board->H != giBoardHeight ) + continue ; + break; + } + + // TODO: Combine counts of how many times a state has been played + + if( saved_board ) + { + char bs[giBoardWidth*4]; + int ofs = 0; + + + if( Colour != COLOUR_RED ) + { + ofs = giBoardHeight-4; + char *bs2 = saved_board->NormalisedBoard; + memcpy(bs + giBoardWidth*0, bs2 + giBoardWidth*(4-1), giBoardWidth); + memcpy(bs + giBoardWidth*1, bs2 + giBoardWidth*(4-2), giBoardWidth); + memcpy(bs + giBoardWidth*2, bs2 + giBoardWidth*(4-3), giBoardWidth); + memcpy(bs + giBoardWidth*3, bs2 + giBoardWidth*(4-4), giBoardWidth); + } + else + { + memcpy(bs, saved_board->NormalisedBoard, giBoardWidth*4); + } +// for( int i = 0; i < 4; i ++ ) { +// fprintf(stderr, "%.*s\n", giBoardWidth, bs + giBoardWidth*i); +// } + + // Set guessed ranks + for( int i = 0; i < giBoardWidth*4; i ++ ) + { + tPiece *p = GetPieceByPos(i % giBoardWidth, i/giBoardWidth + ofs ); +// fprintf(stderr, "%c", bs[i]); +// if(i % giBoardWidth == giBoardWidth-1) +// fprintf(stderr, "\n"); + if( bs[i] == '\0' && p ) + break; + if( bs[i] != '\0' && !p ) + break; + if( p ) + p->GuessedRank = CharToRank(bs[i]); + } + } + + fclose(fp); +} + +void DB_WriteBackInitialState(const char *DBFile, enum eColours Colour, tPiece *Pieces) +{ + char bs[giBoardHeight*giBoardWidth]; + memset(bs, 0, sizeof(bs)); + + for( int i = 0; i < N_PIECES; i ++ ) + { + if( Pieces[i].StartY < 0 ) continue ; + char *bp = &bs[ Pieces[i].StartY*giBoardWidth + Pieces[i].StartX ]; + + if( *bp != '\0' ) + { + // Oops? + } + else + { + *bp = cRANK_CHARS[ Pieces[i].Rank ]; + } + } + + // Normalise board to RED + if( Colour != COLOUR_RED ) + { + memcpy(bs + giBoardWidth*0, bs + giBoardWidth*(giBoardHeight-1), giBoardWidth); + memcpy(bs + giBoardWidth*1, bs + giBoardWidth*(giBoardHeight-2), giBoardWidth); + memcpy(bs + giBoardWidth*2, bs + giBoardWidth*(giBoardHeight-3), giBoardWidth); + memcpy(bs + giBoardWidth*3, bs + giBoardWidth*(giBoardHeight-4), giBoardWidth); + } + + + off_t offset; + tSavedBoardState *saved_board; + FILE *fp = fopen(DBFile, "r+"); + if( !fp ) { + fp = fopen(DBFile, "w"); + } + + // Read board states, checking for a same state + while( (saved_board = DB_int_ReadState(fp, &offset)) ) + { +// fprintf(stderr, "DBG: %i == %i? and %i == %i\n", +// saved_board->W, giBoardWidth, saved_board->H, giBoardHeight +// ); + + if( saved_board->W != giBoardWidth ) + continue ; + if( saved_board->H != giBoardHeight ) + continue ; + + BOOL b_different = false; + + for( int i = 0; i < 4*giBoardWidth; i ++ ) + { + if( saved_board->NormalisedBoard[i] == '#' || bs[i] == '#' ) + continue ; + if( saved_board->NormalisedBoard[i] != bs[i] ) { + fprintf(stderr, "DBG: '%c' != '%c'\n", saved_board->NormalisedBoard[i], bs[i]); + b_different = true; + break; + } + } + + if( b_different ) continue ; + + break; + } + + if( saved_board ) + { + saved_board->Count ++; + fseek(fp, offset, SEEK_SET); + // Merge + for( int i = 0; i < 4*giBoardWidth; i ++ ) + { + if( saved_board->NormalisedBoard[i] == '#' ) + saved_board->NormalisedBoard[i] = bs[i]; + } + // Write back + fwrite(saved_board, sizeof(*saved_board) + giBoardWidth*4, 1, fp); + } + else + { + saved_board = malloc( sizeof(*saved_board) + giBoardWidth*4 ); + saved_board->W = giBoardWidth; + saved_board->H = giBoardHeight; + saved_board->Count = 1; + memcpy(saved_board->NormalisedBoard, bs, 4*giBoardWidth); + DB_int_AppendTag(fp, TAG_BOARDSTATE, sizeof(*saved_board) + giBoardWidth*4, saved_board); + } + free(saved_board); + + fclose(fp); +} + +tSavedBoardState *DB_int_ReadState(FILE *fp, off_t *offset) +{ + tTag tag; + tSavedBoardState *ret = NULL; + + do { + if( fread(&tag, sizeof(tag), 1, fp) != 1 ) + break ; + if( tag.Tag == TAG_BOARDSTATE ) + { + *offset = ftell(fp); + ret = malloc(tag.Length); + fread(ret, tag.Length, 1, fp); + } + fseek(fp, tag.Length, SEEK_CUR); + } while(!ret); + + return ret; +} + +void DB_int_AppendTag(FILE *fp, uint16_t Tag, uint16_t Size, void *Data) +{ + fseek(fp, 0, SEEK_END); + fwrite(&Tag, sizeof(uint16_t), 1, fp); + fwrite(&Size, sizeof(uint16_t), 1, fp); + fwrite(Data, Size, 1, fp); +} diff --git a/agents/ramen/info b/agents/ramen/info new file mode 100644 index 0000000..43dd0fc --- /dev/null +++ b/agents/ramen/info @@ -0,0 +1,4 @@ +ramen +John Hodge +C +Fool me once, shame on you. Fool me twice, shame on me. diff --git a/agents/ramen/interface.h b/agents/ramen/interface.h new file mode 100644 index 0000000..cb7e949 --- /dev/null +++ b/agents/ramen/interface.h @@ -0,0 +1,70 @@ +/* + * UCC 2012 Programming Competition Entry + * - "Ramen" + * + * By John Hodge [TPG] + */ +#ifndef _COMMON_H_ +#define _COMMON_H_ + +#if ENABLE_DEBUG +# define DEBUG(s, a...) fprintf(stderr, "DEBUG: "s"\n" ,## a) +#else +# define DEBUG(...) do{}while(0) +#endif +#define ASSERT(val) do{if(!(val)){fprintf(stderr, "ASSERTION FAILED - " #val " at %s:%i\n", __FILE__, __LINE__);exit(-1);} }while(0) + + +#define true 1 +#define false 0 +typedef char BOOL; + +typedef struct sMove tMove; + +enum eDirections +{ + DIR_INVAL, + DIR_LEFT, + DIR_RIGHT, + DIR_UP, + DIR_DOWN +}; + +enum eColours +{ + COLOUR_RED, + COLOUR_BLUE +}; + +enum eResult +{ + RESULT_INVAL, + RESULT_ILLEGAL, + RESULT_OK, + RESULT_KILL, + RESULT_DIES, + RESULT_BOTHDIE, + RESULT_VICTORY +}; + +struct sMove +{ + char x, y; + enum eDirections dir; // eDirections + char dist; + + enum eResult result; + char attacker; + char defender; +}; + +extern int giBoardWidth; +extern int giBoardHeight; +extern char *gaBoardState; + +extern void AI_Initialise(enum eColours Colour, const char *Opponent); +extern void AI_HandleMove(int bMyMove, const tMove *Move); +extern void AI_DoMove(tMove *MyMove); + +#endif + diff --git a/agents/ramen/main.c b/agents/ramen/main.c new file mode 100644 index 0000000..a9a2d71 --- /dev/null +++ b/agents/ramen/main.c @@ -0,0 +1,240 @@ +/* + * UCC 2012 Programming Competition Entry + * - "Ramen" + * + * By John Hodge [TPG] + */ +#define ENABLE_DEBUG 0 +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <regex.h> +#include "interface.h" + +// === CONSTANTS === +static const char *DIR_NAMES[] = {"INVL", "LEFT", "RIGHT", "UP", "DOWN"}; + +// === PROTOTYPES === + int main(int argc, char *argv[]); +void GetMove(char *line, tMove *Move); +void ReadBoardState(FILE *stream, char *dest); + int RunRegex(regex_t *regex, const char *string, int nMatches, regmatch_t *matches, const char *errorMessage); +void CompileRegex(regex_t *regex, const char *pattern, int flags); + +// === GLOBALS === +regex_t gRegex_move; +regex_t gRegex_res; + int giBoardWidth; + int giBoardHeight; +char *gaBoardState; + +// === CODE === +int main(int argc, char *argv[]) +{ + setbuf(stdin, NULL); + setbuf(stdout, NULL); + + // $X $Y $DIRECTION [$MULTIPLIER=1] $OUTCOME + CompileRegex(&gRegex_move, "([0-9]+) ([0-9]+) ([A-Z]+)( [0-9]+)? (.*)", REG_EXTENDED); + // (KILLS|DIES|BOTHDIE) $ATTACKER_RANK $DEFENDER_RANK + CompileRegex(&gRegex_res, "([A-Z_]+) (.) (.)", REG_EXTENDED); + + { + int colour_id; + char colour[6]; + char opponent[128]; + fscanf(stdin, "%s %s %i %i", colour, opponent, &giBoardWidth, &giBoardHeight); + + if( strcmp(colour, "RED") == 0 ) + colour_id = COLOUR_RED; + else if( strcmp(colour, "BLUE") == 0 ) + colour_id = COLOUR_BLUE; + else { + fprintf(stderr, "Oops... nutty manager, colour = %s\n", colour); + colour_id = COLOUR_RED; + } + + DEBUG("colour=%i, opponent='%s', dims = %ix%i", colour_id, opponent, giBoardWidth, giBoardHeight); + + AI_Initialise(colour_id, opponent); + } + + gaBoardState = malloc(giBoardWidth*giBoardHeight); + + for( ;; ) + { + tMove mymove, opponent_move; + char line[32]; + +// DEBUG("Waiting for move"); + ASSERT( fgets(line, sizeof(line), stdin) != NULL ); +// DEBUG("pm line = '%s'", line); + + if( strcmp(line, "\n") == 0 ) + continue ; + + if( strcmp(line, "START\n") == 0 ) + { +// DEBUG("New game"); + ReadBoardState(stdin, gaBoardState); + // TODO: Check if this hasn't happened before + opponent_move.x = 0; + opponent_move.y = 0; + opponent_move.dist = 0; + opponent_move.dir = 0; + } + else if( strncmp(line, "QUIT", 4) == 0 ) + { + // TODO: Result? + break ; + } + else if( strcmp(line, "VICTORY_FLAG\n") == 0 ) + { + // I win! + break; + } + else + { +// DEBUG("GetMove"); + GetMove(line, &opponent_move); +// DEBUG("Read board state"); + ReadBoardState(stdin, gaBoardState); + } + DEBUG("Opposing move %i,%i dir %i dist %i", + opponent_move.x, opponent_move.y, opponent_move.dir, opponent_move.dist); + + // Silly opponent, you lost + if( opponent_move.result == RESULT_VICTORY ) + break; + + // Determine move + AI_HandleMove(0, &opponent_move); + AI_DoMove(&mymove); + DEBUG("Chose move %i,%i %i %i", mymove.x, mymove.y, mymove.dir, mymove.dist); + printf("%i %i %s %i\n", mymove.x, mymove.y, DIR_NAMES[mymove.dir], mymove.dist); + + // Get result of the move + ASSERT( fgets(line, sizeof(line), stdin) != NULL ); +// DEBUG("res line = '%s'", line); +// + GetMove(line, &mymove); + AI_HandleMove(1, &mymove); + + // I WON! + if( mymove.result == RESULT_VICTORY ) + break; + +// DEBUG("Move over"); + } + + return 0; +} + +void GetMove(char *line, tMove *Move) +{ + regmatch_t matches[1+5]; + + // regex (\d+) (\d+) ([A-Z]*)(?: (\d+))? + RunRegex(&gRegex_move, line, 1+5, matches, "Move line"); + + char *xstr = line + matches[1].rm_so; + char *ystr = line + matches[2].rm_so; + char *dirstr = line + matches[3].rm_so; + + Move->x = atoi(xstr); + Move->y = atoi(ystr); +// DEBUG("(%i,%i)", Move->x, Move->y); + // Direction + if( strncmp(dirstr, "UP", 2) == 0 ) + Move->dir = DIR_UP; + else if( strncmp(dirstr, "DOWN", 4) == 0 ) + Move->dir = DIR_DOWN; + else if( strncmp(dirstr, "LEFT", 4) == 0 ) + Move->dir = DIR_LEFT; + else if( strncmp(dirstr, "RIGHT", 5) == 0 ) + Move->dir = DIR_RIGHT; + else { + fprintf(stderr, "Is the manager nuts? Dir = %.*s unk\n", + matches[3].rm_eo + matches[3].rm_so, dirstr + ); + fprintf(stderr, "line = '%s'\n", line); + Move->dir = DIR_INVAL; + } + if( matches[4].rm_so >= 0 ) + Move->dist = atoi(line + matches[4].rm_so + 1); + else + Move->dist = 1; + + // Outcome + char *outcome = line + matches[5].rm_so; + if( strncmp(outcome, "OK", 2) == 0 ) + Move->result = RESULT_OK; + else if( strncmp(outcome, "ILLEGAL", 7) == 0 ) + Move->result = RESULT_ILLEGAL; + else if( strncmp(outcome, "VICTORY_FLAG", 12) == 0 ) + Move->result = RESULT_VICTORY; + else if( strncmp(outcome, "VICTORY_ATTRITION", 17) == 0 ) + Move->result = RESULT_VICTORY; + else + { + regmatch_t res_matches[3+1]; + RunRegex(&gRegex_res, outcome, 3+1, res_matches, "Result portion"); + + char *res_str = outcome + res_matches[1].rm_so; + if( strncmp(res_str, "KILLS ", 6) == 0 ) + Move->result = RESULT_KILL; + else if( strncmp(res_str, "DIES ", 5) == 0 ) + Move->result = RESULT_DIES; + else if( strncmp(res_str, "BOTHDIE ", 8) == 0 ) + Move->result = RESULT_BOTHDIE; + else { + fprintf(stderr, "Is the manager nuts? Result = %.*s\n", + res_matches[1].rm_eo + res_matches[1].rm_so, res_str + ); + Move->result = RESULT_INVAL; + } + + Move->attacker = *(outcome + res_matches[2].rm_so); + Move->defender = *(outcome + res_matches[3].rm_so); + } +} + +void ReadBoardState(FILE *stream, char *dest) +{ + for( int i = 0; i < giBoardHeight; i ++ ) + { + char tmp[giBoardWidth+2]; + fgets(tmp, sizeof(tmp), stream); + DEBUG("BS %.*s", giBoardWidth, tmp); + memcpy(dest+i*giBoardWidth, tmp, giBoardWidth); + } +} + +int RunRegex(regex_t *regex, const char *string, int nMatches, regmatch_t *matches, const char *errorMessage) +{ + int ret; + + ret = regexec(regex, string, nMatches, matches, 0); + if( ret ) { + size_t len = regerror(ret, regex, NULL, 0); + char errorStr[len]; + regerror(ret, regex, errorStr, len); + fprintf(stderr, "string = '%s'\n", string); + fprintf(stderr, "%s\n%s", errorMessage, errorStr); + exit(-1); + } + + return ret; +} + +void CompileRegex(regex_t *regex, const char *pattern, int flags) +{ + int ret = regcomp(regex, pattern, flags); + if( ret ) { + size_t len = regerror(ret, regex, NULL, 0); + char errorStr[len]; + regerror(ret, regex, errorStr, len); + fprintf(stderr, "Regex compilation failed - %s\n", errorStr); + exit(-1); + } +} diff --git a/judge/simulator/simulate.py b/judge/simulator/simulate.py index b055945..d8db775 100755 --- a/judge/simulator/simulate.py +++ b/judge/simulator/simulate.py @@ -51,7 +51,7 @@ if len(sys.argv) >= 5: #Score dictionary - Tuple is of the form: (end score, other score, other result) where end is the player on whose turn the result occurs, other is the other player, other result indicates what to record the outcome as for the other player. -scores = {"VICTORY":(3,1, "DEFEAT"), "DEFEAT":(1,3, "VICTORY"), "SURRENDER":(0,3, "VICTORY"), "DRAW":(2,2, "DRAW"), "DRAW_DEFAULT":(1,1, "DRAW_DEFAULT"), "ILLEGAL":(-1,2, "DEFAULT"), "DEFAULT":(2,-1, "ILLEGAL"), "BOTH_ILLEGAL":(-1,-1, "BOTH_ILLEGAL"), "INTERNAL_ERROR":(0,0, "INTERNAL_ERROR"), "BAD_SETUP":(0,0,"BAD_SETUP")} +scores = {"VICTORY":(0.3,0.1, "DEFEAT"), "DEFEAT":(0.1,0.3, "VICTORY"), "SURRENDER":(0,0.3, "VICTORY"), "DRAW":(0.2,0.2, "DRAW"), "DRAW_DEFAULT":(0.1,0.1, "DRAW_DEFAULT"), "ILLEGAL":(-0.1,0.2, "DEFAULT"), "DEFAULT":(0.2,-0.1, "ILLEGAL"), "BOTH_ILLEGAL":(-0.1,-0.1, "BOTH_ILLEGAL"), "INTERNAL_ERROR":(0,0, "INTERNAL_ERROR"), "BAD_SETUP":(0,0,"BAD_SETUP")} #Verbose - print lots of useless stuff about what you are doing (kind of like matches talking on irc...) -- GitLab