static void buildin_assert(const vector<LuaValue>& args, vector<LuaValue>& rets) { if (args[0].getBoolean()) { rets.assign(args.begin(), args.end()); } else { if (args.size() > 1) ASSERT1(0, args[1].toString()); else ASSERT1(0, "assertion failed!"); } }
*/ REBVAL *Get_Object(REBVAL *objval, REBCNT index) /* ** Get an instance variable from an object value. ** ***********************************************************************/ { REBSER *obj = VAL_OBJ_FRAME(objval); ASSERT1(IS_FRAME(BLK_HEAD(obj)), RP_BAD_OBJ_FRAME); ASSERT1(index < SERIES_TAIL(obj), RP_BAD_OBJ_INDEX); return FRM_VALUES(obj) + index; }
void storeDelayedExpression(DATA* data, int exprNumber, double exprValue, double time) { TIME_AND_VALUE tpl; DEBUG_INFO3(LOG_EVENTS, "storeDelayed[%d] %g:%g", exprNumber, time, exprValue); /* Allocate more space for expressions */ ASSERT1(exprNumber < data->modelData.nDelayExpressions, "storeDelayedExpression: invalid expression number %d", exprNumber); ASSERT1(0 <= exprNumber, "storeDelayedExpression: invalid expression number %d", exprNumber); ASSERT(data->simulationInfo.tStart <= time, "storeDelayedExpression: time is smaller than starting time. Value ignored"); tpl.time = time; tpl.value = exprValue; appendRingData(data->simulationInfo.delayStructure[exprNumber], &tpl); }
void iosim_get_path_to_device (int iodriverno, int devno, intchar *buspath, intchar *slotpath) { int depth; int currbus; char inslotno; char outslotno; int master; #ifdef DEBUG_IOSIM fprintf(outputfile, "%f: iosim_get_path_to_controller iodriverno %d, devno %d, buspath %p, slotpath %p\n", simtime, iodriverno, devno, buspath, slotpath ); fflush(outputfile); #endif depth = device_get_depth(devno); currbus = device_get_inbus(devno); inslotno = (char) device_get_slotno(devno); master = controller_get_bus_master(currbus); while (depth > 0) { /* fprintf (outputfile, "devno %d, depth %d, currbus %d, inslotno %d, master %d\n", devno, depth, currbus, inslotno, master); */ outslotno = (char) controller_get_outslot(master, currbus); buspath->byte[depth] = (char) currbus; slotpath->byte[depth] = (inslotno & 0x0F) | (outslotno << 4); depth--; currbus = controller_get_inbus(master); inslotno = (char) controller_get_slotno(master); master = controller_get_bus_master(currbus); /* Bus must have at least one controller */ ASSERT1((master != -1) || (depth <= 0), "currbus", currbus); } outslotno = (char) iodriverno; buspath->byte[depth] = currbus; slotpath->byte[depth] = (inslotno & 0x0F) | (outslotno << 4); }
/* Уничтожение буфера. Функция вызывается только из внутренних задач.*/ static void combuf_destroy(const combuf_t combuf) { ASSERT1(CHECK_COMBUF(combuf), "invalid combuf = %u", combuf); /* Пометить буфер для удаления */ DESTROY(combuf); /* Если буфер последний в очереди, то удаляем его и * следующие буферы в очереди ( если они помечены для удаления ) */ if (IS_BACK(combuf)) { cb_store_t _busy; cb_store_t cb_size; do { cb_size = SIZE(back); back = SUM(back, cb_size); __critical_enter(); busy -= cb_size; _busy = busy; __critical_exit(); } while ((0 < _busy) && IS_DESTROYED(back)); } }
void RNamedObject::InternalInit(LPCTSTR prefix, LPCTSTR name){ //RASSERT1(prefix); //RASSERT1(name); // TODO(Omaha): Enable this code after we have a better understanding of // Private Object Namespaces. #if 0 if (IsPrivateNamespaceAvailable(is_machine)) { attr->name = kGoopdatePrivateNamespacePrefix; } else { ASSERT1(!SystemInfo::IsRunningOnVistaOrLater()); #endif size_t bsize = _tcslen(name)+_tcslen(prefix); LPTSTR sid_string = NULL; if (holdem_utils::GetCurrentSID(&sid_string)){ bsize += _tcslen(sid_string); } name_ = new TCHAR[bsize+2]; if (sid_string){ wsprintf(name_, _T("%s%s%s"), prefix, name, sid_string); LocalFree(sid_string); }else{ wsprintf(name_, _T("%s%s"), prefix, name); } } }
static void mergeAction(Action &dact, Action sact, const LR0ItemCollectionFamily& family) { if (sact.type == Action::T_Null) ASSERT(0); else if(sact.type == Action::T_Shift) { if (dact.type == Action::T_Null) dact = sact; else ASSERT(0); } else if (sact.type == Action::T_Reduce) { if (dact.type == Action::T_Null) dact = sact; else if (dact.type == Action::T_Shift) { int shiftPid = -1; for (auto item : family.ID2Collection[dact.value]) { if (item.pos > 0) { if (shiftPid == -1) shiftPid = item.productID; else ASSERT(0); // ??? } } auto sterm = getProductConflictToken(sact.value); auto dterm = getProductConflictToken(shiftPid); if (sterm == -1 || dterm == -1) { ASSERT1(0, "shift & reduce conflict -" + productBodyToString(sact.value) + " & " + productBodyToString(shiftPid)); } if (sterm == dterm) { if (getTermAssoc(sterm) == 'l') dact = sact; } else { if (getTermPriority(sterm) > getTermPriority(dterm)) dact = sact; } } else if (dact.type == Action::T_Reduce) { auto sterm = getProductConflictToken(sact.value); auto dterm = getProductConflictToken(dact.value); if (sterm == -1 || dterm == -1) { ASSERT1(0, "reduce & reduce conflict -" + productBodyToString(sact.value) + " & " + productBodyToString(dact.value)); } if (sterm == dterm) { ASSERT(0); } else { if (getTermPriority(sterm) > getTermPriority(dterm)) dact = sact; } } else ASSERT(0); } else ASSERT(0); }
struct ssd *getssd (int devno) { struct ssd *s; ASSERT1((devno >= 0) && (devno < MAXDEVICES), "devno", devno); s = disksim->ssdinfo->ssds[devno]; return (disksim->ssdinfo->ssds[devno]); }
uint8_t combuf_read(const combuf_t combuf, const combuf_pos_t pos) { ASSERT1(CHECK_COMBUF(combuf), "invalid combuf = %d", combuf); ASSERT2(pos < PAYLOAD_SIZE(combuf), "invalid pos = %hhu ( combuf = %d)", pos, combuf); return PAYLOAD_ITEM(combuf, pos); }
*/ REBYTE *Get_Field_Name(REBSER *obj, REBCNT index) /* ** Get the name of a field of an object. ** ***********************************************************************/ { ASSERT1(index < SERIES_TAIL(obj), RP_BAD_OBJ_INDEX); return Get_Sym_Name(FRM_WORD_SYM(obj, index)); }
INLINE void device_bus_delay_complete (int devno, ioreq_event *curr, int sentbusno) { ASSERT1 ((devno >= 0) && (devno < numdevices), "devno", devno); return disksim->deviceinfo->devices[devno]->bus_delay_complete(devno, curr, sentbusno); }
*/ REBVAL *Get_Field(REBSER *obj, REBCNT index) /* ** Get an instance variable from an object series. ** ***********************************************************************/ { ASSERT1(index < SERIES_TAIL(obj), RP_BAD_OBJ_INDEX); return FRM_VALUES(obj) + index; }
INLINE double device_get_acctime (int devno, ioreq_event *req, double maxtime) { ASSERT1 ((devno >= 0) && (devno < numdevices), "devno", devno); return disksim->deviceinfo->devices[devno]->get_acctime(devno, req, maxtime); }
INLINE void device_bus_ownership_grant (int devno, ioreq_event *curr, int busno, double arbdelay) { ASSERT1 ((devno >= 0) && (devno < numdevices), "devno", devno); return disksim->deviceinfo->devices[devno]->bus_ownership_grant(devno, curr, busno, arbdelay); }
result_t combuf_write(const combuf_t combuf, const combuf_pos_t pos, const uint8_t data) { ASSERT1(CHECK_COMBUF(combuf), "invalid combuf = %d", combuf); ASSERT2(pos < PAYLOAD_SIZE(combuf), "invalid pos = %hhu ( combuf = %d)", pos, combuf); PAYLOAD_ITEM(combuf, pos) = data; return ENOERR; }
INLINE int device_get_distance (int devno, ioreq_event *req, int exact, int direction) { ASSERT1 ((devno >= 0) && (devno < numdevices), "devno", devno); return disksim->deviceinfo->devices[devno]->get_distance(devno, req, exact, direction); }
double device_get_seektime (int devno, ioreq_event *req, int checkcache, double maxtime) { ASSERT1 ((devno >= 0) && (devno < numdevices), "devno", devno); return disksim->deviceinfo->devices[devno]->get_seektime(devno, req, checkcache, maxtime); }
/* функция подсчёта контрольной суммы */ static uint8_t calc_csum(const combuf_t combuf) { uint8_t crc = 0; cb_offset_t i = 0; cb_store_t cb_size; ASSERT1(CHECK_COMBUF(combuf), "invalid combuf = %d", combuf); cb_size = SIZE(combuf) - COMBUF_END_SIZE; for (; i < cb_size; i++) crc += PAYLOAD_ITEM(combuf, i); return crc; }
*/ REBVAL *Get_System(REBCNT i1, REBCNT i2) /* ** Return a second level object field of the system object. ** ***********************************************************************/ { REBVAL *obj; obj = VAL_OBJ_VALUES(ROOT_SYSTEM) + i1; if (!i2) return obj; ASSERT1(IS_OBJECT(obj), RP_BAD_OBJ_INDEX); return Get_Field(VAL_OBJ_FRAME(obj), i2); }
INLINE void device_get_mapping (int maptype, int devno, int blkno, int *cylptr, int *surfaceptr, int *blkptr) { ASSERT1 ((devno >= 0) && (devno < numdevices), "devno", devno); return disksim->deviceinfo->devices[devno]->get_mapping(maptype, devno, blkno, cylptr, surfaceptr, blkptr); }
*/ static void Bind_Block_Words(REBSER *frame, REBVAL *value, REBCNT mode) /* ** Inner loop of bind block. Modes are: ** ** BIND_ONLY Only bind the words found in the frame. ** BIND_SET Add set-words to the frame during the bind. ** BIND_ALL Add words to the frame during the bind. ** BIND_DEEP Recurse into sub-blocks. ** ** NOTE: BIND_SET must be used carefully, because it does not ** bind prior instances of the word before the set-word. That is ** forward references are not allowed. ** ***********************************************************************/ { REBINT *binds = WORDS_HEAD(Bind_Table); // GC safe to do here REBCNT n; REBFLG selfish = !IS_SELFLESS(frame); for (; NOT_END(value); value++) { if (ANY_WORD(value)) { //Print("Word: %s", Get_Sym_Name(VAL_WORD_CANON(value))); // Is the word found in this frame? if (NZ(n = binds[VAL_WORD_CANON(value)])) { if (n == NO_RESULT) n = 0; // SELF word ASSERT1(n < SERIES_TAIL(frame), RP_BIND_BOUNDS); // Word is in frame, bind it: VAL_WORD_INDEX(value) = n; VAL_WORD_FRAME(value) = frame; } else if (selfish && VAL_WORD_CANON(value) == SYM_SELF) { VAL_WORD_INDEX(value) = 0; VAL_WORD_FRAME(value) = frame; } else { // Word is not in frame. Add it if option is specified: if ((mode & BIND_ALL) || ((mode & BIND_SET) && (IS_SET_WORD(value)))) { Append_Frame(frame, value, 0); binds[VAL_WORD_CANON(value)] = VAL_WORD_INDEX(value); } } } else if (ANY_BLOCK(value) && (mode & BIND_DEEP)) Bind_Block_Words(frame, VAL_BLK_DATA(value), mode); else if ((IS_FUNCTION(value) || IS_CLOSURE(value)) && (mode & BIND_FUNC)) Bind_Block_Words(frame, BLK_HEAD(VAL_FUNC_BODY(value)), mode); } }
/* Helper for the owl_hotspots() function below. */ static void mark_dragon_hotspot_values(float values[BOARDMAX], int dr, float contribution, char active_board[BOARDMAX]) { int pos; int k; ASSERT1(IS_STONE(board[dr]), dr); for (pos = BOARDMIN; pos < BOARDMAX; pos++) { if (board[pos] != EMPTY) continue; for (k = 0; k < 8; k++) { int pos2 = pos + delta[k]; if (IS_STONE(board[pos2]) && (is_same_dragon(pos2, dr) || (are_neighbor_dragons(pos2, dr) && board[pos2] == board[dr])) && (countlib(pos2) <= 4 || is_edge_vertex(pos))) { if (k < 4) { if (is_same_dragon(pos2, dr)) values[pos] += contribution; else values[pos] += 0.5 * contribution; break; } else { /* If pos2 = SOUTHWEST(pos), this construction makes * pos3 = SOUTH(pos) and * pos4 = WEST(pos) * and corresponding for all other diagonal movements. */ int pos3 = pos + delta[k % 4]; int pos4 = pos + delta[(k+1) % 4]; if (board[pos3] == EMPTY || countlib(pos3) <= 2 || board[pos4] == EMPTY || countlib(pos4) <= 2) values[pos] += 0.5 * contribution; break; } } } /* If not close to the dragon, but within the active area, give * negative hotspot contribution. */ if (k == 8 && active_board[pos] == EMPTY) { values[pos] -= 0.5 * contribution; } } }
result_t combuf_send(const combuf_t combuf) { cb_offset_t _out_offset; ASSERT1(CHECK_COMBUF(combuf), "invalid combuf = %d", combuf); __critical_enter(); CONTROL(combuf) |= READY_MASK; _out_offset = out_offset; if (-2 == out_offset) out_offset = 0; __critical_exit(); if (-2 == _out_offset) if( ISZIGLOAD ) __post_task( &task_combuf_send ); return ENOERR; }
*/ void Do_Action(REBVAL *func) /* ***********************************************************************/ { REBVAL *ds = DS_RETURN; REBCNT type = VAL_TYPE(D_ARG(1)); Eval_Natives++; ASSERT1(type < REB_MAX, RP_BAD_TYPE_ACTION); // Handle special datatype test cases (eg. integer?) if (VAL_FUNC_ACT(func) == 0) { VAL_SET(D_RET, REB_LOGIC); VAL_LOGIC(D_RET) = (type == VAL_INT64(BLK_LAST(VAL_FUNC_SPEC(func)))); return; } Do_Act(D_RET, type, VAL_FUNC_ACT(func)); }
void DynamicProgrammingTest::Init(void) { Add("Test", [&](){ unsigned long long expect[100] = { 1, 2, 3, 4, 5, 6, 7, 9, 12, 16, 20, 25, 30, 36, 48, 64, 80, 100, 125, 150, 192, 256, 320, 400, 500, 625, 768, 1024, 1280, 1600, 2000, 2500, 3125, 4096, 5120, 6400, 8000, 10000, 12500, 16384, 20480, 25600, 32000, 40000, 50000, 65536, 81920, 102400, 128000, 160000, 200000, 262144, 327680, 409600, 512000, 640000, 800000, 1048576, 1310720, 1638400, 2048000, 2560000, 3200000, 4194304, 5242880, 6553600, 8192000, 10240000, 12800000, 16777216, 20971520, 26214400, 32768000, 40960000, 51200000, 67108864, 83886080, 104857600, 131072000, 163840000, 204800000, 268435456, 335544320, 419430400, 524288000, 655360000, 819200000, 1073741824, 1342177280, 1677721600, 2097152000, 2621440000, 3276800000, 4294967296, 5368709120, 6710886400, 8388608000, 10485760000, 13107200000, 17179869184 }; unsigned long long actual[100]; Test::DynamicProgramming::LongestStringWithKeystrokes(100, actual); for (int i = 0; i < 100; i++) { Logger().WriteInformation("%d: %llu %s %llu\n", i + 1, actual[i], actual[i] == expect[i] ? "==" : "!=", expect[i]); ASSERT1(actual[i] == expect[i]); } }); }
/* Look for a valid read result in the persistent cache. * Return 1 if found, 0 otherwise. */ int search_persistent_reading_cache(int routine, int str, int *result, int *move) { int k; struct reading_cache *entry; k = find_persistent_reading_cache_entry(routine, str); if (k == -1) return 0; /* Match found. Increase score and fill in the answer. */ entry = &(persistent_reading_cache[k]); entry->score += entry->nodes; if (result) *result = entry->result; if (move) *move = entry->move; ASSERT1(entry->result == 0 || entry->move == NO_MOVE || ON_BOARD(entry->move), entry->move); if ((debug & DEBUG_READING_PERFORMANCE) && entry->nodes >= MIN_READING_NODES_TO_REPORT) { if (entry->result != 0) gprintf("%o%s %1m = %d %1m, cached (%d nodes) ", routine == ATTACK ? "attack" : "defend", str, entry->result, entry->move, entry->nodes); else gprintf("%o%s %1m = %d, cached (%d nodes) ", routine == ATTACK ? "attack" : "defend", str, entry->result, entry->nodes); dump_stack(); } return 1; }
/* Locate a matching entry in the persistent reading cache. Return the * entry number or -1 if none found. */ static int find_persistent_reading_cache_entry(int routine, int str) { int k; int r; ASSERT1(str == find_origin(str), str); for (k = 0; k < persistent_reading_cache_size; k++) { /* Check that everything matches. */ struct reading_cache *entry = &(persistent_reading_cache[k]); int apos = 0; if (entry->routine != routine || entry->str != str || entry->remaining_depth < (depth - stackp) || entry->boardsize != board_size) continue; for (r = 0; r < MAX_READING_CACHE_DEPTH; r++) { apos = entry->stack[r]; if (apos == 0 || (entry->board[apos] != GRAY && board[apos] != entry->board[apos])) break; } if (r < MAX_READING_CACHE_DEPTH && apos != 0) continue; if (!verify_stored_board(entry->board)) continue; return k; } return -1; }
void iodriver_initialize (int standalone) { int numdevs; struct ioq * queueset[MAXDEVICES]; int i, j; iodriver *curriodriver; i = numiodrivers; /* Code will be broken by multiple iodrivers */ ASSERT1(numiodrivers == 1, "numiodrivers", numiodrivers); ioqueue_initialize (OVERALLQUEUE, 0); for (i = 0; i < numiodrivers; i++) { curriodriver = iodrivers[i]; curriodriver->type = standalone; if (standalone != STANDALONE) { curriodriver->scale = 1.0; } numdevs = controller_get_numcontrollers(); curriodriver->numctlrs = numdevs; curriodriver->ctlrs = (ctlr*) DISKSIM_malloc(numdevs * (sizeof(ctlr))); ASSERT(curriodriver->ctlrs != NULL); for (j=0; j < numdevs; j++) { ctlr *currctlr = &curriodriver->ctlrs[j]; currctlr->ctlno = j; currctlr->flags = 0; if (controller_C700_based(j) == TRUE) { /* fprintf (outputfile, "This one is c700_based - %d\n", j); */ currctlr->flags |= DRIVER_C700; } currctlr->buspath.value = 0; currctlr->slotpath.value = 0; iosim_get_path_to_controller(i, currctlr->ctlno, &currctlr->buspath, &currctlr->slotpath); currctlr->numoutstanding = 0; currctlr->pendio = NULL; currctlr->oversized = NULL; } numdevs = device_get_numdevices(); curriodriver->numdevices = numdevs; curriodriver->devices = (device*) DISKSIM_malloc(numdevs * (sizeof(device))); ASSERT(curriodriver->devices != NULL); for (j = 0; j < numdevs; j++) { device *currdev = &curriodriver->devices[j]; currdev->devno = j; currdev->busy = FALSE; currdev->flag = 0; currdev->queue = ioqueue_copy(curriodriver->queue); ioqueue_initialize(currdev->queue, j); queueset[j] = currdev->queue; currdev->buspath.value = 0; currdev->slotpath.value = 0; iosim_get_path_to_device(i, currdev->devno, &currdev->buspath, &currdev->slotpath); iodriver_set_ctl_to_device(i, currdev); get_device_maxoutstanding(curriodriver, currdev); } logorg_initialize(sysorgs, numsysorgs, queueset, drv_printlocalitystats, drv_printblockingstats, drv_printinterferestats, drv_printstreakstats, drv_printstampstats, drv_printintarrstats, drv_printidlestats, drv_printsizestats); /* fprintf (outputfile, "Back from logorg_initialize\n"); */ } stat_initialize(statdeffile, statdesc_emptyqueue, &emptyqueuestats); stat_initialize(statdeffile, statdesc_initiatenext, &initiatenextstats); #if 0 print_paths_to_devices(); print_paths_to_ctlrs(); #endif }
void iodriver_schedule (int iodriverno, ioreq_event *curr) { ctlr *ctl; #ifdef DEBUG_IODRIVER fprintf (outputfile, "%f: iodriver_schedule - devno %d, blkno %lld, bcount %d, read %d\n", simtime, curr->devno, curr->blkno, curr->bcount, (curr->flags & READ)); #endif ASSERT1(curr->type == IO_ACCESS_ARRIVE, "curr->type", curr->type); if ((iodrivers[iodriverno]->consttime != 0.0) && (iodrivers[iodriverno]->consttime != IODRIVER_TRACED_QUEUE_TIMES)) { curr->type = IO_INTERRUPT; if (iodrivers[iodriverno]->consttime > 0.0) { curr->time = iodrivers[iodriverno]->consttime; } else { curr->time = ((double) curr->tempint2 / (double) 1000); } curr->cause = COMPLETION; intr_request((event *) curr); return; } ctl = iodrivers[iodriverno]->devices[(curr->devno)].ctl; if ((ctl) && (ctl->flags & DRIVER_C700)) { if ((ctl->pendio) && ((curr->devno != ctl->pendio->next->devno) || (curr->opid != ctl->pendio->next->opid) || (curr->blkno != ctl->pendio->next->blkno))) { curr->next = ctl->pendio->next; ctl->pendio->next = curr; ctl->pendio = curr; return; } else if (ctl->pendio == NULL) { ctl->pendio = ioreq_copy(curr); ctl->pendio->next = ctl->pendio; } if (ctl->flags & DRIVER_CTLR_BUSY) { addtoextraq((event *) curr); return; } } curr->busno = iodrivers[iodriverno]->devices[(curr->devno)].buspath.value; curr->slotno = iodrivers[iodriverno]->devices[(curr->devno)].slotpath.value; if (iodrivers[iodriverno]->devices[(curr->devno)].queuectlr != -1) { int ctlrno = iodrivers[iodriverno]->devices[(curr->devno)].queuectlr; ctl = &iodrivers[iodriverno]->ctlrs[ctlrno]; if ((ctl->maxreqsize) && (curr->bcount > ctl->maxreqsize)) { ioreq_event *totalreq = ioreq_copy(curr); /* fprintf (outputfile, "%f, oversized request: opid %d, blkno %lld, bcount %d, maxreqsize %d\n", simtime, curr->opid, curr->blkno, curr->bcount, ctl->maxreqsize); */ curr->bcount = ctl->maxreqsize; if (ctl->oversized) { totalreq->next = ctl->oversized->next; ctl->oversized->next = totalreq; } else { totalreq->next = totalreq; ctl->oversized = totalreq; } } } iodriver_send_event_down_path(curr); /* fprintf (outputfile, "Leaving iodriver_schedule\n"); */ }
/* Find moves turning supposed territory into seki. This is not * detected above since it either involves an ALIVE dragon adjacent to * a CRITICAL dragon, or an ALIVE dragon whose eyespace can be invaded * and turned into a seki. * * Currently we only search for tactically critical strings with * dragon status dead, which are neighbors of only one opponent * dragon, which is alive. Through semeai analysis we then determine * whether such a string can in fact live in seki. Relevant testcases * include gunnar:42 and gifu03:2. */ static void find_moves_to_make_seki() { int str; int defend_move; int resulta, resultb; for (str = BOARDMIN; str < BOARDMAX; str++) { if (IS_STONE(board[str]) && is_worm_origin(str, str) && attack_and_defend(str, NULL, NULL, NULL, &defend_move) && dragon[str].status == DEAD && DRAGON2(str).hostile_neighbors == 1) { int k; int color = board[str]; int opponent = NO_MOVE; int certain; struct eyevalue reduced_genus; for (k = 0; k < DRAGON2(str).neighbors; k++) { opponent = dragon2[DRAGON2(str).adjacent[k]].origin; if (board[opponent] != color) break; } ASSERT1(opponent != NO_MOVE, opponent); if (dragon[opponent].status != ALIVE) continue; /* FIXME: These heuristics are used for optimization. We don't * want to call expensive semeai code if the opponent * dragon has more than one eye elsewhere. However, the * heuristics might still need improvement. */ compute_dragon_genus(opponent, &reduced_genus, str); if (DRAGON2(opponent).moyo_size > 10 || min_eyes(&reduced_genus) > 1) continue; owl_analyze_semeai_after_move(defend_move, color, opponent, str, &resulta, &resultb, NULL, 1, &certain, 0); /* Do not trust uncertain results. In fact it should only take a * few nodes to determine the semeai result, if it is a proper * potential seki position. */ if (resultb != WIN && certain) { int d = dragon[str].id; DEBUG(DEBUG_SEMEAI, "Move to make seki at %1m (%1m vs %1m)\n", defend_move, str, opponent); dragon2[d].semeais++; update_status(str, CRITICAL, CRITICAL); dragon2[d].semeai_defense_point = defend_move; dragon2[d].semeai_defense_certain = certain; dragon2[d].semeai_defense_target = opponent; /* We need to determine a proper attack move (the one that * prevents seki). Currently we try the defense move first, * and if it doesn't work -- all liberties of the string. */ owl_analyze_semeai_after_move(defend_move, OTHER_COLOR(color), str, opponent, &resulta, NULL, NULL, 1, NULL, 0); if (resulta != WIN) dragon2[d].semeai_attack_point = defend_move; else { int k; int libs[MAXLIBS]; int liberties = findlib(str, MAXLIBS, libs); for (k = 0; k < liberties; k++) { owl_analyze_semeai_after_move(libs[k], OTHER_COLOR(color), str, opponent, &resulta, NULL, NULL, 1, NULL, 0); if (resulta != WIN) { dragon2[d].semeai_attack_point = libs[k]; break; } } /* FIXME: What should we do if none of the tried attacks worked? */ if (k == liberties) dragon2[d].semeai_attack_point = defend_move; } DEBUG(DEBUG_SEMEAI, "Move to prevent seki at %1m (%1m vs %1m)\n", dragon2[d].semeai_attack_point, opponent, str); dragon2[d].semeai_attack_certain = certain; dragon2[d].semeai_attack_target = opponent; } } } }