Commit 35f93e44 authored by Jonathan Michalon's avatar Jonathan Michalon

LibOVCC: implemented a way to score fields

This field scoring implementation seem to work (in spite of hacks)
but need more testing and optimisation.
parent f5099a69
......@@ -306,6 +306,81 @@ namespace OVCC
return complete;
}
/**
* Get a list of TileObjects of a city and together the list forming the
* fileds around it
*
* @param object The first city object
* @param pos The position of that objects on the board
* @param city An out list of CITY objects
* @param fields An out list of FIELDs objects
* @return Whether the city is complete
*/
public bool get_city_with_fields (TileObject object,
Position pos,
out SList<TileObject> city,
out SList<TileObject> fields)
{
city = new SList<TileObject>();
fields = new SList<TileObject>();
var complete = get_city_with_fields_rec (object, pos, ref city, ref fields);
return complete;
}
/* recursive handler for the previous function */
private bool get_city_with_fields_rec (TileObject object,
Position pos,
ref SList <TileObject> city,
ref SList <TileObject> fields)
{
if (city.find (object) != null)
return true;
var complete = true;
city.prepend (object);
/* loop on each link */
foreach (var link in object.links) {
var otherpos = pos;
if (link in TileObjectLinks.TOP)
otherpos.y--;
else if (link in TileObjectLinks.RIGHT)
otherpos.x++;
else if (link in TileObjectLinks.BOTTOM)
otherpos.y++;
else if (link in TileObjectLinks.LEFT)
otherpos.x--;
else
assert_not_reached ();
var othertile = get_tile (otherpos);
if (othertile != null) {
var neighbour = othertile.get_object_linking (link.mirror_links ());
if (neighbour != null &&
!get_city_with_fields_rec (neighbour, otherpos, ref city, ref fields))
complete = false;
} else {
complete = false;
}
var tile = get_tile (pos);
assert (tile != null);
var newfields = tile.get_touching_objects(object, TileObjectType.FIELD);
foreach (var f in newfields) {
bool dummy;
var components = get_connected (f, pos, out dummy);
foreach (var c in components) {
if (fields.find (c) == null) {
fields.prepend (c);
}
}
}
}
return complete;
}
public void get_bounds (out int left,
out int top,
out int right,
......
......@@ -235,7 +235,7 @@ namespace OVCC
bool complete;
var components = board.get_connected (o, pos, out complete);
if (complete) {
make_score_city_path (components, complete);
make_score_city_path_fields (components, complete);
}
break;
}
......@@ -277,6 +277,7 @@ namespace OVCC
/* do work when game finished (count points) */
private void after_game_finished ()
{
var visited_cities = new SList<TileObject> ();
board.foreach ((b, p, t) => {
foreach (var o in t.objects) {
if (o.occupant != null) {
......@@ -285,7 +286,7 @@ namespace OVCC
case TileObjectType.CITY:
bool complete;
var components = board.get_connected (o, p, out complete);
make_score_city_path (components, complete);
make_score_city_path_fields (components, complete);
break;
case TileObjectType.MONASTERY:
make_score_monastery (o, p, false);
......@@ -295,6 +296,18 @@ namespace OVCC
break;
}
}
/* fields */
if (o.otype == TileObjectType.CITY && visited_cities.find (o) == null) {
SList<TileObject> city;
SList<TileObject> fields;
var complete = board.get_city_with_fields (o, p, out city, out fields);
foreach (var c in city) {
visited_cities.prepend (c);
}
if (complete) {
make_score_city_path_fields (fields, false);
}
}
}
return true;
});
......@@ -303,8 +316,8 @@ namespace OVCC
/* handel linked components for scoring -- paths & cities
* makes the players score according to the rules
* removes the pawns */
private void make_score_city_path (SList<TileObject> components,
bool complete)
private void make_score_city_path_fields (SList<TileObject> components,
bool complete)
{
/* nonsense on empty list */
assert (components.length() != 0);
......@@ -337,7 +350,9 @@ namespace OVCC
}
list.set_data (o.occupant.player.nick, cur);
/* removing pawn now is efficient and not wrong */
remove_pawn (o.occupant);
if (components.nth_data(0).otype != TileObjectType.FIELD) {
remove_pawn (o.occupant);
}
}
}
var scorers = new SList<string>();
......@@ -374,10 +389,18 @@ namespace OVCC
player.score += 2;
} else {
/* score according to type */
if (components.nth_data(0).otype == TileObjectType.CITY) {
switch (components.nth_data(0).otype) {
case TileObjectType.CITY:
/* TODO change when end */
player.score += counts * 2;
} else {
break;
case TileObjectType.PATH:
/* TODO change when end */
player.score += counts;
break;
case TileObjectType.FIELD:
player.score += 3;
break;
}
}
}
......
......@@ -59,6 +59,24 @@ namespace OVCC
{
return this ^ l;
}
/* get a TileObjectLinks of the links touching us */
public TileObjectLinks get_touching_links ()
{
var touching = this;
foreach (var link in this) {
var prev = link >> 1;
var next = link << 1;
if (link == TOP_LEFT)
prev = LEFT_RIGHT;
if (link == LEFT_RIGHT)
prev = TOP_LEFT;
touching = touching.addition (prev).addition (next);
}
return this.misses (touching);
}
/* this function reverses the nbits firts bits of an integer */
private static uint reverse_bits (uint bits, int nbits)
{
......
......@@ -147,6 +147,34 @@ namespace OVCC
return null;
}
/**
* Compute a list of objects touching another, selecting a type
*
* @param object The reference object
* @param type The type of the objects to compute
* @return The promised list
*/
public SList<TileObject> get_touching_objects (TileObject object,
TileObjectType type)
{
var list = new SList<TileObject>();
/* add each object in the list of links touching ours */
foreach (var l in object.links.get_touching_links()) {
var candidate = get_object_linking (l);
if (candidate != null) {
if (candidate.otype == type) {
if (list.find(candidate) == null) {
list.prepend (candidate);
}
}
}
}
/* FIXME some expansion tiles need more tweaks here */
return list;
}
public void dump ()
{
stdout.printf ("t%02u", id);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment