Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
S
supercomputer_lab
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Gaurav Kukreja
supercomputer_lab
Commits
17980573
Commit
17980573
authored
Jul 11, 2012
by
Gaurav Kukreja
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
PV-Split Interactive Code
Signed-off-by:
Gaurav Kukreja
<
mailme.gaurav@gmail.com
>
parent
bdd2968e
Show whitespace changes
Inline
Side-by-side
Showing
29 changed files
with
6868 additions
and
1 deletion
+6868
-1
Aufgabe5.html
mpi-assign5/pv-split-interative/Aufgabe5.html
+92
-0
Makefile
mpi-assign5/pv-split-interative/Makefile
+58
-0
README
mpi-assign5/pv-split-interative/README
+163
-0
TODO
mpi-assign5/pv-split-interative/TODO
+9
-0
board.cpp
mpi-assign5/pv-split-interative/board.cpp
+1061
-0
board.h
mpi-assign5/pv-split-interative/board.h
+216
-0
eval.cpp
mpi-assign5/pv-split-interative/eval.cpp
+251
-0
eval.h
mpi-assign5/pv-split-interative/eval.h
+94
-0
move.cpp
mpi-assign5/pv-split-interative/move.cpp
+294
-0
move.h
mpi-assign5/pv-split-interative/move.h
+173
-0
network.cpp
mpi-assign5/pv-split-interative/network.cpp
+551
-0
network.h
mpi-assign5/pv-split-interative/network.h
+229
-0
player.cpp
mpi-assign5/pv-split-interative/player.cpp
+362
-0
player.cpp1
mpi-assign5/pv-split-interative/player.cpp1
+404
-0
position-endgame
mpi-assign5/pv-split-interative/position-endgame
+32
-0
position-midgame1
mpi-assign5/pv-split-interative/position-midgame1
+30
-0
position-midgame2
mpi-assign5/pv-split-interative/position-midgame2
+31
-0
position-start
mpi-assign5/pv-split-interative/position-start
+17
-0
referee.cpp
mpi-assign5/pv-split-interative/referee.cpp
+317
-0
search-abid-pvsplit.cpp
mpi-assign5/pv-split-interative/search-abid-pvsplit.cpp
+335
-0
search-abid.cpp
mpi-assign5/pv-split-interative/search-abid.cpp
+335
-0
search-minimax.cpp
mpi-assign5/pv-split-interative/search-minimax.cpp
+183
-0
search-onelevel.cpp
mpi-assign5/pv-split-interative/search-onelevel.cpp
+76
-0
search.cpp
mpi-assign5/pv-split-interative/search.cpp
+336
-0
search.h
mpi-assign5/pv-split-interative/search.h
+164
-0
start.cpp
mpi-assign5/pv-split-interative/start.cpp
+243
-0
tags
mpi-assign5/pv-split-interative/tags
+475
-0
Makefile
mpi-assign5/pv-split/Makefile
+2
-1
search-abid-pvsplit.cpp
mpi-assign5/pv-split/search-abid-pvsplit.cpp
+335
-0
No files found.
mpi-assign5/pv-split-interative/Aufgabe5.html
0 → 100644
View file @
17980573
<h1>
Aufgabe 5: Parallelisierung Spielsuche
</h2>
<h2>
Am Beispiel des Brettspiels Abalone
<br>
HPC-Praktikum SS07
</h2>
<P>
<h3>
1. Minimax
</h3>
Zur Einarbeitung in die f
ü
r die sp
ä
tere Parallelisierung
ben
ö
tigten Codeteile soll zun
ä
chst eine sequentielle
Minimax-Suchestrategie entwickelt werden.
Implementieren sie die Minimax-Suchestrategie f
ü
r Abalone in einer
Klasse MinimaxStrategy mit OneLevelStrategy als Vorlage und
SearchStrategy::_maxDepth als Tiefe, bis zu der Minimax suchen soll;
Aufrufbeispiele und Details zum Code sind in der README-Datei zum Code
zu finden.
<P>
Welche Leistung (Einheit "Bewertete Stellungen pro Sekunde") erreichen Sie
bei Nutzung "bester" Compileroptionen auf der Altix
bei verschiedenen Maximal-Suchtiefen (2,3,4,5) bezogen auf
<UL>
<LI>
die Anfangsposition des Spiels
<LI>
die Position in "position-midgame1"
<LI>
"position-midgame2" und
<LI>
"position-endgame"?
</UL>
Notieren sie sich auch die absolute Anzahl durchgef
ü
hrter Bewertungen.
Hinweis: "Bewertungen/s" gibt "player -v ..." aus.
<h3>
2. Parallelisierung Minimax
</h3>
Parallelisieren Sie die Minimaxsuche entweder mit OpenMP
(eventuell mit Workqueuing-Konstrukten; siehe Manual des Intel
Compilers) oder MPI
mit einer geeigneten Parallelisierungsstrategie
(f
ü
r MPI m
ü
ssen Sie player.c:main() entsprechend ab
ä
ndern).
<P>
Welchen Speedup
bekommen Sie f
ü
r die in (1) beschriebenen Parameter, also bezogen
auf der Performance-Wert "Bewertungen/s" f
ü
r 2,4,6,8 Prozessoren?
Wann kann der erreichbare Speedup von der aktuellen Stellung abh
ä
ngen?
<P>
Hinweis:
<UL>
<LI>
Ü
berlegen Sie, welche Variablen bei der Parallelisierung mit
OpenMP als privat deklariert werden m
ü
ssen. Dazu geh
ö
ren
bei C++ auch Objekte, die in jedem Thread privat vorhanden sein
m
ü
ssen, damit sich die Threads keine Daten
ü
berschreiben
(z.B. das Objekt f
ü
r die Spielposition).
</UL>
<h3>
3. Einfache Parallelisierung Alpha-Beta
</h3>
Der vorgegebene Alpha-Beta-Alogrithmus (ABID) l
ä
sst unn
ö
tige
Bewertungen aus. Um wieviel Prozent sinkt die absolute Anzahl
bewerteter Stellungen in den in Teilaufgabe (1) notierten F
ä
llen?
<P>
Was w
ä
re eine einfache Parallelisierung des Alpha-Beta-Algorithmus?
Implementieren Sie Ihre einfache Strategie. Der Suchparallelisierungs-Overhead
ist der Prozentsatz an unn
ö
tig durchgef
ü
hrten Bewertungen. Wie hoch
ist dieser Overhead in ihrer einfachen Strategie bei 2,3,4,6 Prozessoren und
den in Teilaufgabe (1) vorgegebenen Stellungen?
Welche Probleme hat die Parallelisierung ausserdem? Hinweise kann eine
Speedup-Kurve geben (und bei MPI-Code der Traceanalyzer!).
<h3>
4. Effiziente Parallelisierung Alpha-Beta
</h3>
Um zu einer besseren Parallelisierung zu gelangen, ist eine gut ausbalancierte
Partitionierung des erwarteten Berechnungsaufwandes wichtig. Man kann davon
ausgehen, dass der Alpha-Beta Suchbaum mit passender Heuristik der minimalen
Form sehr nahe kommt. Wie sieht diese aus?
<I>
F
ü
ndig wird man in "Lu: Parallel
Search of Narrow Game Trees", siehe HPC-Webseite
</I>
. In der Arbeit sind
auch Parallelisierungsstrategien beschrieben.
Eine wichtige Strategie ist
PVSplit, die in einem minimalen Alpha-Beta-Suchbaum die Kinder der sogenannten
ALL-Knoten in einer Tiefensuche parallel behandelt.
Implementieren Sie PVSplit in OpenMP oder MPI f
ü
r Abalone.
Geben Sie entsprechend zu Aufgabe 3 Speedupwerte f
ü
r ihre
Parallelisierung von PVSplit an.
<P>
Hinweise:
<UL>
<LI>
Bei Nutzung von OpenMP sollten Sie hier Workqueuing-Konstrukte
einsetzen
<LI>
Welche Bedingung und Codestelle bezeichnet einen ALL-Knoten in PVSplit?
Genau an diesen Stellen muss parallelisiert werden.
</UL>
mpi-assign5/pv-split-interative/Makefile
0 → 100644
View file @
17980573
### Compiler
### Chosen compiler has to be in path (use "module" to setup environment)
# Use this for GCC (warning: GCC < 4.2.x does not support OpenMP)
#CXX = g++
# Use this for the Intel C++ compiler ("icc" is only the C version)
#CXX = g++
# Use this for MPI
CXX
=
mpiCC
### Options
# Useful options for GCC
#CXXFLAGS=-O3
#LDFLAGS=
# Useful options for Intel C++
CXXFLAGS
=
-O3
LDFLAGS
=
LIB_OBJS
=
move.o board.o network.o search.o eval.o
SEARCH_OBJS
=
$(LIB_OBJS)
search-abid-pvsplit.o
#SEARCH_OBJS = $(LIB_OBJS) search-abid.o search-onelevel.o search-minimax.o
#SEARCH_OBJS = $(LIB_OBJS) search-parallel-minimax.o search-parallel-abid.cpp
all
:
player start referee
player
:
player.o $(SEARCH_OBJS)
$(CXX)
$(CXXFLAGS)
$(LDFLAGS)
-o
$@
$<
$(SEARCH_OBJS)
start
:
start.o $(LIB_OBJS)
$(CXX)
$(CXXFLAGS)
$(LDFLAGS)
-o
$@
$<
$(LIB_OBJS)
referee
:
referee.o $(LIB_OBJS)
$(CXX)
$(CXXFLAGS)
$(LDFLAGS)
-o
$@
$<
$(LIB_OBJS)
clean
:
rm
-rf
*
.o
*
~ player start referee networktest
networktest
:
tests/networktest.o network.o
$(CXX)
-o
networktest tests/networktest.o network.o
board.o
:
board.h board.cpp search.cpp
move.o
:
move.h move.cpp
network.o
:
network.h network.cpp
player.o
:
player.cpp
search.o
:
search.cpp board.cpp move.cpp
eval.o
:
eval.cpp board.cpp
start.o
:
start.cpp board.cpp move.cpp
referee.o
:
referee.cpp board.cpp move.cpp
search-onelevel.o
:
search.h board.h eval.h
search-abid.o
:
search.h board.h
search-minimax.o
:
search.h board.h eval.h
#search-parallel-minimax.o: search.h board.h eval.h
mpi-assign5/pv-split-interative/README
0 → 100644
View file @
17980573
Sequentieller Computerspieler fuer Abalone
==========================================
Abalone ist ein Brettspiel der Kategorie "2-Personen-Nullsummen-Spiel
mit vollstaendiger Information." Dabei bedeutet "Nullsummen-Spiel",
dass der Vorteil des einen Spielers der Nachteil des anderen ist, und
"Vollstaendige Information", dass es keine Zufallskomponente gibt.
Die Regeln gibt es unter
http://uk.abalonegames.com/rules/basic_rules/official_rules.html
und eine GUI-Version fuer Linux gibt es bei den KDE3 Spielen
("Kenolaba"). Der "Netwerk-Modus" dieser GUI benutzt denselben
Kommunikationsbus (siehe unten) wie die Programme hier.
Technische Beschreibung
========================
Die Kommunikation zwischen den Spielern basiert auf dem Austausch von
Spielpositionen auf einem Kommunikationsbus, an den sich mehrere
Prozesse anschliessen koennen. Auf dem Bus versandte Spielpositionen
werden an alle angeschlossenen Prozesse weitergeleitet.
Ein Kommunikationsbus wird identifiziert ueber eine Nummer und einen
Rechnernamen, auf dem der Kommunikationsbus existiert (die Implementierung
benutzt fuer den Kommunikationsbus einen TCP-Port auf dem Rechner, der
frei sein muss; Standard-Busnummer ist 23412).
Bei den folgenden Programmen laesst sich der Kommunikationsbus mit
Parameter "-p" angeben. Debuginformationen werden mit "-v" oder "-vv"
(mehr) ausgegeben. Hilfe zu Kommandozeilenoptionen mit "-h".
Teil der Spielposition ist uebrigens die Zugnummer und eine globale Zeit
bis zum erzwungenen Ende der Partie in Sekunden (wichtig fuer den
Turniermodus bei Benutzung eines Schiedsrichters - siehe unten).
Programm "player"
-----------------
Dies ist ein Computerspieler, der eine vorgegebene Farbe spielt, die man
optional als Argument übergibt. Farben sind entweder "X" oder "O" (Standard).
Farbe X spielt z.B. das Kommando "player X". Eine Spielstärke als Zahl kann
in der Kommandozeile als zweites Argument angegeben werden. Wie dieser
Wert genutzt wird, hängt von der im Computerspieler genutzten Strategie
ab; bei Spiel auf Zeit beispielsweise ist eine Spielstärke ohne Bedeutung.
Der Computerspieler schliesst sich einem Kommunikationsbus an
(Standardbus: "localhost:23412"), und wartet auf Spielpositionen.
Bekommt er eine Position, in der er spielen soll, berechnet er den besten
Zug und schickt die resultierende Spielposition an den Bus zurueck.
Programm "start"
----------------
Dieses Programm startet Spiele, beobachtet sie, und beendet sich, wenn
ein Spieler gewonnen hat. Allerdings kann es keinen Einfluss darauf nehmen,
wenn ein Spieler betruegt, d.h. Spielpositionen verschickt, die er gar
nicht erreichen kann, oder bei einem Spiel auf Zeit die verfügbaren
Zeiten falsch abändert. Gibt man einen Dateinamen als Argument an,
startet das Spiel an der in der Datei vorgegebenen Position.
Programm "referee" ("Schiedsrichter")
-------------------------------------
Dies hat dieselbe Funktion wie "start", kann aber als Schiedsrichter ein Spiel
überwachen, indem er das Spiel zwischen 2 Kommunikationsbussen vermittelt.
Dazu muss auf dem einen Bus ein Spieler fuer "O", und auf dem anderen ein
Spieler fuer "X" sitzen.
Der Schiedsrichter verschickt die Startposition (bzw. Position aus einer
gegebenen Datei) an beide Busse und wartet auf neue Positionen, die er
nur dann weitergibt an den anderen Bus, wenn sie sich durch einen
gültigen Zug ergeben. Dabei gibt der Schiedsrichter allein die Zeit vor
(seit Start des Spiels oder wie in der Datei vorgegeben). Der Schiedsrichter
entscheidet auch, wann ein Spieler wegen Zeitueberschreitung vorloren hat.
Aufrufbeispiele
================
Kompilieren mit "make".
Ohne Schiedsrichter:
player O &
player X &
start
Mit Schiedsrichter:
player -p 3000 O &
player -p 4000 X &
referee -p 3000 -p 4000
Die Startreihenfolge ist jeweils egal, da "start" and "referee" die
aktuelle Position an neue Teilnehmer im Kommunikationsbus
verschicken. Damit kann man Teilnehmer jederzeit abschiessen ('kill'en) und
neustarten: Sie klinken sich automatisch wieder ein.
Bei einem Spiel auf Zeit startet der Schiedsrichter,
sobald ein einziger (!) weiterer Teilnehmer existiert.
Beispiel fuer Netwerkspiel mit Tunneln
======================================
Auf Rechner "comp1" soll Spieler O laufen, wird sind auf "mycomp".
Zwischen mycomp und comp1 ist eine Firewall, die nur SSH erlaubt.
Auf mycomp soll Spieler X und ein Beobachter/Starter laufen.
Zum Verständnis ist es wichtig zu wissen, dass ein "Kommunikationsbus"
aus Punkt-zu-Punkt TCP-Verbindungen zwischen allen Teilnehmern eines
Busses bestehen, wobei jeweils der nächstfreie TCP-Port benutzt wird.
Beim Start eines Teilnehmers belegt er einen eingehenden Port (LISTEN),
der der Kanalnummer oder einer nächsthöhrem unbelegten Port entspricht.
Da ein Spieler auf dem entfernten "comp1" laufen soll, starten wir
SSH mit einem lokalen Forward auf den entfernten Rechner. Für lokale
Teilnehmer scheint damit der entfernte Teilnehmer lokal zu existieren.
Da die 2 lokalen Teilnehmer vom entfernten Rechner aus erreichbar
sein müssen, müssen 2 weitere Tunnel vom entfernten Rechner auf den
lokalen Rechner eingerichtet werden ("remote forwards").
Einloggen auf comp1 (z.B. Kommunikationskanal 5000):
ssh -L 5000:localhost:5000 -R 5001:localhost:5001 -R 5002:localhost:5002 comp1
comp1> ./player -p 5000 O
mycomp>./player -p 5000 X &
mycomp>./start -p 5000
Implementierung einer eigenen Suchstrategie
===========================================
Der Code ist in relativ einfachem C++ geschrieben. Für ein zur
Implementierung einer eigenen Suchstratie ausreichendes Verständnisses
des Codes sollte es genügen, sich die in "search-onelevel.cpp" implementierte
Strategie genau anzuschauen. Dieser Code ist dazu ausführlich
dokumentiert, und zeigt, welche Schritte für eine eigene Suchstrategie
vorgenommen werden müssen.
Für eine neue sequentielle Strategie (oder Parallelisierung mit OpenMP)
reicht es aus, diese Datei als Vorlage zu nehmen. Bei Parallelisierung
mit MPI muss main() so abgeändert werden, dass "Rank 0" den bisherigen
Code darin ausführt, und jeder andere MPI-Task in eine zu implementierende
Funktion springt, die auf Anfragen von Rank 0 wartet (Master-Slave).
"search-onelevel.cpp" ist ein Beispiel einer einfachen Suchstrategie
mit einer Vorausschau von einem Zug. Im Gegensatz zu dieser einfachen
Strategie sollte immer eine einstellbare Suchstärke
berücksichtigt werden, die als "_maxDepth" in SearchStrategy
erreichbar ist, und über den Kommandozeilenparameter definiert wird.
Beispiel einer komplexen Suchstrategie (Alpha-Beta mit
Tiefensuche: "Alpha/Beta with Iterative Deepening") ist in
search-abid.cpp zu finden.
Die Auswahl einer Suchstrategie erfolgt mit "player -s <Nummer> ...",
wobei die Zuordnung zwischen der Nummer einer Strategie und ihrem
Namen in der Hilfe angegeben wird, erreichbar über "player -h".
mpi-assign5/pv-split-interative/TODO
0 → 100644
View file @
17980573
Referee:
* Protocol extensions:
- ...
General:
* Network: Multiple messages on one TCP connection
* Network: Real asynch. breaks (really needed?)
* Gameconsole: Send messages
mpi-assign5/pv-split-interative/board.cpp
0 → 100644
View file @
17980573
/*
* Classes
* - Board: represents a game state
* - EvalScheme: evaluation scheme
*
* (c) 1997-2005, Josef Weidendorfer
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "search.h"
#include "board.h"
extern
int
thread_rank
;
#if 0
#include <assert.h>
#define CHECK(b) assert(b)
#else
#define CHECK(b)
#endif
/// MoveCounter
MoveCounter
::
MoveCounter
()
{
init
();
}
void
MoveCounter
::
init
()
{
for
(
int
i
=
0
;
i
<
Move
::
typeCount
;
i
++
)
_moveCount
[
i
]
=
0
;
for
(
int
i
=
0
;
i
<
inARowCount
;
i
++
)
_rowCount
[
i
]
=
0
;
}
int
MoveCounter
::
moveSum
()
{
int
sum
=
_moveCount
[
0
];
for
(
int
i
=
1
;
i
<
Move
::
typeCount
;
i
++
)
sum
+=
_moveCount
[
i
];
return
sum
;
}
/****************************** Class Board ****************************/
/* Board for start of a game */
int
Board
::
startBoard
[]
=
{
10
,
10
,
10
,
10
,
10
,
10
,
10
,
10
,
10
,
10
,
10
,
10
,
1
,
1
,
1
,
1
,
1
,
10
,
10
,
10
,
10
,
10
,
10
,
1
,
1
,
1
,
1
,
1
,
1
,
10
,
10
,
10
,
10
,
10
,
0
,
0
,
1
,
1
,
1
,
0
,
0
,
10
,
10
,
10
,
10
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
10
,
10
,
10
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
10
,
10
,
10
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
10
,
10
,
10
,
10
,
0
,
0
,
2
,
2
,
2
,
0
,
0
,
10
,
10
,
10
,
10
,
10
,
2
,
2
,
2
,
2
,
2
,
2
,
10
,
10
,
10
,
10
,
10
,
10
,
2
,
2
,
2
,
2
,
2
,
10
,
10
,
10
,
10
,
10
,
10
,
10
,
10
,
10
,
10
,
10
,
10
};
/* first centrum of board, then rings around (numbers are indexes) */
int
Board
::
order
[]
=
{
60
,
61
,
72
,
71
,
59
,
48
,
49
,
62
,
73
,
84
,
83
,
82
,
70
,
58
,
47
,
36
,
37
,
38
,
50
,
63
,
74
,
85
,
96
,
95
,
94
,
93
,
81
,
69
,
57
,
46
,
35
,
24
,
25
,
26
,
27
,
39
,
51
,
64
,
75
,
86
,
97
,
108
,
107
,
106
,
105
,
104
,
92
,
80
,
68
,
56
,
45
,
34
,
23
,
12
,
13
,
14
,
15
,
16
,
28
,
40
,
52
};
int
Board
::
direction
[]
=
{
-
11
,
1
,
12
,
11
,
-
1
,
-
12
,
-
11
,
1
};
Board
::
Board
()
{
clear
();
_verbose
=
0
;
_ev
=
0
;
}
void
Board
::
begin
(
int
startColor
)
{
int
i
;
for
(
i
=
0
;
i
<
AllFields
;
i
++
)
field
[
i
]
=
startBoard
[
i
];
storedFirst
=
storedLast
=
0
;
color
=
startColor
;
color1Count
=
color2Count
=
14
;
_msecsToPlay
[
color1
]
=
_msecsToPlay
[
color2
]
=
0
;
::
srand
(
0
);
// Initialize random sequence
}
void
Board
::
clear
()
{
int
i
;
for
(
i
=
0
;
i
<
AllFields
;
i
++
)
field
[
i
]
=
(
startBoard
[
i
]
==
out
)
?
out
:
free
;
storedFirst
=
storedLast
=
0
;
color1Count
=
color2Count
=
0
;
_msecsToPlay
[
color1
]
=
_msecsToPlay
[
color2
]
=
0
;
}
/** countFrom
*
* Used for board evaluation to count allowed move types and
* connectiveness. VERY similar to move generation.
*/
void
Board
::
countFrom
(
int
startField
,
int
color
,
MoveCounter
&
MCounter
)
{
int
d
,
dir
,
c
,
actField
,
c2
;
bool
left
,
right
;
/* 6 directions */
for
(
d
=
1
;
d
<
7
;
d
++
)
{
dir
=
fieldDiffOfDir
(
d
);
/* 2nd field */
c
=
field
[
actField
=
startField
+
dir
];
if
(
c
==
free
)
{
MCounter
.
incType
(
Move
::
move1
);
continue
;
}
if
(
c
!=
color
)
continue
;
/* 2nd == color */
MCounter
.
incRow
(
MoveCounter
::
inARow2
);
/* left side move 2 */
left
=
(
field
[
startField
+
fieldDiffOfDir
(
d
-
1
)]
==
free
);
if
(
left
)
{
left
=
(
field
[
actField
+
fieldDiffOfDir
(
d
-
1
)]
==
free
);
if
(
left
)
MCounter
.
incType
(
Move
::
left2
);
}
/* right side move 2 */
right
=
(
field
[
startField
+
fieldDiffOfDir
(
d
+
1
)]
==
free
);
if
(
right
)
{
right
=
(
field
[
actField
+
fieldDiffOfDir
(
d
+
1
)]
==
free
);
if
(
right
)
MCounter
.
incType
(
Move
::
right2
);
}
/* 3rd field */
c
=
field
[
actField
+=
dir
];
if
(
c
==
free
)
{
/* (c c .) */
MCounter
.
incType
(
Move
::
move2
);
continue
;
}
else
if
(
c
==
out
)
{
continue
;
}
else
if
(
c
!=
color
)
{
/* 4th field */
c
=
field
[
actField
+=
dir
];
if
(
c
==
free
)
{
/* (c c o .) */
MCounter
.
incType
(
Move
::
push1with2
);
}
else
if
(
c
==
out
)
{
/* (c c o |) */
MCounter
.
incType
(
Move
::
out1with2
);
}
continue
;
}
/* 3nd == color */
MCounter
.
incRow
(
MoveCounter
::
inARow3
);
/* left side move 3 */
if
(
left
)
{
left
=
(
field
[
actField
+
fieldDiffOfDir
(
d
-
1
)]
==
free
);
if
(
left
)
MCounter
.
incType
(
Move
::
left3
);
}
/* right side move 3 */
if
(
right
)
{
right
=
(
field
[
actField
+
fieldDiffOfDir
(
d
+
1
)]
==
free
);
if
(
right
)
MCounter
.
incType
(
Move
::
right3
);
}
/* 4th field */
c
=
field
[
actField
+=
dir
];
if
(
c
==
free
)
{
/* (c c c .) */
MCounter
.
incType
(
Move
::
move3
);
continue
;
}
else
if
(
c
==
out
)
{
continue
;
}
else
if
(
c
!=
color
)
{
/* 4nd == opponent */
/* 5. field */
c2
=
field
[
actField
+=
dir
];
if
(
c2
==
free
)
{
/* (c c c o .) */
MCounter
.
incType
(
Move
::
push1with3
);
continue
;
}
else
if
(
c2
==
out
)
{
/* (c c c o |) */
MCounter
.
incType
(
Move
::
out1with3
);
continue
;
}
if
(
c2
!=
c
)
continue
;
/* 5nd == opponent */
/* 6. field */
c2
=
field
[
actField
+=
dir
];
if
(
c2
==
free
)
{
/* (c c c o o .) */
MCounter
.
incType
(
Move
::
push2
);
}
else
if
(
c2
==
out
)
{
/* (c c c o o |) */
MCounter
.
incType
(
Move
::
out2
);
}
continue
;
}
/* 4nd == color */
MCounter
.
incRow
(
MoveCounter
::
inARow4
);
/* 5th field */
c
=
field
[
actField
+=
dir
];
if
(
c
!=
color
)
continue
;
/* 4nd == color */
MCounter
.
incRow
(
MoveCounter
::
inARow5
);
}
}
/* generate moves starting at field <startField> */
void
Board
::
generateFieldMoves
(
int
startField
,
MoveList
&
list
)
{
int
d
,
dir
,
c
,
actField
;
bool
left
,
right
;
int
opponent
=
(
color
==
color1
)
?
color2
:
color1
;
assert
(
field
[
startField
]
==
color
);
/* 6 directions */
for
(
d
=
1
;
d
<
7
;
d
++
)
{
dir
=
direction
[
d
];
/* 2nd field */
c
=
field
[
actField
=
startField
+
dir
];
if
(
c
==
free
)
{
/* (c .) */
list
.
insert
(
startField
,
d
,
Move
::
move1
);
continue
;
}
if
(
c
!=
color
)
continue
;
/* 2nd == color */
left
=
(
field
[
startField
+
direction
[
d
-
1
]]
==
free
);
if
(
left
)
{
left
=
(
field
[
actField
+
direction
[
d
-
1
]]
==
free
);
if
(
left
)
/* 2 left */
list
.
insert
(
startField
,
d
,
Move
::
left2
);
}
right
=
(
field
[
startField
+
direction
[
d
+
1
]]
==
free
);
if
(
right
)
{
right
=
(
field
[
actField
+
direction
[
d
+
1
]]
==
free
);
if
(
right
)
/* 2 right */
list
.
insert
(
startField
,
d
,
Move
::
right2
);
}
/* 3rd field */
c
=
field
[
actField
+=
dir
];
if
(
c
==
free
)
{
/* (c c .) */
list
.
insert
(
startField
,
d
,
Move
::
move2
);
continue
;
}
else
if
(
c
==
opponent
)
{
/* 4th field */
c
=
field
[
actField
+=
dir
];
if
(
c
==
free
)
{
/* (c c o .) */
list
.
insert
(
startField
,
d
,
Move
::
push1with2
);
}
else
if
(
c
==
out
)
{
/* (c c o |) */
list
.
insert
(
startField
,
d
,
Move
::
out1with2
);
}
continue
;
}
if
(
c
!=
color
)
continue
;
/* 3nd == color */
if
(
left
)
{
if
(
field
[
actField
+
direction
[
d
-
1
]]
==
free
)
/* 3 left */
list
.
insert
(
startField
,
d
,
Move
::
left3
);
}
if
(
right
)
{
if
(
field
[
actField
+
direction
[
d
+
1
]]
==
free
)
/* 3 right */
list
.
insert
(
startField
,
d
,
Move
::
right3
);
}
/* 4th field */
c
=
field
[
actField
+=
dir
];
if
(
c
==
free
)
{
/* (c c c .) */
list
.
insert
(
startField
,
d
,
Move
::
move3
);
continue
;
}
if
(
c
!=
opponent
)
continue
;
/* 4nd == opponent */
/* 5. field */
c
=
field
[
actField
+=
dir
];
if
(
c
==
free
)
{
/* (c c c o .) */
list
.
insert
(
startField
,
d
,
Move
::
push1with3
);
continue
;
}
else
if
(
c
==
out
)
{
/* (c c c o |) */
list
.
insert
(
startField
,
d
,
Move
::
out1with3
);
continue
;
}
if
(
c
!=
opponent
)
continue
;
/* 5nd == opponent */
/* 6. field */
c
=
field
[
actField
+=
dir
];
if
(
c
==
free
)
{
/* (c c c o o .) */
list
.
insert
(
startField
,
d
,
Move
::
push2
);
}
else
if
(
c
==
out
)
{
/* (c c c o o |) */
list
.
insert
(
startField
,
d
,
Move
::
out2
);
}
}
}
void
Board
::
generateMoves
(
MoveList
&
list
)
{
int
actField
,
f
;
for
(
f
=
0
;
f
<
RealFields
;
f
++
)
{
actField
=
order
[
f
];
if
(
field
[
actField
]
==
color
)
generateFieldMoves
(
actField
,
list
);
}
}
Move
Board
::
moveToReach
(
Board
*
b
,
bool
fuzzy
)
{
Move
m
;
/* can not move from invalid position */
int
state
=
validState
();
if
((
state
!=
valid1
)
&&
(
state
!=
valid2
))
return
m
;
if
(
!
fuzzy
)
{
if
(
b
->
moveNo
()
!=
_moveNo
+
1
)
{
if
(
_verbose
)
printf
(
"Board::moveToReach: moveNo %d => %d ?!
\n
"
,
_moveNo
,
b
->
moveNo
());
return
m
;
}
/* only time left for player can have decreased */
int
opponent
=
(
color
==
color1
)
?
color2
:
color1
;
if
(
_msecsToPlay
[
opponent
]
!=
b
->
msecsToPlay
(
opponent
))
{
if
(
_verbose
)
printf
(
"Board::moveToReach: Opponent time changed ?!
\n
"
);
return
m
;
}
if
(
_msecsToPlay
[
color
]
<
b
->
msecsToPlay
(
color
))
{
if
(
_verbose
)
printf
(
"Board::moveToReach: Player time increased ?!
\n
"
);
return
m
;
}
}
/* detect move drawn */
MoveList
l
;
generateMoves
(
l
);
if
(
_verbose
)
{
printf
(
"Board::moveToReach - %d allowed moves:
\n
"
,
l
.
getLength
());
Move
found
;
int
type
=
Move
::
none
;
while
(
l
.
getNext
(
m
,
Move
::
maxMoveType
))
{
playMove
(
m
);
bool
isSame
=
hasSameFields
(
b
);
takeBack
();
if
(
isSame
)
found
=
m
;
if
(
m
.
type
!=
type
)
{
type
=
m
.
type
;
printf
(
" %s:
\n
"
,
m
.
typeName
());
}
printf
(
" %s%s
\n
"
,
m
.
name
(),
isSame
?
" <== Choosen"
:
""
);
}
m
=
found
;
}
else
{
while
(
l
.
getNext
(
m
,
Move
::
maxMoveType
))
{
playMove
(
m
);
bool
isSame
=
hasSameFields
(
b
);
takeBack
();
if
(
isSame
)
break
;
}
}
return
m
;
}
bool
Board
::
hasSameFields
(
Board
*
b
)
{
int
f
,
actField
;
for
(
f
=
0
;
f
<
RealFields
;
f
++
)
{
actField
=
order
[
f
];
if
(
field
[
actField
]
!=
(
*
b
)[
actField
]
)
return
false
;
}
return
true
;
}
void
Board
::
playMove
(
const
Move
&
m
,
int
msecs
)
{
int
f
,
dir
,
dir2
;
int
opponent
=
(
color
==
color1
)
?
color2
:
color1
;
CHECK
(
isConsistent
()
);
if
(
++
storedLast
==
MvsStored
)
storedLast
=
0
;
/* Buffer full -> delete oldest entry */
if
(
storedLast
==
storedFirst
)
if
(
++
storedFirst
==
MvsStored
)
storedFirst
=
0
;
storedMove
[
storedLast
]
=
m
;
f
=
m
.
field
;
CHECK
(
(
m
.
type
>=
0
)
&&
(
m
.
type
<
Move
::
none
));
CHECK
(
field
[
f
]
==
color
);
field
[
f
]
=
free
;
dir
=
direction
[
m
.
direction
];
switch
(
m
.
type
)
{
case
Move
:
:
out2
:
/* (c c c o o |) */
CHECK
(
field
[
f
+
dir
]
==
color
);
CHECK
(
field
[
f
+
2
*
dir
]
==
color
);
CHECK
(
field
[
f
+
3
*
dir
]
==
opponent
);
CHECK
(
field
[
f
+
4
*
dir
]
==
opponent
);
CHECK
(
field
[
f
+
5
*
dir
]
==
out
);
field
[
f
+
3
*
dir
]
=
color
;
break
;
case
Move
:
:
out1with3
:
/* (c c c o |) */
CHECK
(
field
[
f
+
dir
]
==
color
);
CHECK
(
field
[
f
+
2
*
dir
]
==
color
);
CHECK
(
field
[
f
+
3
*
dir
]
==
opponent
);
CHECK
(
field
[
f
+
4
*
dir
]
==
out
);
field
[
f
+
3
*
dir
]
=
color
;
break
;
case
Move
:
:
move3
:
/* (c c c .) */
CHECK
(
field
[
f
+
dir
]
==
color
);
CHECK
(
field
[
f
+
2
*
dir
]
==
color
);
CHECK
(
field
[
f
+
3
*
dir
]
==
free
);
field
[
f
+
3
*
dir
]
=
color
;
break
;
case
Move
:
:
out1with2
:
/* (c c o |) */
CHECK
(
field
[
f
+
dir
]
==
color
);
CHECK
(
field
[
f
+
2
*
dir
]
==
opponent
);
CHECK
(
field
[
f
+
3
*
dir
]
==
out
);
field
[
f
+
2
*
dir
]
=
color
;
break
;
case
Move
:
:
move2
:
/* (c c .) */
CHECK
(
field
[
f
+
dir
]
==
color
);
CHECK
(
field
[
f
+
2
*
dir
]
==
free
);
field
[
f
+
2
*
dir
]
=
color
;
break
;
case
Move
:
:
push2
:
/* (c c c o o .) */
CHECK
(
field
[
f
+
dir
]
==
color
);
CHECK
(
field
[
f
+
2
*
dir
]
==
color
);
CHECK
(
field
[
f
+
3
*
dir
]
==
opponent
);
CHECK
(
field
[
f
+
4
*
dir
]
==
opponent
);
CHECK
(
field
[
f
+
5
*
dir
]
==
free
);
field
[
f
+
3
*
dir
]
=
color
;
field
[
f
+
5
*
dir
]
=
opponent
;
break
;
case
Move
:
:
left3
:
dir2
=
direction
[
m
.
direction
-
1
];
CHECK
(
field
[
f
+
dir
]
==
color
);
CHECK
(
field
[
f
+
2
*
dir
]
==
color
);
CHECK
(
field
[
f
+
dir2
]
==
free
);
CHECK
(
field
[
f
+
dir
+
dir2
]
==
free
);
CHECK
(
field
[
f
+
2
*
dir
+
dir2
]
==
free
);
field
[
f
+
dir2
]
=
color
;
field
[
f
+=
dir
]
=
free
;
field
[
f
+
dir2
]
=
color
;
field
[
f
+=
dir
]
=
free
;
field
[
f
+
dir2
]
=
color
;
break
;
case
Move
:
:
right3
:
dir2
=
direction
[
m
.
direction
+
1
];
CHECK
(
field
[
f
+
dir
]
==
color
);
CHECK
(
field
[
f
+
2
*
dir
]
==
color
);
CHECK
(
field
[
f
+
dir2
]
==
free
);
CHECK
(
field
[
f
+
dir
+
dir2
]
==
free
);
CHECK
(
field
[
f
+
2
*
dir
+
dir2
]
==
free
);
field
[
f
+
dir2
]
=
color
;
field
[
f
+=
dir
]
=
free
;
field
[
f
+
dir2
]
=
color
;
field
[
f
+=
dir
]
=
free
;
field
[
f
+
dir2
]
=
color
;
break
;
case
Move
:
:
push1with3
:
/* (c c c o .) => (. c c c o) */
CHECK
(
field
[
f
+
dir
]
==
color
);
CHECK
(
field
[
f
+
2
*
dir
]
==
color
);
CHECK
(
field
[
f
+
3
*
dir
]
==
opponent
);
CHECK
(
field
[
f
+
4
*
dir
]
==
free
);
field
[
f
+
3
*
dir
]
=
color
;
field
[
f
+
4
*
dir
]
=
opponent
;
break
;
case
Move
:
:
push1with2
:
/* (c c o .) => (. c c o) */
CHECK
(
field
[
f
+
dir
]
==
color
);
CHECK
(
field
[
f
+
2
*
dir
]
==
opponent
);
CHECK
(
field
[
f
+
3
*
dir
]
==
free
);
field
[
f
+
2
*
dir
]
=
color
;
field
[
f
+
3
*
dir
]
=
opponent
;
break
;
case
Move
:
:
left2
:
dir2
=
direction
[
m
.
direction
-
1
];
CHECK
(
field
[
f
+
dir
]
==
color
);
CHECK
(
field
[
f
+
dir2
]
==
free
);
CHECK
(
field
[
f
+
dir
+
dir2
]
==
free
);
field
[
f
+
dir2
]
=
color
;
field
[
f
+=
dir
]
=
free
;
field
[
f
+
dir2
]
=
color
;
break
;
case
Move
:
:
right2
:
dir2
=
direction
[
m
.
direction
+
1
];
CHECK
(
field
[
f
+
dir
]
==
color
);
CHECK
(
field
[
f
+
dir2
]
==
free
);
CHECK
(
field
[
f
+
dir
+
dir2
]
==
free
);
field
[
f
+
dir2
]
=
color
;
field
[
f
+=
dir
]
=
free
;
field
[
f
+
dir2
]
=
color
;
break
;
case
Move
:
:
move1
:
/* (c .) => (. c) */
CHECK
(
field
[
f
+
dir
]
==
free
);
field
[
f
+
dir
]
=
color
;
break
;
default
:
break
;
}
if
(
m
.
isOutMove
())
{
if
(
color
==
color1
)
color2Count
--
;
else
color1Count
--
;
}
/* adjust move number and time */
_moveNo
++
;
if
((
_msecsToPlay
[
color
]
>
0
)
&&
(
msecs
>
0
))
{
if
(
_msecsToPlay
[
color
]
>
msecs
)
_msecsToPlay
[
color
]
-=
msecs
;
else
_msecsToPlay
[
color
]
=
0
;
}
/* change actual color */
color
=
opponent
;
CHECK
(
isConsistent
()
);
}
bool
Board
::
takeBack
()
{
int
f
,
dir
,
dir2
;
int
opponent
=
color
;
Move
&
m
=
storedMove
[
storedLast
];
CHECK
(
isConsistent
()
);
if
(
storedFirst
==
storedLast
)
return
false
;
/* change actual color */
color
=
(
color
==
color1
)
?
color2
:
color1
;
if
(
m
.
isOutMove
())
{
if
(
color
==
color1
)
color2Count
++
;
else
color1Count
++
;
}
f
=
m
.
field
;
CHECK
(
field
[
f
]
==
free
);
field
[
f
]
=
color
;
dir
=
direction
[
m
.
direction
];
switch
(
m
.
type
)
{
case
Move
:
:
out2
:
/* (. c c c o |) => (c c c o o |) */
CHECK
(
field
[
f
+
dir
]
==
color
);
CHECK
(
field
[
f
+
2
*
dir
]
==
color
);
CHECK
(
field
[
f
+
3
*
dir
]
==
color
);
CHECK
(
field
[
f
+
4
*
dir
]
==
opponent
);
CHECK
(
field
[
f
+
5
*
dir
]
==
out
);
field
[
f
+
3
*
dir
]
=
opponent
;
break
;
case
Move
:
:
out1with3
:
/* (. c c c |) => (c c c o |) */
CHECK
(
field
[
f
+
dir
]
==
color
);
CHECK
(
field
[
f
+
2
*
dir
]
==
color
);
CHECK
(
field
[
f
+
3
*
dir
]
==
color
);
CHECK
(
field
[
f
+
4
*
dir
]
==
out
);
field
[
f
+
3
*
dir
]
=
opponent
;
break
;
case
Move
:
:
move3
:
/* (. c c c) => (c c c .) */
CHECK
(
field
[
f
+
dir
]
==
color
);
CHECK
(
field
[
f
+
2
*
dir
]
==
color
);
CHECK
(
field
[
f
+
3
*
dir
]
==
color
);
field
[
f
+
3
*
dir
]
=
free
;
break
;
case
Move
:
:
out1with2
:
/* (. c c | ) => (c c o |) */
CHECK
(
field
[
f
+
dir
]
==
color
);
CHECK
(
field
[
f
+
2
*
dir
]
==
color
);
CHECK
(
field
[
f
+
3
*
dir
]
==
out
);
field
[
f
+
2
*
dir
]
=
opponent
;
break
;
case
Move
:
:
move2
:
/* (. c c) => (c c .) */
CHECK
(
field
[
f
+
dir
]
==
color
);
CHECK
(
field
[
f
+
2
*
dir
]
==
color
);
field
[
f
+
2
*
dir
]
=
free
;
break
;
case
Move
:
:
push2
:
/* (. c c c o o) => (c c c o o .) */
CHECK
(
field
[
f
+
dir
]
==
color
);
CHECK
(
field
[
f
+
2
*
dir
]
==
color
);
CHECK
(
field
[
f
+
3
*
dir
]
==
color
);
CHECK
(
field
[
f
+
4
*
dir
]
==
opponent
);
CHECK
(
field
[
f
+
5
*
dir
]
==
opponent
);
field
[
f
+
3
*
dir
]
=
opponent
;
field
[
f
+
5
*
dir
]
=
free
;
break
;
case
Move
:
:
left3
:
dir2
=
direction
[
m
.
direction
-
1
];
CHECK
(
field
[
f
+
dir
]
==
free
);
CHECK
(
field
[
f
+
2
*
dir
]
==
free
);
CHECK
(
field
[
f
+
dir2
]
==
color
);
CHECK
(
field
[
f
+
dir
+
dir2
]
==
color
);
CHECK
(
field
[
f
+
2
*
dir
+
dir2
]
==
color
);
field
[
f
+
dir2
]
=
free
;
field
[
f
+=
dir
]
=
color
;
field
[
f
+
dir2
]
=
free
;
field
[
f
+=
dir
]
=
color
;
field
[
f
+
dir2
]
=
free
;
break
;
case
Move
:
:
right3
:
dir2
=
direction
[
m
.
direction
+
1
];
CHECK
(
field
[
f
+
dir
]
==
free
);
CHECK
(
field
[
f
+
2
*
dir
]
==
free
);
CHECK
(
field
[
f
+
dir2
]
==
color
);
CHECK
(
field
[
f
+
dir
+
dir2
]
==
color
);
CHECK
(
field
[
f
+
2
*
dir
+
dir2
]
==
color
);
field
[
f
+
dir2
]
=
free
;
field
[
f
+=
dir
]
=
color
;
field
[
f
+
dir2
]
=
free
;
field
[
f
+=
dir
]
=
color
;
field
[
f
+
dir2
]
=
free
;
break
;
case
Move
:
:
push1with3
:
/* (. c c c o) => (c c c o .) */
CHECK
(
field
[
f
+
dir
]
==
color
);
CHECK
(
field
[
f
+
2
*
dir
]
==
color
);
CHECK
(
field
[
f
+
3
*
dir
]
==
color
);
CHECK
(
field
[
f
+
4
*
dir
]
==
opponent
);
field
[
f
+
3
*
dir
]
=
opponent
;
field
[
f
+
4
*
dir
]
=
free
;
break
;
case
Move
:
:
push1with2
:
/* (. c c o) => (c c o .) */
CHECK
(
field
[
f
+
dir
]
==
color
);
CHECK
(
field
[
f
+
2
*
dir
]
==
color
);
CHECK
(
field
[
f
+
3
*
dir
]
==
opponent
);
field
[
f
+
2
*
dir
]
=
opponent
;
field
[
f
+
3
*
dir
]
=
free
;
break
;
case
Move
:
:
left2
:
dir2
=
direction
[
m
.
direction
-
1
];
CHECK
(
field
[
f
+
dir
]
==
free
);
CHECK
(
field
[
f
+
dir2
]
==
color
);
CHECK
(
field
[
f
+
dir
+
dir2
]
==
color
);
field
[
f
+
dir2
]
=
free
;
field
[
f
+=
dir
]
=
color
;
field
[
f
+
dir2
]
=
free
;
break
;
case
Move
:
:
right2
:
dir2
=
direction
[
m
.
direction
+
1
];
CHECK
(
field
[
f
+
dir
]
==
free
);
CHECK
(
field
[
f
+
dir2
]
==
color
);
CHECK
(
field
[
f
+
dir
+
dir2
]
==
color
);
field
[
f
+
dir2
]
=
free
;
field
[
f
+=
dir
]
=
color
;
field
[
f
+
dir2
]
=
free
;
break
;
case
Move
:
:
move1
:
/* (. c) => (c .) */
CHECK
(
field
[
f
+
dir
]
==
color
);
field
[
f
+
dir
]
=
free
;
break
;
default
:
break
;
}
if
(
--
storedLast
<
0
)
storedLast
=
MvsStored
-
1
;
/* adjust move number. Time is intentionally not reset */
_moveNo
--
;
CHECK
(
isConsistent
()
);
return
true
;
}
int
Board
::
movesStored
()
{
int
c
=
storedLast
-
storedFirst
;
if
(
c
<
0
)
c
+=
MvsStored
;
return
c
;
}
/** validState
*
* Check for a valid board position to play from:
* (1) Number of balls for each color has to be between 9 and 14
* (2) There must be a move possible for actual color
*/
int
Board
::
validState
()
{
MoveCounter
mc
;
int
c1
=
0
,
c2
=
0
;
int
i
,
j
,
moveCount
,
res
;
int
color
=
actColor
();
for
(
i
=
0
;
i
<
AllFields
;
i
++
)
{
j
=
field
[
i
];
if
(
j
==
color1
)
c1
++
;
if
(
j
==
color2
)
c2
++
;
if
(
j
==
color
)
countFrom
(
i
,
color
,
mc
);
}
color1Count
=
c1
;
color2Count
=
c2
;
moveCount
=
mc
.
moveSum
();
if
(
c1
==
0
&&
c2
==
0
)
res
=
empty
;
// impossible token counts
else
if
(
c1
>
14
||
c2
>
14
||
(
c1
<
9
&&
c2
<
9
))
res
=
invalid
;
else
if
(
c1
<
9
)
res
=
win2
;
else
if
(
c2
<
9
)
res
=
win1
;
// counts are in valid range...
else
if
(
moveCount
>
0
)
{
if
(
color
==
color1
)
{
if
(
_msecsToPlay
[
color1
]
>
0
&&
_msecsToPlay
[
color2
]
<=
0
)
res
=
timeout2
;
else
res
=
valid1
;
}
else
{
if
(
_msecsToPlay
[
color2
]
>
0
&&
_msecsToPlay
[
color1
]
<=
0
)
res
=
timeout1
;
else
res
=
valid2
;
}
}
// color which has to draw can not do any move... win for opponent!
else
if
(
color
==
color1
)
res
=
win2
;
else
res
=
win1
;
#ifdef MYTRACE
if
(
spyLevel
>
2
)
{
indent
(
spyDepth
);
printf
(
"Valid: %s (Color1 %d, Color2 %d, moveCount of %d: %d)
\n
"
,
(
res
==
empty
)
?
"empty"
:
(
res
==
valid
)
?
"valid"
:
"invalid"
,
c1
,
c2
,
color
,
moveCount
);
}
#endif
return
res
;
}
char
*
Board
::
stateDescription
(
int
s
)
{
switch
(
s
)
{
case
empty
:
return
"Empty board"
;
case
invalid
:
return
"Invalid board"
;
case
valid1
:
return
"O about to move..."
;
case
valid2
:
return
"X about to move..."
;
case
timeout1
:
return
"O timed out. X wins!"
;
case
timeout2
:
return
"X timed out. O wins!"
;
case
win1
:
return
"O wins the game!"
;
case
win2
:
return
"X wins the game!"
;
default
:
break
;
}
return
"Unknown state?"
;
}
bool
Board
::
isConsistent
()
{
int
c1
=
0
,
c2
=
0
;
int
i
,
j
;
for
(
i
=
0
;
i
<
RealFields
;
i
++
)
{
j
=
field
[
order
[
i
]];
if
(
j
==
color1
)
c1
++
;
if
(
j
==
color2
)
c2
++
;
}
return
(
color1Count
==
c1
&&
color2Count
==
c2
);
}
void
Board
::
setSearchStrategy
(
SearchStrategy
*
ss
)
{
_ss
=
ss
;
}
void
Board
::
setDepth
(
int
d
)
{
if
(
!
_ss
)
return
;
_ss
->
setMaxDepth
(
d
+
1
);
}
Move
&
Board
::
bestMove
()
{
static
Move
best
;
best
=
_ss
->
bestMove
(
this
);
return
best
;
}
Move
&
Board
::
nextMove
()
{
return
_ss
->
nextMove
();
}
void
Board
::
stopSearch
()
{
_ss
->
stopSearch
();
}
Move
Board
::
randomMove
()
{
Move
m
;
MoveList
list
;
generateMoves
(
list
);
int
l
=
list
.
getLength
();
int
j
=
(
::
rand
()
%
l
)
+
1
;
while
(
j
!=
0
)
{
list
.
getNext
(
m
,
Move
::
none
);
j
--
;
}
return
m
;
}
void
Board
::
print
()
{
printf
(
getState
()
);
}
/* Returns a board human readable board representation.
* The returned string will be overwritten in later calls.
*/
char
*
Board
::
getState
()
{
static
char
b
[
1024
];
int
pos
=
0
;
int
row
,
i
;
char
spaces
[]
=
" "
;
const
char
*
z
[]
=
{
". "
,
"O "
,
"X "
,
"o "
,
"x "
};
pos
=
sprintf
(
b
,
"
\n
"
);
if
(
_moveNo
>=
0
)
{
pos
+=
sprintf
(
b
+
pos
,
"#%d"
,
_moveNo
);
pos
+=
sprintf
(
b
+
pos
,
" O: %d"
,
color1Count
);
if
(
_msecsToPlay
[
color1
]
>
0
)
pos
+=
sprintf
(
b
+
pos
,
" (%d.%03d s)"
,
_msecsToPlay
[
color1
]
/
1000
,
_msecsToPlay
[
color1
]
%
1000
);
pos
+=
sprintf
(
b
+
pos
,
", X: %d"
,
color2Count
);
if
(
_msecsToPlay
[
color2
]
>
0
)
pos
+=
sprintf
(
b
+
pos
,
" (%d.%03d s)"
,
_msecsToPlay
[
color2
]
/
1000
,
_msecsToPlay
[
color2
]
%
1000
);
pos
+=
sprintf
(
b
+
pos
,
"
\n
"
);
}
pos
+=
sprintf
(
b
+
pos
,
" -----------
\n
"
);
for
(
row
=
0
;
row
<
4
;
row
++
)
{
pos
+=
sprintf
(
b
+
pos
,
"%s/ "
,
spaces
+
row
);
for
(
i
=
0
;
i
<
5
+
row
;
i
++
)
pos
+=
sprintf
(
b
+
pos
,
"%s"
,
z
[
field
[
row
*
11
+
12
+
i
]]);
pos
+=
sprintf
(
b
+
pos
,
"
\\\n
"
);
}
pos
+=
sprintf
(
b
+
pos
,
" | "
);
for
(
i
=
0
;
i
<
9
;
i
++
)
pos
+=
sprintf
(
b
+
pos
,
"%s"
,
z
[
field
[
56
+
i
]]);
pos
+=
sprintf
(
b
+
pos
,
"|
\n
"
);
for
(
row
=
0
;
row
<
4
;
row
++
)
{
pos
+=
sprintf
(
b
+
pos
,
"%s
\\
"
,
spaces
+
3
-
row
);
for
(
i
=
0
;
i
<
8
-
row
;
i
++
)
pos
+=
sprintf
(
b
+
pos
,
"%s"
,
z
[
field
[
68
+
row
*
12
+
i
]]);
pos
+=
sprintf
(
b
+
pos
,
"/
\n
"
);
}
pos
+=
sprintf
(
b
+
pos
,
" -----------
\n
"
);
return
b
;
}
bool
Board
::
setState
(
char
*
s
)
{
int
row
=
0
,
column
=
0
;
bool
found
=
false
;
color1Count
=
0
;
color2Count
=
0
;
_msecsToPlay
[
color1
]
=
0
;
_msecsToPlay
[
color2
]
=
0
;
if
(
s
==
0
)
return
false
;
while
(
*
s
)
{
if
(
*
s
==
'#'
)
{
int
m
=
0
;
int
color
=
-
1
;
s
++
;
// parse "#<moveNo> - [O: <count> / <secsToPlay>, X:]"
while
((
*
s
>=
'0'
)
&&
(
*
s
<=
'9'
))
m
=
10
*
m
+
(
*
s
++
-
'0'
);
_moveNo
=
m
;
while
(
*
s
)
{
if
(
*
s
==
'\n'
)
break
;
if
(
*
s
==
'O'
)
{
color
=
color1
;
}
if
(
*
s
==
'X'
)
{
color
=
color2
;
}
if
((
*
s
==
'('
)
&&
(
color
>-
1
))
{
s
++
;
int
secs
=
0
,
msecs
=
0
;
while
(
*
s
==
' '
)
s
++
;
while
((
*
s
>=
'0'
)
&&
(
*
s
<=
'9'
))
secs
=
10
*
secs
+
(
*
s
++
-
'0'
);
if
(
*
s
==
'.'
)
{
int
val
=
100
;
s
++
;
while
((
*
s
>=
'0'
)
&&
(
*
s
<=
'9'
))
{
msecs
+=
val
*
(
*
s
++
-
'0'
);
val
/=
10
;
}
}
_msecsToPlay
[
color
]
=
1000
*
secs
+
msecs
;
color
=
-
1
;
}
s
++
;
}
}
if
(
row
*
11
+
12
+
column
>
AllFields
)
break
;
if
(
*
s
==
'.'
||
*
s
==
'X'
||
*
s
==
'O'
||
*
s
==
'x'
||
*
s
==
'o'
)
{
found
=
true
;
field
[
row
*
11
+
12
+
column
]
=
(
*
s
==
'O'
)
?
color1
:
(
*
s
==
'o'
)
?
color1
:
(
*
s
==
'X'
)
?
color2
:
(
*
s
==
'x'
)
?
color2
:
free
;
if
(
field
[
row
*
11
+
12
+
column
]
==
color1
)
color1Count
++
;
if
(
field
[
row
*
11
+
12
+
column
]
==
color2
)
color2Count
++
;
column
++
;
}
if
(
found
&&
(
*
s
==
'\n'
))
{
row
++
;
if
(
row
<
5
)
column
=
0
;
else
column
=
row
-
4
;
if
(
row
>
8
)
break
;
}
s
++
;
}
if
(
row
<
9
)
return
false
;
color
=
((
_moveNo
%
2
)
==
0
)
?
color1
:
color2
;
return
true
;
}
void
Board
::
setSpyLevel
(
int
level
)
{
spyLevel
=
level
;
}
mpi-assign5/pv-split-interative/board.h
0 → 100644
View file @
17980573
/*
* Classes
* - Board: represents a game state
* - EvalScheme: evaluation scheme
*
* (c) 1997-2005, Josef Weidendorfer
*/
#ifndef BOARD_H
#define BOARD_H
#include "move.h"
class
SearchStrategy
;
class
Evaluator
;
/**
* Class MoveCounter
*
* Helper class for board characteristics:
* Counter for move types and connectivity
* See Board::countFrom().
*/
class
MoveCounter
{
public
:
enum
InARowType
{
inARow2
=
0
,
inARow3
,
inARow4
,
inARow5
,
inARowCount
};
MoveCounter
();
void
init
();
int
moveCount
(
int
t
)
{
return
_moveCount
[
t
];
}
void
incType
(
int
t
)
{
_moveCount
[
t
]
++
;
}
int
moveSum
();
int
rowCount
(
int
r
)
{
return
_rowCount
[
r
];
}
void
incRow
(
int
r
)
{
_rowCount
[
r
]
++
;
}
private
:
int
_moveCount
[
Move
::
typeCount
];
int
_rowCount
[
inARowCount
];
};
/**
* Board: represents a game state
*
* Includes methods for
* - play/take back moves
* - generate allowed moves
* - calculate rating for position
* - search for best move
*/
class
Board
{
friend
class
Evaluator
;
public
:
Board
();
~
Board
()
{};
/* different states of one field */
enum
{
out
=
10
,
free
=
0
,
color1
,
color2
,
color1bright
,
color2bright
};
enum
{
AllFields
=
121
,
/* visible + ring of unvisible around */
RealFields
=
61
,
/* number of visible fields */
MvsStored
=
100
};
enum
{
empty
=
0
,
valid1
,
// valid state with color1 to draw
valid2
,
// valid state with color2 to draw
timeout1
,
// time out for color1 -> win for color2
timeout2
,
// time out for color2 -> win for color1
win1
,
// color1 won
win2
,
// color2 won
invalid
};
/* fill Board with defined values */
void
begin
(
int
startColor
);
/* start of a game */
void
clear
();
/* empty board */
/* fields can't be changed ! */
int
operator
[](
int
no
)
const
;
int
actColor
()
const
{
return
color
;
}
/* helper in evaluation: calculate move type counts */
void
countFrom
(
int
startField
,
int
color
,
MoveCounter
&
);
/* Generate list of allowed moves for player with <color>
* Returns a calculated value for actual position */
void
generateMoves
(
MoveList
&
list
);
/* Check if a game position is reachable from the current one.
* If <fuzzy> is false, this check includes times and move number.
* Returns move which was played. Returns move of type Move::none if not.
*/
Move
moveToReach
(
Board
*
,
bool
fuzzy
);
/** Check if another board has same tokens set */
bool
hasSameFields
(
Board
*
);
/* Play the given move.
* Played moves can be taken back (<MvsStored> moves are remembered)
* Time to play is adjusted if msecs > 0.
*
* Warning: Only moves that are generated with Board::generateMoves()
* should be passed. If the move cannot be played, an assertion is raised.
*/
void
playMove
(
const
Move
&
m
,
int
msecs
=
0
);
bool
takeBack
();
/* if not remembered, do nothing */
int
movesStored
();
/* return how many moves are remembered */
Move
&
lastMove
()
{
return
storedMove
[
storedLast
];
}
void
showHist
();
/* Evaluator to use */
void
setEvaluator
(
Evaluator
*
ev
)
{
_ev
=
ev
;
}
void
setActColor
(
int
c
)
{
color
=
c
;
}
void
setColor1Count
(
int
c
)
{
color1Count
=
c
;
}
void
setColor2Count
(
int
c
)
{
color2Count
=
c
;
}
void
setField
(
int
i
,
int
v
)
{
field
[
i
]
=
v
;
}
void
setSpyLevel
(
int
);
int
getColor1Count
()
{
return
color1Count
;
}
int
getColor2Count
()
{
return
color2Count
;
}
bool
isValid
()
{
return
(
color1Count
>
8
&&
color2Count
>
8
);
}
/* Is this position valid, a winner position or invalid? */
int
validState
();
/* returns a string for the valid state */
static
char
*
stateDescription
(
int
);
/* Check that color1Count & color2Count is consistent with board */
bool
isConsistent
();
/* Searching best move */
void
setSearchStrategy
(
SearchStrategy
*
ss
);
void
setDepth
(
int
d
);
Move
&
bestMove
();
/* next move in prinipal variation */
Move
&
nextMove
();
Move
randomMove
();
void
stopSearch
();
void
setMoveNo
(
int
n
)
{
_moveNo
=
n
;
}
void
setMSecsToPlay
(
int
c
,
int
s
)
{
_msecsToPlay
[
c
]
=
s
;
}
int
moveNo
()
{
return
_moveNo
;
}
int
msecsToPlay
(
int
c
)
{
return
_msecsToPlay
[
c
];
}
/* Readable ASCII representation */
char
*
getState
();
/* Returns true if new state was set */
bool
setState
(
char
*
);
void
setVerbose
(
int
v
)
{
_verbose
=
v
;
}
void
updateSpy
(
bool
b
)
{
bUpdateSpy
=
b
;
}
/* simple terminal view of position */
void
print
();
static
int
fieldDiffOfDir
(
int
d
)
{
return
direction
[
d
];
}
private
:
void
setFieldValues
();
/* helper function for generateMoves */
void
generateFieldMoves
(
int
,
MoveList
&
);
// random seed
int
seed
;
int
field
[
AllFields
];
/* actual board */
int
color1Count
,
color2Count
;
int
color
;
/* actual color */
Move
storedMove
[
MvsStored
];
/* stored moves */
int
storedFirst
,
storedLast
;
/* stored in ring puffer manner */
int
_moveNo
;
/* move number in current game */
int
_msecsToPlay
[
3
];
/* time in seconds to play */
bool
show
,
bUpdateSpy
;
int
spyLevel
,
spyDepth
;
SearchStrategy
*
_ss
;
Evaluator
*
_ev
;
int
_verbose
;
/* constant arrays */
static
int
startBoard
[
AllFields
];
static
int
order
[
RealFields
];
static
int
direction
[
8
];
public
:
/* for fast evaluation */
int
*
fieldArray
()
{
return
field
;
}
};
inline
int
Board
::
operator
[](
int
no
)
const
{
return
(
no
<
12
||
no
>
120
)
?
out
:
field
[
no
];
}
#endif
mpi-assign5/pv-split-interative/eval.cpp
0 → 100644
View file @
17980573
/**
* EvalScheme and Evaluator
*/
#include "eval.h"
// Default Values
static
int
defaultRingValue
[]
=
{
45
,
35
,
25
,
10
,
0
};
static
int
defaultRingDiff
[]
=
{
0
,
10
,
10
,
8
,
5
};
static
int
defaultStoneValue
[]
=
{
0
,
-
800
,
-
1800
,
-
3000
,
-
4400
,
-
6000
};
static
int
defaultMoveValue
[
Move
::
typeCount
]
=
{
40
,
30
,
30
,
15
,
14
,
13
,
5
,
5
,
5
,
2
,
2
,
2
,
1
};
static
int
defaultInARowValue
[
MoveCounter
::
inARowCount
]
=
{
2
,
5
,
4
,
3
};
/**
* Constructor: Set Default values
*/
EvalScheme
::
EvalScheme
(
char
*
file
)
{
setDefaults
();
read
(
file
);
}
void
EvalScheme
::
setDefaults
()
{
for
(
int
i
=
0
;
i
<
6
;
i
++
)
_stoneValue
[
i
]
=
defaultStoneValue
[
i
];
for
(
int
i
=
0
;
i
<
Move
::
typeCount
;
i
++
)
_moveValue
[
i
]
=
defaultMoveValue
[
i
];
for
(
int
i
=
0
;
i
<
MoveCounter
::
inARowCount
;
i
++
)
_inARowValue
[
i
]
=
defaultInARowValue
[
i
];
for
(
int
i
=
0
;
i
<
5
;
i
++
)
_ringValue
[
i
]
=
defaultRingValue
[
i
];
for
(
int
i
=
0
;
i
<
5
;
i
++
)
_ringDiff
[
i
]
=
defaultRingDiff
[
i
];
}
void
EvalScheme
::
read
(
char
*
file
)
{
if
(
file
==
0
||
*
file
==
0
)
return
;
// TODO
}
void
EvalScheme
::
save
(
char
*
file
)
{
// TODO
}
void
EvalScheme
::
setRingValue
(
int
ring
,
int
value
)
{
if
(
ring
>=
0
&&
ring
<
5
)
_ringValue
[
ring
]
=
value
;
}
void
EvalScheme
::
setRingDiff
(
int
ring
,
int
value
)
{
if
(
ring
>=
1
&&
ring
<
5
)
_ringDiff
[
ring
]
=
value
;
}
void
EvalScheme
::
setStoneValue
(
int
stoneDiff
,
int
value
)
{
if
(
stoneDiff
>
0
&&
stoneDiff
<
6
)
_stoneValue
[
stoneDiff
]
=
value
;
}
void
EvalScheme
::
setMoveValue
(
int
type
,
int
value
)
{
if
(
type
>=
0
&&
type
<
Move
::
typeCount
)
_moveValue
[
type
]
=
value
;
}
void
EvalScheme
::
setInARowValue
(
int
stones
,
int
value
)
{
if
(
stones
>=
0
&&
stones
<
MoveCounter
::
inARowCount
)
_inARowValue
[
stones
]
=
value
;
}
/// Evaluator
int
Evaluator
::
fieldValue
[
61
];
Evaluator
::
Evaluator
()
{
_evalScheme
=
0
;
}
void
Evaluator
::
setEvalScheme
(
EvalScheme
*
scheme
)
{
if
(
!
scheme
)
scheme
=
new
EvalScheme
(
0
);
_evalScheme
=
scheme
;
setFieldValues
();
}
void
Evaluator
::
setFieldValues
()
{
if
(
!
_evalScheme
)
return
;
int
i
,
j
=
0
,
k
=
59
;
int
ringValue
[
5
],
ringDiff
[
5
];
for
(
i
=
0
;
i
<
5
;
i
++
)
{
ringDiff
[
i
]
=
_evalScheme
->
ringDiff
(
i
);
ringValue
[
i
]
=
_evalScheme
->
ringValue
(
i
);
if
(
ringDiff
[
i
]
<
1
)
ringDiff
[
i
]
=
1
;
}
fieldValue
[
0
]
=
ringValue
[
0
];
for
(
i
=
1
;
i
<
7
;
i
++
)
fieldValue
[
i
]
=
ringValue
[
1
]
+
((
j
+=
k
)
%
ringDiff
[
1
]);
for
(
i
=
7
;
i
<
19
;
i
++
)
fieldValue
[
i
]
=
ringValue
[
2
]
+
((
j
+=
k
)
%
ringDiff
[
2
]);
for
(
i
=
19
;
i
<
37
;
i
++
)
fieldValue
[
i
]
=
ringValue
[
3
]
+
((
j
+=
k
)
%
ringDiff
[
3
]);
for
(
i
=
37
;
i
<
61
;
i
++
)
fieldValue
[
i
]
=
ringValue
[
4
]
+
((
j
+=
k
)
%
ringDiff
[
4
]);
}
void
Evaluator
::
setBoard
(
Board
*
b
)
{
_board
=
b
;
field
=
b
->
fieldArray
();
}
/* Calculate a evaluation for actual position
*
* A higher value means a better position for opponent
* NB: This means a higher value for better position of
* 'color before last move'
*/
int
Evaluator
::
calcEvaluation
(
Board
*
b
)
{
setBoard
(
b
);
int
color
=
b
->
actColor
();
if
(
!
_evalScheme
)
{
// Use default values if not set
setEvalScheme
();
}
MoveCounter
cColor
,
cOpponent
;
int
f
,
i
,
j
;
/* different evaluation types */
int
fieldValueSum
=
0
,
stoneValueSum
=
0
;
int
moveValueSum
=
0
,
inARowValueSum
=
0
;
int
valueSum
;
/* First check simple winner condition */
int
color1Count
=
_board
->
getColor1Count
();
int
color2Count
=
_board
->
getColor2Count
();
if
(
color1Count
<
9
)
valueSum
=
(
color
==
color1
)
?
16000
:
-
16000
;
else
if
(
color2Count
<
9
)
valueSum
=
(
color
==
color2
)
?
16000
:
-
16000
;
else
{
/* Calculate fieldValueSum and count move types and connectivity */
for
(
i
=
0
;
i
<
RealFields
;
i
++
)
{
j
=
field
[
f
=
Board
::
order
[
i
]];
if
(
j
==
free
)
continue
;
if
(
j
==
color
)
{
b
->
countFrom
(
f
,
j
,
cColor
);
fieldValueSum
-=
fieldValue
[
i
];
}
else
{
b
->
countFrom
(
f
,
j
,
cOpponent
);
fieldValueSum
+=
fieldValue
[
i
];
}
}
/* If color can't do any moves, opponent wins... */
if
(
cColor
.
moveSum
()
==
0
)
valueSum
=
16000
;
else
{
for
(
int
t
=
0
;
t
<
Move
::
typeCount
;
t
++
)
moveValueSum
+=
_evalScheme
->
moveValue
(
t
)
*
(
cOpponent
.
moveCount
(
t
)
-
cColor
.
moveCount
(
t
));
for
(
int
i
=
0
;
i
<
MoveCounter
::
inARowCount
;
i
++
)
inARowValueSum
+=
_evalScheme
->
inARowValue
(
i
)
*
(
cOpponent
.
rowCount
(
i
)
-
cColor
.
rowCount
(
i
));
if
(
color
==
color2
)
stoneValueSum
=
_evalScheme
->
stoneValue
(
14
-
color1Count
)
-
_evalScheme
->
stoneValue
(
14
-
color2Count
);
else
stoneValueSum
=
_evalScheme
->
stoneValue
(
14
-
color2Count
)
-
_evalScheme
->
stoneValue
(
14
-
color1Count
);
valueSum
=
fieldValueSum
+
moveValueSum
+
inARowValueSum
+
stoneValueSum
;
}
}
#ifdef MYTRACE
if
(
spyLevel
>
2
)
{
indent
(
spyDepth
);
printf
(
"Eval %d (field %d, move %d, inARow %d, stone %d)
\n
"
,
valueSum
,
fieldValueSum
,
moveValueSum
,
inARowValueSum
,
stoneValueSum
);
}
#endif
return
valueSum
;
}
void
Evaluator
::
changeEvaluation
()
{
int
i
,
tmp
;
/* innermost ring */
tmp
=
fieldValue
[
1
];
for
(
i
=
1
;
i
<
6
;
i
++
)
fieldValue
[
i
]
=
fieldValue
[
i
+
1
];
fieldValue
[
6
]
=
tmp
;
tmp
=
fieldValue
[
7
];
for
(
i
=
7
;
i
<
18
;
i
++
)
fieldValue
[
i
]
=
fieldValue
[
i
+
1
];
fieldValue
[
18
]
=
tmp
;
tmp
=
fieldValue
[
19
];
for
(
i
=
19
;
i
<
36
;
i
++
)
fieldValue
[
i
]
=
fieldValue
[
i
+
1
];
fieldValue
[
36
]
=
tmp
;
/* the outermost ring */
tmp
=
fieldValue
[
37
];
for
(
i
=
37
;
i
<
60
;
i
++
)
fieldValue
[
i
]
=
fieldValue
[
i
+
1
];
fieldValue
[
60
]
=
tmp
;
}
mpi-assign5/pv-split-interative/eval.h
0 → 100644
View file @
17980573
/**
* EvalScheme and Evaluator
*
* A board evaluation scheme using a combination of 3 evaluations:
* - Token difference
* - Place
* - Movability / Connectivity
*
* Coefficients used for these evaluations are variable.
*
* The constructor gets a name, and tries to read the coefficients
* from a configuration file, if nothing found, use default values
*/
#ifndef EVAL_H
#define EVAL_H
#include "board.h"
class
EvalScheme
{
public
:
EvalScheme
(
char
*
);
~
EvalScheme
()
{}
void
setDefaults
();
void
read
(
char
*
file
);
void
save
(
char
*
file
);
void
setRingValue
(
int
ring
,
int
value
);
void
setRingDiff
(
int
ring
,
int
value
);
void
setStoneValue
(
int
stoneDiff
,
int
value
);
void
setMoveValue
(
int
type
,
int
value
);
void
setInARowValue
(
int
stones
,
int
value
);
int
ringValue
(
int
r
)
{
return
(
r
>=
0
&&
r
<
5
)
?
_ringValue
[
r
]
:
0
;
}
int
ringDiff
(
int
r
)
{
return
(
r
>
0
&&
r
<
5
)
?
_ringDiff
[
r
]
:
0
;
}
int
stoneValue
(
int
s
)
{
return
(
s
>
0
&&
s
<
6
)
?
_stoneValue
[
s
]
:
0
;
}
int
moveValue
(
int
t
)
{
return
(
t
>=
0
&&
t
<
Move
::
typeCount
)
?
_moveValue
[
t
]
:
0
;}
int
inARowValue
(
int
s
)
{
return
(
s
>=
0
&&
s
<
MoveCounter
::
inARowCount
)
?
_inARowValue
[
s
]
:
0
;
}
private
:
int
_ringValue
[
5
],
_ringDiff
[
5
];
int
_stoneValue
[
6
],
_moveValue
[
Move
::
none
];
int
_inARowValue
[
MoveCounter
::
inARowCount
];
};
class
Evaluator
{
public
:
/* different states of one field */
enum
{
out
=
10
,
free
=
0
,
color1
,
color2
,
color1bright
,
color2bright
};
enum
{
AllFields
=
121
,
/* visible + ring of unvisible around */
RealFields
=
61
,
/* number of visible fields */
MvsStored
=
100
};
Evaluator
();
/* Evaluation Scheme to use */
void
setEvalScheme
(
EvalScheme
*
scheme
=
0
);
EvalScheme
*
evalScheme
()
{
return
_evalScheme
;
}
void
setFieldValues
();
int
minValue
()
{
return
-
15000
;
}
int
maxValue
()
{
return
15000
;
}
/* Calculate a value for actual position
* (greater if better for color1) */
int
calcEvaluation
(
Board
*
);
/* Evalution is based on values which can be changed
* a little (so computer's moves aren't always the same) */
void
changeEvaluation
();
void
setBoard
(
Board
*
);
private
:
Board
*
_board
;
EvalScheme
*
_evalScheme
;
int
*
field
;
/* ratings; semi constant - are rotated by changeRating() */
static
int
fieldValue
[
Board
::
RealFields
];
};
#endif
mpi-assign5/pv-split-interative/move.cpp
0 → 100644
View file @
17980573
/*
* Classes
* - Move: a move on the game board
* - MoveTypeCounter, InARowCounter: evaluation helpers
* - MoveList: stores list of moves allowed from a position
* - Variation: stores move sequences
*
* (c) 1997-2005, Josef Weidendorfer
*/
#include <assert.h>
#include <stdio.h>
#include "move.h"
#include "board.h"
static
const
char
*
nameOfDir
(
int
dir
)
{
dir
=
dir
%
6
;
return
(
dir
==
1
)
?
"Right"
:
(
dir
==
2
)
?
"RightDown"
:
(
dir
==
3
)
?
"LeftDown"
:
(
dir
==
4
)
?
"Left"
:
(
dir
==
5
)
?
"LeftUp"
:
(
dir
==
0
)
?
"RightUp"
:
"??"
;
}
static
char
*
nameOfPos
(
int
p
)
{
static
char
tmp
[
3
];
tmp
[
0
]
=
(
char
)(
'A'
+
(
p
-
12
)
/
11
);
tmp
[
1
]
=
(
char
)(
'1'
+
(
p
-
12
)
%
11
);
tmp
[
2
]
=
0
;
return
tmp
;
}
/// Move
char
*
Move
::
name
()
const
{
static
char
s
[
30
];
int
pos
;
/* sideway moves... */
if
(
type
==
left3
||
type
==
right3
)
{
int
f1
,
f2
,
df
;
f1
=
f2
=
field
;
df
=
2
*
Board
::
fieldDiffOfDir
(
direction
);
if
(
df
>
0
)
f2
+=
df
;
else
f1
+=
df
;
pos
=
sprintf
(
s
,
"%s-"
,
nameOfPos
(
f1
));
const
char
*
dir
=
(
type
==
left3
)
?
nameOfDir
(
direction
-
1
)
:
nameOfDir
(
direction
+
1
);
sprintf
(
s
+
pos
,
"%s/%s"
,
nameOfPos
(
f2
),
dir
);
}
else
if
(
type
==
left2
||
type
==
right2
)
{
int
f1
,
f2
,
df
;
f1
=
f2
=
field
;
df
=
Board
::
fieldDiffOfDir
(
direction
);
if
(
df
>
0
)
f2
+=
df
;
else
f1
+=
df
;
pos
=
sprintf
(
s
,
"%s-"
,
nameOfPos
(
f1
));
const
char
*
dir
=
(
type
==
left2
)
?
nameOfDir
(
direction
-
1
)
:
nameOfDir
(
direction
+
1
);
sprintf
(
s
+
pos
,
"%s/%s"
,
nameOfPos
(
f2
),
dir
);
}
else
if
(
type
==
none
)
{
return
"??"
;
}
else
{
int
p
=
sprintf
(
s
,
"%s/%s"
,
nameOfPos
(
field
),
nameOfDir
(
direction
));
if
(
type
<
3
)
sprintf
(
s
+
p
,
"/Out"
);
else
if
(
type
<
6
)
sprintf
(
s
+
p
,
"/Push"
);
}
return
s
;
}
char
*
Move
::
typeName
()
const
{
switch
(
type
)
{
case
out2
:
return
"Out, pushing 2 opponents with 3"
;
case
out1with3
:
return
"Out, pushing 1 opponent with 3"
;
case
out1with2
:
return
"Out, pushing 1 opponent with 2"
;
case
push2
:
return
"Pushing 2 opponents with 3"
;
case
push1with3
:
return
"Pushing 1 opponent with 3"
;
case
push1with2
:
return
"Pushing 1 opponent with 2"
;
case
move3
:
return
"Moving 3 in a row"
;
case
left3
:
return
"Moving 3 left sideways"
;
case
right3
:
return
"Moving 3 right sideways"
;
case
left2
:
return
"Moving 2 left sideways"
;
case
right2
:
return
"Moving 2 right sideways"
;
case
move2
:
return
"Moving 2 in a row"
;
case
move1
:
return
"Moving 1"
;
default
:
break
;
}
return
"Invalid type"
;
}
void
Move
::
print
()
const
{
printf
(
"%s"
,
name
()
);
}
/// MoveList
MoveList
::
MoveList
()
{
clear
();
}
void
MoveList
::
clear
()
{
int
i
;
for
(
i
=
0
;
i
<
Move
::
typeCount
;
i
++
)
first
[
i
]
=
actual
[
i
]
=
-
1
;
nextUnused
=
0
;
actualType
=
-
1
;
}
void
MoveList
::
insert
(
Move
m
)
{
int
t
=
m
.
type
;
/* valid and possible ? */
if
(
t
<
0
||
t
>=
Move
::
typeCount
)
return
;
//if (nextUnused == MaxMoves) return;
assert
(
nextUnused
<
MaxMoves
);
/* adjust queue */
if
(
first
[
t
]
==
-
1
)
{
first
[
t
]
=
last
[
t
]
=
nextUnused
;
}
else
{
assert
(
last
[
t
]
<
nextUnused
);
next
[
last
[
t
]]
=
nextUnused
;
last
[
t
]
=
nextUnused
;
}
next
[
nextUnused
]
=
-
1
;
move
[
nextUnused
]
=
m
;
nextUnused
++
;
}
bool
MoveList
::
isElement
(
int
f
)
{
int
i
;
for
(
i
=
0
;
i
<
nextUnused
;
i
++
)
if
(
move
[
i
].
field
==
f
)
return
true
;
return
false
;
}
bool
MoveList
::
isElement
(
Move
&
m
,
int
startType
,
bool
del
)
{
int
i
;
for
(
i
=
0
;
i
<
nextUnused
;
i
++
)
{
Move
&
mm
=
move
[
i
];
if
(
mm
.
field
!=
m
.
field
)
continue
;
/* if direction is supplied it has to match */
if
((
m
.
direction
>
0
)
&&
(
mm
.
direction
!=
m
.
direction
))
continue
;
/* if type is supplied it has to match */
if
((
m
.
type
!=
Move
::
none
)
&&
(
m
.
type
!=
mm
.
type
))
continue
;
if
(
m
.
type
==
mm
.
type
)
{
/* exact match; eventually supply direction */
m
.
direction
=
mm
.
direction
;
if
(
del
)
mm
.
type
=
Move
::
none
;
return
true
;
}
switch
(
mm
.
type
)
{
case
Move
:
:
left3
:
case
Move
:
:
right3
:
if
(
startType
==
start3
||
startType
==
all
)
{
m
.
type
=
mm
.
type
;
m
.
direction
=
mm
.
direction
;
if
(
del
)
mm
.
type
=
Move
::
none
;
return
true
;
}
break
;
case
Move
:
:
left2
:
case
Move
:
:
right2
:
if
(
startType
==
start2
||
startType
==
all
)
{
m
.
type
=
mm
.
type
;
m
.
direction
=
mm
.
direction
;
if
(
del
)
mm
.
type
=
Move
::
none
;
return
true
;
}
break
;
default
:
if
(
startType
==
start1
||
startType
==
all
)
{
/* unexact match: supply type */
m
.
type
=
mm
.
type
;
m
.
direction
=
mm
.
direction
;
if
(
del
)
mm
.
type
=
Move
::
none
;
return
true
;
}
}
}
return
false
;
}
bool
MoveList
::
getNext
(
Move
&
m
,
int
maxType
)
{
if
(
actualType
==
Move
::
typeCount
)
return
false
;
while
(
1
)
{
while
(
actualType
<
0
||
actual
[
actualType
]
==
-
1
)
{
actualType
++
;
if
(
actualType
==
Move
::
typeCount
)
return
false
;
actual
[
actualType
]
=
first
[
actualType
];
if
(
actualType
>
maxType
)
return
false
;
}
m
=
move
[
actual
[
actualType
]];
actual
[
actualType
]
=
next
[
actual
[
actualType
]];
if
(
m
.
type
!=
Move
::
none
)
break
;
}
return
true
;
}
int
MoveList
::
count
(
int
maxType
)
{
int
c
=
0
;
int
type
=
actualType
;
int
act
=
0
;
if
(
type
>=
0
)
act
=
actual
[
type
];
while
(
1
)
{
while
(
type
<
0
||
act
==
-
1
)
{
type
++
;
if
(
type
==
Move
::
typeCount
)
return
c
;
act
=
first
[
type
];
if
(
type
>
maxType
)
return
c
;
}
c
++
;
act
=
next
[
act
];
}
return
c
;
}
/// Variation
void
Variation
::
clear
(
int
d
)
{
int
i
,
j
;
for
(
i
=
0
;
i
<
maxDepth
;
i
++
)
for
(
j
=
0
;
j
<
maxDepth
;
j
++
)
{
move
[
i
][
j
].
type
=
Move
::
none
;
}
actMaxDepth
=
(
d
<
maxDepth
)
?
d
:
maxDepth
-
1
;
}
void
Variation
::
update
(
int
d
,
Move
&
m
)
{
int
i
;
if
(
d
>
actMaxDepth
)
return
;
for
(
i
=
d
+
1
;
i
<=
actMaxDepth
;
i
++
)
{
move
[
d
][
i
]
=
move
[
d
+
1
][
i
];
move
[
d
+
1
][
i
].
type
=
Move
::
none
;
}
move
[
d
][
d
]
=
m
;
}
mpi-assign5/pv-split-interative/move.h
0 → 100644
View file @
17980573
/*
* Classes
* - Move: a move on the game board
* - MoveTypeCounter, InARowCounter: evaluation helpers
* - MoveList: stores list of moves allowed from a position
* - Variation: stores move sequences
*
* (c) 1997-2005, Josef Weidendorfer
*/
#ifndef MOVE_H
#define MOVE_H
/**
* Class Move
*
* A move on the game board.
* A move is given by a start position number on the board
* (for board numbering, see board.h), a direction (out of 6),
* and the type of the move. Type includes the number of own
* and opponents tokens taken part in the move, and side-way
* moves.
*/
class
Move
{
public
:
/* Directions */
enum
{
Right
=
1
,
RightDown
,
LeftDown
,
Left
,
LeftUp
,
RightUp
};
/* Type of move: Moves are searched in this order */
enum
MoveType
{
out2
=
0
,
out1with3
,
out1with2
,
push2
,
push1with3
,
push1with2
,
move3
,
left3
,
right3
,
left2
,
right2
,
move2
,
move1
,
none
};
/* Constants to specify move type ranges. For this to work,
* the enum order in MoveType must not be changed!
*/
enum
{
typeCount
=
none
,
maxOutType
=
out1with2
,
maxPushType
=
push1with2
,
maxMoveType
=
move1
};
/* Constructor for an invalid move */
Move
()
{
type
=
none
;
field
=
0
;
direction
=
0
;
}
/* Move starting at f, direction d, and Type t */
Move
(
short
f
,
char
d
,
MoveType
t
)
{
field
=
f
;
direction
=
d
,
type
=
t
;
}
/* Does this move push out an opponents token? */
bool
isOutMove
()
const
{
return
type
<=
out1with2
;
}
/* Does this move push opponent tokens? */
bool
isPushMove
()
const
{
return
type
<=
push1with2
;
}
/* for communication to outer world */
char
*
name
()
const
;
char
*
typeName
()
const
;
/* debugging output */
void
print
()
const
;
/* Allow public R/W access... */
short
field
;
unsigned
char
direction
;
MoveType
type
;
};
/**
* Class MoveList
*
* Stores a fixed number of moves (for efficince)
* <getNext> returns reference of next move ordered according to type
* <insert> does nothing if there isn't enough free space
*
* Recommend usage (* means 0 or more times):
* [ clear() ; insert() * ; isElement() * ; getNext() * ] *
*/
class
MoveList
{
public
:
MoveList
();
enum
{
MaxMoves
=
150
};
/* for isElement: search for moves starting with 1/2/3 fields */
enum
{
all
,
start1
,
start2
,
start3
};
void
clear
();
void
insert
(
Move
);
bool
isElement
(
int
f
);
bool
isElement
(
Move
&
,
int
startType
,
bool
del
=
false
);
void
insert
(
short
f
,
char
d
,
Move
::
MoveType
t
)
{
insert
(
Move
(
f
,
d
,
t
)
);
}
int
getLength
()
{
return
nextUnused
;
}
int
count
(
int
maxType
=
Move
::
typeCount
);
/**
* Get next move from the list into the Move instance
* given by first arg which is passed by reference.
*
* Move types are sorted, and you can specify the maximal
* type allowed to be returned. Default is to return all moves.
*
* Return false if no more moves (with given type constrain)
*/
bool
getNext
(
Move
&
,
int
maxType
=
Move
::
none
);
private
:
Move
move
[
MaxMoves
];
int
next
[
MaxMoves
];
int
first
[
Move
::
typeCount
];
int
last
[
Move
::
typeCount
];
int
actual
[
Move
::
typeCount
];
int
nextUnused
,
actualType
;
};
/**
* Stores best move sequence = principal variation
*
* Implementation uses upper left triangle of a matrix,
* with row 0 holding best sequence found so far from
* real current game position, row 1 holding best sequence
* starting from currently searched depth 1 in game tree,
* row 2 from depth 2 and so on.
*
* Uses:
* - A new best move sequence at search depth d was found.
* copy current move of depth d into [d][0], and the rest from row d+1.
* - Read principal variation on starting a new alpha/beta search.
* This heuristic is assumed to lead to a lot of cutoffs happening.
* - Read finally found best move from [0][0]
* - Allow for computer hints to the opponent by looking at [0][1]
*/
class
Variation
{
public
:
enum
{
maxDepth
=
10
};
Variation
()
{
clear
(
1
);
}
/* Does the best sequence have a move for depth d ? */
bool
hasMove
(
int
d
)
{
return
(
d
>
actMaxDepth
)
?
false
:
(
move
[
0
][
d
].
type
!=
Move
::
none
);
}
/* Get move at index i from best move chain */
Move
&
operator
[](
int
i
)
{
return
(
i
<
0
||
i
>=
maxDepth
)
?
move
[
0
][
0
]
:
move
[
0
][
i
];
}
/* Get move chain at depth d */
Move
*
chain
(
int
d
)
{
return
(
d
<
0
||
d
>=
maxDepth
)
?
&
(
move
[
0
][
0
])
:
&
(
move
[
d
][
d
]);
}
/* Update best move from depth d, starting with move m at this depth */
void
update
(
int
d
,
Move
&
m
);
/* Clear sequence storage for moves from depth d */
void
clear
(
int
d
);
/* Set maximum supported depth */
void
setMaxDepth
(
int
d
)
{
actMaxDepth
=
(
d
>
maxDepth
)
?
maxDepth
-
1
:
d
;
}
private
:
Move
move
[
maxDepth
][
maxDepth
];
int
actMaxDepth
;
};
#endif
/* _MOVE_H_ */
mpi-assign5/pv-split-interative/network.cpp
0 → 100644
View file @
17980573
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/select.h>
#include <arpa/inet.h>
#include "network.h"
// set to 1 to get debug messages
int
verbose
=
0
;
// NetworkLoop
NetworkLoop
::
NetworkLoop
()
{
domainList
=
0
;
timerList
=
0
;
max_readfd
=
-
1
;
FD_ZERO
(
&
readfds
);
}
bool
NetworkLoop
::
install
(
NetworkDomain
*
d
)
{
if
(
d
->
isListening
())
return
false
;
int
fd
=
d
->
startListening
(
this
);
if
(
fd
>=
0
)
{
FD_SET
(
fd
,
&
readfds
);
if
(
fd
>
max_readfd
)
max_readfd
=
fd
;
}
if
(
verbose
>
1
)
printf
(
"NetworkLoop::install: Callbacks for NetworkDomain %d
\n
"
,
d
->
ID
());
d
->
next
=
domainList
;
domainList
=
d
;
return
true
;
}
bool
NetworkLoop
::
install
(
NetworkTimer
*
t
)
{
t
->
reset
();
t
->
next
=
timerList
;
timerList
=
t
;
if
(
verbose
>
1
)
printf
(
"NetworkLoop::install: Timer with %d msecs
\n
"
,
t
->
msecs
());
return
true
;
}
void
NetworkLoop
::
remove
(
NetworkDomain
*
domain
)
{
NetworkDomain
*
d
,
*
prev
=
0
;
for
(
d
=
domainList
;
d
!=
0
;
prev
=
d
,
d
=
d
->
next
)
if
(
d
==
domain
)
break
;
if
(
d
==
0
)
return
;
int
fd
=
d
->
listeningFD
();
if
(
fd
>=
0
)
{
FD_CLR
(
fd
,
&
readfds
);
while
(
max_readfd
>=
0
)
{
if
(
FD_ISSET
(
max_readfd
,
&
readfds
))
break
;
max_readfd
--
;
}
}
d
->
close
();
if
(
prev
)
prev
->
next
=
d
->
next
;
else
domainList
=
d
->
next
;
d
->
next
=
0
;
}
/* subtrace tv2 from tv1 */
void
subTimeval
(
struct
timeval
*
tv1
,
struct
timeval
*
tv2
)
{
tv1
->
tv_sec
-=
tv2
->
tv_sec
;
if
(
tv1
->
tv_usec
<
tv2
->
tv_usec
)
{
tv1
->
tv_sec
--
;
tv1
->
tv_usec
+=
1000000
-
tv2
->
tv_usec
;
}
else
tv1
->
tv_usec
-=
tv2
->
tv_usec
;
}
int
NetworkLoop
::
run
()
{
struct
timeval
tv
,
*
ptv
,
tv2
;
NetworkTimer
*
t
,
*
tprev
,
*
tnext
;
tv2
.
tv_sec
=
0
;
tv2
.
tv_usec
=
0
;
exit_loop
=
false
;
if
(
verbose
>
1
)
printf
(
"NetworkLoop::run: Waiting for events
\n
"
);
while
(
!
exit_loop
)
{
if
(
timerList
==
0
)
ptv
=
0
;
else
{
ptv
=
&
tv
;
timerList
->
set
(
&
tv
);
t
=
timerList
->
next
;
for
(;
t
!=
0
;
t
=
t
->
next
)
t
->
minLeft
(
&
tv
);
tv2
=
tv
;
}
fd_set
rfds
=
readfds
;
select
(
max_readfd
+
1
,
&
rfds
,
NULL
,
NULL
,
ptv
);
if
(
verbose
>
1
)
printf
(
"NetworkLoop::run: Got a event...
\n
"
);
NetworkDomain
*
d
=
domainList
;
for
(;
d
!=
0
;
d
=
d
->
next
)
d
->
check
(
&
rfds
);
if
(
ptv
)
{
// Warning: Linux specific
subTimeval
(
&
tv2
,
ptv
);
tprev
=
0
;
t
=
timerList
;
for
(;
t
!=
0
;
tprev
=
t
,
t
=
tnext
)
{
tnext
=
t
->
next
;
if
(
t
->
subLeft
(
&
tv2
))
{
// remove timer, it could be added again in timeout()
if
(
tprev
)
tprev
->
next
=
tnext
;
else
timerList
=
tnext
;
if
(
verbose
>
1
)
printf
(
"NetworkLoop::run: Timeout
\n
"
);
t
->
timeout
(
this
);
}
}
}
}
return
exit_value
;
}
void
NetworkLoop
::
exit
(
int
v
)
{
exit_loop
=
true
;
exit_value
=
v
;
}
bool
NetworkLoop
::
pending
()
{
fd_set
rfds
=
readfds
;
select
(
max_readfd
+
1
,
&
rfds
,
NULL
,
NULL
,
NULL
);
for
(
int
i
=
0
;
i
<=
max_readfd
;
i
++
)
if
(
FD_ISSET
(
i
,
&
rfds
))
return
true
;
return
false
;
}
void
NetworkLoop
::
processPending
()
{
fd_set
rfds
=
readfds
;
select
(
max_readfd
+
1
,
&
rfds
,
NULL
,
NULL
,
NULL
);
NetworkDomain
*
d
=
domainList
;
for
(;
d
!=
0
;
d
=
d
->
next
)
d
->
check
(
&
rfds
);
}
/// NetworkTimer
NetworkTimer
::
NetworkTimer
(
int
msecs
)
{
_msecs
=
msecs
;
next
=
0
;
}
void
NetworkTimer
::
timeout
(
NetworkLoop
*
)
{
printf
(
"Timeout after %d.%03d secs!
\n
"
,
_msecs
/
1000
,
_msecs
%
1000
);
}
void
NetworkTimer
::
reset
()
{
_left
.
tv_sec
=
_msecs
/
1000
;
_left
.
tv_usec
=
(
_msecs
%
1000
)
*
1000
;
}
void
NetworkTimer
::
set
(
struct
timeval
*
tv
)
{
tv
->
tv_sec
=
_left
.
tv_sec
;
tv
->
tv_usec
=
_left
.
tv_usec
;
}
void
NetworkTimer
::
minLeft
(
struct
timeval
*
tv
)
{
if
(
_left
.
tv_sec
<
tv
->
tv_sec
)
{
tv
->
tv_sec
=
_left
.
tv_sec
;
tv
->
tv_usec
=
_left
.
tv_usec
;
return
;
}
if
(
_left
.
tv_sec
>
tv
->
tv_sec
)
return
;
if
(
_left
.
tv_usec
>
tv
->
tv_usec
)
return
;
tv
->
tv_usec
=
_left
.
tv_usec
;
}
bool
NetworkTimer
::
subLeft
(
struct
timeval
*
tv
)
{
if
(
_left
.
tv_sec
<
tv
->
tv_sec
)
return
true
;
if
(
_left
.
tv_sec
==
tv
->
tv_sec
)
if
(
_left
.
tv_usec
<=
tv
->
tv_usec
)
return
true
;
subTimeval
(
&
_left
,
tv
);
return
false
;
}
/// Connection
Connection
::
Connection
(
NetworkDomain
*
d
,
Connection
*
n
,
const
char
*
h
,
int
p
,
struct
sockaddr_in
s
,
bool
r
)
{
setHost
(
h
);
port
=
p
;
sin
=
s
;
reachable
=
r
;
domain
=
d
;
next
=
n
;
}
Connection
::~
Connection
()
{
if
(
reachable
)
{
char
tmp
[
50
];
int
len
=
sprintf
(
tmp
,
"unreg %d"
,
domain
->
listeningPort
());
sendString
(
tmp
,
len
);
}
}
void
Connection
::
setHost
(
const
char
*
h
)
{
if
(
h
==
0
)
host
[
0
]
=
0
;
else
{
int
l
=
strlen
(
h
);
if
(
l
>
99
)
l
=
99
;
strncpy
(
host
,
h
,
l
);
host
[
l
]
=
0
;
}
}
char
*
Connection
::
addr
()
{
static
char
tmp
[
256
];
sprintf
(
tmp
,
"%s:%d"
,
host
[
0
]
?
host
:
inet_ntoa
(
sin
.
sin_addr
),
ntohs
(
sin
.
sin_port
));
return
tmp
;
}
bool
Connection
::
sendString
(
const
char
*
str
,
int
len
)
{
if
(
!
reachable
)
return
false
;
int
s
=
::
socket
(
PF_INET
,
SOCK_STREAM
,
0
);
if
(
s
<
0
)
{
printf
(
"Connection::sendString: Error in socket()
\n
"
);
return
false
;
}
if
(
::
connect
(
s
,
(
struct
sockaddr
*
)
&
sin
,
sizeof
(
sin
))
<
0
)
{
if
(
verbose
)
printf
(
"Connection::sendString: Error in connect to %s
\n
"
,
addr
());
reachable
=
false
;
return
false
;
}
write
(
s
,
str
,
len
);
::
close
(
s
);
if
(
verbose
>
1
)
printf
(
"Connection::sendString: Sent to %s: '%s'
\n
"
,
addr
(),
str
);
return
true
;
}
bool
Connection
::
start
()
{
if
(
verbose
)
printf
(
"Connection::start: %s
\n
"
,
addr
());
char
tmp
[
50
];
int
len
=
sprintf
(
tmp
,
"reg %d"
,
domain
->
listeningPort
());
reachable
=
true
;
if
(
!
sendString
(
tmp
,
len
))
{
reachable
=
false
;
return
false
;
}
domain
->
newConnection
(
this
);
return
true
;
}
/// NetworkDomain
NetworkDomain
::
NetworkDomain
(
int
id
)
{
myID
=
id
;
myPort
=
-
1
;
fd
=
-
1
;
loop
=
0
;
connectionList
=
0
;
}
NetworkDomain
::~
NetworkDomain
()
{
if
(
loop
)
loop
->
remove
(
this
);
}
int
NetworkDomain
::
startListening
(
NetworkLoop
*
l
)
{
struct
sockaddr_in
name
;
int
i
,
j
;
if
(
loop
)
return
-
1
;
loop
=
l
;
fd
=
::
socket
(
PF_INET
,
SOCK_STREAM
,
0
);
if
(
fd
<
0
)
return
fd
;
for
(
i
=
0
;
i
<
5
;
i
++
)
{
myPort
=
myID
+
i
;
name
.
sin_family
=
AF_INET
;
name
.
sin_port
=
htons
(
myPort
);
name
.
sin_addr
.
s_addr
=
htonl
(
INADDR_ANY
);
if
(
bind
(
fd
,
(
struct
sockaddr
*
)
&
name
,
sizeof
(
name
))
>=
0
)
break
;
if
(
verbose
)
printf
(
"NetworkDomain::startListening: Port %d in use
\n
"
,
myPort
);
}
mySin
=
name
;
if
(
verbose
)
printf
(
"NetworkDomain::startListening: Using Port %d
\n
"
,
myPort
);
if
(
i
==
5
)
{
printf
(
"NetworkDomain::startListening: Error starting domain %d
\n
"
,
myID
);
::
close
(
fd
);
fd
=
-
1
;
myPort
=
-
1
;
return
fd
;
}
// connect to all instances of this domain on localhost
for
(
j
=
0
;
j
<
5
;
j
++
)
{
if
(
j
==
i
)
continue
;
prepareConnection
(
"localhost"
,
myID
+
j
);
}
if
(
::
listen
(
fd
,
5
)
<
0
)
{
printf
(
"NetworkDomain::startListening: Error in listen
\n
"
);
::
close
(
fd
);
fd
=
-
1
;
return
fd
;
}
Connection
*
c
;
for
(
c
=
connectionList
;
c
!=
0
;
c
=
c
->
next
)
if
(
!
c
->
reachable
)
c
->
start
();
return
fd
;
}
void
NetworkDomain
::
close
()
{
if
(
fd
<
0
)
return
;
::
close
(
fd
);
Connection
*
l
,
*
lnext
;
for
(
l
=
connectionList
;
l
!=
0
;
l
=
lnext
)
{
lnext
=
l
->
next
;
delete
l
;
}
loop
=
0
;
}
void
NetworkDomain
::
check
(
fd_set
*
set
)
{
if
(
FD_ISSET
(
fd
,
set
))
gotConnection
();
}
Connection
*
NetworkDomain
::
getNewConnection
(
const
char
*
h
,
struct
sockaddr_in
sin
)
{
Connection
*
c
;
for
(
c
=
connectionList
;
c
!=
0
;
c
=
c
->
next
)
if
(
c
->
sin
.
sin_addr
.
s_addr
==
sin
.
sin_addr
.
s_addr
&&
c
->
sin
.
sin_port
==
sin
.
sin_port
)
break
;
if
(
c
)
{
if
(
h
)
c
->
setHost
(
h
);
c
->
reachable
=
false
;
}
else
{
c
=
new
Connection
(
this
,
connectionList
,
h
,
ntohs
(
sin
.
sin_port
),
sin
,
false
);
connectionList
=
c
;
}
return
c
;
}
void
NetworkDomain
::
gotConnection
()
{
static
char
tmp
[
1024
];
int
len
=
0
;
struct
sockaddr_in
sin
;
socklen_t
sz
=
sizeof
(
sin
);
if
(
verbose
>
1
)
printf
(
"NetworkDomain::GotConnection:
\n
"
);
int
s
=
accept
(
fd
,(
struct
sockaddr
*
)
&
sin
,
&
sz
);
if
(
s
<
0
)
{
printf
(
" Error in accept
\n
"
);
return
;
}
while
(
read
(
s
,
tmp
+
len
,
1
)
==
1
)
len
++
;
::
close
(
s
);
tmp
[
len
]
=
0
;
len
++
;
if
(
verbose
>
1
)
printf
(
" Got from %s:%d : '%s'
\n
"
,
inet_ntoa
(
sin
.
sin_addr
),
ntohs
(
sin
.
sin_port
),
tmp
);
if
(
strncmp
(
tmp
,
"reg "
,
4
)
==
0
)
{
int
port
=
atoi
(
tmp
+
4
);
sin
.
sin_port
=
htons
(
port
);
Connection
*
c
=
getNewConnection
(
0
,
sin
);
c
->
reachable
=
true
;
if
(
verbose
)
printf
(
"Reg of %s
\n
"
,
c
->
addr
());
newConnection
(
c
);
return
;
}
if
(
strncmp
(
tmp
,
"unreg "
,
6
)
==
0
)
{
int
port
=
atoi
(
tmp
+
6
);
sin
.
sin_port
=
htons
(
port
);
Connection
*
c
,
*
cprev
=
0
;
for
(
c
=
connectionList
;
c
!=
0
;
cprev
=
c
,
c
=
c
->
next
)
if
(
c
->
sin
.
sin_addr
.
s_addr
==
sin
.
sin_addr
.
s_addr
&&
c
->
sin
.
sin_port
==
sin
.
sin_port
)
break
;
if
(
c
==
0
)
{
printf
(
"Error: UnReg of %s:%d. Not Found
\n
"
,
inet_ntoa
(
sin
.
sin_addr
),
ntohs
(
sin
.
sin_port
));
return
;
}
if
(
cprev
)
cprev
->
next
=
c
->
next
;
else
connectionList
=
c
->
next
;
if
(
verbose
)
printf
(
"UnReg of %s:%d
\n
"
,
inet_ntoa
(
sin
.
sin_addr
),
ntohs
(
sin
.
sin_port
));
return
;
}
received
(
tmp
);
}
int
NetworkDomain
::
count
()
{
int
cc
=
0
;
for
(
Connection
*
c
=
connectionList
;
c
!=
0
;
c
=
c
->
next
)
if
(
c
->
reachable
)
cc
++
;
return
cc
;
}
void
NetworkDomain
::
received
(
char
*
str
)
{
printf
(
"NetworkDomain::received: '%s' in domain %d
\n
"
,
str
,
ID
());
}
void
NetworkDomain
::
newConnection
(
Connection
*
c
)
{
if
(
verbose
)
printf
(
"NetworkDomain::newConnection: %s, now %d active connections
\n
"
,
c
->
addr
(),
count
());
}
void
NetworkDomain
::
addConnection
(
const
char
*
host
,
int
port
)
{
Connection
*
c
=
prepareConnection
(
host
,
port
);
if
(
c
)
c
->
start
();
}
Connection
*
NetworkDomain
::
prepareConnection
(
const
char
*
host
,
int
port
)
{
struct
hostent
*
hostinfo
;
struct
sockaddr_in
name
;
memset
(
&
name
,
0
,
sizeof
(
struct
sockaddr_in
));
name
.
sin_family
=
AF_INET
;
name
.
sin_port
=
htons
(
port
);
hostinfo
=
gethostbyname
(
host
);
if
(
hostinfo
==
NULL
)
{
printf
(
"NetworkDomain::prepareConnection: Error: Unknown host %s.
\n
"
,
host
);
return
0
;
}
name
.
sin_addr
=
*
(
struct
in_addr
*
)
hostinfo
->
h_addr
;
return
getNewConnection
(
host
,
name
);
}
void
NetworkDomain
::
broadcast
(
const
char
*
str
)
{
int
len
=
strlen
(
str
);
for
(
Connection
*
c
=
connectionList
;
c
!=
0
;
c
=
c
->
next
)
c
->
sendString
(
str
,
len
);
}
mpi-assign5/pv-split-interative/network.h
0 → 100644
View file @
17980573
/*
* Simple Network Communication via event-driven loop
*
* (C) 2005, Josef Weidendorfer
*
* Install a communication domain which is a listening socket
* on a port and a set of remote connection to this port.
* You can register callbacks for incoming ASCII data on
* communcation domains and broadcast your own data into a domain.
*/
#ifndef NETWORK_H
#define NETWORK_H
#include <sys/types.h>
#include <netinet/in.h>
class
NetworkDomain
;
class
NetworkTimer
;
/**
* Event loop for network communication
*/
class
NetworkLoop
{
public
:
NetworkLoop
();
/**
* Install a listening socket on the port given by the NetworkDomain.
* Incoming connections are accepted, and incoming
* data will lead to callbacks specified in the NetworkDomain.
* Returns true if successfull.
*/
bool
install
(
NetworkDomain
*
);
/**
* Install a oneshot timer object. Install the timer again in
* timeout() for regular calls.
*/
bool
install
(
NetworkTimer
*
);
/**
* Remove a NetworkDomain. Existing connections will be closed.
*/
void
remove
(
NetworkDomain
*
);
/**
* Blocks in a select() on network connections and
* calls registered callbacks on incoming data.
* Call exit() to leave the event loop with given exit value.
*/
int
run
();
/**
* While running inside of a event loop via run(),
* call this function the trigger quitting the loop, i.e.
* returning from run().
*/
void
exit
(
int
value
=
1
);
/**
* Are incoming data pending?
*/
bool
pending
();
/**
* Process pending data
*/
void
processPending
();
private
:
NetworkDomain
*
domainList
;
NetworkTimer
*
timerList
;
bool
exit_loop
;
int
exit_value
;
/* Set of file descriptors used in select.
* This includes listening and data sockets
*/
fd_set
readfds
;
int
max_readfd
;
};
/**
* A timer to be used with NetworkLoop.
*
* Install an instance into the loop to get timeout() called
* after <secs> seconds.
*/
class
NetworkTimer
{
public
:
NetworkTimer
(
int
msecs
);
virtual
~
NetworkTimer
()
{}
int
msecs
()
{
return
_msecs
;
}
virtual
void
timeout
(
NetworkLoop
*
);
/**
* Internal.
* Helpers for NetworkLoop
*/
void
reset
();
void
set
(
struct
timeval
*
);
void
minLeft
(
struct
timeval
*
);
bool
subLeft
(
struct
timeval
*
);
NetworkTimer
*
next
;
private
:
int
_msecs
;
struct
timeval
_left
;
};
/**
* An active connection in a communication domain
*/
class
Connection
{
public
:
Connection
(
NetworkDomain
*
,
Connection
*
,
const
char
*
,
int
,
struct
sockaddr_in
,
bool
);
~
Connection
();
void
setHost
(
const
char
*
h
);
/**
* Send a string to this connection.
*/
bool
sendString
(
const
char
*
str
,
int
len
);
/* Get string for remote end */
char
*
addr
();
/**
* Internal.
* Called from NetworkDomain to send registration string
*/
bool
start
();
char
host
[
100
];
int
port
;
struct
sockaddr_in
sin
;
bool
reachable
;
NetworkDomain
*
domain
;
Connection
*
next
;
};
/**
* The Network domainclass can be subclassed to send and to
* receive multicasts from other Network instances in
* other processes/machines.
*/
class
NetworkDomain
{
public
:
enum
{
defaultPort
=
23412
};
/* install listening TCP socket on port */
NetworkDomain
(
int
port
=
defaultPort
);
virtual
~
NetworkDomain
();
bool
isListening
()
{
return
(
fd
>=
0
);
}
/**
* Returns the file descriptor for the listening socket
*/
int
startListening
(
NetworkLoop
*
);
/**
* Close all connections and listening socket
*/
void
close
();
int
ID
()
{
return
myID
;
}
int
listeningPort
()
{
return
myPort
;
}
int
listeningFD
()
{
return
fd
;
}
void
addConnection
(
const
char
*
host
,
int
port
);
void
broadcast
(
const
char
*
str
);
/* return number of connections */
int
count
();
/* For list of domains used in a NetworkLoop.
* Can be done this way as a NetworkDomain can only be used
* in one NetworkLoop at a time
*/
NetworkDomain
*
next
;
/**
* Internal use.
* NetworkLoop asks to check for pending connections and data
*/
void
check
(
fd_set
*
);
/**
* Internal use.
* Overwrite this to react on new connections
*/
virtual
void
newConnection
(
Connection
*
);
protected
:
/* overwrite this in your subclass to receive
* strings broadcasted */
virtual
void
received
(
char
*
str
);
Connection
*
prepareConnection
(
const
char
*
host
,
int
port
);
private
:
void
gotConnection
();
/* factory for connections to not get multiply connections to one target */
Connection
*
getNewConnection
(
const
char
*
h
,
struct
sockaddr_in
sin
);
NetworkLoop
*
loop
;
Connection
*
connectionList
;
struct
sockaddr_in
mySin
;
int
fd
,
myID
,
myPort
;
};
#endif
mpi-assign5/pv-split-interative/player.cpp
0 → 100644
View file @
17980573
/**
* Computer player
*
* (1) Connects to a game communication channel,
* (2) Waits for a game position requiring to draw a move,
* (3) Does a best move search, and broadcasts the resulting position,
* Jump to (2)
*
* (C) 2005, Josef Weidendorfer
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
#include <mpi.h>
#include "board.h"
#include "search.h"
#include "eval.h"
#include "network.h"
#define pretty_print(name, val) printf("%s = %d: %s: %s: %d\n", name, val, __FILE__,__FUNCTION__,__LINE__);
int
thread_rank
;
int
num_threads
;
/* Global, static vars */
NetworkLoop
l
;
Board
b
;
Evaluator
ev
;
/* Which color to play? */
int
myColor
=
Board
::
color1
;
/* Which search strategy to use? */
int
strategyNo
=
0
;
/* Max search depth */
int
maxDepth
=
0
;
/* Maximal number of moves before terminating (negative for infinity) */
int
maxMoves
=
-
1
;
/* to set verbosity of NetworkLoop implementation */
extern
int
verbose
;
/* remote channel */
char
*
host
=
0
;
/* not used on default */
int
rport
=
23412
;
/* local channel */
int
lport
=
13133
;
/* change evaluation after move? */
bool
changeEval
=
true
;
/**
* MyDomain
*
* Class for communication handling for player:
* - start search for best move if a position is received
* in which this player is about to draw
*/
class
MyDomain
:
public
NetworkDomain
{
public
:
MyDomain
(
int
p
)
:
NetworkDomain
(
p
)
{}
void
sendBoard
();
protected
:
void
received
(
char
*
str
);
};
void
MyDomain
::
sendBoard
()
{
static
char
tmp
[
500
];
sprintf
(
tmp
,
"pos %s
\n
"
,
b
.
getState
());
if
(
verbose
)
printf
(
tmp
+
4
);
broadcast
(
tmp
);
}
void
MyDomain
::
received
(
char
*
str
)
{
for
(
int
i
=
1
;
i
<
num_threads
;
i
++
)
MPI_Send
(
str
,
1024
,
MPI_CHAR
,
i
,
10
,
MPI_COMM_WORLD
);
if
(
strncmp
(
str
,
"quit"
,
4
)
==
0
)
{
l
.
exit
();
return
;
}
if
(
strncmp
(
str
,
"pos "
,
4
)
!=
0
)
return
;
b
.
setState
(
str
+
4
);
if
(
verbose
)
{
printf
(
"
\n\n
==========================================
\n
"
);
printf
(
str
+
4
);
}
int
state
=
b
.
validState
();
if
((
state
!=
Board
::
valid1
)
&&
(
state
!=
Board
::
valid2
))
{
printf
(
"%s
\n
"
,
Board
::
stateDescription
(
state
));
switch
(
state
)
{
case
Board
:
:
timeout1
:
case
Board
:
:
timeout2
:
case
Board
:
:
win1
:
case
Board
:
:
win2
:
l
.
exit
();
default
:
break
;
}
return
;
}
if
(
b
.
actColor
()
&
myColor
)
{
struct
timeval
t1
,
t2
;
gettimeofday
(
&
t1
,
0
);
Move
m
=
b
.
bestMove
();
gettimeofday
(
&
t2
,
0
);
int
msecsPassed
=
(
1000
*
t2
.
tv_sec
+
t2
.
tv_usec
/
1000
)
-
(
1000
*
t1
.
tv_sec
+
t1
.
tv_usec
/
1000
);
printf
(
"%s "
,
(
myColor
==
Board
::
color1
)
?
"O"
:
"X"
);
if
(
m
.
type
==
Move
::
none
)
{
printf
(
" can not draw any move ?! Sorry.
\n
"
);
return
;
}
printf
(
"draws '%s' (after %d.%03d secs)...
\n
"
,
m
.
name
(),
msecsPassed
/
1000
,
msecsPassed
%
1000
);
b
.
playMove
(
m
,
msecsPassed
);
sendBoard
();
if
(
changeEval
)
ev
.
changeEvaluation
();
/* stop player at win position */
int
state
=
b
.
validState
();
if
((
state
!=
Board
::
valid1
)
&&
(
state
!=
Board
::
valid2
))
{
printf
(
"%s
\n
"
,
Board
::
stateDescription
(
state
));
switch
(
state
)
{
case
Board
:
:
timeout1
:
case
Board
:
:
timeout2
:
case
Board
:
:
win1
:
case
Board
:
:
win2
:
l
.
exit
();
default
:
break
;
}
}
maxMoves
--
;
if
(
maxMoves
==
0
)
{
printf
(
"Terminating because given number of moves drawn.
\n
"
);
broadcast
(
"quit
\n
"
);
l
.
exit
();
}
}
}
/*
* Main program
*/
void
printHelp
(
char
*
prg
,
bool
printHeader
)
{
if
(
printHeader
)
printf
(
"Computer player V 0.1 - (C) 2005 Josef Weidendorfer
\n
"
"Search for a move on receiving a position in which we are expected to draw.
\n\n
"
);
printf
(
"Usage: %s [options] [X|O] [<strength>]
\n\n
"
" X Play side X
\n
"
" O Play side O (default)
\n
"
" <strength> Playing strength, depending on strategy
\n
"
" A time limit can reduce this
\n\n
"
,
prg
);
printf
(
" Options:
\n
"
" -h / --help Print this help text
\n
"
" -v / -vv Be verbose / more verbose
\n
"
" -s <strategy> Number of strategy to use for computer (see below)
\n
"
" -n Do not change evaluation function after own moves
\n
"
" -<integer> Maximal number of moves before terminating
\n
"
" -p [host:][port] Connection to broadcast channel
\n
"
" (default: 23412)
\n\n
"
);
printf
(
" Available search strategies for option '-s':
\n
"
);
char
**
strs
=
SearchStrategy
::
strategies
();
for
(
int
i
=
0
;
strs
[
i
];
i
++
)
printf
(
" %2d : Strategy '%s'%s
\n
"
,
i
,
strs
[
i
],
(
i
==
strategyNo
)
?
" (default)"
:
""
);
printf
(
"
\n
"
);
exit
(
1
);
}
void
parseArgs
(
int
argc
,
char
*
argv
[])
{
int
arg
=
0
;
while
(
arg
+
1
<
argc
)
{
arg
++
;
if
(
strcmp
(
argv
[
arg
],
"-h"
)
==
0
||
strcmp
(
argv
[
arg
],
"--help"
)
==
0
)
printHelp
(
argv
[
0
],
true
);
if
(
strncmp
(
argv
[
arg
],
"-v"
,
2
)
==
0
)
{
verbose
=
1
;
while
(
argv
[
arg
][
verbose
+
1
]
==
'v'
)
verbose
++
;
continue
;
}
if
(
strcmp
(
argv
[
arg
],
"-n"
)
==
0
)
{
changeEval
=
false
;
continue
;
}
if
((
strcmp
(
argv
[
arg
],
"-s"
)
==
0
)
&&
(
arg
+
1
<
argc
))
{
arg
++
;
if
(
argv
[
arg
][
0
]
>=
'0'
&&
argv
[
arg
][
0
]
<=
'9'
)
strategyNo
=
argv
[
arg
][
0
]
-
'0'
;
continue
;
}
if
((
argv
[
arg
][
0
]
==
'-'
)
&&
(
argv
[
arg
][
1
]
>=
'0'
)
&&
(
argv
[
arg
][
1
]
<=
'9'
))
{
int
pos
=
2
;
maxMoves
=
argv
[
arg
][
1
]
-
'0'
;
while
((
argv
[
arg
][
pos
]
>=
'0'
)
&&
(
argv
[
arg
][
pos
]
<=
'9'
))
{
maxMoves
=
maxMoves
*
10
+
argv
[
arg
][
pos
]
-
'0'
;
pos
++
;
}
continue
;
}
if
((
strcmp
(
argv
[
arg
],
"-p"
)
==
0
)
&&
(
arg
+
1
<
argc
))
{
arg
++
;
if
(
argv
[
arg
][
0
]
>
'0'
&&
argv
[
arg
][
0
]
<=
'9'
)
{
lport
=
atoi
(
argv
[
arg
]);
continue
;
}
char
*
c
=
strrchr
(
argv
[
arg
],
':'
);
int
p
=
0
;
if
(
c
!=
0
)
{
*
c
=
0
;
p
=
atoi
(
c
+
1
);
}
host
=
argv
[
arg
];
if
(
p
)
rport
=
p
;
continue
;
}
if
(
argv
[
arg
][
0
]
==
'X'
)
{
myColor
=
Board
::
color2
;
continue
;
}
if
(
argv
[
arg
][
0
]
==
'O'
)
{
myColor
=
Board
::
color1
;
continue
;
}
int
strength
=
atoi
(
argv
[
arg
]);
if
(
strength
==
0
)
{
printf
(
"ERROR - Unknown option %s
\n
"
,
argv
[
arg
]);
printHelp
(
argv
[
0
],
false
);
}
maxDepth
=
strength
;
}
}
int
main
(
int
argc
,
char
*
argv
[])
{
MPI_Init
(
&
argc
,
&
argv
);
MPI_Comm_size
(
MPI_COMM_WORLD
,
&
num_threads
);
MPI_Comm_rank
(
MPI_COMM_WORLD
,
&
thread_rank
);
parseArgs
(
argc
,
argv
);
#if 0
if(thread_rank < 4)
myColor = Board::color1;
else {
myColor = Board::color2;
thread_rank = thread_rank - 4;
}
#endif
SearchStrategy
*
ss
=
SearchStrategy
::
create
(
strategyNo
);
if
(
verbose
)
printf
(
"Using strategy '%s' ...
\n
"
,
ss
->
name
());
ss
->
setMaxDepth
(
maxDepth
);
b
.
setSearchStrategy
(
ss
);
ss
->
setEvaluator
(
&
ev
);
ss
->
registerCallbacks
(
new
SearchCallbacks
(
verbose
));
if
(
thread_rank
==
0
)
{
MyDomain
d
(
lport
);
if
(
host
)
d
.
addConnection
(
host
,
rport
);
l
.
install
(
&
d
);
l
.
run
();
}
else
{
while
(
1
)
{
MPI_Status
mpi_st
;
Slave_Input
slave_input
;
Slave_Output
slave_output
;
MPI_Recv
(
&
slave_input
,
sizeof
(
Slave_Input
),
MPI_BYTE
,
0
,
10
,
MPI_COMM_WORLD
,
&
mpi_st
);
// depth= -1 is a signal for the slave to quit
if
(
slave_input
.
depth
==
-
1
)
break
;
ss
->
_board
=
&
b
;
ss
->
_board
->
setState
(
slave_input
.
boardstate
);
ss
->
_board
->
playMove
(
slave_input
.
move
);
((
ABIDStrategy
*
)
ss
)
->
_currentMaxDepth
=
slave_input
.
currentMaxDepth
;
ss
->
_sc
->
_leavesVisited
=
0
;
ss
->
_sc
->
_nodesVisited
=
0
;
/* check for a win position first */
if
(
!
ss
->
_board
->
isValid
())
{
slave_output
.
eval
=
(
14999
-
(
slave_input
.
depth
-
1
));
}
else
{
if
((
slave_input
.
depth
==
slave_input
.
currentMaxDepth
)
&&
(
slave_input
.
move
.
type
>
Move
::
maxPushType
))
slave_output
.
eval
=
ss
->
evaluate
();
else
slave_output
.
eval
=
-
((
ABIDStrategy
*
)
ss
)
->
alphabeta
(
slave_input
.
depth
,
slave_input
.
alpha
,
slave_input
.
beta
);
}
((
ABIDStrategy
*
)
ss
)
->
_pv
.
update
(
slave_input
.
depth
-
1
,
slave_input
.
move
);
slave_output
.
pv
=
((
ABIDStrategy
*
)
ss
)
->
_pv
;
slave_output
.
num_leaves
=
ss
->
_sc
->
_leavesVisited
;
slave_output
.
num_nodes
=
ss
->
_sc
->
_nodesVisited
;
MPI_Send
(
&
slave_output
,
sizeof
(
Slave_Output
),
MPI_BYTE
,
0
,
10
,
MPI_COMM_WORLD
);
}
}
MPI_Finalize
();
}
mpi-assign5/pv-split-interative/player.cpp1
0 → 100644
View file @
17980573
/**
* Computer player
*
* (1) Connects to a game communication channel,
* (2) Waits for a game position requiring to draw a move,
* (3) Does a best move search, and broadcasts the resulting position,
* Jump to (2)
*
* (C) 2005, Josef Weidendorfer
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
#include <mpi.h>
#include "board.h"
#include "search.h"
#include "eval.h"
#include "network.h"
#define pretty_print(name, val) printf("%s = %d: %s: %s: %d\n", name, val, __FILE__,__FUNCTION__,__LINE__);
int thread_rank;
int num_threads;
FILE *file;
/* Global, static vars */
NetworkLoop l;
Board b;
Evaluator ev;
/* Which color to play? */
int myColor = Board::color1;
/* Which search strategy to use? */
int strategyNo = 0;
/* Max search depth */
int maxDepth = 0;
/* Maximal number of moves before terminating (negative for infinity) */
int maxMoves = -1;
/* to set verbosity of NetworkLoop implementation */
extern int verbose;
/* remote channel */
char* host = 0; /* not used on default */
int rport = 23412;
/* local channel */
int lport = 13133;
/* change evaluation after move? */
bool changeEval = true;
char global_tmp[500];
/**
* MyDomain
*
* Class for communication handling for player:
* - start search for best move if a position is received
* in which this player is about to draw
*/
class MyDomain: public NetworkDomain
{
public:
MyDomain(int p) : NetworkDomain(p) {}
void sendBoard();
// protected:
void received(char* str);
};
void MyDomain::sendBoard()
{
static char tmp[500];
sprintf(tmp, "pos %s\n", b.getState());
if (verbose) printf(tmp+4);
broadcast(tmp);
}
void MyDomain::received(char* str)
{
if (strncmp(str, "quit", 4)==0) {
l.exit();
return;
}
if (strncmp(str, "pos ", 4)!=0) return;
b.setState(str+4);
if (verbose) {
printf("\n\n==========================================\n");
printf(str+4);
}
int state = b.validState();
if ((state != Board::valid1) &&
(state != Board::valid2)) {
printf("%s\n", Board::stateDescription(state));
switch(state) {
case Board::timeout1:
case Board::timeout2:
case Board::win1:
case Board::win2:
l.exit();
default:
break;
}
return;
}
if (b.actColor() & myColor) {
struct timeval t1, t2;
gettimeofday(&t1,0);
Move m = b.bestMove();
gettimeofday(&t2,0);
int msecsPassed =
(1000* t2.tv_sec + t2.tv_usec / 1000) -
(1000* t1.tv_sec + t1.tv_usec / 1000);
printf("%s ", (myColor == Board::color1) ? "O":"X");
if (m.type == Move::none) {
printf(" can not draw any move ?! Sorry.\n");
return;
}
printf("draws '%s' (after %d.%03d secs)...\n",
m.name(), msecsPassed/1000, msecsPassed%1000);
b.playMove(m, msecsPassed);
sendBoard();
if (changeEval)
ev.changeEvaluation();
/* stop player at win position */
int state = b.validState();
if ((state != Board::valid1) &&
(state != Board::valid2)) {
printf("%s\n", Board::stateDescription(state));
switch(state) {
case Board::timeout1:
case Board::timeout2:
case Board::win1:
case Board::win2:
l.exit();
default:
break;
}
}
maxMoves--;
if (maxMoves == 0) {
printf("Terminating because given number of moves drawn.\n");
broadcast("quit\n");
l.exit();
}
}
}
/*
* Main program
*/
void printHelp(char* prg, bool printHeader)
{
if (printHeader)
printf("Computer player V 0.1 - (C) 2005 Josef Weidendorfer\n"
"Search for a move on receiving a position in which we are expected to draw.\n\n");
printf("Usage: %s [options] [X|O] [<strength>]\n\n"
" X Play side X\n"
" O Play side O (default)\n"
" <strength> Playing strength, depending on strategy\n"
" A time limit can reduce this\n\n" ,
prg);
printf(" Options:\n"
" -h / --help Print this help text\n"
" -v / -vv Be verbose / more verbose\n"
" -s <strategy> Number of strategy to use for computer (see below)\n"
" -n Do not change evaluation function after own moves\n"
" -<integer> Maximal number of moves before terminating\n"
" -p [host:][port] Connection to broadcast channel\n"
" (default: 23412)\n\n");
printf(" Available search strategies for option '-s':\n");
char** strs = SearchStrategy::strategies();
for(int i = 0; strs[i]; i++)
printf(" %2d : Strategy '%s'%s\n", i, strs[i],
(i==strategyNo) ? " (default)":"");
printf("\n");
exit(1);
}
void parseArgs(int argc, char* argv[])
{
int arg=0;
while(arg+1<argc) {
arg++;
if (strcmp(argv[arg],"-h")==0 ||
strcmp(argv[arg],"--help")==0) printHelp(argv[0], true);
if (strncmp(argv[arg],"-v",2)==0) {
verbose = 1;
while(argv[arg][verbose+1] == 'v') verbose++;
continue;
}
if (strcmp(argv[arg],"-n")==0) {
changeEval = false;
continue;
}
if ((strcmp(argv[arg],"-s")==0) && (arg+1<argc)) {
arg++;
if (argv[arg][0]>='0' && argv[arg][0]<='9')
strategyNo = argv[arg][0] - '0';
continue;
}
if ((argv[arg][0] == '-') &&
(argv[arg][1] >= '0') &&
(argv[arg][1] <= '9')) {
int pos = 2;
maxMoves = argv[arg][1] - '0';
while((argv[arg][pos] >= '0') &&
(argv[arg][pos] <= '9')) {
maxMoves = maxMoves * 10 + argv[arg][pos] - '0';
pos++;
}
continue;
}
if ((strcmp(argv[arg],"-p")==0) && (arg+1<argc)) {
arg++;
if (argv[arg][0]>'0' && argv[arg][0]<='9') {
lport = atoi(argv[arg]);
continue;
}
char* c = strrchr(argv[arg],':');
int p = 0;
if (c != 0) {
*c = 0;
p = atoi(c+1);
}
host = argv[arg];
if (p) rport = p;
continue;
}
if ((strcmp(argv[arg],"-f")==0) && (arg+1<argc)) {
arg++;
file = fopen(argv[arg], "r");
//arg++;
continue;
}
if (argv[arg][0] == 'X') {
myColor = Board::color2;
continue;
}
if (argv[arg][0] == 'O') {
myColor = Board::color1;
continue;
}
int strength = atoi(argv[arg]);
if (strength == 0) {
printf("ERROR - Unknown option %s\n", argv[arg]);
printHelp(argv[0], false);
}
maxDepth = strength;
}
}
extern int avg_kleavesPerSec;
extern int _msecs;
Move m;
int main(int argc, char* argv[])
{
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &num_threads);
MPI_Comm_rank(MPI_COMM_WORLD, &thread_rank);
parseArgs(argc, argv);
if (file){
int len = 0, c;
while( len<499 && (c=fgetc(file)) != EOF)
global_tmp[len++] = (char) c;
global_tmp[len++]=0;
//printf("Gaurav\n");
//printf("%s",global_tmp);
//printf("Gaurav\n");
}
SearchStrategy* ss = SearchStrategy::create(strategyNo);
if (verbose)
printf("Using strategy '%s' ...\n", ss->name());
ss->setMaxDepth(maxDepth);
b.setSearchStrategy( ss );
ss->setEvaluator(&ev);
ss->registerCallbacks(new SearchCallbacks(verbose));
if(thread_rank == 0) {
MyDomain d(lport);
// d.received(global_tmp);
if (host) d.addConnection(host, rport);
l.install(&d);
l.run();
// Send a signal to the slaves, that they should quit
Slave_Input slave_input;
slave_input.depth = -1;
int slave_id;
for (slave_id = 0; slave_id < num_threads-1; slave_id++)
MPI_Send(&slave_input, sizeof(Slave_Input), MPI_BYTE, slave_id + 1, 10, MPI_COMM_WORLD);
//printf("Average leaves visited per sec = %d k/s\n", avg_kleavesPerSec);
}
else
{
while (1)
{
MPI_Status mpi_st;
Slave_Input slave_input;
Slave_Output slave_output;
MPI_Recv (&slave_input, sizeof(Slave_Input), MPI_BYTE, 0, 10, MPI_COMM_WORLD, &mpi_st);
// depth= -1 is a signal for the slave to quit
if (slave_input.depth == -1)
break;
ss->_board = &b;
ss->_board->setState(slave_input.boardstate);
ss->_board->playMove(slave_input.move);
((ABIDStrategy*)ss)->_currentMaxDepth = slave_input.currentMaxDepth;
ss->_sc->_leavesVisited = 0;
ss->_sc->_nodesVisited = 0;
/* check for a win position first */
if (!ss->_board->isValid())
{
slave_output.eval = (14999-(slave_input.depth-1));
}
else
{
if ((slave_input.depth == slave_input.currentMaxDepth) && (slave_input.move.type > Move::maxPushType ))
slave_output.eval = ss->evaluate();
else
slave_output.eval = -((ABIDStrategy*)ss)->alphabeta(slave_input.depth, slave_input.alpha, slave_input.beta);
}
((ABIDStrategy*)ss)->_pv.update(slave_input.depth-1, slave_input.move);
slave_output.pv = ((ABIDStrategy*)ss)->_pv;
slave_output.num_leaves = ss->_sc->_leavesVisited;
slave_output.num_nodes = ss->_sc->_nodesVisited;
MPI_Send(&slave_output, sizeof(Slave_Output), MPI_BYTE, 0, 10, MPI_COMM_WORLD);
}
}
/*
int *avg_list;
avg_list = (int*)malloc(sizeof(int)*num_threads);
MPI_Gather (&avg_kleavesPerSec, 1, MPI_INT,
avg_list, 1, MPI_INT, 0, MPI_COMM_WORLD);
if(thread_rank == 0)
{
int average;
for(int i=0;i<num_threads;i++) {
average += avg_list[i];
}
printf("\n\n\n%d, %d, %d, %f, %s\n", num_threads, maxDepth, average, _msecs/1000.0, ss->_bestMove.name());
}*/
MPI_Finalize();
}
mpi-assign5/pv-split-interative/position-endgame
0 → 100644
View file @
17980573
pos #69 O: 14, X: 10
-----------
/ . . . . . \
/ . O . . . . \
/ . . O . . . . \
/ . . X . O . . . \
| . X X O O O O . . |
\ . X . O O O . . /
\ . O O O O . . /
\ . X X X X . /
\ . . X . X /
-----------
X about to move...
=========================================================
Start from this position with
./start position-endgame
Results for "./player <Strength> X"
(Sequential search, Pentium M, 1.6 GHz)
Strength | Move | Evaluated | Time [s] | Rate
| | | -O3 | [Evals/s]
1 I9/RightUp 384
2 I7/LeftUp/Psh 1 796 .042 43 k
3 I7/LeftUp/Psh 17 823 .169 105 k
4 I7/LeftUp/Psh 23 266 .255 91 k
5 I7/LeftUp/Psh 1 520 313 5.715 266 k
6 I7/LeftUp/Psh 11 196 668 39.575 283 k
mpi-assign5/pv-split-interative/position-midgame1
0 → 100644
View file @
17980573
pos #29 O: 14, X: 14
-----------
/ . . . . . \
/ . O O O O . \
/ . O O . O . . \
/ . . O O O . . . \
| . . O O O . . . . |
\ . X O X X X . . /
\ . X X X X X . /
\ X X X X X . /
\ . . . . . /
-----------
X about to move...
=========================================================
Start from this position with
./start position-midgame1
Results for "./player <Strength> X"
(Sequential search, Pentium M, 1.6 GHz)
Strength | Move | Evaluated | Time [s] | Rate
| | | -O3 | [Evals/s]
1 F3/LeftDown 71
2 F3-G4/Left 5 199 .064 81 k
3 F3-G4/Left 120 718 .649 186 k
4 G4/LeftUp 2 485 542 11.067 225 k
5 G4/RightDown 15 018 100 70.446 213 k
mpi-assign5/pv-split-interative/position-midgame2
0 → 100644
View file @
17980573
pos #120 O: 14, X: 12
-----------
/ . . . . . \
/ O O O O O . \
/ . O O X O . . \
/ . O X O O . . . \
| . O O X X X . . . |
\ . . O X X X . . /
\ . . X . X . . /
\ . X . X . . /
\ . . . . . /
-----------
O about to move...
=========================================================
Start from this position with
./start position-midgame2
Results for "./player <Strength> O"
(Sequential search, Pentium M, 1.6 GHz)
Strength | Move | Evaluated | Time [s] | Rate
| | | -O3 | [Evals/s]
1 E3-F4/LeftDown 257
2 B1/RightUp 4 358 .062 70 k
3 C2-E2/Left 97 908 .505 194 k
4 B1/LeftDown 1 519 234 5.007 303 k
5 C2-D2/Left 4 411 737 15.265 289 k
mpi-assign5/pv-split-interative/position-start
0 → 100644
View file @
17980573
pos #1 O: 14, X: 14
-----------
/ O O O O O \
/ O O O O O O \
/ . . O O O . . \
/ . . . . . . . . \
| . . . . . . . . . |
\ . . . . . . . . /
\ . . X X X . . /
\ X X X X X X /
\ X X X X X /
-----------
X about to move...
=========================================================
mpi-assign5/pv-split-interative/referee.cpp
0 → 100644
View file @
17980573
/**
* Referee
*
* Send a start position into 2 game communication channels,
* observe positions sent in one channel, and if valid, broadcast
* them into other channel.
* For a time limited game, times are updated by referee itself.
*
* (C) 2005, Josef Weidendorfer
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
#include "board.h"
#include "network.h"
/* Global, static vars */
static
NetworkLoop
l
;
static
Board
b
;
/* Time of last draw */
static
struct
timeval
t1
;
class
MyDomain
;
static
MyDomain
*
d1
=
0
,
*
d2
=
0
;
/*
* Do other members in the channels exist at all?
* Only start time if there are players.
*
* Note: We can not distinguish between observers and players,
* so game always start when another member is seen.
*/
static
bool
d1MemberExists
=
false
;
static
bool
d2MemberExists
=
false
;
/* time limit in seconds (0: no time limit) */
static
int
secsToPlay
=
0
;
static
int
msecsToPlay
[
3
]
=
{
0
,
0
,
0
};
/* to set verbosity of NetworkLoop implementation */
extern
int
verbose
;
#define DEFAULT_DOMAIN_PORT 13375
#define DEFAULT_DOMAIN_DIFF 50
/* remote channel */
static
char
*
host
[
2
]
=
{
0
,
0
};
/* not used per default */
static
int
rport
[
2
]
=
{
DEFAULT_DOMAIN_PORT
,
DEFAULT_DOMAIN_PORT
+
DEFAULT_DOMAIN_DIFF
};
/* local channel */
static
int
lport
[
2
]
=
{
DEFAULT_DOMAIN_PORT
,
DEFAULT_DOMAIN_PORT
+
DEFAULT_DOMAIN_DIFF
};
/* Where to read position to broadcast from? (0: start position) */
static
FILE
*
file
=
0
;
class
MyDomain
:
public
NetworkDomain
{
public
:
MyDomain
(
int
p
)
:
NetworkDomain
(
p
)
{}
void
sendBoard
();
protected
:
void
received
(
char
*
str
);
void
newConnection
(
Connection
*
);
};
void
MyDomain
::
sendBoard
()
{
static
char
tmp
[
500
];
sprintf
(
tmp
,
"pos %s
\n
"
,
b
.
getState
());
if
(
verbose
)
{
printf
(
tmp
+
4
);
int
state
=
b
.
validState
();
printf
(
"%s
\n
"
,
Board
::
stateDescription
(
state
));
}
broadcast
(
tmp
);
}
void
MyDomain
::
received
(
char
*
str
)
{
if
(
strncmp
(
str
,
"quit"
,
4
)
==
0
)
{
l
.
exit
();
return
;
}
if
(
strncmp
(
str
,
"pos "
,
4
)
!=
0
)
return
;
if
(
b
.
validState
()
!=
Board
::
empty
)
{
Board
newBoard
;
newBoard
.
setState
(
str
+
4
);
Move
m
=
b
.
moveToReach
(
&
newBoard
,
false
);
if
(
m
.
type
==
Move
::
none
)
{
printf
(
"WARNING: Got a board which is not reachable via a valid move !?
\n
"
);
return
;
}
else
{
struct
timeval
t2
;
gettimeofday
(
&
t2
,
0
);
int
msecsPassed
=
(
1000
*
t2
.
tv_sec
+
t2
.
tv_usec
/
1000
)
-
(
1000
*
t1
.
tv_sec
+
t1
.
tv_usec
/
1000
);
t1
=
t2
;
int
*
pMSecs
;
if
(
b
.
actColor
()
==
Board
::
color1
)
{
pMSecs
=
&
(
msecsToPlay
[
Board
::
color1
]);
printf
(
"O"
);
}
else
{
pMSecs
=
&
(
msecsToPlay
[
Board
::
color2
]);
printf
(
"X"
);
}
printf
(
" draws '%s' (after %d.%03d secs)...
\n
"
,
m
.
name
(),
msecsPassed
/
1000
,
msecsPassed
%
1000
);
if
(
*
pMSecs
>
msecsPassed
)
*
pMSecs
-=
msecsPassed
;
else
*
pMSecs
=
0
;
}
}
b
.
setState
(
str
+
4
);
/* force our objective view regarding time */
b
.
setMSecsToPlay
(
Board
::
color1
,
msecsToPlay
[
Board
::
color1
]
);
b
.
setMSecsToPlay
(
Board
::
color2
,
msecsToPlay
[
Board
::
color2
]
);
printf
(
b
.
getState
());
int
state
=
b
.
validState
();
printf
(
"%s
\n
"
,
Board
::
stateDescription
(
state
));
switch
(
state
)
{
case
Board
:
:
timeout1
:
case
Board
:
:
timeout2
:
case
Board
:
:
win1
:
case
Board
:
:
win2
:
l
.
exit
();
default
:
break
;
}
/* send to other domain */
if
(
d1
==
this
)
if
(
d2
)
d2
->
sendBoard
();
if
(
d2
==
this
)
if
(
d1
)
d1
->
sendBoard
();
}
void
MyDomain
::
newConnection
(
Connection
*
c
)
{
NetworkDomain
::
newConnection
(
c
);
static
char
tmp
[
500
];
int
len
=
sprintf
(
tmp
,
"pos %s
\n
"
,
b
.
getState
());
c
->
sendString
(
tmp
,
len
);
/* adjust time if this is first connection for the channel */
if
(
!
d1MemberExists
&&
(
this
==
d1
))
{
d1MemberExists
=
true
;
gettimeofday
(
&
t1
,
0
);
}
if
(
!
d2MemberExists
&&
(
this
==
d2
))
{
d2MemberExists
=
true
;
gettimeofday
(
&
t1
,
0
);
}
}
static
void
printHelp
(
char
*
prg
,
bool
printHeader
)
{
if
(
printHeader
)
printf
(
"Referee V 0.1 - (C) 2005 Josef Weidendorfer
\n
"
"Broadcast a game position into 2 domains, observe moves played in one domain,
\n
"
"and if valid, broadcast to other domain. Stops playing times itself.
\n\n
"
);
printf
(
"Usage: %s [options] [<file>|-]
\n\n
"
" <file> File containing game position (default: start position)
\n
"
" - Position is read from standard input
\n\n
"
,
prg
);
printf
(
" Options:
\n
"
" -h / --help Print this help text
\n
"
" -v / -vv Be verbose / more verbose
\n
"
" -t <timeToPlay> Start in tournament modus (limited time)
\n
"
" -p [host:][port] Connection to first (second) broadcast channel
\n
"
" (default: %d / %d)
\n\n
"
,
DEFAULT_DOMAIN_PORT
,
DEFAULT_DOMAIN_PORT
+
DEFAULT_DOMAIN_DIFF
);
exit
(
1
);
}
static
void
parseArgs
(
int
argc
,
char
*
argv
[])
{
int
domainsSet
=
0
;
int
arg
=
0
;
while
(
arg
+
1
<
argc
)
{
arg
++
;
if
(
argv
[
arg
][
0
]
==
'-'
)
{
if
(
strcmp
(
argv
[
arg
],
"-h"
)
==
0
||
strcmp
(
argv
[
arg
],
"--help"
)
==
0
)
printHelp
(
argv
[
0
],
true
);
if
(
strcmp
(
argv
[
arg
],
"-v"
)
==
0
)
{
verbose
=
1
;
continue
;
}
if
(
strcmp
(
argv
[
arg
],
"-vv"
)
==
0
)
{
verbose
=
2
;
continue
;
}
if
((
strcmp
(
argv
[
arg
],
"-t"
)
==
0
)
&&
(
arg
+
1
<
argc
))
{
arg
++
;
secsToPlay
=
atoi
(
argv
[
arg
]);
if
(
secsToPlay
==
0
)
{
printf
(
"%s: WARNING - Ignoring tournament; %d secs to play
\n
"
,
argv
[
0
],
secsToPlay
);
}
continue
;
}
if
((
strcmp
(
argv
[
arg
],
"-p"
)
==
0
)
&&
(
arg
+
1
<
argc
))
{
arg
++
;
if
(
domainsSet
>
1
)
{
printf
(
"%s: WARNING - Domain specification %s ignored.
\n
"
,
argv
[
0
],
argv
[
arg
]);
continue
;
}
if
(
argv
[
arg
][
0
]
>
'0'
&&
argv
[
arg
][
0
]
<=
'9'
)
{
lport
[
domainsSet
]
=
atoi
(
argv
[
arg
]);
domainsSet
++
;
continue
;
}
char
*
c
=
strrchr
(
argv
[
arg
],
':'
);
int
p
=
0
;
if
(
c
!=
0
)
{
*
c
=
0
;
p
=
atoi
(
c
+
1
);
}
host
[
domainsSet
]
=
argv
[
arg
];
if
(
p
)
rport
[
domainsSet
]
=
p
;
domainsSet
++
;
continue
;
}
if
(
strcmp
(
argv
[
arg
],
"-"
)
==
0
)
{
file
=
stdin
;
continue
;
}
printf
(
"%s: ERROR - Unknown option %s
\n
"
,
argv
[
0
],
argv
[
arg
]);
printHelp
(
argv
[
0
],
false
);
}
file
=
fopen
(
argv
[
arg
],
"r"
);
if
(
!
file
)
{
printf
(
"%s: ERROR - Can not open '%s' for reading start position
\n
"
,
argv
[
0
],
argv
[
arg
]);
printHelp
(
argv
[
0
],
false
);
}
break
;
}
if
(
lport
[
0
]
==
lport
[
1
])
{
lport
[
1
]
=
lport
[
0
]
+
DEFAULT_DOMAIN_DIFF
;
printf
(
"Local port for domain 2 set to %d
\n
"
,
lport
[
1
]);
}
}
int
main
(
int
argc
,
char
*
argv
[])
{
parseArgs
(
argc
,
argv
);
b
.
setVerbose
(
verbose
);
if
(
file
)
{
char
tmp
[
500
];
int
len
=
0
,
c
;
while
(
len
<
499
&&
(
c
=
fgetc
(
file
))
!=
EOF
)
tmp
[
len
++
]
=
(
char
)
c
;
tmp
[
len
++
]
=
0
;
if
(
!
b
.
setState
(
tmp
))
{
printf
(
"%s: WARNING - Can not parse given position; using start position
\n
"
,
argv
[
0
]);
b
.
begin
(
Board
::
color1
);
}
}
else
b
.
begin
(
Board
::
color1
);
if
(
secsToPlay
>=
0
)
{
msecsToPlay
[
Board
::
color1
]
=
1000
*
secsToPlay
;
msecsToPlay
[
Board
::
color2
]
=
1000
*
secsToPlay
;
}
else
{
msecsToPlay
[
Board
::
color1
]
=
b
.
msecsToPlay
(
Board
::
color1
);
msecsToPlay
[
Board
::
color2
]
=
b
.
msecsToPlay
(
Board
::
color2
);
}
b
.
setMSecsToPlay
(
Board
::
color1
,
msecsToPlay
[
Board
::
color1
]
);
b
.
setMSecsToPlay
(
Board
::
color2
,
msecsToPlay
[
Board
::
color2
]
);
/*
* Register domains at NetworkLoop. Existing members will
* get sent the board via MyDomain::newConnection
*/
d1
=
new
MyDomain
(
lport
[
0
]);
if
(
host
[
0
])
d1
->
addConnection
(
host
[
0
],
rport
[
0
]);
d2
=
new
MyDomain
(
lport
[
1
]);
if
(
host
[
1
])
d2
->
addConnection
(
host
[
1
],
rport
[
1
]);
l
.
install
(
d1
);
l
.
install
(
d2
);
d1MemberExists
=
d1
->
count
()
>
0
;
d2MemberExists
=
d2
->
count
()
>
0
;
gettimeofday
(
&
t1
,
0
);
return
l
.
run
();
}
mpi-assign5/pv-split-interative/search-abid-pvsplit.cpp
0 → 100644
View file @
17980573
/**
* A real world, sequential strategy:
* Alpha/Beta with Iterative Deepening (ABID)
*
* (c) 2005, Josef Weidendorfer
*/
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#include <string.h>
#include "search.h"
#include "board.h"
extern
int
thread_rank
;
extern
int
num_threads
;
/**
* Entry point for search
*
* Does iterative deepening and alpha/beta width handling, and
* calls alpha/beta search
*/
void
ABIDStrategy
::
searchBestMove
()
{
int
alpha
=
-
15000
,
beta
=
15000
;
int
nalpha
,
nbeta
,
currentValue
=
0
;
_pv
.
clear
(
_maxDepth
);
_currentBestMove
.
type
=
Move
::
none
;
_currentMaxDepth
=
1
;
/* iterative deepening loop */
do
{
/* searches on same level with different alpha/beta windows */
while
(
1
)
{
nalpha
=
alpha
,
nbeta
=
beta
;
_inPV
=
(
_pv
[
0
].
type
!=
Move
::
none
);
if
(
_sc
&&
_sc
->
verbose
())
{
char
tmp
[
100
];
sprintf
(
tmp
,
"Alpha/Beta [%d;%d] with max depth %d"
,
alpha
,
beta
,
_currentMaxDepth
);
_sc
->
substart
(
tmp
);
}
currentValue
=
pv_split
(
alpha
,
beta
);
printf
(
"Subsearch finished with currentValue = %d
\n
"
,
currentValue
);
/* stop searching if a win position is found */
if
(
currentValue
>
14900
||
currentValue
<
-
14900
)
_stopSearch
=
true
;
/* Don't break out if we haven't found a move */
if
(
_currentBestMove
.
type
==
Move
::
none
)
_stopSearch
=
false
;
if
(
_stopSearch
)
break
;
/* if result is outside of current alpha/beta window,
* the search has to be rerun with widened alpha/beta
*/
if
(
currentValue
<=
nalpha
)
{
alpha
=
-
15000
;
if
(
beta
<
15000
)
beta
=
currentValue
+
1
;
continue
;
}
if
(
currentValue
>=
nbeta
)
{
if
(
alpha
>
-
15000
)
alpha
=
currentValue
-
1
;
beta
=
15000
;
continue
;
}
break
;
}
/* Window in both directions cause of deepening */
alpha
=
currentValue
-
200
,
beta
=
currentValue
+
200
;
if
(
_stopSearch
)
break
;
_currentMaxDepth
++
;
}
while
(
_currentMaxDepth
<=
_maxDepth
);
_bestMove
=
_currentBestMove
;
}
int
ABIDStrategy
::
pv_split
(
int
alpha0
,
int
beta0
)
{
bool
cutoff
;
int
depth
;
int
value
;
int
currentValue
=
-
15000
;
int
slave_id
;
int
num_slaves
;
int
pending_jobs
;
Slave_Input
slave_input
;
Slave_Output
*
slave_output
;
MPI_Request
*
rcv_rq
;
MoveList
list
;
Move
m
,
*
movechain
;
int
*
alpha
,
*
beta
;
rcv_rq
=
(
MPI_Request
*
)
malloc
(
num_threads
*
sizeof
(
MPI_Request
));
slave_output
=
(
Slave_Output
*
)
malloc
(
num_threads
*
sizeof
(
Slave_Output
));
movechain
=
(
Move
*
)
malloc
((
_currentMaxDepth
+
1
)
*
sizeof
(
Move
));
alpha
=
(
int
*
)
malloc
((
_currentMaxDepth
+
2
)
*
sizeof
(
int
));
beta
=
(
int
*
)
malloc
((
_currentMaxDepth
+
2
)
*
sizeof
(
int
));
alpha
[
0
]
=
alpha0
;
beta
[
0
]
=
beta0
;
_currentBestMove
.
type
=
Move
::
none
;
// Play moves from the pv until you reach the lowest level
// If pv-moves are not possible use random moves
// Store the sequence of moves in movechain
depth
=
0
;
while
(
depth
<
(
_currentMaxDepth
-
1
))
{
list
.
clear
();
_board
->
generateMoves
(
list
);
m
=
_pv
[
depth
];
// check if pv-move is possible
if
((
m
.
type
!=
Move
::
none
)
&&
(
!
list
.
isElement
(
m
,
0
,
false
)))
m
.
type
=
Move
::
none
;
// get random move if pv-move is not possible
if
(
m
.
type
==
Move
::
none
)
list
.
getNext
(
m
,
Move
::
none
);
_board
->
playMove
(
m
);
movechain
[
depth
]
=
m
;
alpha
[
depth
+
1
]
=
-
beta
[
depth
];
beta
[
depth
+
1
]
=
-
alpha
[
depth
];
depth
++
;
}
// Start at the second lowest level and move back up the gametree
// Devide the work at each level
depth
=
_currentMaxDepth
-
1
;
while
(
depth
>=
0
)
{
slave_id
=
0
;
list
.
clear
();
_board
->
generateMoves
(
list
);
// delete the move we already checked from the list
if
(
depth
<
_currentMaxDepth
-
1
)
list
.
isElement
(
movechain
[
depth
],
0
,
true
);
strcpy
(
slave_input
.
boardstate
,
_board
->
getState
());
slave_input
.
alpha
=
-
beta
[
depth
];
slave_input
.
beta
=
-
alpha
[
depth
];
slave_input
.
depth
=
depth
+
1
;
slave_input
.
currentMaxDepth
=
_currentMaxDepth
;
printf
(
"Thread 0 testing %d moves at depth = %d
\n
"
,
list
.
getLength
(),
depth
);
while
(
list
.
getNext
(
m
,
Move
::
none
)
)
{
slave_input
.
move
=
m
;
MPI_Send
(
&
slave_input
,
sizeof
(
Slave_Input
),
MPI_BYTE
,
slave_id
+
1
,
10
,
MPI_COMM_WORLD
);
MPI_Irecv
(
&
slave_output
[
slave_id
],
sizeof
(
Slave_Output
),
MPI_BYTE
,
slave_id
+
1
,
10
,
MPI_COMM_WORLD
,
&
rcv_rq
[
slave_id
]);
slave_id
++
;
if
(
slave_id
>=
(
num_threads
-
1
))
break
;
}
num_slaves
=
slave_id
;
pending_jobs
=
num_slaves
;
cutoff
=
false
;
while
(
pending_jobs
>
0
)
{
MPI_Waitany
(
num_slaves
,
rcv_rq
,
&
slave_id
,
MPI_STATUS_IGNORE
);
_sc
->
_leavesVisited
+=
slave_output
[
slave_id
].
num_leaves
;
_sc
->
_nodesVisited
+=
slave_output
[
slave_id
].
num_nodes
;
value
=
slave_output
[
slave_id
].
eval
;
if
(
value
>
currentValue
)
{
currentValue
=
value
;
_pv
=
slave_output
[
slave_id
].
pv
;
if
(
_sc
)
_sc
->
foundBestMove
(
depth
,
_pv
[
depth
],
currentValue
);
if
(
currentValue
>
alpha
[
depth
])
{
alpha
[
depth
]
=
currentValue
;
slave_input
.
beta
=
-
alpha
[
depth
];
}
/* alpha/beta cut off or win position ... */
if
(
currentValue
>
14900
||
currentValue
>=
beta
[
depth
])
cutoff
=
true
;
}
if
((
list
.
getNext
(
m
,
Move
::
none
))
&&
(
cutoff
==
false
))
{
slave_input
.
move
=
m
;
MPI_Send
(
&
slave_input
,
sizeof
(
Slave_Input
),
MPI_BYTE
,
slave_id
+
1
,
10
,
MPI_COMM_WORLD
);
MPI_Irecv
(
&
slave_output
[
slave_id
],
sizeof
(
Slave_Output
),
MPI_BYTE
,
slave_id
+
1
,
10
,
MPI_COMM_WORLD
,
&
rcv_rq
[
slave_id
]);
}
else
pending_jobs
--
;
}
if
(
depth
>
0
)
{
_board
->
takeBack
();
_pv
.
update
(
depth
-
1
,
movechain
[
depth
-
1
]);
currentValue
=
-
currentValue
;
if
(
currentValue
>
alpha
[
depth
-
1
])
alpha
[
depth
-
1
]
=
currentValue
;
}
if
(
depth
==
0
)
_currentBestMove
=
_pv
[
0
];
if
(
_sc
)
_sc
->
finishedNode
(
depth
,
_pv
.
chain
(
depth
));
depth
--
;
}
free
(
slave_output
);
free
(
rcv_rq
);
free
(
movechain
);
free
(
alpha
);
free
(
beta
);
return
currentValue
;
}
/*
* Alpha/Beta search
*
* - first, start with principal variation
* - depending on depth, we only do depth search for some move types
*/
int
ABIDStrategy
::
alphabeta
(
int
depth
,
int
alpha
,
int
beta
)
{
int
currentValue
=
-
14999
+
depth
,
value
;
Move
m
;
MoveList
list
;
bool
depthPhase
,
doDepthSearch
;
/* We make a depth search for the following move types... */
int
maxType
=
(
depth
<
_currentMaxDepth
-
1
)
?
Move
::
maxMoveType
:
(
depth
<
_currentMaxDepth
)
?
Move
::
maxPushType
:
Move
::
maxOutType
;
_board
->
generateMoves
(
list
);
if
(
_sc
&&
_sc
->
verbose
())
{
char
tmp
[
100
];
sprintf
(
tmp
,
"Alpha/Beta [%d;%d], %d moves (%d depth)"
,
alpha
,
beta
,
list
.
count
(
Move
::
none
),
list
.
count
(
maxType
));
_sc
->
startedNode
(
depth
,
tmp
);
}
// don't use moves from the principal variation
m
.
type
=
Move
::
none
;
// first, play all moves with depth search
depthPhase
=
true
;
while
(
1
)
{
// get next move
if
(
m
.
type
==
Move
::
none
)
{
if
(
depthPhase
)
depthPhase
=
list
.
getNext
(
m
,
maxType
);
if
(
!
depthPhase
)
if
(
!
list
.
getNext
(
m
,
Move
::
none
))
break
;
}
// we could start with a non-depth move from principal variation
doDepthSearch
=
depthPhase
&&
(
m
.
type
<=
maxType
);
_board
->
playMove
(
m
);
/* check for a win position first */
if
(
!
_board
->
isValid
())
{
/* Shorter path to win position is better */
value
=
14999
-
depth
;
}
else
{
if
(
doDepthSearch
)
{
/* opponent searches for its maximum; but we want the
* minimum: so change sign (for alpha/beta window too!)
*/
value
=
-
alphabeta
(
depth
+
1
,
-
beta
,
-
alpha
);
}
else
{
value
=
evaluate
();
}
}
_board
->
takeBack
();
/* best move so far? */
if
(
value
>
currentValue
)
{
currentValue
=
value
;
_pv
.
update
(
depth
,
m
);
/* alpha/beta cut off or win position ... */
if
(
currentValue
>
14900
||
currentValue
>=
beta
)
{
if
(
_sc
)
_sc
->
finishedNode
(
depth
,
_pv
.
chain
(
depth
));
return
currentValue
;
}
/* maximize alpha */
if
(
currentValue
>
alpha
)
alpha
=
currentValue
;
}
if
(
_stopSearch
)
break
;
// depthPhase=false;
m
.
type
=
Move
::
none
;
}
if
(
_sc
)
_sc
->
finishedNode
(
depth
,
_pv
.
chain
(
depth
));
return
currentValue
;
}
// register ourselve
ABIDStrategy
abidStrategy
;
mpi-assign5/pv-split-interative/search-abid.cpp
0 → 100644
View file @
17980573
/**
* A real world, sequential strategy:
* Alpha/Beta with Iterative Deepening (ABID)
*
* (c) 2005, Josef Weidendorfer
*/
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#include <string.h>
#include "search.h"
#include "board.h"
extern
int
thread_rank
;
extern
int
num_threads
;
/**
* Entry point for search
*
* Does iterative deepening and alpha/beta width handling, and
* calls alpha/beta search
*/
void
ABIDStrategy
::
searchBestMove
()
{
int
alpha
=
-
15000
,
beta
=
15000
;
int
nalpha
,
nbeta
,
currentValue
=
0
;
_pv
.
clear
(
_maxDepth
);
_currentBestMove
.
type
=
Move
::
none
;
_currentMaxDepth
=
1
;
/* iterative deepening loop */
do
{
/* searches on same level with different alpha/beta windows */
while
(
1
)
{
nalpha
=
alpha
,
nbeta
=
beta
;
_inPV
=
(
_pv
[
0
].
type
!=
Move
::
none
);
if
(
_sc
&&
_sc
->
verbose
())
{
char
tmp
[
100
];
sprintf
(
tmp
,
"Alpha/Beta [%d;%d] with max depth %d"
,
alpha
,
beta
,
_currentMaxDepth
);
_sc
->
substart
(
tmp
);
}
currentValue
=
pv_split
(
alpha
,
beta
);
printf
(
"Subsearch finished with currentValue = %d
\n
"
,
currentValue
);
/* stop searching if a win position is found */
if
(
currentValue
>
14900
||
currentValue
<
-
14900
)
_stopSearch
=
true
;
/* Don't break out if we haven't found a move */
if
(
_currentBestMove
.
type
==
Move
::
none
)
_stopSearch
=
false
;
if
(
_stopSearch
)
break
;
/* if result is outside of current alpha/beta window,
* the search has to be rerun with widened alpha/beta
*/
if
(
currentValue
<=
nalpha
)
{
alpha
=
-
15000
;
if
(
beta
<
15000
)
beta
=
currentValue
+
1
;
continue
;
}
if
(
currentValue
>=
nbeta
)
{
if
(
alpha
>
-
15000
)
alpha
=
currentValue
-
1
;
beta
=
15000
;
continue
;
}
break
;
}
/* Window in both directions cause of deepening */
alpha
=
currentValue
-
200
,
beta
=
currentValue
+
200
;
if
(
_stopSearch
)
break
;
_currentMaxDepth
++
;
}
while
(
_currentMaxDepth
<=
_maxDepth
);
_bestMove
=
_currentBestMove
;
}
int
ABIDStrategy
::
pv_split
(
int
alpha0
,
int
beta0
)
{
bool
cutoff
;
int
depth
;
int
value
;
int
currentValue
=
-
15000
;
int
slave_id
;
int
num_slaves
;
int
pending_jobs
;
Slave_Input
slave_input
;
Slave_Output
*
slave_output
;
MPI_Request
*
rcv_rq
;
MoveList
list
;
Move
m
,
*
movechain
;
int
*
alpha
,
*
beta
;
rcv_rq
=
(
MPI_Request
*
)
malloc
(
num_threads
*
sizeof
(
MPI_Request
));
slave_output
=
(
Slave_Output
*
)
malloc
(
num_threads
*
sizeof
(
Slave_Output
));
movechain
=
(
Move
*
)
malloc
((
_currentMaxDepth
+
1
)
*
sizeof
(
Move
));
alpha
=
(
int
*
)
malloc
((
_currentMaxDepth
+
2
)
*
sizeof
(
int
));
beta
=
(
int
*
)
malloc
((
_currentMaxDepth
+
2
)
*
sizeof
(
int
));
alpha
[
0
]
=
alpha0
;
beta
[
0
]
=
beta0
;
_currentBestMove
.
type
=
Move
::
none
;
// Play moves from the pv until you reach the lowest level
// If pv-moves are not possible use random moves
// Store the sequence of moves in movechain
depth
=
0
;
while
(
depth
<
(
_currentMaxDepth
-
1
))
{
list
.
clear
();
_board
->
generateMoves
(
list
);
m
=
_pv
[
depth
];
// check if pv-move is possible
if
((
m
.
type
!=
Move
::
none
)
&&
(
!
list
.
isElement
(
m
,
0
,
false
)))
m
.
type
=
Move
::
none
;
// get random move if pv-move is not possible
if
(
m
.
type
==
Move
::
none
)
list
.
getNext
(
m
,
Move
::
none
);
_board
->
playMove
(
m
);
movechain
[
depth
]
=
m
;
alpha
[
depth
+
1
]
=
-
beta
[
depth
];
beta
[
depth
+
1
]
=
-
alpha
[
depth
];
depth
++
;
}
// Start at the second lowest level and move back up the gametree
// Devide the work at each level
depth
=
_currentMaxDepth
-
1
;
while
(
depth
>=
0
)
{
slave_id
=
0
;
list
.
clear
();
_board
->
generateMoves
(
list
);
// delete the move we already checked from the list
if
(
depth
<
_currentMaxDepth
-
1
)
list
.
isElement
(
movechain
[
depth
],
0
,
true
);
strcpy
(
slave_input
.
boardstate
,
_board
->
getState
());
slave_input
.
alpha
=
-
beta
[
depth
];
slave_input
.
beta
=
-
alpha
[
depth
];
slave_input
.
depth
=
depth
+
1
;
slave_input
.
currentMaxDepth
=
_currentMaxDepth
;
printf
(
"Thread 0 testing %d moves at depth = %d
\n
"
,
list
.
getLength
(),
depth
);
while
(
list
.
getNext
(
m
,
Move
::
none
)
)
{
slave_input
.
move
=
m
;
MPI_Send
(
&
slave_input
,
sizeof
(
Slave_Input
),
MPI_BYTE
,
slave_id
+
1
,
10
,
MPI_COMM_WORLD
);
MPI_Irecv
(
&
slave_output
[
slave_id
],
sizeof
(
Slave_Output
),
MPI_BYTE
,
slave_id
+
1
,
10
,
MPI_COMM_WORLD
,
&
rcv_rq
[
slave_id
]);
slave_id
++
;
if
(
slave_id
>=
(
num_threads
-
1
))
break
;
}
num_slaves
=
slave_id
;
pending_jobs
=
num_slaves
;
cutoff
=
false
;
while
(
pending_jobs
>
0
)
{
MPI_Waitany
(
num_slaves
,
rcv_rq
,
&
slave_id
,
MPI_STATUS_IGNORE
);
_sc
->
_leavesVisited
+=
slave_output
[
slave_id
].
num_leaves
;
_sc
->
_nodesVisited
+=
slave_output
[
slave_id
].
num_nodes
;
value
=
slave_output
[
slave_id
].
eval
;
if
(
value
>
currentValue
)
{
currentValue
=
value
;
_pv
=
slave_output
[
slave_id
].
pv
;
if
(
_sc
)
_sc
->
foundBestMove
(
depth
,
_pv
[
depth
],
currentValue
);
if
(
currentValue
>
alpha
[
depth
])
{
alpha
[
depth
]
=
currentValue
;
slave_input
.
beta
=
-
alpha
[
depth
];
}
/* alpha/beta cut off or win position ... */
if
(
currentValue
>
14900
||
currentValue
>=
beta
[
depth
])
cutoff
=
true
;
}
if
((
list
.
getNext
(
m
,
Move
::
none
))
&&
(
cutoff
==
false
))
{
slave_input
.
move
=
m
;
MPI_Send
(
&
slave_input
,
sizeof
(
Slave_Input
),
MPI_BYTE
,
slave_id
+
1
,
10
,
MPI_COMM_WORLD
);
MPI_Irecv
(
&
slave_output
[
slave_id
],
sizeof
(
Slave_Output
),
MPI_BYTE
,
slave_id
+
1
,
10
,
MPI_COMM_WORLD
,
&
rcv_rq
[
slave_id
]);
}
else
pending_jobs
--
;
}
if
(
depth
>
0
)
{
_board
->
takeBack
();
_pv
.
update
(
depth
-
1
,
movechain
[
depth
-
1
]);
currentValue
=
-
currentValue
;
if
(
currentValue
>
alpha
[
depth
-
1
])
alpha
[
depth
-
1
]
=
currentValue
;
}
if
(
depth
==
0
)
_currentBestMove
=
_pv
[
0
];
if
(
_sc
)
_sc
->
finishedNode
(
depth
,
_pv
.
chain
(
depth
));
depth
--
;
}
free
(
slave_output
);
free
(
rcv_rq
);
free
(
movechain
);
free
(
alpha
);
free
(
beta
);
return
currentValue
;
}
/*
* Alpha/Beta search
*
* - first, start with principal variation
* - depending on depth, we only do depth search for some move types
*/
int
ABIDStrategy
::
alphabeta
(
int
depth
,
int
alpha
,
int
beta
)
{
int
currentValue
=
-
14999
+
depth
,
value
;
Move
m
;
MoveList
list
;
bool
depthPhase
,
doDepthSearch
;
/* We make a depth search for the following move types... */
int
maxType
=
(
depth
<
_currentMaxDepth
-
1
)
?
Move
::
maxMoveType
:
(
depth
<
_currentMaxDepth
)
?
Move
::
maxPushType
:
Move
::
maxOutType
;
_board
->
generateMoves
(
list
);
if
(
_sc
&&
_sc
->
verbose
())
{
char
tmp
[
100
];
sprintf
(
tmp
,
"Alpha/Beta [%d;%d], %d moves (%d depth)"
,
alpha
,
beta
,
list
.
count
(
Move
::
none
),
list
.
count
(
maxType
));
_sc
->
startedNode
(
depth
,
tmp
);
}
// don't use moves from the principal variation
m
.
type
=
Move
::
none
;
// first, play all moves with depth search
depthPhase
=
true
;
while
(
1
)
{
// get next move
if
(
m
.
type
==
Move
::
none
)
{
if
(
depthPhase
)
depthPhase
=
list
.
getNext
(
m
,
maxType
);
if
(
!
depthPhase
)
if
(
!
list
.
getNext
(
m
,
Move
::
none
))
break
;
}
// we could start with a non-depth move from principal variation
doDepthSearch
=
depthPhase
&&
(
m
.
type
<=
maxType
);
_board
->
playMove
(
m
);
/* check for a win position first */
if
(
!
_board
->
isValid
())
{
/* Shorter path to win position is better */
value
=
14999
-
depth
;
}
else
{
if
(
doDepthSearch
)
{
/* opponent searches for its maximum; but we want the
* minimum: so change sign (for alpha/beta window too!)
*/
value
=
-
alphabeta
(
depth
+
1
,
-
beta
,
-
alpha
);
}
else
{
value
=
evaluate
();
}
}
_board
->
takeBack
();
/* best move so far? */
if
(
value
>
currentValue
)
{
currentValue
=
value
;
_pv
.
update
(
depth
,
m
);
/* alpha/beta cut off or win position ... */
if
(
currentValue
>
14900
||
currentValue
>=
beta
)
{
if
(
_sc
)
_sc
->
finishedNode
(
depth
,
_pv
.
chain
(
depth
));
return
currentValue
;
}
/* maximize alpha */
if
(
currentValue
>
alpha
)
alpha
=
currentValue
;
}
if
(
_stopSearch
)
break
;
// depthPhase=false;
m
.
type
=
Move
::
none
;
}
if
(
_sc
)
_sc
->
finishedNode
(
depth
,
_pv
.
chain
(
depth
));
return
currentValue
;
}
// register ourselve
ABIDStrategy
abidStrategy
;
mpi-assign5/pv-split-interative/search-minimax.cpp
0 → 100644
View file @
17980573
/*
* Very simple example strategy:
* Search all possible positions reachable via one move,
* and return the move leading to best position
*
* (c) 2006, Josef Weidendorfer
*/
#include <stdio.h>
#include "search.h"
#include "board.h"
#include "eval.h"
#define pretty_print(name, val) printf("%s = %d: %s: %s: %d\n", name, val, __FILE__,__FUNCTION__,__LINE__);
#define likely(x) __builtin_expect((x),1)
#define unlikely(x) __builtin_expect((x),0)
/**
* To create your own search strategy:
* - copy this file into another one,
* - change the class name one the name given in constructor,
* - adjust clone() to return an instance of your class
* - adjust last line of this file to create a global instance
* of your class
* - adjust the Makefile to include your class in SEARCH_OBJS
* - implement searchBestMove()
*
* Advises for implementation of searchBestMove():
* - call foundBestMove() when finding a best move since search start
* - call finishedNode() when finishing evaluation of a tree node
* - Use _maxDepth for strength level (maximal level searched in tree)
*/
class
MinimaxStrategy
:
public
SearchStrategy
{
public
:
// Defines the name of the strategy
MinimaxStrategy
()
:
SearchStrategy
(
"MINIMAX"
)
{}
// Factory method: just return a new instance of this class
SearchStrategy
*
clone
()
{
return
new
MinimaxStrategy
();
}
private
:
/**
* Implementation of the strategy.
*/
void
searchBestMove
();
int
minimax
();
};
int
current_depth
=
0
;
#define MAX_DEPTH 3
int
MinimaxStrategy
::
minimax
()
{
Move
m
;
MoveList
list
;
// int maxEval, minEval;
int
bestEval
;
int
eval
;
int
sign
;
if
(
current_depth
==
MAX_DEPTH
)
return
evaluate
();
bestEval
=
-
17000
;
// maxEval = -17000;
// minEval = 17000;
generateMoves
(
list
);
if
(
evaluate
()
==
16000
)
{
if
(
current_depth
==
0
)
finishedNode
(
0
,
0
);
pretty_print
(
"current_depth"
,
current_depth
);
return
((
current_depth
%
2
)
==
0
)
?
-
16000
:
16000
;
}
if
((
MAX_DEPTH
-
current_depth
)
%
2
==
1
)
sign
=
1
;
else
sign
=
-
1
;
while
(
list
.
getNext
(
m
))
{
if
(
current_depth
<
MAX_DEPTH
)
{
current_depth
++
;
playMove
(
m
);
eval
=
minimax
();
takeBack
();
current_depth
--
;
}
if
(
sign
*
eval
>
bestEval
)
{
bestEval
=
sign
*
eval
;
if
(
unlikely
(
current_depth
==
0
))
{
pretty_print
(
"Eval"
,
bestEval
);
foundBestMove
(
0
,
m
,
eval
);
}
}
#if 0
if((MAX_DEPTH - current_depth +1) % 2 == 0)
{
if(eval > maxEval)
{
maxEval=eval;
if(current_depth == 0) {
pretty_print("Eval", eval);
foundBestMove(0, m, eval);
}
}
}
else
{
if(eval < minEval)
{
minEval=eval;
if(current_depth == 0) {
pretty_print("Eval2", eval);
foundBestMove(0, m, eval);
}
}
}
#endif
}
bestEval
=
sign
*
bestEval
;
if
(
current_depth
==
0
)
finishedNode
(
0
,
0
);
#if 0
if((MAX_DEPTH - current_depth +1) % 2 == 0)
return maxEval;
else
return minEval;
#endif
return
bestEval
;
}
void
MinimaxStrategy
::
searchBestMove
()
{
// KUKU : Here we have to implement the minimax strategy
// Minimax strategy tries to minimize the maximum possible outcome of opponent.
// At each turn, we check for each move the max positive outcome for opponent.
// We choose the move for which the max is least.
// To check this, we look at more than one levels in the Game Tree.
// we try to maximize bestEvaluation
/* int bestEval = minEvaluation();
int eval;
Move m;
MoveList list;
// generate list of allowed moves, put them into <list>
generateMoves(list);
// loop over all moves
while(list.getNext(m)) {
// draw move, evalute, and restore position
playMove(m);
eval = evaluate();
takeBack();
if (eval > bestEval) {
bestEval = eval;
foundBestMove(0, m, eval);
}
}
finishedNode(0,0);
*/
minimax
();
}
// register ourselve as a search strategy
MinimaxStrategy
minimaxStrategy
;
mpi-assign5/pv-split-interative/search-onelevel.cpp
0 → 100644
View file @
17980573
/**
* Very simple example strategy:
* Search all possible positions reachable via one move,
* and return the move leading to best position
*
* (c) 2006, Josef Weidendorfer
*/
#include "search.h"
#include "board.h"
#include "eval.h"
/**
* To create your own search strategy:
* - copy this file into another one,
* - change the class name one the name given in constructor,
* - adjust clone() to return an instance of your class
* - adjust last line of this file to create a global instance
* of your class
* - adjust the Makefile to include your class in SEARCH_OBJS
* - implement searchBestMove()
*
* Advises for implementation of searchBestMove():
* - call foundBestMove() when finding a best move since search start
* - call finishedNode() when finishing evaluation of a tree node
* - Use _maxDepth for strength level (maximal level searched in tree)
*/
class
OneLevelStrategy
:
public
SearchStrategy
{
public
:
// Defines the name of the strategy
OneLevelStrategy
()
:
SearchStrategy
(
"OneLevel"
)
{}
// Factory method: just return a new instance of this class
SearchStrategy
*
clone
()
{
return
new
OneLevelStrategy
();
}
private
:
/**
* Implementation of the strategy.
*/
void
searchBestMove
();
};
void
OneLevelStrategy
::
searchBestMove
()
{
// we try to maximize bestEvaluation
int
bestEval
=
minEvaluation
();
int
eval
;
Move
m
;
MoveList
list
;
// generate list of allowed moves, put them into <list>
generateMoves
(
list
);
// loop over all moves
while
(
list
.
getNext
(
m
))
{
// draw move, evalute, and restore position
playMove
(
m
);
eval
=
evaluate
();
takeBack
();
if
(
eval
>
bestEval
)
{
bestEval
=
eval
;
foundBestMove
(
0
,
m
,
eval
);
}
}
finishedNode
(
0
,
0
);
}
// register ourselve as a search strategy
OneLevelStrategy
oneLevelStrategy
;
mpi-assign5/pv-split-interative/search.cpp
0 → 100644
View file @
17980573
/*
* Search the game play tree for move leading to
* position with highest evaluation
*
* (c) 2005, Josef Weidendorfer
*/
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <stdlib.h>
#include "board.h"
#include "search.h"
#include "eval.h"
/// SearchCallbacks
static
struct
timeval
t1
,
t2
;
static
int
kevalsPerSec
=
30
;
static
int
evalCounter
=
0
;
void
SearchCallbacks
::
start
(
int
msecsForSearch
)
{
_leavesVisited
=
0
;
_nodesVisited
=
0
;
gettimeofday
(
&
t1
,
0
);
evalCounter
=
0
;
_msecsForSearch
=
msecsForSearch
;
if
(
!
_verbose
)
return
;
if
(
_msecsForSearch
>
0
)
printf
(
" Search started (ca. %d.%03d secs) ...
\n
"
,
_msecsForSearch
/
1000
,
_msecsForSearch
%
1000
);
else
printf
(
" Search started ...
\n
"
);
}
void
SearchCallbacks
::
substart
(
char
*
s
)
{
if
(
!
_verbose
)
return
;
printf
(
" Subsearch %s ...
\n
"
,
s
);
}
int
i
=
0
;
unsigned
int
avg_kleavesPerSec
=
0
;
int
_msecs
;
void
SearchCallbacks
::
finished
(
Move
&
m
)
{
gettimeofday
(
&
t2
,
0
);
_msecsPassed
=
(
1000
*
t2
.
tv_sec
+
t2
.
tv_usec
/
1000
)
-
(
1000
*
t1
.
tv_sec
+
t1
.
tv_usec
/
1000
);
_msecs
=
_msecsPassed
;
if
(
!
_verbose
)
return
;
if
(
_msecsPassed
<
1
)
_msecsPassed
=
1
;
if
(
_nodesVisited
<
1
)
_nodesVisited
=
1
;
printf
(
" Search finished after %d.%03d secs
\n
"
,
_msecsPassed
/
1000
,
_msecsPassed
%
1000
);
printf
(
" Found move '%s'
\n
"
,
m
.
name
());
printf
(
" Leaves visited: %d (%d k/s)
\n
"
,
_leavesVisited
,
_leavesVisited
/
_msecsPassed
);
printf
(
" Nodes visited: %d (%d leaves per node)
\n
"
,
_nodesVisited
,
_leavesVisited
/
_nodesVisited
);
avg_kleavesPerSec
=
(
i
*
avg_kleavesPerSec
+
_leavesVisited
/
_msecsPassed
)
/
(
i
+
1
);
i
++
;
int
eps
=
_leavesVisited
/
_msecsPassed
;
if
(
eps
>
kevalsPerSec
)
kevalsPerSec
=
eps
;
}
bool
SearchCallbacks
::
afterEval
()
{
_leavesVisited
++
;
/*
int ms = _msecsForSearch / 3;
if (ms > 500) ms = 500;
if (ms < 200) ms = 200;
evalCounter++;
if (evalCounter < ms * kevalsPerSec) return false;
// FIXME: Check for network events
evalCounter = 0;
gettimeofday(&t2,0);
_msecsPassed =
(1000* t2.tv_sec + t2.tv_usec / 1000) -
(1000* t1.tv_sec + t1.tv_usec / 1000);
if (_msecsPassed <1) _msecsPassed = 1;
if (_nodesVisited<1) _nodesVisited = 1;
int eps = _leavesVisited / _msecsPassed;
if (_verbose)
printf(" EvalRate %d k/s (%d evals, %d msecs)\n",
eps, _leavesVisited, _msecsPassed);
if (eps>kevalsPerSec) kevalsPerSec = eps;
if ((_msecsForSearch > 0) && (_msecsPassed > _msecsForSearch)) {
printf(" Stop!\n");
return true;
}
*/
return
false
;
}
void
SearchCallbacks
::
foundBestMove
(
int
d
,
const
Move
&
m
,
int
value
)
{
if
(
d
+
2
>=
_verbose
)
return
;
static
char
*
spaces
=
" "
;
printf
(
" %sNew best move '%s', value %d ...
\n
"
,
spaces
+
20
-
d
,
m
.
name
(),
value
);
}
int
_leaveStart
[
10
],
_nodeStart
[
10
];
void
SearchCallbacks
::
startedNode
(
int
d
,
char
*
s
)
{
if
(
d
+
1
>=
_verbose
)
return
;
if
(
d
<
10
)
{
_leaveStart
[
d
]
=
_leavesVisited
;
_nodeStart
[
d
]
=
_nodesVisited
;
}
static
char
*
spaces
=
" "
;
printf
(
" %sStarted node at depth %d (%s)
\n
"
,
spaces
+
20
-
d
,
d
,
s
);
}
void
SearchCallbacks
::
finishedNode
(
int
d
,
Move
*
chain
)
{
_nodesVisited
++
;
if
(
d
+
1
>=
_verbose
)
return
;
static
char
*
spaces
=
" "
;
printf
(
" %sFinished node at depth %d"
,
spaces
+
20
-
d
,
d
);
if
(
chain
)
{
int
c
=
0
;
while
(
(
c
<
4
)
&&
(
chain
->
type
!=
Move
::
none
))
{
printf
(
"%s%s"
,
(
c
==
0
)
?
" ("
:
", "
,
chain
->
name
());
chain
++
;
c
++
;
}
printf
(
")"
);
}
printf
(
"
\n
"
);
if
(
d
<
10
)
{
int
l
=
_leavesVisited
-
_leaveStart
[
d
];
int
n
=
_nodesVisited
-
_nodeStart
[
d
];
if
(
n
<
1
)
n
=
1
;
printf
(
" %s %d leaves, %d nodes visited (%d leaves per node)
\n
"
,
spaces
+
20
-
d
,
l
,
n
,
l
/
n
);
}
}
/// SearchStrategy
static
SearchStrategy
*
searchStrategies
=
0
;
SearchStrategy
::
SearchStrategy
(
char
*
n
,
int
prio
)
{
_maxDepth
=
1
;
_sc
=
0
;
_ev
=
0
;
_name
=
n
;
_next
=
0
;
_prio
=
prio
;
// register if not already registered
SearchStrategy
*
ss
=
searchStrategies
,
*
prev
=
0
;
while
(
ss
)
{
if
(
strcmp
(
ss
->
_name
,
n
)
==
0
)
return
;
if
(
ss
->
_prio
>
prio
)
break
;
prev
=
ss
;
ss
=
ss
->
_next
;
}
if
(
prev
)
{
_next
=
prev
->
_next
;
prev
->
_next
=
this
;
}
else
{
_next
=
searchStrategies
;
searchStrategies
=
this
;
}
}
char
**
SearchStrategy
::
strategies
()
{
static
char
**
sslist
=
0
;
int
count
=
0
;
SearchStrategy
*
ss
=
searchStrategies
;
while
(
ss
)
{
count
++
;
ss
=
ss
->
_next
;
}
sslist
=
(
char
**
)
realloc
(
sslist
,
sizeof
(
char
*
)
*
(
count
+
1
)
);
count
=
0
;
ss
=
searchStrategies
;
while
(
ss
)
{
sslist
[
count
]
=
ss
->
_name
;
count
++
;
ss
=
ss
->
_next
;
}
sslist
[
count
]
=
0
;
return
sslist
;
}
SearchStrategy
*
SearchStrategy
::
create
(
char
*
n
)
{
SearchStrategy
*
ss
=
searchStrategies
;
while
(
ss
)
{
if
(
strcmp
(
ss
->
_name
,
n
)
==
0
)
return
ss
;
ss
=
ss
->
_next
;
}
return
0
;
}
SearchStrategy
*
SearchStrategy
::
create
(
int
i
)
{
int
count
=
0
;
SearchStrategy
*
ss
=
searchStrategies
;
while
(
ss
)
{
if
(
count
==
i
)
return
ss
;
count
++
;
ss
=
ss
->
_next
;
}
return
0
;
}
Move
&
SearchStrategy
::
bestMove
(
Board
*
b
)
{
if
(
_sc
)
{
int
ms
=
b
->
msecsToPlay
(
b
->
actColor
());
if
(
ms
>
0
)
{
int
minTokens
=
b
->
getColor1Count
();
int
tokens
=
b
->
getColor2Count
();
if
(
tokens
<
minTokens
)
minTokens
=
tokens
;
int
mvs
=
60
-
10
*
(
14
-
minTokens
);
ms
=
ms
/
mvs
;
}
_sc
->
start
(
ms
);
}
_board
=
b
;
_bestMove
.
type
=
Move
::
none
;
_stopSearch
=
false
;
searchBestMove
();
if
(
_sc
)
_sc
->
finished
(
_bestMove
);
return
_bestMove
;
}
Move
&
SearchStrategy
::
nextMove
()
{
static
Move
m
;
return
m
;
// returns invalid
}
int
SearchStrategy
::
evaluate
()
{
int
v
=
_ev
->
calcEvaluation
(
_board
);
if
(
_sc
)
_stopSearch
=
_sc
->
afterEval
();
return
v
;
}
int
SearchStrategy
::
minEvaluation
()
{
return
_ev
?
_ev
->
minValue
()
:
-
1
;
}
int
SearchStrategy
::
maxEvaluation
()
{
return
_ev
?
_ev
->
maxValue
()
:
-
1
;
}
void
SearchStrategy
::
generateMoves
(
MoveList
&
list
)
{
if
(
_board
)
_board
->
generateMoves
(
list
);
}
void
SearchStrategy
::
playMove
(
const
Move
&
m
)
{
if
(
_board
)
_board
->
playMove
(
m
);
}
bool
SearchStrategy
::
takeBack
()
{
return
_board
?
_board
->
takeBack
()
:
false
;
}
void
SearchStrategy
::
foundBestMove
(
int
d
,
const
Move
&
m
,
int
eval
)
{
if
(
d
==
0
)
_bestMove
=
m
;
if
(
_sc
)
_sc
->
foundBestMove
(
d
,
m
,
eval
);
}
void
SearchStrategy
::
finishedNode
(
int
d
,
Move
*
bestList
)
{
if
(
_sc
)
_sc
->
finishedNode
(
d
,
bestList
);
}
mpi-assign5/pv-split-interative/search.h
0 → 100644
View file @
17980573
/*
* Search the game play tree for move leading to
* position with highest evaluation
*
* (c) 2005, Josef Weidendorfer
*/
#ifndef SEARCH_H
#define SEARCH_H
#include "move.h"
class
Board
;
class
Evaluator
;
class
SearchStrategy
;
class
SearchCallbacks
{
public
:
SearchCallbacks
(
int
v
=
0
)
{
_verbose
=
v
;
}
virtual
~
SearchCallbacks
()
{}
// called at beginning of new search. If <msecs> >0,
// we will stop search (via afterEval) after that time
virtual
void
start
(
int
msecsForSearch
);
// called at beginning of new sub search
virtual
void
substart
(
char
*
);
// called after search is done
virtual
void
finished
(
Move
&
);
// called after each evaluation
// returns true to request stop of search
virtual
bool
afterEval
();
// called when a new best move is found at depth d
virtual
void
foundBestMove
(
int
d
,
const
Move
&
,
int
value
);
// called before children are visited
virtual
void
startedNode
(
int
d
,
char
*
);
/**
* Called after needed children are visited
* Second parameter gives array of best move sequence found
*/
virtual
void
finishedNode
(
int
d
,
Move
*
);
int
msecsPassed
()
{
return
_msecsPassed
;
}
int
verbose
()
{
return
_verbose
;
}
int
_leavesVisited
,
_nodesVisited
;
private
:
int
_verbose
;
int
_msecsPassed
,
_msecsForSearch
;
};
/*
* Base class for search strategies
*
* Implement searchBestMove !
*/
class
SearchStrategy
{
public
:
SearchStrategy
(
char
*
n
,
int
prio
=
5
);
virtual
~
SearchStrategy
()
{};
/* get list of names of available strategies */
static
char
**
strategies
();
/* factory for a named strategy */
static
SearchStrategy
*
create
(
char
*
);
static
SearchStrategy
*
create
(
int
);
char
*
name
()
{
return
_name
;
}
void
registerCallbacks
(
SearchCallbacks
*
sc
)
{
_sc
=
sc
;
}
void
setMaxDepth
(
int
d
)
{
_maxDepth
=
d
;
}
void
setEvaluator
(
Evaluator
*
e
)
{
_ev
=
e
;
}
/* Start search and return best move. */
Move
&
bestMove
(
Board
*
);
/* return best move in depth 1 if last search got one */
virtual
Move
&
nextMove
();
/* factory method: should return instance of derived class */
virtual
SearchStrategy
*
clone
()
=
0
;
void
stopSearch
()
{
_stopSearch
=
true
;
}
// protected:
/**
* Overwrite this to implement your search strategy
* and set _bestMove
*/
virtual
void
searchBestMove
()
=
0
;
/**
* Some dispatcher methods for convenience.
* Call these from your search function
*/
int
minEvaluation
();
int
maxEvaluation
();
// see Board::generateMoves
void
generateMoves
(
MoveList
&
list
);
// see Board::playMove
void
playMove
(
const
Move
&
m
);
// see Board::takeBack
bool
takeBack
();
// see SearchCallbacks::foundBestMove
void
foundBestMove
(
int
d
,
const
Move
&
m
,
int
eval
);
// see SearchCallbacks::finishedNode
void
finishedNode
(
int
d
,
Move
*
bestList
);
// see Evaluator::calcEvaluation
int
evaluate
();
int
_maxDepth
;
Board
*
_board
;
bool
_stopSearch
;
SearchCallbacks
*
_sc
;
Evaluator
*
_ev
;
Move
_bestMove
;
private
:
char
*
_name
;
int
_prio
;
SearchStrategy
*
_next
;
};
class
ABIDStrategy
:
public
SearchStrategy
{
public
:
ABIDStrategy
()
:
SearchStrategy
(
"ABID"
,
2
)
{}
SearchStrategy
*
clone
()
{
return
new
ABIDStrategy
();
}
Move
&
nextMove
()
{
return
_pv
[
1
];
}
/* recursive alpha/beta search */
int
alphabeta
(
int
depth
,
int
alpha
,
int
beta
);
/* prinicipal variation found in last search */
Variation
_pv
;
int
_currentMaxDepth
;
private
:
void
searchBestMove
();
int
pv_split
(
int
alpha0
,
int
beta0
);
Move
_currentBestMove
;
bool
_inPV
;
};
struct
Slave_Input
{
int
alpha
,
beta
;
int
depth
;
int
currentMaxDepth
;
char
boardstate
[
1024
];
Move
move
;
};
struct
Slave_Output
{
int
eval
;
int
num_leaves
,
num_nodes
;
Variation
pv
;
};
#endif
mpi-assign5/pv-split-interative/start.cpp
0 → 100644
View file @
17980573
/**
* Send a start position into a game communication channel,
* and observe positions sent in the channel
*
* (C) 2005, Josef Weidendorfer
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "board.h"
#include "network.h"
/* Global, static vars */
static
NetworkLoop
l
;
static
Board
b
;
/* Start game? */
static
bool
start
=
true
;
/* only show reachable positions with valid moves */
static
bool
onlyReachable
=
true
;
/* time limit in seconds (0: no time limit, -1: not set) */
static
int
secsToPlay
=
-
1
;
/* to set verbosity of NetworkLoop implementation */
extern
int
verbose
;
#define DEFAULT_DOMAIN_PORT 13133
/* remote channel */
static
char
*
host
=
0
;
/* not used on default */
static
int
rport
=
DEFAULT_DOMAIN_PORT
;
/* local channel */
static
int
lport
=
DEFAULT_DOMAIN_PORT
;
/* Where to read position to broadcast from? (0: start position) */
static
FILE
*
file
=
0
;
class
MyDomain
:
public
NetworkDomain
{
public
:
MyDomain
(
int
p
)
:
NetworkDomain
(
p
)
{}
void
sendBoard
();
protected
:
void
received
(
char
*
str
);
void
newConnection
(
Connection
*
);
};
void
MyDomain
::
sendBoard
()
{
static
char
tmp
[
500
];
sprintf
(
tmp
,
"pos %s
\n
"
,
b
.
getState
());
printf
(
tmp
+
4
);
int
state
=
b
.
validState
();
printf
(
"%s
\n
"
,
Board
::
stateDescription
(
state
));
broadcast
(
tmp
);
}
void
MyDomain
::
received
(
char
*
str
)
{
if
(
strncmp
(
str
,
"quit"
,
4
)
==
0
)
{
l
.
exit
();
return
;
}
if
(
strncmp
(
str
,
"pos "
,
4
)
!=
0
)
return
;
if
(
b
.
validState
()
!=
Board
::
empty
)
{
Board
newBoard
;
newBoard
.
setState
(
str
+
4
);
Move
m
=
b
.
moveToReach
(
&
newBoard
,
false
);
if
(
m
.
type
==
Move
::
none
)
{
printf
(
"WARNING: Got a board which is not reachable via a valid move !?
\n
"
);
if
(
onlyReachable
)
return
;
}
else
{
if
(
b
.
actColor
()
==
Board
::
color1
)
printf
(
"O draws move '%s'...
\n
"
,
m
.
name
());
else
printf
(
"X draws move '%s'...
\n
"
,
m
.
name
());
}
}
b
.
setState
(
str
+
4
);
printf
(
str
+
4
);
int
state
=
b
.
validState
();
printf
(
"%s
\n
"
,
Board
::
stateDescription
(
state
));
switch
(
state
)
{
case
Board
:
:
timeout1
:
case
Board
:
:
timeout2
:
case
Board
:
:
win1
:
case
Board
:
:
win2
:
l
.
exit
();
default
:
break
;
}
}
void
MyDomain
::
newConnection
(
Connection
*
c
)
{
NetworkDomain
::
newConnection
(
c
);
static
char
tmp
[
500
];
int
len
=
sprintf
(
tmp
,
"pos %s
\n
"
,
b
.
getState
());
c
->
sendString
(
tmp
,
len
);
}
static
void
printHelp
(
char
*
prg
,
bool
printHeader
)
{
if
(
printHeader
)
printf
(
"Start V 0.2 - (C) 2005 Josef Weidendorfer
\n
"
"Broadcast a game position, observe the game and quit in winning state.
\n\n
"
);
printf
(
"Usage: %s [options] [<file>|-]
\n\n
"
" <file> File containing start position (default: start position)
\n
"
" - Position is read from standard input
\n\n
"
,
prg
);
printf
(
" Options:
\n
"
" -h / --help Print this help text
\n
"
" -v / -vv Be verbose / more verbose
\n
"
" -o Only observe, no start
\n
"
" -t <timeToPlay> Start in tournament modus (limited time)
\n
"
" -a Show all positions (default: only via valid moves)
\n
"
" -p [host:][port] Connection to broadcast channel
\n
"
" (default: %d)
\n\n
"
,
DEFAULT_DOMAIN_PORT
);
exit
(
1
);
}
static
void
parseArgs
(
int
argc
,
char
*
argv
[])
{
int
arg
=
0
;
while
(
arg
+
1
<
argc
)
{
arg
++
;
if
(
argv
[
arg
][
0
]
==
'-'
)
{
if
(
strcmp
(
argv
[
arg
],
"-h"
)
==
0
||
strcmp
(
argv
[
arg
],
"--help"
)
==
0
)
printHelp
(
argv
[
0
],
true
);
if
(
strcmp
(
argv
[
arg
],
"-v"
)
==
0
)
{
verbose
=
1
;
continue
;
}
if
(
strcmp
(
argv
[
arg
],
"-vv"
)
==
0
)
{
verbose
=
2
;
continue
;
}
if
(
strcmp
(
argv
[
arg
],
"-o"
)
==
0
)
{
start
=
false
;
continue
;
}
if
(
strcmp
(
argv
[
arg
],
"-a"
)
==
0
)
{
onlyReachable
=
false
;
continue
;
}
if
((
strcmp
(
argv
[
arg
],
"-t"
)
==
0
)
&&
(
arg
+
1
<
argc
))
{
arg
++
;
secsToPlay
=
atoi
(
argv
[
arg
]);
if
(
secsToPlay
==
0
)
{
printf
(
"%s: WARNING - Ignoring tournament; %d secs to play
\n
"
,
argv
[
0
],
secsToPlay
);
}
continue
;
}
if
((
strcmp
(
argv
[
arg
],
"-p"
)
==
0
)
&&
(
arg
+
1
<
argc
))
{
arg
++
;
if
(
argv
[
arg
][
0
]
>
'0'
&&
argv
[
arg
][
0
]
<=
'9'
)
{
lport
=
atoi
(
argv
[
arg
]);
continue
;
}
char
*
c
=
strrchr
(
argv
[
arg
],
':'
);
int
p
=
0
;
if
(
c
!=
0
)
{
*
c
=
0
;
p
=
atoi
(
c
+
1
);
}
host
=
argv
[
arg
];
if
(
p
)
rport
=
p
;
continue
;
}
if
(
strcmp
(
argv
[
arg
],
"-"
)
==
0
)
{
file
=
stdin
;
continue
;
}
printf
(
"%s: ERROR - Unknown option %s
\n
"
,
argv
[
0
],
argv
[
arg
]);
printHelp
(
argv
[
0
],
false
);
}
file
=
fopen
(
argv
[
arg
],
"r"
);
if
(
!
file
)
{
printf
(
"%s: ERROR - Can not open '%s' for reading start position
\n
"
,
argv
[
0
],
argv
[
arg
]);
printHelp
(
argv
[
0
],
false
);
}
break
;
}
}
int
main
(
int
argc
,
char
*
argv
[])
{
parseArgs
(
argc
,
argv
);
b
.
setVerbose
(
verbose
);
MyDomain
d
(
lport
);
if
(
host
)
d
.
addConnection
(
host
,
rport
);
l
.
install
(
&
d
);
if
(
start
)
{
if
(
file
)
{
char
tmp
[
500
];
int
len
=
0
,
c
;
while
(
len
<
499
&&
(
c
=
fgetc
(
file
))
!=
EOF
)
tmp
[
len
++
]
=
(
char
)
c
;
tmp
[
len
++
]
=
0
;
printf
(
"Gaurav
\n
"
);
printf
(
"%s"
,
tmp
);
printf
(
"Gaurav
\n
"
);
if
(
!
b
.
setState
(
tmp
))
{
printf
(
"%s: WARNING - Can not parse given position; using start position
\n
"
,
argv
[
0
]);
b
.
begin
(
Board
::
color1
);
}
}
else
b
.
begin
(
Board
::
color1
);
if
(
secsToPlay
>=
0
)
{
b
.
setMSecsToPlay
(
Board
::
color1
,
1000
*
secsToPlay
);
b
.
setMSecsToPlay
(
Board
::
color2
,
1000
*
secsToPlay
);
}
d
.
sendBoard
();
}
return
l
.
run
();
}
mpi-assign5/pv-split-interative/tags
0 → 100644
View file @
17980573
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/
!_TAG_PROGRAM_NAME Exuberant Ctags //
!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/
!_TAG_PROGRAM_VERSION 5.7 //
ABIDStrategy search-abid.cpp /^ ABIDStrategy(): SearchStrategy("ABID", 2) {}$/;" f class:ABIDStrategy
ABIDStrategy search-abid.cpp /^class ABIDStrategy: public SearchStrategy$/;" c file:
ABIDStrategy search-parallel-abid.cpp /^ ABIDStrategy(): SearchStrategy("PARALLEL-ABID", 2) {}$/;" f class:ABIDStrategy
ABIDStrategy search-parallel-abid.cpp /^class ABIDStrategy: public SearchStrategy$/;" c file:
AllFields board.h /^ enum { AllFields = 121, \/* visible + ring of unvisible around *\/$/;" e enum:Board::__anon2
AllFields eval.h /^ enum { AllFields = 121, \/* visible + ring of unvisible around *\/$/;" e enum:Evaluator::__anon5
BOARD_H board.h 10;" d
Board board.cpp /^Board::Board()$/;" f class:Board
Board board.h /^class Board$/;" c
CHECK board.cpp 21;" d file:
CXX Makefile /^CXX = mpiCC$/;" m
CXXFLAGS Makefile /^CXXFLAGS=-O3$/;" m
Connection network.cpp /^Connection::Connection(NetworkDomain* d, Connection* n,$/;" f class:Connection
Connection network.h /^class Connection {$/;" c
DEFAULT_DOMAIN_DIFF referee.cpp 49;" d file:
DEFAULT_DOMAIN_PORT referee.cpp 48;" d file:
DEFAULT_DOMAIN_PORT start.cpp 32;" d file:
EVAL_H eval.h 17;" d
EvalScheme eval.cpp /^EvalScheme::EvalScheme(char* file)$/;" f class:EvalScheme
EvalScheme eval.h /^class EvalScheme$/;" c
Evaluator eval.cpp /^Evaluator::Evaluator()$/;" f class:Evaluator
Evaluator eval.h /^class Evaluator$/;" c
ID network.h /^ int ID() { return myID; }$/;" f class:NetworkDomain
InARowType board.h /^ enum InARowType { inARow2 = 0, inARow3, inARow4, inARow5, inARowCount };$/;" g class:MoveCounter
LDFLAGS Makefile /^LDFLAGS=$/;" m
LIB_OBJS Makefile /^LIB_OBJS = move.o board.o network.o search.o eval.o$/;" m
Left move.h /^ enum { Right=1, RightDown, LeftDown, Left, LeftUp, RightUp };$/;" e enum:Move::__anon6
LeftDown move.h /^ enum { Right=1, RightDown, LeftDown, Left, LeftUp, RightUp };$/;" e enum:Move::__anon6
LeftUp move.h /^ enum { Right=1, RightDown, LeftDown, Left, LeftUp, RightUp };$/;" e enum:Move::__anon6
MAX_DEPTH search-minimax.cpp 52;" d file:
MAX_DEPTH search-parallel-minimax.cpp 59;" d file:
MOVE_H move.h 12;" d
MaxMoves move.h /^ enum { MaxMoves = 150 };$/;" e enum:MoveList::__anon8
MinimaxStrategy search-minimax.cpp /^ MinimaxStrategy(): SearchStrategy("MINIMAX") {}$/;" f class:MinimaxStrategy
MinimaxStrategy search-minimax.cpp /^class MinimaxStrategy: public SearchStrategy$/;" c file:
MinimaxStrategy search-parallel-minimax.cpp /^ MinimaxStrategy(): SearchStrategy("PARALLEL-MINIMAX") {}$/;" f class:MinimaxStrategy
MinimaxStrategy search-parallel-minimax.cpp /^class MinimaxStrategy: public SearchStrategy$/;" c file:
Move move.h /^ Move() { type = none; field = 0; direction = 0; }$/;" f class:Move
Move move.h /^ Move(short f, char d, MoveType t)$/;" f class:Move
Move move.h /^class Move$/;" c
MoveCounter board.cpp /^MoveCounter::MoveCounter()$/;" f class:MoveCounter
MoveCounter board.h /^class MoveCounter$/;" c
MoveList move.cpp /^MoveList::MoveList()$/;" f class:MoveList
MoveList move.h /^class MoveList$/;" c
MoveType move.h /^ enum MoveType { out2 = 0, out1with3, out1with2, push2,$/;" g class:Move
MvsStored board.h /^ MvsStored = 100 };$/;" e enum:Board::__anon2
MvsStored eval.h /^ MvsStored = 100 };$/;" e enum:Evaluator::__anon5
MyDomain player.cpp /^ MyDomain(int p) : NetworkDomain(p) {}$/;" f class:MyDomain
MyDomain player.cpp /^class MyDomain: public NetworkDomain$/;" c file:
MyDomain referee.cpp /^ MyDomain(int p) : NetworkDomain(p) {}$/;" f class:MyDomain
MyDomain referee.cpp /^class MyDomain: public NetworkDomain$/;" c file:
MyDomain start.cpp /^ MyDomain(int p) : NetworkDomain(p) {}$/;" f class:MyDomain
MyDomain start.cpp /^class MyDomain: public NetworkDomain$/;" c file:
NETWORK_H network.h 13;" d
NetworkDomain network.cpp /^NetworkDomain::NetworkDomain(int id)$/;" f class:NetworkDomain
NetworkDomain network.h /^class NetworkDomain$/;" c
NetworkLoop network.cpp /^NetworkLoop::NetworkLoop()$/;" f class:NetworkLoop
NetworkLoop network.h /^class NetworkLoop$/;" c
NetworkTimer network.cpp /^NetworkTimer::NetworkTimer(int msecs)$/;" f class:NetworkTimer
NetworkTimer network.h /^class NetworkTimer$/;" c
OneLevelStrategy search-onelevel.cpp /^ OneLevelStrategy(): SearchStrategy("OneLevel") {}$/;" f class:OneLevelStrategy
OneLevelStrategy search-onelevel.cpp /^class OneLevelStrategy: public SearchStrategy$/;" c file:
RealFields board.h /^ RealFields = 61, \/* number of visible fields *\/$/;" e enum:Board::__anon2
RealFields eval.h /^ RealFields = 61, \/* number of visible fields *\/$/;" e enum:Evaluator::__anon5
Right move.h /^ enum { Right=1, RightDown, LeftDown, Left, LeftUp, RightUp };$/;" e enum:Move::__anon6
RightDown move.h /^ enum { Right=1, RightDown, LeftDown, Left, LeftUp, RightUp };$/;" e enum:Move::__anon6
RightUp move.h /^ enum { Right=1, RightDown, LeftDown, Left, LeftUp, RightUp };$/;" e enum:Move::__anon6
SEARCH_H search.h 9;" d
SEARCH_OBJS Makefile /^SEARCH_OBJS = $(LIB_OBJS) search-parallel-minimax.o search-parallel-abid.cpp$/;" m
SearchCallbacks search.h /^ SearchCallbacks(int v = 0) { _verbose = v; }$/;" f class:SearchCallbacks
SearchCallbacks search.h /^class SearchCallbacks$/;" c
SearchStrategy search.cpp /^SearchStrategy::SearchStrategy(char* n, int prio)$/;" f class:SearchStrategy
SearchStrategy search.h /^class SearchStrategy$/;" c
Variation move.h /^ Variation() { clear(1); }$/;" f class:Variation
Variation move.h /^class Variation$/;" c
_bestMove search.h /^ Move _bestMove;$/;" m class:SearchStrategy
_board eval.h /^ Board* _board;$/;" m class:Evaluator
_board search.h /^ Board* _board;$/;" m class:SearchStrategy
_currentBestMove search-abid.cpp /^ Move _currentBestMove;$/;" m class:ABIDStrategy file:
_currentBestMove search-parallel-abid.cpp /^ Move _currentBestMove;$/;" m class:ABIDStrategy file:
_currentMaxDepth search-abid.cpp /^ int _currentMaxDepth;$/;" m class:ABIDStrategy file:
_currentMaxDepth search-parallel-abid.cpp /^ int _currentMaxDepth;$/;" m class:ABIDStrategy file:
_ev board.h /^ Evaluator* _ev;$/;" m class:Board
_ev search.h /^ Evaluator* _ev;$/;" m class:SearchStrategy
_evalScheme eval.h /^ EvalScheme* _evalScheme;$/;" m class:Evaluator
_inARowValue eval.h /^ int _inARowValue[MoveCounter::inARowCount];$/;" m class:EvalScheme
_inPV search-abid.cpp /^ bool _inPV;$/;" m class:ABIDStrategy file:
_inPV search-parallel-abid.cpp /^ bool _inPV;$/;" m class:ABIDStrategy file:
_leaveStart search.cpp /^int _leaveStart[10], _nodeStart[10];$/;" v
_leavesVisited search.h /^ int _leavesVisited, _nodesVisited;$/;" m class:SearchCallbacks
_left network.h /^ struct timeval _left;$/;" m class:NetworkTimer typeref:struct:NetworkTimer::timeval
_maxDepth search.h /^ int _maxDepth;$/;" m class:SearchStrategy
_moveCount board.h /^ int _moveCount[Move::typeCount];$/;" m class:MoveCounter
_moveNo board.h /^ int _moveNo; \/* move number in current game *\/$/;" m class:Board
_moveValue eval.h /^ int _stoneValue[6], _moveValue[Move::none];$/;" m class:EvalScheme
_msecs network.h /^ int _msecs;$/;" m class:NetworkTimer
_msecsForSearch search.h /^ int _msecsPassed, _msecsForSearch;$/;" m class:SearchCallbacks
_msecsPassed search.h /^ int _msecsPassed, _msecsForSearch;$/;" m class:SearchCallbacks
_msecsToPlay board.h /^ int _msecsToPlay[3]; \/* time in seconds to play *\/$/;" m class:Board
_name search.h /^ char* _name;$/;" m class:SearchStrategy
_next search.h /^ SearchStrategy* _next;$/;" m class:SearchStrategy
_nodeStart search.cpp /^int _leaveStart[10], _nodeStart[10];$/;" v
_nodesVisited search.h /^ int _leavesVisited, _nodesVisited;$/;" m class:SearchCallbacks
_prio search.h /^ int _prio;$/;" m class:SearchStrategy
_pv search-abid.cpp /^ Variation _pv;$/;" m class:ABIDStrategy file:
_pv search-parallel-abid.cpp /^ Variation _pv;$/;" m class:ABIDStrategy file:
_ringDiff eval.h /^ int _ringValue[5], _ringDiff[5];$/;" m class:EvalScheme
_ringValue eval.h /^ int _ringValue[5], _ringDiff[5];$/;" m class:EvalScheme
_rowCount board.h /^ int _rowCount[inARowCount];$/;" m class:MoveCounter
_sc search.h /^ SearchCallbacks* _sc;$/;" m class:SearchStrategy
_ss board.h /^ SearchStrategy* _ss;$/;" m class:Board
_stoneValue eval.h /^ int _stoneValue[6], _moveValue[Move::none];$/;" m class:EvalScheme
_stopSearch search.h /^ bool _stopSearch;$/;" m class:SearchStrategy
_verbose board.h /^ int _verbose;$/;" m class:Board
_verbose search.h /^ int _verbose;$/;" m class:SearchCallbacks
abidStrategy search-abid.cpp /^ABIDStrategy abidStrategy;$/;" v
abidStrategy search-parallel-abid.cpp /^ABIDStrategy abidStrategy;$/;" v
actColor board.h /^ int actColor() const$/;" f class:Board
actMaxDepth move.h /^ int actMaxDepth;$/;" m class:Variation
actual move.h /^ int actual[Move::typeCount];$/;" m class:MoveList
actualType move.h /^ int nextUnused, actualType;$/;" m class:MoveList
addConnection network.cpp /^void NetworkDomain::addConnection(const char* host, int port)$/;" f class:NetworkDomain
addr network.cpp /^char* Connection::addr()$/;" f class:Connection
afterEval search.cpp /^bool SearchCallbacks::afterEval()$/;" f class:SearchCallbacks
all move.h /^ enum { all , start1, start2, start3 };$/;" e enum:MoveList::__anon9
alphabeta search-abid.cpp /^int ABIDStrategy::alphabeta(int depth, int alpha, int beta)$/;" f class:ABIDStrategy
alphabeta search-parallel-abid.cpp /^int ABIDStrategy::alphabeta(int depth, int alpha, int beta)$/;" f class:ABIDStrategy
avg_kleavesPerSec search.cpp /^unsigned int avg_kleavesPerSec = 0;$/;" v
b player.cpp /^Board b;$/;" v
b referee.cpp /^static Board b;$/;" v file:
b start.cpp /^static Board b;$/;" v file:
bUpdateSpy board.h /^ bool show, bUpdateSpy;$/;" m class:Board
begin board.cpp /^void Board::begin(int startColor)$/;" f class:Board
bestMove board.cpp /^Move& Board::bestMove()$/;" f class:Board
bestMove search.cpp /^Move& SearchStrategy::bestMove(Board* b)$/;" f class:SearchStrategy
broadcast network.cpp /^void NetworkDomain::broadcast(const char* str)$/;" f class:NetworkDomain
calcEvaluation eval.cpp /^int Evaluator::calcEvaluation(Board* b)$/;" f class:Evaluator
chain move.h /^ Move* chain(int d)$/;" f class:Variation
changeEval player.cpp /^bool changeEval = true;$/;" v
changeEvaluation eval.cpp /^void Evaluator::changeEvaluation()$/;" f class:Evaluator
check network.cpp /^void NetworkDomain::check(fd_set* set)$/;" f class:NetworkDomain
clear board.cpp /^void Board::clear()$/;" f class:Board
clear move.cpp /^void MoveList::clear()$/;" f class:MoveList
clear move.cpp /^void Variation::clear(int d)$/;" f class:Variation
clone search-abid.cpp /^ SearchStrategy* clone() { return new ABIDStrategy(); }$/;" f class:ABIDStrategy
clone search-minimax.cpp /^ SearchStrategy* clone() { return new MinimaxStrategy(); }$/;" f class:MinimaxStrategy
clone search-onelevel.cpp /^ SearchStrategy* clone() { return new OneLevelStrategy(); }$/;" f class:OneLevelStrategy
clone search-parallel-abid.cpp /^ SearchStrategy* clone() { return new ABIDStrategy(); }$/;" f class:ABIDStrategy
clone search-parallel-minimax.cpp /^ SearchStrategy* clone() { return new MinimaxStrategy(); }$/;" f class:MinimaxStrategy
close network.cpp /^void NetworkDomain::close()$/;" f class:NetworkDomain
color board.h /^ int color; \/* actual color *\/$/;" m class:Board
color1 board.h /^ color1, color2, color1bright, color2bright$/;" e enum:Board::__anon1
color1 eval.h /^ color1, color2, color1bright, color2bright$/;" e enum:Evaluator::__anon4
color1Count board.h /^ int color1Count, color2Count;$/;" m class:Board
color1bright board.h /^ color1, color2, color1bright, color2bright$/;" e enum:Board::__anon1
color1bright eval.h /^ color1, color2, color1bright, color2bright$/;" e enum:Evaluator::__anon4
color2 board.h /^ color1, color2, color1bright, color2bright$/;" e enum:Board::__anon1
color2 eval.h /^ color1, color2, color1bright, color2bright$/;" e enum:Evaluator::__anon4
color2Count board.h /^ int color1Count, color2Count;$/;" m class:Board
color2bright board.h /^ color1, color2, color1bright, color2bright$/;" e enum:Board::__anon1
color2bright eval.h /^ color1, color2, color1bright, color2bright$/;" e enum:Evaluator::__anon4
connectionList network.h /^ Connection* connectionList;$/;" m class:NetworkDomain
count move.cpp /^int MoveList::count(int maxType)$/;" f class:MoveList
count network.cpp /^int NetworkDomain::count()$/;" f class:NetworkDomain
countFrom board.cpp /^void Board::countFrom(int startField, int color,$/;" f class:Board
create search.cpp /^SearchStrategy* SearchStrategy::create(char* n)$/;" f class:SearchStrategy
create search.cpp /^SearchStrategy* SearchStrategy::create(int i)$/;" f class:SearchStrategy
current_depth search-minimax.cpp /^int current_depth=0;$/;" v
current_depth search-parallel-minimax.cpp /^int current_depth=0;$/;" v
d1 referee.cpp /^static MyDomain *d1 = 0, *d2 = 0;$/;" v file:
d1MemberExists referee.cpp /^static bool d1MemberExists = false;$/;" v file:
d2 referee.cpp /^static MyDomain *d1 = 0, *d2 = 0;$/;" v file:
d2MemberExists referee.cpp /^static bool d2MemberExists = false;$/;" v file:
defaultInARowValue eval.cpp /^static int defaultInARowValue[MoveCounter::inARowCount]= { 2, 5, 4, 3 };$/;" v file:
defaultMoveValue eval.cpp /^static int defaultMoveValue[Move::typeCount] = { 40,30,30, 15,14,13, $/;" v file:
defaultPort network.h /^ enum { defaultPort = 23412 };$/;" e enum:NetworkDomain::__anon11
defaultRingDiff eval.cpp /^static int defaultRingDiff[] = { 0, 10, 10, 8, 5 };$/;" v file:
defaultRingValue eval.cpp /^static int defaultRingValue[] = { 45, 35, 25, 10, 0 };$/;" v file:
defaultStoneValue eval.cpp /^static int defaultStoneValue[]= { 0,-800,-1800,-3000,-4400,-6000 };$/;" v file:
direction board.cpp /^int Board::direction[]= { -11,1,12,11,-1,-12,-11,1 };$/;" m class:Board file:
direction board.h /^ static int direction[8];$/;" m class:Board
direction move.h /^ unsigned char direction;$/;" m class:Move
domain network.h /^ NetworkDomain* domain;$/;" m class:Connection
domainList network.h /^ NetworkDomain* domainList;$/;" m class:NetworkLoop
empty board.h /^ enum { empty=0, $/;" e enum:Board::__anon3
ev player.cpp /^Evaluator ev;$/;" v
evalCounter search.cpp /^static int evalCounter = 0;$/;" v file:
evalScheme eval.h /^ EvalScheme* evalScheme() { return _evalScheme; }$/;" f class:Evaluator
evaluate search.cpp /^int SearchStrategy::evaluate()$/;" f class:SearchStrategy
exit network.cpp /^void NetworkLoop::exit(int v)$/;" f class:NetworkLoop
exit_loop network.h /^ bool exit_loop;$/;" m class:NetworkLoop
exit_value network.h /^ int exit_value;$/;" m class:NetworkLoop
fd network.h /^ int fd, myID, myPort;$/;" m class:NetworkDomain
field board.h /^ int field[AllFields]; \/* actual board *\/$/;" m class:Board
field eval.h /^ int* field;$/;" m class:Evaluator
field move.h /^ short field;$/;" m class:Move
fieldArray board.h /^ int* fieldArray() { return field; }$/;" f class:Board
fieldDiffOfDir board.h /^ static int fieldDiffOfDir(int d) { return direction[d]; }$/;" f class:Board
fieldValue eval.cpp /^int Evaluator::fieldValue[61];$/;" m class:Evaluator file:
fieldValue eval.h /^ static int fieldValue[Board::RealFields];$/;" m class:Evaluator
file referee.cpp /^static FILE* file = 0;$/;" v file:
file start.cpp /^static FILE* file = 0;$/;" v file:
finished search.cpp /^void SearchCallbacks::finished(Move& m)$/;" f class:SearchCallbacks
finishedNode search.cpp /^void SearchCallbacks::finishedNode(int d, Move* chain)$/;" f class:SearchCallbacks
finishedNode search.cpp /^void SearchStrategy::finishedNode(int d, Move* bestList)$/;" f class:SearchStrategy
first move.h /^ int first[Move::typeCount];$/;" m class:MoveList
foundBestMove search.cpp /^void SearchCallbacks::foundBestMove(int d, const Move& m, int value)$/;" f class:SearchCallbacks
foundBestMove search.cpp /^void SearchStrategy::foundBestMove(int d, const Move& m, int eval)$/;" f class:SearchStrategy
free board.h /^ out = 10, free = 0,$/;" e enum:Board::__anon1
free eval.h /^ out = 10, free = 0,$/;" e enum:Evaluator::__anon4
generateFieldMoves board.cpp /^void Board::generateFieldMoves(int startField, MoveList& list)$/;" f class:Board
generateMoves board.cpp /^void Board::generateMoves(MoveList& list)$/;" f class:Board
generateMoves search.cpp /^void SearchStrategy::generateMoves(MoveList& list)$/;" f class:SearchStrategy
getColor1Count board.h /^ int getColor1Count() { return color1Count; }$/;" f class:Board
getColor2Count board.h /^ int getColor2Count() { return color2Count; }$/;" f class:Board
getLength move.h /^ int getLength()$/;" f class:MoveList
getNewConnection network.cpp /^Connection* NetworkDomain::getNewConnection(const char* h,$/;" f class:NetworkDomain
getNext move.cpp /^bool MoveList::getNext(Move& m, int maxType)$/;" f class:MoveList
getState board.cpp /^char* Board::getState()$/;" f class:Board
gotConnection network.cpp /^void NetworkDomain::gotConnection()$/;" f class:NetworkDomain
hasMove move.h /^ bool hasMove(int d)$/;" f class:Variation
hasSameFields board.cpp /^bool Board::hasSameFields(Board* b)$/;" f class:Board
host network.h /^ char host[100];$/;" m class:Connection
host player.cpp /^char* host = 0; \/* not used on default *\/$/;" v
host referee.cpp /^static char* host[2] = {0,0}; \/* not used per default *\/$/;" v file:
host start.cpp /^static char* host = 0; \/* not used on default *\/$/;" v file:
i search.cpp /^int i=0;$/;" v
inARow2 board.h /^ enum InARowType { inARow2 = 0, inARow3, inARow4, inARow5, inARowCount };$/;" e enum:MoveCounter::InARowType
inARow3 board.h /^ enum InARowType { inARow2 = 0, inARow3, inARow4, inARow5, inARowCount };$/;" e enum:MoveCounter::InARowType
inARow4 board.h /^ enum InARowType { inARow2 = 0, inARow3, inARow4, inARow5, inARowCount };$/;" e enum:MoveCounter::InARowType
inARow5 board.h /^ enum InARowType { inARow2 = 0, inARow3, inARow4, inARow5, inARowCount };$/;" e enum:MoveCounter::InARowType
inARowCount board.h /^ enum InARowType { inARow2 = 0, inARow3, inARow4, inARow5, inARowCount };$/;" e enum:MoveCounter::InARowType
inARowValue eval.h /^ int inARowValue(int s)$/;" f class:EvalScheme
incRow board.h /^ void incRow(int r) { _rowCount[r]++; }$/;" f class:MoveCounter
incType board.h /^ void incType(int t) { _moveCount[t]++; }$/;" f class:MoveCounter
init board.cpp /^void MoveCounter::init()$/;" f class:MoveCounter
insert move.cpp /^void MoveList::insert(Move m)$/;" f class:MoveList
insert move.h /^ void insert(short f, char d, Move::MoveType t)$/;" f class:MoveList
install network.cpp /^bool NetworkLoop::install(NetworkDomain* d)$/;" f class:NetworkLoop
install network.cpp /^bool NetworkLoop::install(NetworkTimer* t)$/;" f class:NetworkLoop
invalid board.h /^ invalid };$/;" e enum:Board::__anon3
isConsistent board.cpp /^bool Board::isConsistent()$/;" f class:Board
isElement move.cpp /^bool MoveList::isElement(Move &m, int startType, bool del)$/;" f class:MoveList
isElement move.cpp /^bool MoveList::isElement(int f)$/;" f class:MoveList
isListening network.h /^ bool isListening() { return (fd>=0); }$/;" f class:NetworkDomain
isOutMove move.h /^ bool isOutMove() const { return type <= out1with2; }$/;" f class:Move
isPushMove move.h /^ bool isPushMove() const { return type <= push1with2; }$/;" f class:Move
isValid board.h /^ bool isValid() { return (color1Count>8 && color2Count>8); }$/;" f class:Board
kevalsPerSec search.cpp /^static int kevalsPerSec = 30;$/;" v file:
l player.cpp /^NetworkLoop l;$/;" v
l referee.cpp /^static NetworkLoop l;$/;" v file:
l start.cpp /^static NetworkLoop l;$/;" v file:
last move.h /^ int last[Move::typeCount];$/;" m class:MoveList
lastMove board.h /^ Move& lastMove()$/;" f class:Board
left2 move.h /^ left2, right2, move2, move1, none };$/;" e enum:Move::MoveType
left3 move.h /^ push1with3, push1with2, move3, left3, right3,$/;" e enum:Move::MoveType
likely search-minimax.cpp 15;" d file:
likely search-parallel-minimax.cpp 17;" d file:
listeningFD network.h /^ int listeningFD() { return fd; }$/;" f class:NetworkDomain
listeningPort network.h /^ int listeningPort() { return myPort; }$/;" f class:NetworkDomain
loop network.h /^ NetworkLoop* loop;$/;" m class:NetworkDomain
lport player.cpp /^int lport = 13133;$/;" v
lport referee.cpp /^static int lport[2] = {DEFAULT_DOMAIN_PORT, DEFAULT_DOMAIN_PORT + DEFAULT_DOMAIN_DIFF};$/;" v file:
lport start.cpp /^static int lport = DEFAULT_DOMAIN_PORT;$/;" v file:
main player.cpp /^int main(int argc, char* argv[])$/;" f
main referee.cpp /^int main(int argc, char* argv[])$/;" f
main start.cpp /^int main(int argc, char* argv[])$/;" f
maxDepth move.h /^ enum { maxDepth = 10 };$/;" e enum:Variation::__anon10
maxDepth player.cpp /^int maxDepth = 0;$/;" v
maxEvaluation search.cpp /^int SearchStrategy::maxEvaluation()$/;" f class:SearchStrategy
maxMoveType move.h /^ maxMoveType = move1 };$/;" e enum:Move::__anon7
maxMoves player.cpp /^int maxMoves = -1;$/;" v
maxOutType move.h /^ maxOutType = out1with2,$/;" e enum:Move::__anon7
maxPushType move.h /^ maxPushType = push1with2,$/;" e enum:Move::__anon7
maxValue eval.h /^ int maxValue() { return 15000; }$/;" f class:Evaluator
max_readfd network.h /^ int max_readfd;$/;" m class:NetworkLoop
minEvaluation search.cpp /^int SearchStrategy::minEvaluation()$/;" f class:SearchStrategy
minLeft network.cpp /^void NetworkTimer::minLeft(struct timeval* tv)$/;" f class:NetworkTimer
minValue eval.h /^ int minValue() { return -15000; }$/;" f class:Evaluator
minimax search-minimax.cpp /^int MinimaxStrategy::minimax()$/;" f class:MinimaxStrategy
minimax search-parallel-minimax.cpp /^int MinimaxStrategy::minimax()$/;" f class:MinimaxStrategy
minimaxStrategy search-minimax.cpp /^MinimaxStrategy minimaxStrategy;$/;" v
minimaxStrategy search-parallel-minimax.cpp /^MinimaxStrategy minimaxStrategy;$/;" v
move move.h /^ Move move[MaxMoves];$/;" m class:MoveList
move move.h /^ Move move[maxDepth][maxDepth];$/;" m class:Variation
move1 move.h /^ left2, right2, move2, move1, none };$/;" e enum:Move::MoveType
move2 move.h /^ left2, right2, move2, move1, none };$/;" e enum:Move::MoveType
move3 move.h /^ push1with3, push1with2, move3, left3, right3,$/;" e enum:Move::MoveType
moveCount board.h /^ int moveCount(int t) { return _moveCount[t]; }$/;" f class:MoveCounter
moveNo board.h /^ int moveNo() { return _moveNo; }$/;" f class:Board
moveSum board.cpp /^int MoveCounter::moveSum()$/;" f class:MoveCounter
moveToReach board.cpp /^Move Board::moveToReach(Board* b, bool fuzzy)$/;" f class:Board
moveValue eval.h /^ int moveValue(int t)$/;" f class:EvalScheme
movesStored board.cpp /^int Board::movesStored()$/;" f class:Board
msecs network.h /^ int msecs() { return _msecs; }$/;" f class:NetworkTimer
msecsPassed search.h /^ int msecsPassed() { return _msecsPassed; }$/;" f class:SearchCallbacks
msecsToPlay board.h /^ int msecsToPlay(int c) { return _msecsToPlay[c]; }$/;" f class:Board
msecsToPlay referee.cpp /^static int msecsToPlay[3] = {0,0,0};$/;" v file:
myColor player.cpp /^int myColor = Board::color1;$/;" v
myID network.h /^ int fd, myID, myPort;$/;" m class:NetworkDomain
myPort network.h /^ int fd, myID, myPort;$/;" m class:NetworkDomain
mySin network.h /^ struct sockaddr_in mySin;$/;" m class:NetworkDomain typeref:struct:NetworkDomain::sockaddr_in
name move.cpp /^char* Move::name() const$/;" f class:Move
name search.h /^ char* name() { return _name; }$/;" f class:SearchStrategy
nameOfDir move.cpp /^static const char* nameOfDir(int dir)$/;" f file:
nameOfPos move.cpp /^static char* nameOfPos(int p)$/;" f file:
newConnection network.cpp /^void NetworkDomain::newConnection(Connection* c)$/;" f class:NetworkDomain
newConnection referee.cpp /^void MyDomain::newConnection(Connection* c)$/;" f class:MyDomain
newConnection start.cpp /^void MyDomain::newConnection(Connection* c)$/;" f class:MyDomain
next move.h /^ int next[MaxMoves];$/;" m class:MoveList
next network.h /^ Connection* next;$/;" m class:Connection
next network.h /^ NetworkTimer* next;$/;" m class:NetworkTimer
next network.h /^ NetworkDomain* next;$/;" m class:NetworkDomain
nextMove board.cpp /^Move& Board::nextMove()$/;" f class:Board
nextMove search-abid.cpp /^ Move& nextMove() { return _pv[1]; }$/;" f class:ABIDStrategy
nextMove search-parallel-abid.cpp /^ Move& nextMove() { return _pv[1]; }$/;" f class:ABIDStrategy
nextMove search.cpp /^Move& SearchStrategy::nextMove()$/;" f class:SearchStrategy
nextUnused move.h /^ int nextUnused, actualType;$/;" m class:MoveList
none move.h /^ left2, right2, move2, move1, none };$/;" e enum:Move::MoveType
num_threads player.cpp /^int num_threads;$/;" v
oneLevelStrategy search-onelevel.cpp /^OneLevelStrategy oneLevelStrategy;$/;" v
onlyReachable start.cpp /^static bool onlyReachable = true;$/;" v file:
operator [] board.h /^inline int Board::operator[](int no) const$/;" f class:Board
operator [] move.h /^ Move& operator[](int i)$/;" f class:Variation
order board.cpp /^int Board::order[]={$/;" m class:Board file:
order board.h /^ static int order[RealFields];$/;" m class:Board
out board.h /^ out = 10, free = 0,$/;" e enum:Board::__anon1
out eval.h /^ out = 10, free = 0,$/;" e enum:Evaluator::__anon4
out1with2 move.h /^ enum MoveType { out2 = 0, out1with3, out1with2, push2,$/;" e enum:Move::MoveType
out1with3 move.h /^ enum MoveType { out2 = 0, out1with3, out1with2, push2,$/;" e enum:Move::MoveType
out2 move.h /^ enum MoveType { out2 = 0, out1with3, out1with2, push2,$/;" e enum:Move::MoveType
parseArgs player.cpp /^void parseArgs(int argc, char* argv[])$/;" f
parseArgs referee.cpp /^static void parseArgs(int argc, char* argv[])$/;" f file:
parseArgs start.cpp /^static void parseArgs(int argc, char* argv[])$/;" f file:
pending network.cpp /^bool NetworkLoop::pending()$/;" f class:NetworkLoop
playMove board.cpp /^void Board::playMove(const Move& m, int msecs)$/;" f class:Board
playMove search.cpp /^void SearchStrategy::playMove(const Move& m)$/;" f class:SearchStrategy
port network.h /^ int port;$/;" m class:Connection
prepareConnection network.cpp /^Connection* NetworkDomain::prepareConnection(const char* host, int port)$/;" f class:NetworkDomain
pretty_print player.cpp 24;" d file:
pretty_print search-minimax.cpp 13;" d file:
pretty_print search-parallel-abid.cpp 15;" d file:
pretty_print search-parallel-minimax.cpp 15;" d file:
print board.cpp /^void Board::print()$/;" f class:Board
print move.cpp /^void Move::print() const$/;" f class:Move
printHelp player.cpp /^void printHelp(char* prg, bool printHeader)$/;" f
printHelp referee.cpp /^static void printHelp(char* prg, bool printHeader)$/;" f file:
printHelp start.cpp /^static void printHelp(char* prg, bool printHeader)$/;" f file:
processPending network.cpp /^void NetworkLoop::processPending()$/;" f class:NetworkLoop
push1with2 move.h /^ push1with3, push1with2, move3, left3, right3,$/;" e enum:Move::MoveType
push1with3 move.h /^ push1with3, push1with2, move3, left3, right3,$/;" e enum:Move::MoveType
push2 move.h /^ enum MoveType { out2 = 0, out1with3, out1with2, push2,$/;" e enum:Move::MoveType
randomMove board.cpp /^Move Board::randomMove()$/;" f class:Board
reachable network.h /^ bool reachable;$/;" m class:Connection
read eval.cpp /^void EvalScheme::read(char* file)$/;" f class:EvalScheme
readfds network.h /^ fd_set readfds;$/;" m class:NetworkLoop
received network.cpp /^void NetworkDomain::received(char* str)$/;" f class:NetworkDomain
received player.cpp /^void MyDomain::received(char* str)$/;" f class:MyDomain
received referee.cpp /^void MyDomain::received(char* str)$/;" f class:MyDomain
received start.cpp /^void MyDomain::received(char* str)$/;" f class:MyDomain
registerCallbacks search.h /^ void registerCallbacks(SearchCallbacks* sc) { _sc = sc; }$/;" f class:SearchStrategy
remove network.cpp /^void NetworkLoop::remove(NetworkDomain* domain)$/;" f class:NetworkLoop
reset network.cpp /^void NetworkTimer::reset()$/;" f class:NetworkTimer
right2 move.h /^ left2, right2, move2, move1, none };$/;" e enum:Move::MoveType
right3 move.h /^ push1with3, push1with2, move3, left3, right3,$/;" e enum:Move::MoveType
ringDiff eval.h /^ int ringDiff(int r) { return (r>0 && r<5) ? _ringDiff[r] : 0; }$/;" f class:EvalScheme
ringValue eval.h /^ int ringValue(int r) { return (r>=0 && r<5) ? _ringValue[r] : 0; }$/;" f class:EvalScheme
rowCount board.h /^ int rowCount(int r) { return _rowCount[r]; }$/;" f class:MoveCounter
rport player.cpp /^int rport = 23412;$/;" v
rport referee.cpp /^static int rport[2] = {DEFAULT_DOMAIN_PORT, DEFAULT_DOMAIN_PORT + DEFAULT_DOMAIN_DIFF};$/;" v file:
rport start.cpp /^static int rport = DEFAULT_DOMAIN_PORT;$/;" v file:
run network.cpp /^int NetworkLoop::run()$/;" f class:NetworkLoop
save eval.cpp /^void EvalScheme::save(char* file)$/;" f class:EvalScheme
searchBestMove search-abid.cpp /^void ABIDStrategy::searchBestMove()$/;" f class:ABIDStrategy
searchBestMove search-minimax.cpp /^void MinimaxStrategy::searchBestMove()$/;" f class:MinimaxStrategy
searchBestMove search-onelevel.cpp /^void OneLevelStrategy::searchBestMove()$/;" f class:OneLevelStrategy
searchBestMove search-parallel-abid.cpp /^void ABIDStrategy::searchBestMove()$/;" f class:ABIDStrategy
searchBestMove search-parallel-minimax.cpp /^void MinimaxStrategy::searchBestMove()$/;" f class:MinimaxStrategy
searchStrategies search.cpp /^static SearchStrategy* searchStrategies = 0;$/;" v file:
secsToPlay referee.cpp /^static int secsToPlay = 0;$/;" v file:
secsToPlay start.cpp /^static int secsToPlay = -1;$/;" v file:
seed board.h /^ int seed;$/;" m class:Board
sendBoard player.cpp /^void MyDomain::sendBoard()$/;" f class:MyDomain
sendBoard referee.cpp /^void MyDomain::sendBoard()$/;" f class:MyDomain
sendBoard start.cpp /^void MyDomain::sendBoard()$/;" f class:MyDomain
sendString network.cpp /^bool Connection::sendString(const char* str, int len)$/;" f class:Connection
set network.cpp /^void NetworkTimer::set(struct timeval* tv)$/;" f class:NetworkTimer
setActColor board.h /^ void setActColor(int c) { color=c; }$/;" f class:Board
setBoard eval.cpp /^void Evaluator::setBoard(Board* b)$/;" f class:Evaluator
setColor1Count board.h /^ void setColor1Count(int c) { color1Count = c; }$/;" f class:Board
setColor2Count board.h /^ void setColor2Count(int c) { color2Count = c; }$/;" f class:Board
setDefaults eval.cpp /^void EvalScheme::setDefaults()$/;" f class:EvalScheme
setDepth board.cpp /^void Board::setDepth(int d)$/;" f class:Board
setEvalScheme eval.cpp /^void Evaluator::setEvalScheme(EvalScheme* scheme)$/;" f class:Evaluator
setEvaluator board.h /^ void setEvaluator(Evaluator* ev) { _ev = ev; }$/;" f class:Board
setEvaluator search.h /^ void setEvaluator(Evaluator* e) { _ev = e; }$/;" f class:SearchStrategy
setField board.h /^ void setField(int i, int v) { field[i] = v; }$/;" f class:Board
setFieldValues eval.cpp /^void Evaluator::setFieldValues()$/;" f class:Evaluator
setHost network.cpp /^void Connection::setHost(const char* h)$/;" f class:Connection
setInARowValue eval.cpp /^void EvalScheme::setInARowValue(int stones, int value)$/;" f class:EvalScheme
setMSecsToPlay board.h /^ void setMSecsToPlay(int c, int s) { _msecsToPlay[c] = s; }$/;" f class:Board
setMaxDepth move.h /^ void setMaxDepth(int d)$/;" f class:Variation
setMaxDepth search.h /^ void setMaxDepth(int d) { _maxDepth = d; }$/;" f class:SearchStrategy
setMoveNo board.h /^ void setMoveNo(int n) { _moveNo = n; }$/;" f class:Board
setMoveValue eval.cpp /^void EvalScheme::setMoveValue(int type, int value)$/;" f class:EvalScheme
setRingDiff eval.cpp /^void EvalScheme::setRingDiff(int ring, int value)$/;" f class:EvalScheme
setRingValue eval.cpp /^void EvalScheme::setRingValue(int ring, int value)$/;" f class:EvalScheme
setSearchStrategy board.cpp /^void Board::setSearchStrategy(SearchStrategy* ss)$/;" f class:Board
setSpyLevel board.cpp /^void Board::setSpyLevel(int level)$/;" f class:Board
setState board.cpp /^bool Board::setState(char* s)$/;" f class:Board
setStoneValue eval.cpp /^void EvalScheme::setStoneValue(int stoneDiff, int value)$/;" f class:EvalScheme
setVerbose board.h /^ void setVerbose(int v) { _verbose = v; }$/;" f class:Board
show board.h /^ bool show, bUpdateSpy;$/;" m class:Board
sin network.h /^ struct sockaddr_in sin;$/;" m class:Connection typeref:struct:Connection::sockaddr_in
spyDepth board.h /^ int spyLevel, spyDepth;$/;" m class:Board
spyLevel board.h /^ int spyLevel, spyDepth;$/;" m class:Board
start network.cpp /^bool Connection::start()$/;" f class:Connection
start search.cpp /^void SearchCallbacks::start(int msecsForSearch)$/;" f class:SearchCallbacks
start start.cpp /^static bool start = true;$/;" v file:
start1 move.h /^ enum { all , start1, start2, start3 };$/;" e enum:MoveList::__anon9
start2 move.h /^ enum { all , start1, start2, start3 };$/;" e enum:MoveList::__anon9
start3 move.h /^ enum { all , start1, start2, start3 };$/;" e enum:MoveList::__anon9
startBoard board.cpp /^int Board::startBoard[]={$/;" m class:Board file:
startBoard board.h /^ static int startBoard[AllFields];$/;" m class:Board
startListening network.cpp /^int NetworkDomain::startListening(NetworkLoop* l)$/;" f class:NetworkDomain
startedNode search.cpp /^void SearchCallbacks::startedNode(int d, char* s)$/;" f class:SearchCallbacks
stateDescription board.cpp /^char* Board::stateDescription(int s)$/;" f class:Board
stoneValue eval.h /^ int stoneValue(int s) { return (s>0 && s<6) ? _stoneValue[s] : 0; }$/;" f class:EvalScheme
stopSearch board.cpp /^void Board::stopSearch()$/;" f class:Board
stopSearch search.h /^ void stopSearch() { _stopSearch = true; }$/;" f class:SearchStrategy
storedFirst board.h /^ int storedFirst, storedLast; \/* stored in ring puffer manner *\/$/;" m class:Board
storedLast board.h /^ int storedFirst, storedLast; \/* stored in ring puffer manner *\/$/;" m class:Board
storedMove board.h /^ Move storedMove[MvsStored]; \/* stored moves *\/$/;" m class:Board
strategies search.cpp /^char** SearchStrategy::strategies()$/;" f class:SearchStrategy
strategyNo player.cpp /^int strategyNo = 0;$/;" v
subLeft network.cpp /^bool NetworkTimer::subLeft(struct timeval* tv)$/;" f class:NetworkTimer
subTimeval network.cpp /^void subTimeval(struct timeval* tv1, struct timeval* tv2)$/;" f
substart search.cpp /^void SearchCallbacks::substart(char* s)$/;" f class:SearchCallbacks
t1 referee.cpp /^static struct timeval t1;$/;" v typeref:struct:timeval file:
t1 search.cpp /^static struct timeval t1, t2;$/;" v typeref:struct:timeval file:
t2 search.cpp /^static struct timeval t1, t2;$/;" v typeref:struct: file:
takeBack board.cpp /^bool Board::takeBack()$/;" f class:Board
takeBack search.cpp /^bool SearchStrategy::takeBack()$/;" f class:SearchStrategy
thread_rank player.cpp /^int thread_rank;$/;" v
timeout network.cpp /^void NetworkTimer::timeout(NetworkLoop*)$/;" f class:NetworkTimer
timeout1 board.h /^ timeout1, \/\/ time out for color1 -> win for color2$/;" e enum:Board::__anon3
timeout2 board.h /^ timeout2, \/\/ time out for color2 -> win for color1$/;" e enum:Board::__anon3
timerList network.h /^ NetworkTimer* timerList;$/;" m class:NetworkLoop
type move.h /^ MoveType type;$/;" m class:Move
typeCount move.h /^ enum { typeCount = none,$/;" e enum:Move::__anon7
typeName move.cpp /^char* Move::typeName() const$/;" f class:Move
unlikely search-minimax.cpp 16;" d file:
unlikely search-parallel-minimax.cpp 18;" d file:
update move.cpp /^void Variation::update(int d, Move& m)$/;" f class:Variation
updateSpy board.h /^ void updateSpy(bool b) { bUpdateSpy = b; }$/;" f class:Board
valid1 board.h /^ valid1, \/\/ valid state with color1 to draw$/;" e enum:Board::__anon3
valid2 board.h /^ valid2, \/\/ valid state with color2 to draw$/;" e enum:Board::__anon3
validState board.cpp /^int Board::validState()$/;" f class:Board
verbose network.cpp /^int verbose = 0;$/;" v
verbose search.h /^ int verbose() { return _verbose; }$/;" f class:SearchCallbacks
win1 board.h /^ win1, \/\/ color1 won$/;" e enum:Board::__anon3
win2 board.h /^ win2, \/\/ color2 won$/;" e enum:Board::__anon3
~Board board.h /^ ~Board() {};$/;" f class:Board
~Connection network.cpp /^Connection::~Connection()$/;" f class:Connection
~EvalScheme eval.h /^ ~EvalScheme() {}$/;" f class:EvalScheme
~NetworkDomain network.cpp /^NetworkDomain::~NetworkDomain()$/;" f class:NetworkDomain
~NetworkTimer network.h /^ virtual ~NetworkTimer() {}$/;" f class:NetworkTimer
~SearchCallbacks search.h /^ virtual ~SearchCallbacks() {}$/;" f class:SearchCallbacks
~SearchStrategy search.h /^ virtual ~SearchStrategy() {};$/;" f class:SearchStrategy
mpi-assign5/pv-split/Makefile
View file @
17980573
...
...
@@ -23,7 +23,8 @@ LDFLAGS=
LIB_OBJS
=
move.o board.o network.o search.o eval.o
SEARCH_OBJS
=
$(LIB_OBJS)
search-abid.o search-onelevel.o search-minimax.o
SEARCH_OBJS
=
$(LIB_OBJS)
search-abid-pvsplit.o
#SEARCH_OBJS = $(LIB_OBJS) search-abid.o search-onelevel.o search-minimax.o
#SEARCH_OBJS = $(LIB_OBJS) search-parallel-minimax.o search-parallel-abid.cpp
all
:
player
...
...
mpi-assign5/pv-split/search-abid-pvsplit.cpp
0 → 100644
View file @
17980573
/**
* A real world, sequential strategy:
* Alpha/Beta with Iterative Deepening (ABID)
*
* (c) 2005, Josef Weidendorfer
*/
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#include <string.h>
#include "search.h"
#include "board.h"
extern
int
thread_rank
;
extern
int
num_threads
;
/**
* Entry point for search
*
* Does iterative deepening and alpha/beta width handling, and
* calls alpha/beta search
*/
void
ABIDStrategy
::
searchBestMove
()
{
int
alpha
=
-
15000
,
beta
=
15000
;
int
nalpha
,
nbeta
,
currentValue
=
0
;
_pv
.
clear
(
_maxDepth
);
_currentBestMove
.
type
=
Move
::
none
;
_currentMaxDepth
=
1
;
/* iterative deepening loop */
do
{
/* searches on same level with different alpha/beta windows */
while
(
1
)
{
nalpha
=
alpha
,
nbeta
=
beta
;
_inPV
=
(
_pv
[
0
].
type
!=
Move
::
none
);
if
(
_sc
&&
_sc
->
verbose
())
{
char
tmp
[
100
];
sprintf
(
tmp
,
"Alpha/Beta [%d;%d] with max depth %d"
,
alpha
,
beta
,
_currentMaxDepth
);
_sc
->
substart
(
tmp
);
}
currentValue
=
pv_split
(
alpha
,
beta
);
printf
(
"Subsearch finished with currentValue = %d
\n
"
,
currentValue
);
/* stop searching if a win position is found */
if
(
currentValue
>
14900
||
currentValue
<
-
14900
)
_stopSearch
=
true
;
/* Don't break out if we haven't found a move */
if
(
_currentBestMove
.
type
==
Move
::
none
)
_stopSearch
=
false
;
if
(
_stopSearch
)
break
;
/* if result is outside of current alpha/beta window,
* the search has to be rerun with widened alpha/beta
*/
if
(
currentValue
<=
nalpha
)
{
alpha
=
-
15000
;
if
(
beta
<
15000
)
beta
=
currentValue
+
1
;
continue
;
}
if
(
currentValue
>=
nbeta
)
{
if
(
alpha
>
-
15000
)
alpha
=
currentValue
-
1
;
beta
=
15000
;
continue
;
}
break
;
}
/* Window in both directions cause of deepening */
alpha
=
currentValue
-
200
,
beta
=
currentValue
+
200
;
if
(
_stopSearch
)
break
;
_currentMaxDepth
++
;
}
while
(
_currentMaxDepth
<=
_maxDepth
);
_bestMove
=
_currentBestMove
;
}
int
ABIDStrategy
::
pv_split
(
int
alpha0
,
int
beta0
)
{
bool
cutoff
;
int
depth
;
int
value
;
int
currentValue
=
-
15000
;
int
slave_id
;
int
num_slaves
;
int
pending_jobs
;
Slave_Input
slave_input
;
Slave_Output
*
slave_output
;
MPI_Request
*
rcv_rq
;
MoveList
list
;
Move
m
,
*
movechain
;
int
*
alpha
,
*
beta
;
rcv_rq
=
(
MPI_Request
*
)
malloc
(
num_threads
*
sizeof
(
MPI_Request
));
slave_output
=
(
Slave_Output
*
)
malloc
(
num_threads
*
sizeof
(
Slave_Output
));
movechain
=
(
Move
*
)
malloc
((
_currentMaxDepth
+
1
)
*
sizeof
(
Move
));
alpha
=
(
int
*
)
malloc
((
_currentMaxDepth
+
2
)
*
sizeof
(
int
));
beta
=
(
int
*
)
malloc
((
_currentMaxDepth
+
2
)
*
sizeof
(
int
));
alpha
[
0
]
=
alpha0
;
beta
[
0
]
=
beta0
;
_currentBestMove
.
type
=
Move
::
none
;
// Play moves from the pv until you reach the lowest level
// If pv-moves are not possible use random moves
// Store the sequence of moves in movechain
depth
=
0
;
while
(
depth
<
(
_currentMaxDepth
-
1
))
{
list
.
clear
();
_board
->
generateMoves
(
list
);
m
=
_pv
[
depth
];
// check if pv-move is possible
if
((
m
.
type
!=
Move
::
none
)
&&
(
!
list
.
isElement
(
m
,
0
,
false
)))
m
.
type
=
Move
::
none
;
// get random move if pv-move is not possible
if
(
m
.
type
==
Move
::
none
)
list
.
getNext
(
m
,
Move
::
none
);
_board
->
playMove
(
m
);
movechain
[
depth
]
=
m
;
alpha
[
depth
+
1
]
=
-
beta
[
depth
];
beta
[
depth
+
1
]
=
-
alpha
[
depth
];
depth
++
;
}
// Start at the second lowest level and move back up the gametree
// Devide the work at each level
depth
=
_currentMaxDepth
-
1
;
while
(
depth
>=
0
)
{
slave_id
=
0
;
list
.
clear
();
_board
->
generateMoves
(
list
);
// delete the move we already checked from the list
if
(
depth
<
_currentMaxDepth
-
1
)
list
.
isElement
(
movechain
[
depth
],
0
,
true
);
strcpy
(
slave_input
.
boardstate
,
_board
->
getState
());
slave_input
.
alpha
=
-
beta
[
depth
];
slave_input
.
beta
=
-
alpha
[
depth
];
slave_input
.
depth
=
depth
+
1
;
slave_input
.
currentMaxDepth
=
_currentMaxDepth
;
printf
(
"Thread 0 testing %d moves at depth = %d
\n
"
,
list
.
getLength
(),
depth
);
while
(
list
.
getNext
(
m
,
Move
::
none
)
)
{
slave_input
.
move
=
m
;
MPI_Send
(
&
slave_input
,
sizeof
(
Slave_Input
),
MPI_BYTE
,
slave_id
+
1
,
10
,
MPI_COMM_WORLD
);
MPI_Irecv
(
&
slave_output
[
slave_id
],
sizeof
(
Slave_Output
),
MPI_BYTE
,
slave_id
+
1
,
10
,
MPI_COMM_WORLD
,
&
rcv_rq
[
slave_id
]);
slave_id
++
;
if
(
slave_id
>=
(
num_threads
-
1
))
break
;
}
num_slaves
=
slave_id
;
pending_jobs
=
num_slaves
;
cutoff
=
false
;
while
(
pending_jobs
>
0
)
{
MPI_Waitany
(
num_slaves
,
rcv_rq
,
&
slave_id
,
MPI_STATUS_IGNORE
);
_sc
->
_leavesVisited
+=
slave_output
[
slave_id
].
num_leaves
;
_sc
->
_nodesVisited
+=
slave_output
[
slave_id
].
num_nodes
;
value
=
slave_output
[
slave_id
].
eval
;
if
(
value
>
currentValue
)
{
currentValue
=
value
;
_pv
=
slave_output
[
slave_id
].
pv
;
if
(
_sc
)
_sc
->
foundBestMove
(
depth
,
_pv
[
depth
],
currentValue
);
if
(
currentValue
>
alpha
[
depth
])
{
alpha
[
depth
]
=
currentValue
;
slave_input
.
beta
=
-
alpha
[
depth
];
}
/* alpha/beta cut off or win position ... */
if
(
currentValue
>
14900
||
currentValue
>=
beta
[
depth
])
cutoff
=
true
;
}
if
((
list
.
getNext
(
m
,
Move
::
none
))
&&
(
cutoff
==
false
))
{
slave_input
.
move
=
m
;
MPI_Send
(
&
slave_input
,
sizeof
(
Slave_Input
),
MPI_BYTE
,
slave_id
+
1
,
10
,
MPI_COMM_WORLD
);
MPI_Irecv
(
&
slave_output
[
slave_id
],
sizeof
(
Slave_Output
),
MPI_BYTE
,
slave_id
+
1
,
10
,
MPI_COMM_WORLD
,
&
rcv_rq
[
slave_id
]);
}
else
pending_jobs
--
;
}
if
(
depth
>
0
)
{
_board
->
takeBack
();
_pv
.
update
(
depth
-
1
,
movechain
[
depth
-
1
]);
currentValue
=
-
currentValue
;
if
(
currentValue
>
alpha
[
depth
-
1
])
alpha
[
depth
-
1
]
=
currentValue
;
}
if
(
depth
==
0
)
_currentBestMove
=
_pv
[
0
];
if
(
_sc
)
_sc
->
finishedNode
(
depth
,
_pv
.
chain
(
depth
));
depth
--
;
}
free
(
slave_output
);
free
(
rcv_rq
);
free
(
movechain
);
free
(
alpha
);
free
(
beta
);
return
currentValue
;
}
/*
* Alpha/Beta search
*
* - first, start with principal variation
* - depending on depth, we only do depth search for some move types
*/
int
ABIDStrategy
::
alphabeta
(
int
depth
,
int
alpha
,
int
beta
)
{
int
currentValue
=
-
14999
+
depth
,
value
;
Move
m
;
MoveList
list
;
bool
depthPhase
,
doDepthSearch
;
/* We make a depth search for the following move types... */
int
maxType
=
(
depth
<
_currentMaxDepth
-
1
)
?
Move
::
maxMoveType
:
(
depth
<
_currentMaxDepth
)
?
Move
::
maxPushType
:
Move
::
maxOutType
;
_board
->
generateMoves
(
list
);
if
(
_sc
&&
_sc
->
verbose
())
{
char
tmp
[
100
];
sprintf
(
tmp
,
"Alpha/Beta [%d;%d], %d moves (%d depth)"
,
alpha
,
beta
,
list
.
count
(
Move
::
none
),
list
.
count
(
maxType
));
_sc
->
startedNode
(
depth
,
tmp
);
}
// don't use moves from the principal variation
m
.
type
=
Move
::
none
;
// first, play all moves with depth search
depthPhase
=
true
;
while
(
1
)
{
// get next move
if
(
m
.
type
==
Move
::
none
)
{
if
(
depthPhase
)
depthPhase
=
list
.
getNext
(
m
,
maxType
);
if
(
!
depthPhase
)
if
(
!
list
.
getNext
(
m
,
Move
::
none
))
break
;
}
// we could start with a non-depth move from principal variation
doDepthSearch
=
depthPhase
&&
(
m
.
type
<=
maxType
);
_board
->
playMove
(
m
);
/* check for a win position first */
if
(
!
_board
->
isValid
())
{
/* Shorter path to win position is better */
value
=
14999
-
depth
;
}
else
{
if
(
doDepthSearch
)
{
/* opponent searches for its maximum; but we want the
* minimum: so change sign (for alpha/beta window too!)
*/
value
=
-
alphabeta
(
depth
+
1
,
-
beta
,
-
alpha
);
}
else
{
value
=
evaluate
();
}
}
_board
->
takeBack
();
/* best move so far? */
if
(
value
>
currentValue
)
{
currentValue
=
value
;
_pv
.
update
(
depth
,
m
);
/* alpha/beta cut off or win position ... */
if
(
currentValue
>
14900
||
currentValue
>=
beta
)
{
if
(
_sc
)
_sc
->
finishedNode
(
depth
,
_pv
.
chain
(
depth
));
return
currentValue
;
}
/* maximize alpha */
if
(
currentValue
>
alpha
)
alpha
=
currentValue
;
}
if
(
_stopSearch
)
break
;
// depthPhase=false;
m
.
type
=
Move
::
none
;
}
if
(
_sc
)
_sc
->
finishedNode
(
depth
,
_pv
.
chain
(
depth
));
return
currentValue
;
}
// register ourselve
ABIDStrategy
abidStrategy
;
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment