static config_item *game_configure(game_params *params) { config_item *ret; char buf[80]; ret = snewn(3, config_item); ret[0].name = "Grid size"; ret[0].type = C_STRING; sprintf(buf, "%d", params->w); ret[0].sval = dupstr(buf); ret[0].ival = 0; ret[1].name = "Difficulty"; ret[1].type = C_CHOICES; ret[1].sval = DIFFCONFIG; ret[1].ival = params->diff; ret[2].name = NULL; ret[2].type = C_END; ret[2].sval = NULL; ret[2].ival = 0; return ret; }
static config_item *game_configure(const game_params *params) { config_item *ret; char buf[80]; ret = snewn(6, config_item); ret[0].name = _("Colours"); ret[0].type = C_STRING; sprintf(buf, "%d", params->ncolours); ret[0].u.string.sval = dupstr(buf); ret[1].name = _("Pegs per guess"); ret[1].type = C_STRING; sprintf(buf, "%d", params->npegs); ret[1].u.string.sval = dupstr(buf); ret[2].name = _("Guesses"); ret[2].type = C_STRING; sprintf(buf, "%d", params->nguesses); ret[2].u.string.sval = dupstr(buf); ret[3].name = _("Allow blanks"); ret[3].type = C_BOOLEAN; ret[3].u.boolean.bval = params->allow_blank; ret[4].name = _("Allow duplicates"); ret[4].type = C_BOOLEAN; ret[4].u.boolean.bval = params->allow_multiple; ret[5].name = NULL; ret[5].type = C_END; return ret; }
static config_item *game_configure(game_params *params) { config_item *ret; char buf[80]; ret = snewn(3, config_item); ret[0].name = "Maximum number on dominoes"; ret[0].type = C_STRING; sprintf(buf, "%d", params->n); ret[0].sval = dupstr(buf); ret[0].ival = 0; ret[1].name = "Ensure unique solution"; ret[1].type = C_BOOLEAN; ret[1].sval = NULL; ret[1].ival = params->unique; ret[2].name = NULL; ret[2].type = C_END; ret[2].sval = NULL; ret[2].ival = 0; return ret; }
static config_item *game_configure(const game_params *params) { config_item *ret = snewn(4, config_item); char buf[80]; ret[0].name = _("Width"); ret[0].type = C_STRING; sprintf(buf, "%d", params->w); ret[0].sval = dupstr(buf); ret[0].ival = 0; ret[1].name = _("Height"); ret[1].type = C_STRING; sprintf(buf, "%d", params->h); ret[1].sval = dupstr(buf); ret[1].ival = 0; ret[2].name = _("Board type"); ret[2].type = C_CHOICES; ret[2].sval = TYPECONFIG; ret[2].ival = params->type; ret[3].name = NULL; ret[3].type = C_END; ret[3].sval = NULL; ret[3].ival = 0; return ret; }
static config_item *game_configure(game_params *params) { config_item *ret; char buf[80]; ret = snewn(4, config_item); ret[0].name = _("Width"); ret[0].type = C_STRING; sprintf(buf, "%d", params->w); ret[0].sval = dupstr(buf); ret[0].ival = 0; ret[1].name = _("Height"); ret[1].type = C_STRING; sprintf(buf, "%d", params->h); ret[1].sval = dupstr(buf); ret[1].ival = 0; ret[2].name = _("No. of balls"); ret[2].type = C_STRING; if (params->minballs == params->maxballs) sprintf(buf, "%d", params->minballs); else sprintf(buf, "%d-%d", params->minballs, params->maxballs); ret[2].sval = dupstr(buf); ret[2].ival = 0; ret[3].name = NULL; ret[3].type = C_END; ret[3].sval = NULL; ret[3].ival = 0; return ret; }
static config_item *game_configure(game_params *params) { config_item *ret; char buf[80]; ret = snewn(3, config_item); ret[0].name = "Width"; ret[0].type = C_STRING; sprintf(buf, "%d", params->w); ret[0].sval = dupstr(buf); ret[0].ival = 0; ret[1].name = "Height"; ret[1].type = C_STRING; sprintf(buf, "%d", params->h); ret[1].sval = dupstr(buf); ret[1].ival = 0; ret[2].name = NULL; ret[2].type = C_END; ret[2].sval = NULL; ret[2].ival = 0; return ret; }
static config_item *game_configure(game_params *params) { config_item *ret; char buf[80]; ret = snewn(4, config_item); ret[0].name = _("Width"); ret[0].type = C_STRING; sprintf(buf, "%d", params->w); ret[0].sval = dupstr(buf); ret[0].ival = 0; ret[1].name = _("Height"); ret[1].type = C_STRING; sprintf(buf, "%d", params->h); ret[1].sval = dupstr(buf); ret[1].ival = 0; ret[2].name = _("Number of shuffling moves"); ret[2].type = C_STRING; sprintf(buf, "%d", params->movetarget); ret[2].sval = dupstr(buf); ret[2].ival = 0; ret[3].name = NULL; ret[3].type = C_END; ret[3].sval = NULL; ret[3].ival = 0; return ret; }
static config_item *game_configure(const game_params *params) { config_item *ret = snewn(4, config_item); char buf[80]; ret[0].name = _("Type of solid"); ret[0].type = C_CHOICES; ret[0].sval = _(":Tetrahedron:Cube:Octahedron:Icosahedron"); ret[0].ival = params->solid; ret[1].name = _("Width / top"); ret[1].type = C_STRING; sprintf(buf, "%d", params->d1); ret[1].sval = dupstr(buf); ret[1].ival = 0; ret[2].name = _("Height / bottom"); ret[2].type = C_STRING; sprintf(buf, "%d", params->d2); ret[2].sval = dupstr(buf); ret[2].ival = 0; ret[3].name = NULL; ret[3].type = C_END; ret[3].sval = NULL; ret[3].ival = 0; return ret; }
AuthKbdInt *auth_kbdint_prompts(AuthPolicy *ap, ptrlen username) { AuthKbdInt *aki = snew(AuthKbdInt); switch (ap->kbdint_state) { case 0: aki->title = dupstr("Initial double prompt"); aki->instruction = dupstr("First prompt should echo, second should not"); aki->nprompts = 2; aki->prompts = snewn(aki->nprompts, AuthKbdIntPrompt); aki->prompts[0].prompt = dupstr("Echoey prompt: "); aki->prompts[0].echo = true; aki->prompts[1].prompt = dupstr("Silent prompt: "); aki->prompts[1].echo = false; return aki; case 1: aki->title = dupstr("Zero-prompt step"); aki->instruction = dupstr("Shouldn't see any prompts this time"); aki->nprompts = 0; aki->prompts = NULL; return aki; default: ap->kbdint_state = 0; return NULL; } }
static char *solve_game(game_state *state, game_state *currstate, char *aux, char **error) { int w = state->par.w, a = w*w; int i, ret; digit *soln; char *out; if (aux) return dupstr(aux); soln = snewn(a, digit); memcpy(soln, state->clues->immutable, a); ret = solver(w, state->clues->clues, soln, DIFFCOUNT-1); if (ret == diff_impossible) { *error = "No solution exists for this puzzle"; out = NULL; } else if (ret == diff_ambiguous) { *error = "Multiple solutions exist for this puzzle"; out = NULL; } else { out = snewn(a+2, char); out[0] = 'S'; for (i = 0; i < a; i++) out[i+1] = '0' + soln[i]; out[a+1] = '\0'; } sfree(soln); return out; }
Bignum copybn(Bignum orig) { Bignum b = snewn(orig[0] + 1, BignumInt); if (!b) abort(); /* FIXME */ memcpy(b, orig, (orig[0] + 1) * sizeof(*b)); return b; }
hashmap *Hashmap() { hashmap *h = snew(hashmap); h->data = snewn(NUM_BUCKETS, hashmap_entry); memset(h->data, '\0', sizeof(h->data)); h->num_entries = 0; h->num_buckets = NUM_BUCKETS; return h; }
static Bignum newbn(int length) { Bignum b = snewn(length + 1, BignumInt); if (!b) abort(); /* FIXME */ memset(b, 0, (length + 1) * sizeof(*b)); b[0] = length; return b; }
termline *alloc_newline(const char* chars) { int cols = strlen(chars); termline *line; int j; line = snew(termline); line->chars = snewn(cols, termchar); for (j = 0; j < cols; j++) { line->chars[j].chr = chars[j]; line->chars[j].attr = '.'; } return line; }
static config_item *game_configure(game_params *params) { config_item *ret; char buf[80]; ret = snewn(7, config_item); ret[0].name = "Width"; ret[0].type = C_STRING; sprintf(buf, "%d", params->w); ret[0].sval = dupstr(buf); ret[0].ival = 0; ret[1].name = "Height"; ret[1].type = C_STRING; sprintf(buf, "%d", params->h); ret[1].sval = dupstr(buf); ret[1].ival = 0; ret[2].name = "Rotating block size"; ret[2].type = C_STRING; sprintf(buf, "%d", params->n); ret[2].sval = dupstr(buf); ret[2].ival = 0; ret[3].name = "One number per row"; ret[3].type = C_BOOLEAN; ret[3].sval = NULL; ret[3].ival = params->rowsonly; ret[4].name = "Orientation matters"; ret[4].type = C_BOOLEAN; ret[4].sval = NULL; ret[4].ival = params->orientable; ret[5].name = "Number of shuffling moves"; ret[5].type = C_STRING; sprintf(buf, "%d", params->movetarget); ret[5].sval = dupstr(buf); ret[5].ival = 0; ret[6].name = NULL; ret[6].type = C_END; ret[6].sval = NULL; ret[6].ival = 0; return ret; }
static config_item *game_configure(game_params *params) { config_item *ret; char buf[80]; ret = snewn(6, config_item); ret[0].name = "Width"; ret[0].type = C_STRING; sprintf(buf, "%d", params->w); ret[0].sval = dupstr(buf); ret[0].ival = 0; ret[1].name = "Height"; ret[1].type = C_STRING; sprintf(buf, "%d", params->h); ret[1].sval = dupstr(buf); ret[1].ival = 0; ret[2].name = "No. of colours"; ret[2].type = C_STRING; sprintf(buf, "%d", params->ncols); ret[2].sval = dupstr(buf); ret[2].ival = 0; ret[3].name = "Scoring system"; ret[3].type = C_CHOICES; ret[3].sval = ":(n-1)^2:(n-2)^2"; ret[3].ival = params->scoresub-1; ret[4].name = "Ensure solubility"; ret[4].type = C_BOOLEAN; ret[4].sval = NULL; ret[4].ival = params->soluble; ret[5].name = NULL; ret[5].type = C_END; ret[5].sval = NULL; ret[5].ival = 0; return ret; }
static game_state *dup_game(game_state *state) { int w = state->par.w, a = w*w; game_state *ret = snew(game_state); ret->par = state->par; /* structure copy */ ret->clues = state->clues; ret->clues->refcount++; ret->grid = snewn(a, digit); ret->pencil = snewn(a, int); memcpy(ret->grid, state->grid, a*sizeof(digit)); memcpy(ret->pencil, state->pencil, a*sizeof(int)); ret->completed = state->completed; ret->cheated = state->cheated; return ret; }
static void *dss_newkey(char *data, int len) { char *p; int slen; dss_key *dss; dss = snewn(1,dss_key); getstring(&data, &len, &p, &slen); #ifdef DEBUG_DSS { int i; printf("key:"); for (i = 0; i < len; i++) printf(" %02x", (unsigned char) (data[i])); printf("\n"); } #endif if (!p || slen != 7 || memcmp(p, "ssh-dss", 7)) { sfree(dss); return NULL; } dss->p = getmp(&data, &len); dss->q = getmp(&data, &len); dss->g = getmp(&data, &len); dss->y = getmp(&data, &len); dss->x = NULL; if (!dss->p || !dss->q || !dss->g || !dss->y || !bignum_cmp(dss->q, Zero) || !bignum_cmp(dss->p, Zero)) { /* Invalid key. */ dss_freekey(dss); return NULL; } return dss; }
static void *dss_openssh_createkey(unsigned char **blob, int *len) { char **b = (char **) blob; dss_key *dss; dss = snewn(1,dss_key); dss->p = getmp(b, len); dss->q = getmp(b, len); dss->g = getmp(b, len); dss->y = getmp(b, len); dss->x = getmp(b, len); if (!dss->p || !dss->q || !dss->g || !dss->y || !dss->x || !bignum_cmp(dss->q, Zero) || !bignum_cmp(dss->p, Zero)) { /* Invalid key. */ dss_freekey(dss); return NULL; } return dss; }
static config_item *game_configure(const game_params *params) { config_item *ret; char buf[80]; ret = snewn(5, config_item); ret[0].name = "Width"; ret[0].type = C_STRING; sprintf(buf, "%d", params->w); ret[0].sval = dupstr(buf); ret[0].ival = 0; ret[1].name = "Height"; ret[1].type = C_STRING; sprintf(buf, "%d", params->h); ret[1].sval = dupstr(buf); ret[1].ival = 0; ret[2].name = "Colours"; ret[2].type = C_STRING; sprintf(buf, "%d", params->colours); ret[2].sval = dupstr(buf); ret[2].ival = 0; ret[3].name = "Extra moves permitted"; ret[3].type = C_STRING; sprintf(buf, "%d", params->leniency); ret[3].sval = dupstr(buf); ret[3].ival = 0; ret[4].name = NULL; ret[4].type = C_END; ret[4].sval = NULL; ret[4].ival = 0; return ret; }
static LRESULT CALLBACK SizeTipWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam) { switch (nMsg) { case WM_ERASEBKGND: return TRUE; case WM_PAINT: { HBRUSH hbr; HGDIOBJ holdbr; RECT cr; int wtlen; LPTSTR wt; HDC hdc; PAINTSTRUCT ps; hdc = BeginPaint(hWnd, &ps); SelectObject(hdc, tip_font); SelectObject(hdc, GetStockObject(BLACK_PEN)); hbr = CreateSolidBrush(tip_bg); holdbr = SelectObject(hdc, hbr); GetClientRect(hWnd, &cr); Rectangle(hdc, cr.left, cr.top, cr.right, cr.bottom); wtlen = GetWindowTextLength(hWnd); wt = (LPTSTR) snewn(wtlen + 1, TCHAR); GetWindowText(hWnd, wt, wtlen + 1); SetTextColor(hdc, tip_text); SetBkColor(hdc, tip_bg); TextOut(hdc, cr.left + 3, cr.top + 3, wt, wtlen); sfree(wt); SelectObject(hdc, holdbr); DeleteObject(hbr); EndPaint(hWnd, &ps); } return 0; case WM_NCHITTEST: return HTTRANSPARENT; case WM_DESTROY: DeleteObject(tip_font); tip_font = NULL; break; case WM_SETTEXT: { LPCTSTR str = (LPCTSTR) lParam; SIZE sz; HDC hdc = CreateCompatibleDC(NULL); SelectObject(hdc, tip_font); GetTextExtentPoint32(hdc, str, (int)_tcslen(str), &sz); SetWindowPos(hWnd, NULL, 0, 0, sz.cx + 6, sz.cy + 6, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE); InvalidateRect(hWnd, NULL, FALSE); DeleteDC(hdc); } break; } return DefWindowProc(hWnd, nMsg, wParam, lParam); }
int do_eventsel_loop(HANDLE other_event) { int n, nhandles, nallhandles, netindex, otherindex; long next, ticks; HANDLE *handles; SOCKET *sklist; int skcount; long now = GETTICKCOUNT(); static int timeoutCount = 0; if (sk_isClosed()) { return -1; } if (run_timers(now, &next)) { ticks = next - GETTICKCOUNT(); if (ticks < 0) ticks = 0; /* just in case */ } else { ticks = INFINITE; } if (ticks < 0 || ticks > 100) ticks = 100; handles = handle_get_events(&nhandles); handles = sresize(handles, nhandles+2, HANDLE); nallhandles = nhandles; if (netevent != INVALID_HANDLE_VALUE) handles[netindex = nallhandles++] = netevent; else netindex = -1; if (other_event != INVALID_HANDLE_VALUE) handles[otherindex = nallhandles++] = other_event; else otherindex = -1; n = WaitForMultipleObjects(nallhandles, handles, FALSE, ticks); if (STATUS_TIMEOUT == n) { sfree(handles); ++timeoutCount; return timeoutCount > 50 ? -1 : 0; } timeoutCount = 0; if ((unsigned)(n - WAIT_OBJECT_0) < (unsigned)nhandles) { handle_got_event(handles[n - WAIT_OBJECT_0]); } else if (netindex >= 0 && n == WAIT_OBJECT_0 + netindex) { WSANETWORKEVENTS things; SOCKET socket; extern SOCKET first_socket(int *), next_socket(int *); extern int select_result(WPARAM, LPARAM); int i, socketstate; /* * We must not call select_result() for any socket * until we have finished enumerating within the * tree. This is because select_result() may close * the socket and modify the tree. */ /* Count the active sockets. */ i = 0; for (socket = first_socket(&socketstate); socket != INVALID_SOCKET; socket = next_socket(&socketstate)) i++; /* Expand the buffer if necessary. */ sklist = snewn(i, SOCKET); /* Retrieve the sockets into sklist. */ skcount = 0; for (socket = first_socket(&socketstate); socket != INVALID_SOCKET; socket = next_socket(&socketstate)) { sklist[skcount++] = socket; } /* Now we're done enumerating; go through the list. */ for (i = 0; i < skcount; i++) { WPARAM wp; socket = sklist[i]; wp = (WPARAM) socket; if (!p_WSAEnumNetworkEvents(socket, NULL, &things)) { static const struct { int bit, mask; } eventtypes[] = { {FD_CONNECT_BIT, FD_CONNECT}, {FD_READ_BIT, FD_READ}, {FD_CLOSE_BIT, FD_CLOSE}, {FD_OOB_BIT, FD_OOB}, {FD_WRITE_BIT, FD_WRITE}, {FD_ACCEPT_BIT, FD_ACCEPT}, }; int e; noise_ultralight(socket); noise_ultralight(things.lNetworkEvents); for (e = 0; e < lenof(eventtypes); e++) if (things.lNetworkEvents & eventtypes[e].mask) { LPARAM lp; int err = things.iErrorCode[eventtypes[e].bit]; lp = WSAMAKESELECTREPLY(eventtypes[e].mask, err); select_result(wp, lp); } } } sfree(sklist); } sfree(handles); if (n == WAIT_TIMEOUT) { now = next; } else { now = GETTICKCOUNT(); } if (otherindex >= 0 && n == WAIT_OBJECT_0 + otherindex) return 1; return 0; }
static textconfig text_configure(paragraph *source) { textconfig ret; paragraph *p; int n; /* * Non-negotiables. */ ret.bullet.next = NULL; ret.bullet.alt = NULL; ret.bullet.type = word_Normal; ret.atitle.just_numbers = FALSE; /* ignored */ ret.atitle.number_at_all = TRUE; /* ignored */ /* * Defaults. */ ret.indent = 7; ret.indent_code = 2; ret.listindentbefore = 1; ret.listindentafter = 3; ret.width = 68; ret.atitle.align = CENTRE; ret.atitle.underline = L"\x2550\0=\0\0"; ret.achapter.align = LEFT; ret.achapter.just_numbers = FALSE; ret.achapter.number_at_all = TRUE; ret.achapter.number_suffix = L": "; ret.achapter.underline = L"\x203E\0-\0\0"; ret.nasect = 1; ret.asect = snewn(ret.nasect, alignstruct); ret.asect[0].align = LEFTPLUS; ret.asect[0].just_numbers = TRUE; ret.asect[0].number_at_all = TRUE; ret.asect[0].number_suffix = L" "; ret.asect[0].underline = L"\0"; ret.include_version_id = TRUE; ret.indent_preambles = FALSE; ret.bullet.text = L"\x2022\0-\0\0"; ret.rule = L"\x2500\0-\0\0"; ret.filename = dupstr("output.txt"); ret.startemph = L"_\0_\0\0"; ret.endemph = uadv(ret.startemph); ret.startstrong = L"*\0*\0\0"; ret.endstrong = uadv(ret.startstrong); ret.listsuffix = L"."; ret.charset = CS_ASCII; /* * Default quote characters are Unicode matched single quotes, * falling back to the TeXlike `'. */ ret.lquote = L"\x2018\0\x2019\0`\0'\0\0"; ret.rquote = uadv(ret.lquote); /* * Two-pass configuration so that we can pick up global config * (e.g. `quotes') before having it overridden by specific * config (`text-quotes'), irrespective of the order in which * they occur. */ for (p = source; p; p = p->next) { if (p->type == para_Config) { if (!ustricmp(p->keyword, L"quotes")) { if (*uadv(p->keyword) && *uadv(uadv(p->keyword))) { ret.lquote = uadv(p->keyword); ret.rquote = uadv(ret.lquote); } } } } for (p = source; p; p = p->next) { if (p->type == para_Config) { if (!ustricmp(p->keyword, L"text-indent")) { ret.indent = utoi(uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"text-charset")) { ret.charset = charset_from_ustr(&p->fpos, uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"text-filename")) { sfree(ret.filename); ret.filename = dupstr(adv(p->origkeyword)); } else if (!ustricmp(p->keyword, L"text-indent-code")) { ret.indent_code = utoi(uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"text-width")) { ret.width = utoi(uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"text-list-indent")) { ret.listindentbefore = utoi(uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"text-listitem-indent")) { ret.listindentafter = utoi(uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"text-chapter-align")) { ret.achapter.align = utoalign(uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"text-chapter-underline")) { ret.achapter.underline = uadv(p->keyword); } else if (!ustricmp(p->keyword, L"text-chapter-numeric")) { ret.achapter.just_numbers = utob(uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"text-chapter-shownumber")) { ret.achapter.number_at_all = utob(uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"text-chapter-suffix")) { ret.achapter.number_suffix = uadv(p->keyword); } else if (!ustricmp(p->keyword, L"text-section-align")) { wchar_t *q = uadv(p->keyword); int n = 0; if (uisdigit(*q)) { n = utoi(q); q = uadv(q); } if (n >= ret.nasect) { int i; ret.asect = sresize(ret.asect, n+1, alignstruct); for (i = ret.nasect; i <= n; i++) ret.asect[i] = ret.asect[ret.nasect-1]; ret.nasect = n+1; } ret.asect[n].align = utoalign(q); } else if (!ustricmp(p->keyword, L"text-section-underline")) { wchar_t *q = uadv(p->keyword); int n = 0; if (uisdigit(*q)) { n = utoi(q); q = uadv(q); } if (n >= ret.nasect) { int i; ret.asect = sresize(ret.asect, n+1, alignstruct); for (i = ret.nasect; i <= n; i++) ret.asect[i] = ret.asect[ret.nasect-1]; ret.nasect = n+1; } ret.asect[n].underline = q; } else if (!ustricmp(p->keyword, L"text-section-numeric")) { wchar_t *q = uadv(p->keyword); int n = 0; if (uisdigit(*q)) { n = utoi(q); q = uadv(q); } if (n >= ret.nasect) { int i; ret.asect = sresize(ret.asect, n+1, alignstruct); for (i = ret.nasect; i <= n; i++) ret.asect[i] = ret.asect[ret.nasect-1]; ret.nasect = n+1; } ret.asect[n].just_numbers = utob(q); } else if (!ustricmp(p->keyword, L"text-section-shownumber")) { wchar_t *q = uadv(p->keyword); int n = 0; if (uisdigit(*q)) { n = utoi(q); q = uadv(q); } if (n >= ret.nasect) { int i; ret.asect = sresize(ret.asect, n+1, alignstruct); for (i = ret.nasect; i <= n; i++) ret.asect[i] = ret.asect[ret.nasect-1]; ret.nasect = n+1; } ret.asect[n].number_at_all = utob(q); } else if (!ustricmp(p->keyword, L"text-section-suffix")) { wchar_t *q = uadv(p->keyword); int n = 0; if (uisdigit(*q)) { n = utoi(q); q = uadv(q); } if (n >= ret.nasect) { int i; ret.asect = sresize(ret.asect, n+1, alignstruct); for (i = ret.nasect; i <= n; i++) { ret.asect[i] = ret.asect[ret.nasect-1]; } ret.nasect = n+1; } ret.asect[n].number_suffix = q; } else if (!ustricmp(p->keyword, L"text-title-align")) { ret.atitle.align = utoalign(uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"text-title-underline")) { ret.atitle.underline = uadv(p->keyword); } else if (!ustricmp(p->keyword, L"text-versionid")) { ret.include_version_id = utob(uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"text-indent-preamble")) { ret.indent_preambles = utob(uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"text-bullet")) { ret.bullet.text = uadv(p->keyword); } else if (!ustricmp(p->keyword, L"text-rule")) { ret.rule = uadv(p->keyword); } else if (!ustricmp(p->keyword, L"text-list-suffix")) { ret.listsuffix = uadv(p->keyword); } else if (!ustricmp(p->keyword, L"text-emphasis")) { if (*uadv(p->keyword) && *uadv(uadv(p->keyword))) { ret.startemph = uadv(p->keyword); ret.endemph = uadv(ret.startemph); } } else if (!ustricmp(p->keyword, L"text-strong")) { if (*uadv(p->keyword) && *uadv(uadv(p->keyword))) { ret.startstrong = uadv(p->keyword); ret.endstrong = uadv(ret.startstrong); } } else if (!ustricmp(p->keyword, L"text-quotes")) { if (*uadv(p->keyword) && *uadv(uadv(p->keyword))) { ret.lquote = uadv(p->keyword); ret.rquote = uadv(ret.lquote); } } } } /* * Now process fallbacks on quote characters, underlines, the * rule character, the emphasis characters, and bullets. */ while (*uadv(ret.rquote) && *uadv(uadv(ret.rquote)) && (!cvt_ok(ret.charset, ret.lquote) || !cvt_ok(ret.charset, ret.rquote))) { ret.lquote = uadv(ret.rquote); ret.rquote = uadv(ret.lquote); } while (*uadv(ret.endemph) && *uadv(uadv(ret.endemph)) && (!cvt_ok(ret.charset, ret.startemph) || !cvt_ok(ret.charset, ret.endemph))) { ret.startemph = uadv(ret.endemph); ret.endemph = uadv(ret.startemph); } while (*uadv(ret.endstrong) && *uadv(uadv(ret.endstrong)) && (!cvt_ok(ret.charset, ret.startstrong) || !cvt_ok(ret.charset, ret.endstrong))) { ret.startstrong = uadv(ret.endstrong); ret.endstrong = uadv(ret.startstrong); } while (*ret.atitle.underline && *uadv(ret.atitle.underline) && !cvt_ok(ret.charset, ret.atitle.underline)) ret.atitle.underline = uadv(ret.atitle.underline); while (*ret.achapter.underline && *uadv(ret.achapter.underline) && !cvt_ok(ret.charset, ret.achapter.underline)) ret.achapter.underline = uadv(ret.achapter.underline); for (n = 0; n < ret.nasect; n++) { while (*ret.asect[n].underline && *uadv(ret.asect[n].underline) && !cvt_ok(ret.charset, ret.asect[n].underline)) ret.asect[n].underline = uadv(ret.asect[n].underline); } while (*ret.bullet.text && *uadv(ret.bullet.text) && !cvt_ok(ret.charset, ret.bullet.text)) ret.bullet.text = uadv(ret.bullet.text); while (*ret.rule && *uadv(ret.rule) && !cvt_ok(ret.charset, ret.rule)) ret.rule = uadv(ret.rule); return ret; }
static void *blowfish_ssh1_make_context(void) { /* In SSH-1, need one key for each direction */ return snewn(2, BlowfishContext); }
/* * Returns: * 0 for 'didn't do anything' implying it was already solved. * -1 for 'impossible' (no solution) * 1 for 'single solution' * >1 for 'multiple solutions' (you don't get to know how many, and * the first such solution found will be set. * * and this function may well assert if given an impossible board. */ static int latin_solver_recurse (struct latin_solver *solver, int diff_simple, int diff_set_0, int diff_set_1, int diff_forcing, int diff_recursive, usersolver_t const *usersolvers, void *ctx, ctxnew_t ctxnew, ctxfree_t ctxfree) { int best, bestcount; int o = solver->o, x, y, n; #ifdef STANDALONE_SOLVER char **names = solver->names; #endif best = -1; bestcount = o+1; for (y = 0; y < o; y++) for (x = 0; x < o; x++) if (!solver->grid[y*o+x]) { int count; /* * An unfilled square. Count the number of * possible digits in it. */ count = 0; for (n = 1; n <= o; n++) if (cube(x,y,n)) count++; /* * We should have found any impossibilities * already, so this can safely be an assert. */ assert(count > 1); if (count < bestcount) { bestcount = count; best = y*o+x; } } if (best == -1) /* we were complete already. */ return 0; else { int i, j; digit *list, *ingrid, *outgrid; int diff = diff_impossible; /* no solution found yet */ /* * Attempt recursion. */ y = best / o; x = best % o; list = snewn(o, digit); ingrid = snewn(o*o, digit); outgrid = snewn(o*o, digit); memcpy(ingrid, solver->grid, o*o); /* Make a list of the possible digits. */ for (j = 0, n = 1; n <= o; n++) if (cube(x,y,n)) list[j++] = n; #ifdef STANDALONE_SOLVER if (solver_show_working) { char *sep = ""; printf("%*srecursing on (%d,%d) [", solver_recurse_depth*4, "", x+1, y+1); for (i = 0; i < j; i++) { printf("%s%s", sep, names[list[i]-1]); sep = " or "; } printf("]\n"); } #endif /* * And step along the list, recursing back into the * main solver at every stage. */ for (i = 0; i < j; i++) { int ret; void *newctx; struct latin_solver subsolver; memcpy(outgrid, ingrid, o*o); outgrid[y*o+x] = list[i]; #ifdef STANDALONE_SOLVER if (solver_show_working) printf("%*sguessing %s at (%d,%d)\n", solver_recurse_depth*4, "", names[list[i]-1], x+1, y+1); solver_recurse_depth++; #endif if (ctxnew) { newctx = ctxnew(ctx); } else { newctx = ctx; } latin_solver_alloc(&subsolver, outgrid, o); #ifdef STANDALONE_SOLVER subsolver.names = solver->names; #endif ret = latin_solver_top(&subsolver, diff_recursive, diff_simple, diff_set_0, diff_set_1, diff_forcing, diff_recursive, usersolvers, newctx, ctxnew, ctxfree); latin_solver_free(&subsolver); if (ctxnew) ctxfree(newctx); #ifdef STANDALONE_SOLVER solver_recurse_depth--; if (solver_show_working) { printf("%*sretracting %s at (%d,%d)\n", solver_recurse_depth*4, "", names[list[i]-1], x+1, y+1); } #endif /* we recurse as deep as we can, so we should never find * find ourselves giving up on a puzzle without declaring it * impossible. */ assert(ret != diff_unfinished); /* * If we have our first solution, copy it into the * grid we will return. */ if (diff == diff_impossible && ret != diff_impossible) memcpy(solver->grid, outgrid, o*o); if (ret == diff_ambiguous) diff = diff_ambiguous; else if (ret == diff_impossible) /* do not change our return value */; else { /* the recursion turned up exactly one solution */ if (diff == diff_impossible) diff = diff_recursive; else diff = diff_ambiguous; } /* * As soon as we've found more than one solution, * give up immediately. */ if (diff == diff_ambiguous) break; } sfree(outgrid); sfree(ingrid); sfree(list); if (diff == diff_impossible) return -1; else if (diff == diff_ambiguous) return 2; else { assert(diff == diff_recursive); return 1; } } }
static char *new_game_desc(game_params *params, random_state *rs, char **aux, int interactive) { int w = params->w, a = w*w; digit *grid, *soln, *soln2; int *clues, *order; int i, ret; int diff = params->diff; char *desc, *p; /* * Difficulty exceptions: some combinations of size and * difficulty cannot be satisfied, because all puzzles of at * most that difficulty are actually even easier. * * Remember to re-test this whenever a change is made to the * solver logic! * * I tested it using the following shell command: for d in e h x u; do for i in {3..9}; do echo -n "./towers --generate 1 ${i}d${d}: " perl -e 'alarm 30; exec @ARGV' ./towers --generate 1 ${i}d${d} >/dev/null \ && echo ok done done * Of course, it's better to do that after taking the exceptions * _out_, so as to detect exceptions that should be removed as * well as those which should be added. */ if (diff > DIFF_HARD && w <= 3) diff = DIFF_HARD; grid = NULL; clues = snewn(4*w, int); soln = snewn(a, digit); soln2 = snewn(a, digit); order = snewn(max(4*w,a), int); while (1) { /* * Construct a latin square to be the solution. */ sfree(grid); grid = latin_generate(w, rs); /* * Fill in the clues. */ for (i = 0; i < 4*w; i++) { int start, step, j, k, best; STARTSTEP(start, step, i, w); k = best = 0; for (j = 0; j < w; j++) { if (grid[start+j*step] > best) { best = grid[start+j*step]; k++; } } clues[i] = k; } /* * Remove the grid numbers and then the clues, one by one, * for as long as the game remains soluble at the given * difficulty. */ memcpy(soln, grid, a); if (diff == DIFF_EASY && w <= 5) { /* * Special case: for Easy-mode grids that are small * enough, it's nice to be able to find completely empty * grids. */ memset(soln2, 0, a); ret = solver(w, clues, soln2, diff); if (ret > diff) continue; } for (i = 0; i < a; i++) order[i] = i; shuffle(order, a, sizeof(*order), rs); for (i = 0; i < a; i++) { int j = order[i]; memcpy(soln2, grid, a); soln2[j] = 0; ret = solver(w, clues, soln2, diff); if (ret <= diff) grid[j] = 0; } if (diff > DIFF_EASY) { /* leave all clues on Easy mode */ for (i = 0; i < 4*w; i++) order[i] = i; shuffle(order, 4*w, sizeof(*order), rs); for (i = 0; i < 4*w; i++) { int j = order[i]; int clue = clues[j]; memcpy(soln2, grid, a); clues[j] = 0; ret = solver(w, clues, soln2, diff); if (ret > diff) clues[j] = clue; } } /* * See if the game can be solved at the specified difficulty * level, but not at the one below. */ memcpy(soln2, grid, a); ret = solver(w, clues, soln2, diff); if (ret != diff) continue; /* go round again */ /* * We've got a usable puzzle! */ break; } /* * Encode the puzzle description. */ desc = snewn(40*a, char); p = desc; for (i = 0; i < 4*w; i++) { p += sprintf(p, "%s%.0d", i?"/":"", clues[i]); } for (i = 0; i < a; i++) if (grid[i]) break; if (i < a) { int run = 0; *p++ = ','; for (i = 0; i <= a; i++) { int n = (i < a ? grid[i] : -1); if (!n) run++; else { if (run) { while (run > 0) { int thisrun = min(run, 26); *p++ = thisrun - 1 + 'a'; run -= thisrun; } } else { /* * If there's a number in the very top left or * bottom right, there's no point putting an * unnecessary _ before or after it. */ if (i > 0 && n > 0) *p++ = '_'; } if (n > 0) p += sprintf(p, "%d", n); run = 0; } } } *p++ = '\0'; desc = sresize(desc, p - desc, char); /* * Encode the solution. */ *aux = snewn(a+2, char); (*aux)[0] = 'S'; for (i = 0; i < a; i++) (*aux)[i+1] = '0' + soln[i]; (*aux)[a+1] = '\0'; sfree(grid); sfree(clues); sfree(soln); sfree(soln2); sfree(order); return desc; }
static game_state *new_game(midend *me, game_params *params, char *desc) { int w = params->w, a = w*w; game_state *state = snew(game_state); const char *p = desc; int i; state->par = *params; /* structure copy */ state->clues = snew(struct clues); state->clues->refcount = 1; state->clues->w = w; state->clues->clues = snewn(4*w, int); state->clues->immutable = snewn(a, digit); state->grid = snewn(a, digit); state->pencil = snewn(a, int); for (i = 0; i < a; i++) { state->grid[i] = 0; state->pencil[i] = 0; } memset(state->clues->immutable, 0, a); for (i = 0; i < 4*w; i++) { if (i > 0) { assert(*p == '/'); p++; } if (*p && isdigit((unsigned char)*p)) { state->clues->clues[i] = atoi(p); while (*p && isdigit((unsigned char)*p)) p++; } else state->clues->clues[i] = 0; } if (*p == ',') { int pos = 0; p++; while (*p) { int c = *p++; if (c >= 'a' && c <= 'z') { pos += c - 'a' + 1; } else if (c == '_') { /* do nothing */; } else if (c > '0' && c <= '9') { int val = atoi(p-1); assert(val >= 1 && val <= w); assert(pos < a); state->grid[pos] = state->clues->immutable[pos] = val; pos++; while (*p && isdigit((unsigned char)*p)) p++; } else assert(!"Corrupt game description"); } assert(pos == a); } assert(!*p); state->completed = state->cheated = FALSE; return state; }