/* Undo the last n moves. */ int undomoves(int n) { if (!state.undo.count) return FALSE; while (n-- && undomove()) ; return TRUE; }
void cmd_undo(char *s) { computer[0] = 0; computer[1] = 0; if (ply) undomove(); }
/* Get a keystroke from the user (or from a macro) and perform the * indicated command. A non-zero return value indicates a request to * change the current puzzle, the actual value being a delta. */ static int doturn(void) { switch (input()) { case ARROW_N: if (!movecursor(NORTH)) ding(); break; case ARROW_E: if (!movecursor(EAST)) ding(); break; case ARROW_S: if (!movecursor(SOUTH)) ding(); break; case ARROW_W: if (!movecursor(WEST)) ding(); break; case 'k': if (!shiftfromcurrblock(NORTH)) ding(); break; case 'l': if (!shiftfromcurrblock(EAST)) ding(); break; case 'j': if (!shiftfromcurrblock(SOUTH)) ding(); break; case 'h': if (!shiftfromcurrblock(WEST)) ding(); break; case 'K': if (!newmove(NORTH)) ding(); break; case 'L': if (!newmove(EAST)) ding(); break; case 'J': if (!newmove(SOUTH)) ding(); break; case 'H': if (!newmove(WEST)) ding(); break; case 'x': if (!undomove()) ding(); break; case 'z': if (!redomove()) ding(); break; case 'X': if (!undostep()) ding(); break; case 'Z': if (!redostep()) ding(); break; case 'R': initgamestate(); break; case 's': savestate(); break; case 'r': if (!restorestate()) ding(); break; case 'S': if (!partialsave()) ding(); break; case 'g': drawgoalscreen(); break; case '?': drawhelpscreen(); break; case '\f': break; case 'P': return -1; case 'N': return +1; case 'q': exit(0); case 'Q': exit(0); } return 0; }
/* Check a move for validity in the current state. If it is valid, it * is applied via domove(), otherwise return FALSE. If the move is * equivalent to an undo or a redo, then use that instead; otherwise, * the redo list is reset. */ int newmove(yx delta) { dyx move; int b; yx j; j = state.player + delta; if (state.map[j] & WALL) return FALSE; if (state.undo.count) { move = state.undo.list[state.undo.count - 1]; if (!move.box && move.yx == -delta) return undomove(); } b = state.map[j] & BOX ? TRUE : FALSE; if (b && state.map[j + delta] & (BOX | WALL)) return FALSE; if (state.redo.count) { move = state.redo.list[state.redo.count - 1]; if (move.box == b && move.yx == delta) return redomove(); } move.yx = delta; move.box = b; domove(move); state.redo.count = 0; return TRUE; }
int ab(int lvl, int mark, int lb, int d) { int di, pos, ans, dir, s; s = score(&hist[hno], mark) - lvl; if (lvl <= 0) return s; if (s <= -WINL || s >= WINL) return s; ans = lb; for (di = 0; di < 4; di++) { dir = dirs[di]; for (pos = 0; pos < bsize; pos++) { domove(dir, pos, mark); s = -ab(lvl-1, OTHER(mark), -d, -ans); if (s > ans) ans = s; undomove(); if (ans >= d) goto end; } } end: return ans; }
void computemove(char *dirp, int *posp, int mark) { int pos, di, high, lvl, s, i, j, bdir = 0, bpos = 0; int dir; struct move *mp, *np, *tmp; mp = moves; for (di = 0; di < 4; di++) { dir = dirs[di]; for (pos = 0; pos < bsize; pos++) { mp->dir = dir; mp->pos = pos; mp++; } } mp = moves; np = nmoves; for (lvl = 3; lvl < MAXLVL; lvl++) { high = -INF; for (i = 0; i < bsize4; i++) { domove(mp[i].dir, mp[i].pos, mark); s = -ab(lvl, OTHER(mark), -INF, -high); if (s > high) { high = s; bdir = mp[i].dir; bpos = mp[i].pos; if (WINNER(high)) { goto done; } } undomove(); /* sort the move into np */ for (j = i; j > 0; j--) { if (np[j-1].score >= s) break; np[j] = np[j-1]; } np[j].dir = mp[i].dir; np[j].pos = mp[i].pos; np[j].score = s; } *dirp = bdir; *posp = bpos; DPRINTF(("lvl=%d nscore=%d, high=%d\n", lvl, nscore, high)); nscore = 0; tmp = mp; mp = np; np = tmp; } done: *dirp = bdir; *posp = bpos; DPRINTF(("high=%d\n", high)); }
void showmoves(c) { move_and_score *restore_sp = move_sp; genmoves(c); while (move_sp>restore_sp) { move m; m = popmove(); domove(m); printboard(); undomove(); } }
/* Check a move for validity in the current state. If it is valid, it * is applied via domove(), otherwise return FALSE. If the move is * equivalent to an undo or a redo, then use that instead; otherwise, * the redo list is reset. */ int newmove(int dir) { action move; if (!state.currblock || !canmove(state.currblock, dir)) return FALSE; if (state.undo.count) { move = state.undo.list[state.undo.count - 1]; if (move.id == state.currblock && move.dir == backwards(dir) && !move.door) return undomove(); } if (state.redo.count) { move = state.redo.list[state.redo.count - 1]; if (move.id == state.currblock && move.dir == dir) return redomove(); } domove(makeaction(state.currblock, dir)); state.redo.count = 0; return TRUE; }
short play() { short c; short ret; short undolock = 1; /* locked for undo */ showscreen(); tmpsave(); ret = 0; while( ret == 0) { switch( (c = getch())) { case 'q': /* quit the game */ ret = E_ENDGAME; break; case 's': /* save the games */ if( (ret = savegame()) == 0) ret = E_SAVED; break; case '?': /* show the help file */ showhelp(); showscreen(); break; case CNTL_R: /* refresh the screen */ clear(); showscreen(); break; case 'c': /* temporary save */ tmpsave(); break; case CNTL_U: /* reset to temporary save */ tmpreset(); undolock = 1; showscreen(); break; case 'U': /* undo this level */ moves = pushes = 0; if( (ret = readscreen()) == 0) { showscreen(); undolock = 1; } break; case 'u': /* undo last move */ if( ! undolock) { undomove(); undolock = 1; } break; case 'k': /* up */ case 'K': /* run up */ case CNTL_K: /* run up, stop before object */ case 'j': /* down */ case 'J': /* run down */ case CNTL_J: /* run down, stop before object */ case 'l': /* right */ case 'L': /* run right */ case CNTL_L: /* run right, stop before object */ case 'h': /* left */ case 'H': /* run left */ case CNTL_H: /* run left, stop before object */ do { if( (action = testmove( c)) != 0) { lastaction = action; lastppos.x = ppos.x; lastppos.y = ppos.y; lppc = map[ppos.x][ppos.y]; lasttpos1.x = tpos1.x; lasttpos1.y = tpos1.y; ltp1c = map[tpos1.x][tpos1.y]; lasttpos2.x = tpos2.x; lasttpos2.y = tpos2.y; ltp2c = map[tpos2.x][tpos2.y]; domove( lastaction); undolock = 0; } } while( (action != 0) && (! islower( c)) && (packets != savepack)); break; default: helpmessage(); break; } if( (ret == 0) && (packets == savepack)) { scorelevel = level; scoremoves = moves; scorepushes = pushes; break; } } return( ret); }
void save_leaf(move *pv, int n, int value, int hashed) { #ifndef LEARNING return; #else int s_ply = ply; int searched_value = -1; int stored_board_value = -1; if (tomove() != WHITE) value = -value; stored.search_results[stored.index] = value; /* first check our stored position */ if (stored.boards[stored.index]->piececount[0]>0) { chessboard *temp_board = board; board = stored.boards[stored.index]; countmaterial(); stored_board_value = eval_for_white(); board = temp_board; countmaterial(); if (((stored_board_value > (value - EVAL_INTERVAL)) && (stored_board_value < (value + EVAL_INTERVAL))) || (value > WIN - 50) || (value < LOSE + 50)) { stored.usable[stored.index] = 1; stored.actual[stored.index] = stored_board_value; printf("STORING: qsearch board = %d\n", stored_board_value); } } /* then check to see if our value is the same as our last search */ if (!stored.usable[stored.index]) { if ((stored.search_results[stored.index] == stored.search_results[stored.index-1])) { memcpy(stored.boards[stored.index], stored.boards[stored.index-1], sizeof(chessboard)); stored.usable[stored.index] = 1; stored.actual[stored.index] = stored.actual[stored.index]-1; printf("STORING: previous board = %d\n", stored.search_results[stored.index-1]); } } /* lastly check to see if our pv leads to a correct board eval */ if (!stored.usable[stored.index]) { int i; printf("pv: "); for (i=0;i<n;i++) { if (pv[i] == dummymove) break; domove(pv[i]); printf("%s ", movestring(pv[i])); } printf("\n"); searched_value = eval_for_white(); if ((searched_value > value - EVAL_INTERVAL)&& (searched_value < value + EVAL_INTERVAL)) { memcpy(stored.boards[stored.index], board, sizeof(chessboard)); stored.usable[stored.index] = 1; stored.actual[stored.index] = searched_value; printf("STORING: pv board = %d\n", searched_value); } else { printf("!usable: stored_position %d, " "searched %d, previous %d, stored %d\n", stored_board_value, searched_value, stored.search_results[stored.index-1], value); } while (ply>s_ply) undomove(); } #endif }
int play() { short c; short ret; short testmove(); short undolock = 1; /* locked for undo */ #if ATARIST /* Mess up keyboard to make cursor keys work */ KEY_TABLES *kbt; KEY_TABLES old_kbt; int i; kbt = Keytbl(-1, -1, -1); old_kbt = *kbt; for (i = 0; i < 128; i++) { unshifted[i] = kbt->unshifted[i]; shifted[i] = kbt->shifted[i]; } unshifted[0x48] = 'k'; /* Up */ unshifted[0x50] = 'j'; /* Down */ unshifted[0x4b] = 'h'; /* Left */ unshifted[0x4d] = 'l'; /* Right */ unshifted[0x61] = 'u'; /* Undo */ unshifted[0x62] = '?'; /* Help */ shifted[0x48] = '\013'; /* Up ^K */ shifted[0x50] = '\012'; /* Down ^J */ shifted[0x4b] = '\010'; /* Left ^H */ shifted[0x4d] = '\014'; /* Right ^L */ shifted[0x61] = 'q'; /* Undo */ Keytbl(unshifted, shifted, -1); #endif showscreen(); tmpsave(); ret = 0; while( ret == 0) { switch( (c = get_char())) { case 'q': /* quit the game */ ret = E_ENDGAME; break; case 's': /* save the games */ if( (ret = savegame()) == 0) ret = E_SAVED; break; case '?': /* show the help file */ showhelp(); showscreen(); break; case CNTL_R: /* refresh the screen */ clear(); showscreen(); break; case 'c': /* temporary save */ tmpsave(); break; case CNTL_U: /* reset to temporary save */ tmpreset(); undolock = 1; showscreen(); break; case 'U': /* undo this level */ moves = pushes = 0; if( (ret = readscreen()) == 0) { showscreen(); undolock = 1; } break; case 'u': /* undo last move */ if(state_num > 0) { undomove(); undolock = 0; /*1*/ } break; case 'k': /* up */ case 'K': /* run up */ case CNTL_K: /* run up, stop before object */ case 'j': /* down */ case 'J': /* run down */ case CNTL_J: /* run down, stop before object */ case 'l': /* right */ case 'L': /* run right */ case CNTL_L: /* run right, stop before object */ case 'h': /* left */ case 'H': /* run left */ case CNTL_H: /* run left, stop before object */ do { if( (action = testmove( c)) != 0) { soko_state *s; s = &state[state_num]; s->action = action; s->ppos = ppos; s->lppc = map[ppos.x][ppos.y]; s->tpos1 = tpos1; s->ltp1c = map[tpos1.x][tpos1.y]; s->tpos2 = tpos2; s->ltp2c = map[tpos2.x][tpos2.y]; domove( s->action); undolock = 0; state_num++; } } while( (action != 0) && (! islower( c)) && (packets != savepack)); break; default: helpmessage(); break; } if( (ret == 0) && (packets == savepack)) { scorelevel = level; scoremoves = moves; scorepushes = pushes; break; } } #if ATARIST kbt = Keytbl(-1, -1, -1); kbt->unshifted = old_kbt.unshifted; kbt->shifted = old_kbt.shifted; /* Keytbl(old_kbt.unshifted, old_kbt.shifted, old_kbt.capslock);*/ #endif return ret; }