int main(int argc, char *argv[]) { int first = 1; char buf[80]; progname = argv[0]; if (init(argc, argv)) { /* restored game */ goto PL; } for (;;) { clear_level(); make_level(); put_objects(); put_stairs(); add_traps(); put_mons(); put_player(party_room); print_stats(STAT_ALL); if (first) { sprintf(buf, mesg[10], nick_name); message(buf, 0); } PL: first = 0; play_level(); free_stuff(&level_objects); free_stuff(&level_monsters); } }
int load_level(const char *filename) { struct mesh *m; const char *err; int ret; DEBUG(1, "game: load_level(\"%s\")\n", filename); ret = luaL_dofile(L1, filename); if (ret) { err = lua_tostring(L1, -1); ERROR("error while loading level: %s", err); lua_pop(L1, 1); return 1; } lua_getfield(L1, -1, "vertices"); if (!lua_istable(L1, -1)) { ERROR("expected `vertices' field in Lua level data table"); lua_pop(L1, 2); return 1; } clear_level(); m = mesh_create(); mesh_addluaverts(m, L1, -1); lua_pop(L1, 1); lua_getfield(L1, -1, "faces"); if (!lua_istable(L1, -1)) { mesh_destroy(m); ERROR("expected `faces' field in Lua level data table"); return 1; } mesh_addluafaces(m, L1, -1); lua_pop(L1, 1); lua_setglobal(L1, "level"); level = model_create(m); /* m is no longer needed. */ mesh_destroy(m); gfx_prepmodel(level); gfx->set_level(level); return 0; }
int sokoban_game::start_game() { int iScore = 0; int iMoves = 0; iTotalMoves = 0; int iDirY, iDirX; const int iOffsetX = (TERMX > FULL_SCREEN_WIDTH) ? (TERMX - FULL_SCREEN_WIDTH) / 2 : 0; const int iOffsetY = (TERMY > FULL_SCREEN_HEIGHT) ? (TERMY - FULL_SCREEN_HEIGHT) / 2 : 0; parse_level(); WINDOW *w_sokoban = newwin(FULL_SCREEN_HEIGHT, FULL_SCREEN_WIDTH, iOffsetY, iOffsetX); draw_border(w_sokoban); center_print(w_sokoban, 0, hilite(c_white), _("Sokoban")); std::vector<std::string> shortcuts; shortcuts.push_back(_("<+> next")); // '+': next shortcuts.push_back(_("<-> prev")); // '-': prev shortcuts.push_back(_("<r>eset")); // 'r': reset shortcuts.push_back(_("<q>uit")); // 'q': quit shortcuts.push_back(_("<u>ndo move")); // 'u': undo move int indent = 10; for (size_t i = 0; i < shortcuts.size(); i++) { indent = std::max(indent, utf8_width(shortcuts[i].c_str()) + 1); } indent = std::min(indent, 30); for (size_t i = 0; i < shortcuts.size(); i++) { shortcut_print(w_sokoban, i + 1, FULL_SCREEN_WIDTH - indent, c_white, c_ltgreen, shortcuts[i].c_str()); } int input = '.'; int iPlayerY = 0; int iPlayerX = 0; bool bNewLevel = true; bool bMoved = false; do { if (bNewLevel) { bNewLevel = false; iMoves = 0; vUndo.clear(); iPlayerY = mLevelInfo[iCurrentLevel]["PlayerY"]; iPlayerX = mLevelInfo[iCurrentLevel]["PlayerX"]; mLevel = vLevel[iCurrentLevel]; } print_score(w_sokoban, iScore, iMoves); if (check_win()) { //we won yay if (!mAlreadyWon[iCurrentLevel]) { iScore += 500; mAlreadyWon[iCurrentLevel] = true; } input = '+'; } else { draw_level(w_sokoban); wrefresh(w_sokoban); //Check input input = getch(); } bMoved = false; switch (input) { case KEY_UP: /* up */ iDirY = -1; iDirX = 0; bMoved = true; break; case KEY_DOWN: /* down */ iDirY = 1; iDirX = 0; bMoved = true; break; case KEY_LEFT: /* left */ iDirY = 0; iDirX = -1; bMoved = true; break; case KEY_RIGHT: /* right */ iDirY = 0; iDirX = 1; bMoved = true; break; case 'q': return iScore; break; case 'u': { int iPlayerYNew = 0; int iPlayerXNew = 0; bool bUndoSkip = false; //undo move if (vUndo.size() > 0) { //reset last player pos mLevel[iPlayerY][iPlayerX] = (mLevel[iPlayerY][iPlayerX] == "+") ? "." : " "; iPlayerYNew = vUndo[vUndo.size() - 1].iOldY; iPlayerXNew = vUndo[vUndo.size() - 1].iOldX; mLevel[iPlayerYNew][iPlayerXNew] = vUndo[vUndo.size() - 1].sTileOld; vUndo.pop_back(); bUndoSkip = true; } if (bUndoSkip && vUndo.size() > 0) { iDirY = vUndo[vUndo.size() - 1].iOldY; iDirX = vUndo[vUndo.size() - 1].iOldX; if (vUndo[vUndo.size() - 1].sTileOld == "$" || vUndo[vUndo.size() - 1].sTileOld == "*") { mLevel[iPlayerY][iPlayerX] = (mLevel[iPlayerY][iPlayerX] == ".") ? "*" : "$"; mLevel[iPlayerY + iDirY][iPlayerX + iDirX] = (mLevel[iPlayerY + iDirY][iPlayerX + iDirX] == "*") ? "." : " "; vUndo.pop_back(); } } if (bUndoSkip) { iPlayerY = iPlayerYNew; iPlayerX = iPlayerXNew; } } break; case 'r': //reset level bNewLevel = true; break; case '+': //next level clear_level(w_sokoban); iCurrentLevel++; if (iCurrentLevel >= iNumLevel) { iCurrentLevel = 0; } bNewLevel = true; break; case '-': //prev level clear_level(w_sokoban); iCurrentLevel--; if (iCurrentLevel < 0) { iCurrentLevel = iNumLevel - 1; } bNewLevel = true; break; default: break; } if (bMoved) { //check if we can move the player std::string sMoveTo = mLevel[iPlayerY + iDirY][iPlayerX + iDirX]; bool bMovePlayer = false; if (sMoveTo != "#") { if (sMoveTo == "$" || sMoveTo == "*") { //Check if we can move the package std::string sMovePackTo = mLevel[iPlayerY + (iDirY * 2)][iPlayerX + (iDirX * 2)]; if (sMovePackTo == "." || sMovePackTo == " ") { //move both bMovePlayer = true; mLevel[iPlayerY + (iDirY * 2)][iPlayerX + (iDirX * 2)] = (sMovePackTo == ".") ? "*" : "$"; vUndo.push_back(cUndo(iDirY, iDirX, sMoveTo)); iMoves--; } } else { bMovePlayer = true; } if (bMovePlayer) { //move player vUndo.push_back(cUndo(iPlayerY, iPlayerX, mLevel[iPlayerY][iPlayerX])); mLevel[iPlayerY][iPlayerX] = (mLevel[iPlayerY][iPlayerX] == "+") ? "." : " "; mLevel[iPlayerY + iDirY][iPlayerX + iDirX] = (sMoveTo == "." || sMoveTo == "*") ? "+" : "@"; iPlayerY += iDirY; iPlayerX += iDirX; iMoves++; iTotalMoves++; } } } } while (true); return iScore; }
int sokoban_game::start_game() { int iScore = 0; int iMoves = 0; iTotalMoves = 0; int iDirY, iDirX; const int iOffsetX = (TERMX > FULL_SCREEN_WIDTH) ? (TERMX - FULL_SCREEN_WIDTH) / 2 : 0; const int iOffsetY = (TERMY > FULL_SCREEN_HEIGHT) ? (TERMY - FULL_SCREEN_HEIGHT) / 2 : 0; parse_level(); WINDOW *w_sokoban = newwin(FULL_SCREEN_HEIGHT, FULL_SCREEN_WIDTH, iOffsetY, iOffsetX); draw_border(w_sokoban); center_print(w_sokoban, 0, hilite(c_white), _("Sokoban")); input_context ctxt("SOKOBAN"); ctxt.register_cardinal(); ctxt.register_action("NEXT"); ctxt.register_action("PREV"); ctxt.register_action("RESET"); ctxt.register_action("QUIT"); ctxt.register_action("UNDO"); ctxt.register_action("HELP_KEYBINDINGS"); std::vector<std::string> shortcuts; shortcuts.push_back(_("<+> next")); // '+': next shortcuts.push_back(_("<-> prev")); // '-': prev shortcuts.push_back(_("<r>eset")); // 'r': reset shortcuts.push_back(_("<q>uit")); // 'q': quit shortcuts.push_back(_("<u>ndo move")); // 'u': undo move int indent = 10; for (size_t i = 0; i < shortcuts.size(); i++) { indent = std::max(indent, utf8_width(shortcuts[i].c_str()) + 1); } indent = std::min(indent, 30); for (size_t i = 0; i < shortcuts.size(); i++) { shortcut_print(w_sokoban, i + 1, FULL_SCREEN_WIDTH - indent, c_white, c_ltgreen, shortcuts[i]); } int iPlayerY = 0; int iPlayerX = 0; bool bNewLevel = true; bool bMoved = false; do { if (bNewLevel) { bNewLevel = false; iMoves = 0; vUndo.clear(); iPlayerY = mLevelInfo[iCurrentLevel]["PlayerY"]; iPlayerX = mLevelInfo[iCurrentLevel]["PlayerX"]; mLevel = vLevel[iCurrentLevel]; } print_score(w_sokoban, iScore, iMoves); std::string action; if (check_win()) { //we won yay if (!mAlreadyWon[iCurrentLevel]) { iScore += 500; mAlreadyWon[iCurrentLevel] = true; } action = "NEXT"; } else { draw_level(w_sokoban); wrefresh(w_sokoban); //Check input action = ctxt.handle_input(); } bMoved = false; if (ctxt.get_direction(iDirX, iDirY, action)) { bMoved = true; } else if (action == "QUIT") { return iScore; } else if (action == "UNDO") { int iPlayerYNew = 0; int iPlayerXNew = 0; bool bUndoSkip = false; //undo move if (!vUndo.empty()) { //reset last player pos mLevel[iPlayerY][iPlayerX] = (mLevel[iPlayerY][iPlayerX] == "+") ? "." : " "; iPlayerYNew = vUndo[vUndo.size() - 1].iOldY; iPlayerXNew = vUndo[vUndo.size() - 1].iOldX; mLevel[iPlayerYNew][iPlayerXNew] = vUndo[vUndo.size() - 1].sTileOld; vUndo.pop_back(); bUndoSkip = true; } if (bUndoSkip && !vUndo.empty()) { iDirY = vUndo[vUndo.size() - 1].iOldY; iDirX = vUndo[vUndo.size() - 1].iOldX; if (vUndo[vUndo.size() - 1].sTileOld == "$" || vUndo[vUndo.size() - 1].sTileOld == "*") { mLevel[iPlayerY][iPlayerX] = (mLevel[iPlayerY][iPlayerX] == ".") ? "*" : "$"; mLevel[iPlayerY + iDirY][iPlayerX + iDirX] = (mLevel[iPlayerY + iDirY][iPlayerX + iDirX] == "*") ? "." : " "; vUndo.pop_back(); } } if (bUndoSkip) { iPlayerY = iPlayerYNew; iPlayerX = iPlayerXNew; } } else if (action == "RESET") { //reset level bNewLevel = true; } else if (action == "NEXT") { //next level clear_level(w_sokoban); iCurrentLevel++; if (iCurrentLevel >= iNumLevel) { iCurrentLevel = 0; } bNewLevel = true; } else if (action == "PREV") { //prev level clear_level(w_sokoban); iCurrentLevel--; if (iCurrentLevel < 0) { iCurrentLevel = iNumLevel - 1; } bNewLevel = true; } if (bMoved) { //check if we can move the player std::string sMoveTo = mLevel[iPlayerY + iDirY][iPlayerX + iDirX]; bool bMovePlayer = false; if (sMoveTo != "#") { if (sMoveTo == "$" || sMoveTo == "*") { //Check if we can move the package std::string sMovePackTo = mLevel[iPlayerY + (iDirY * 2)][iPlayerX + (iDirX * 2)]; if (sMovePackTo == "." || sMovePackTo == " ") { //move both bMovePlayer = true; mLevel[iPlayerY + (iDirY * 2)][iPlayerX + (iDirX * 2)] = (sMovePackTo == ".") ? "*" : "$"; vUndo.push_back(cUndo(iDirY, iDirX, sMoveTo)); iMoves--; } } else { bMovePlayer = true; } if (bMovePlayer) { //move player vUndo.push_back(cUndo(iPlayerY, iPlayerX, mLevel[iPlayerY][iPlayerX])); mLevel[iPlayerY][iPlayerX] = (mLevel[iPlayerY][iPlayerX] == "+") ? "." : " "; mLevel[iPlayerY + iDirY][iPlayerX + iDirX] = (sMoveTo == "." || sMoveTo == "*") ? "+" : "@"; iPlayerY += iDirY; iPlayerX += iDirX; iMoves++; iTotalMoves++; } } } } while (true); return iScore; }
/* loads the city level */ void load_city(int populate) { int i,j; pml ml; char site; map *city; map *maze; initrand(E_CITY, 0); /* Get the hedge maze (which is in the city). */ maze = map_open(MAP_hedges); /* Choose a random level from it. */ map_setLevel(maze, random_range(map_getDepth(maze))); /* Get the city. */ city = map_open(MAP_city); map_setLevel(city,0); TempLevel = Level; if (ok_to_free(TempLevel)) { #ifndef SAVE_LEVELS free_level(TempLevel); #endif TempLevel = NULL; } #ifndef SAVE_LEVELS Level = ((plv) checkmalloc(sizeof(levtype))); #else msdos_changelevel(TempLevel,0,-1); Level = &TheLevel; #endif clear_level(Level); Level->depth = 0; Level->environment = E_CITY; /* WDT: Rampart, as a special case, has its width stored in a * global variable. */ WIDTH = Level->level_width = map_getWidth(city); LENGTH = Level->level_length = map_getLength(city); for(j=0; j<Level->level_length; j++) { for(i=0; i<Level->level_width; i++) { lset(i,j,SEEN); site = map_getSiteChar(city,i,j); switch(site) { /* case '@': Player.x = i; Player.y = j; Level->site[i][j].locchar = FLOOR; break; */ case 'g': Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_GARDEN; break; case 'y': Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_CEMETARY; break; case 'p': /* WDT: each of these places needs to be assigned * a function (or replaced with an 'x' in the map) */ case '!': case 'I': case 'E': case 'e': case 'x': assign_city_function(i,j); break; case 't': Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_TEMPLE; CitySiteList[L_TEMPLE-CITYSITEBASE][0] = TRUE; CitySiteList[L_TEMPLE-CITYSITEBASE][1] = i; CitySiteList[L_TEMPLE-CITYSITEBASE][2] = j; break; #if 0 /* WDT: HACK! The new city doesn't use portcullis traps, but has other * uses for 'T'. Um... I'd rather have a use for them (that's what * the jail is supposed to be), so this will stay only for now; with * any luck we'll have things fixed up before the next release. */ case 'T': Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_PORTCULLIS_TRAP; Level->site[i][j].aux = NOCITYMOVE; break; #endif /* end of hack */ case 'R': Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_RAISE_PORTCULLIS; Level->site[i][j].aux = NOCITYMOVE; break; case '7': Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_PORTCULLIS; Level->site[i][j].aux = NOCITYMOVE; break; case 'C': Level->site[i][j].locchar = OPEN_DOOR; Level->site[i][j].p_locf = L_COLLEGE; CitySiteList[L_COLLEGE-CITYSITEBASE][0] = TRUE; CitySiteList[L_COLLEGE-CITYSITEBASE][1] = i; CitySiteList[L_COLLEGE-CITYSITEBASE][2] = j; break; case 's': Level->site[i][j].locchar = OPEN_DOOR; Level->site[i][j].p_locf = L_SORCERORS; CitySiteList[L_SORCERORS-CITYSITEBASE][0] = TRUE; CitySiteList[L_SORCERORS-CITYSITEBASE][1] = i; CitySiteList[L_SORCERORS-CITYSITEBASE][2] = j; break; case 'M': Level->site[i][j].locchar = OPEN_DOOR; Level->site[i][j].p_locf = L_MERC_GUILD; CitySiteList[L_MERC_GUILD-CITYSITEBASE][0] = TRUE; CitySiteList[L_MERC_GUILD-CITYSITEBASE][1] = i; CitySiteList[L_MERC_GUILD-CITYSITEBASE][2] = j; break; case 'K': Level->site[i][j].locchar = OPEN_DOOR; Level->site[i][j].p_locf = L_MONASTERY; CitySiteList[L_MONASTERY-CITYSITEBASE][0] = TRUE; CitySiteList[L_MONASTERY-CITYSITEBASE][1] = i; CitySiteList[L_MONASTERY-CITYSITEBASE][2] = j; break; case 'c': Level->site[i][j].locchar = OPEN_DOOR; Level->site[i][j].p_locf = L_CASTLE; CitySiteList[L_CASTLE-CITYSITEBASE][0] = TRUE; CitySiteList[L_CASTLE-CITYSITEBASE][1] = i; CitySiteList[L_CASTLE-CITYSITEBASE][2] = j; break; case '?': { static int myI = -1, myJ; char site; if ( myI == -1 ) { /* If this is the first time we've seen the hedge maze, * set this as its corner. */ myI = i; myJ = j; } site = map_getSiteChar(maze, i - myI, j - myJ); mazesite(site,i,j,populate); } break; case 'P': Level->site[i][j].locchar = OPEN_DOOR; Level->site[i][j].p_locf = L_ORDER; CitySiteList[L_ORDER-CITYSITEBASE][0] = TRUE; CitySiteList[L_ORDER-CITYSITEBASE][1] = i; CitySiteList[L_ORDER-CITYSITEBASE][2] = j; break; case 'H': Level->site[i][j].locchar = OPEN_DOOR; Level->site[i][j].p_locf = L_CHARITY; CitySiteList[L_CHARITY-CITYSITEBASE][0] = TRUE; CitySiteList[L_CHARITY-CITYSITEBASE][1] = i; CitySiteList[L_CHARITY-CITYSITEBASE][2] = j; break; case 'h': Level->site[i][j].locchar = FLOOR; if (populate) make_horse(i,j); /* from village.c */ break; case 'j': Level->site[i][j].locchar = FLOOR; if (populate) make_justiciar(i,j); break; case 'J': Level->site[i][j].locchar = CLOSED_DOOR; Level->site[i][j].p_locf = L_JAIL; break; case 'A': Level->site[i][j].locchar = OPEN_DOOR; Level->site[i][j].p_locf = L_ARENA; CitySiteList[L_ARENA-CITYSITEBASE][0] = TRUE; CitySiteList[L_ARENA-CITYSITEBASE][1] = i; CitySiteList[L_ARENA-CITYSITEBASE][2] = j; break; case 'B': Level->site[i][j].locchar = OPEN_DOOR; Level->site[i][j].p_locf = L_BANK; CitySiteList[L_BANK-CITYSITEBASE][0] = TRUE; CitySiteList[L_BANK-CITYSITEBASE][1] = i; CitySiteList[L_BANK-CITYSITEBASE][2] = j; lset(i,j,STOPS); lset(i,j+1,STOPS); lset(i+1,j,STOPS); lset(i-1,j,STOPS); lset(i,j-1,STOPS); break; case 'i': Level->site[i][j].locchar = OPEN_DOOR; Level->site[i][j].p_locf = L_TOURIST; CitySiteList[L_TOURIST-CITYSITEBASE][1] = i; CitySiteList[L_TOURIST-CITYSITEBASE][2] = j; lset(i,j,STOPS); lset(i,j+1,STOPS); lset(i+1,j,STOPS); lset(i-1,j,STOPS); lset(i,j-1,STOPS); break; case 'X': Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_COUNTRYSIDE; CitySiteList[L_COUNTRYSIDE-CITYSITEBASE][0] = TRUE; CitySiteList[L_COUNTRYSIDE-CITYSITEBASE][1] = i; CitySiteList[L_COUNTRYSIDE-CITYSITEBASE][2] = j; break; case 'v': Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_VAULT; Level->site[i][j].aux = NOCITYMOVE; lset(i,j,SECRET); break; case 'S': Level->site[i][j].locchar = FLOOR; Level->site[i][j].aux = NOCITYMOVE; lset(i,j,SECRET); break; case 'G': Level->site[i][j].locchar = FLOOR; if (populate) { make_site_monster(i,j,GUARD); Level->site[i][j].creature->aux1 = i; Level->site[i][j].creature->aux2 = j; } break; case 'u': Level->site[i][j].locchar = FLOOR; if (populate) make_minor_undead(i,j); break; case 'U': Level->site[i][j].locchar = FLOOR; if (populate) make_major_undead(i,j); break; case 'V': Level->site[i][j].showchar = WALL; Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_VAULT; if (populate) make_site_treasure(i,j,5); Level->site[i][j].aux = NOCITYMOVE; lset(i,j,SECRET); break; case '%': Level->site[i][j].showchar = WALL; Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_TRAP_SIREN; if (populate) make_site_treasure(i,j,5); Level->site[i][j].aux = NOCITYMOVE; lset(i,j,SECRET); break; case '$': Level->site[i][j].locchar = FLOOR; if (populate) make_site_treasure(i,j,5); break; case '2': Level->site[i][j].locchar = ALTAR; Level->site[i][j].p_locf = L_ALTAR; Level->site[i][j].aux = ODIN; break; case '3': Level->site[i][j].locchar = ALTAR; Level->site[i][j].p_locf = L_ALTAR; Level->site[i][j].aux = SET; break; case '4': Level->site[i][j].locchar = ALTAR; Level->site[i][j].p_locf = L_ALTAR; Level->site[i][j].aux = ATHENA; break; case '5': Level->site[i][j].locchar = ALTAR; Level->site[i][j].p_locf = L_ALTAR; Level->site[i][j].aux = HECATE; break; case '6': Level->site[i][j].locchar = ALTAR; Level->site[i][j].p_locf = L_ALTAR; Level->site[i][j].aux = DESTINY; break; case '^': Level->site[i][j].showchar = WALL; Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = TRAP_BASE+random_range(NUMTRAPS); lset(i,j,SECRET); break; case '"': Level->site[i][j].locchar = HEDGE; break; case '~': Level->site[i][j].locchar = WATER; Level->site[i][j].p_locf = L_WATER; break; case '=': Level->site[i][j].locchar = WATER; Level->site[i][j].p_locf = L_MAGIC_POOL; break; case '*': Level->site[i][j].locchar = WALL; Level->site[i][j].aux = 10; break; case '#': Level->site[i][j].locchar = WALL; Level->site[i][j].aux = 500; break; case 'T':/* currently meaningless in large city map. */ case '>': /* currently meaningless outside of maze.*/ case '.': Level->site[i][j].locchar = FLOOR; break; case ',': Level->site[i][j].showchar = WALL; Level->site[i][j].locchar = FLOOR; Level->site[i][j].aux = NOCITYMOVE; lset(i,j,SECRET); break; case '-': case 'D': /* WDT: should all Ds be changed to -, or should D be given * special treatment? */ Level->site[i][j].locchar = CLOSED_DOOR; break; case '1': Level->site[i][j].locchar = STATUE; break; default: printf("\nOops... missed a case [%d,%d]: '%c' (%d)\n", i,j,site,site); morewait(); } if (loc_statusp(i,j,SEEN)) { if (loc_statusp(i,j,SECRET)) Level->site[i][j].showchar = WALL; else Level->site[i][j].showchar = Level->site[i][j].locchar; } } } map_close(maze); map_close(city); City = Level; /* make all city monsters asleep, and shorten their wakeup range to 2 */ /* to prevent players from being molested by vicious monsters on */ /* the streets */ for(ml=Level->mlist; ml!=NULL; ml=ml->next) { m_status_reset(ml->m,AWAKE); ml->m->wakeup = 2; } initrand(E_RESTORE, 0); }
int sokoban_game::start_game() { int iScore = 0; int iMoves = 0; iTotalMoves = 0; int iDirY, iDirX; const int iOffsetX = (TERMX > FULL_SCREEN_WIDTH) ? (TERMX-FULL_SCREEN_WIDTH)/2 : 0; const int iOffsetY = (TERMY > FULL_SCREEN_HEIGHT) ? (TERMY-FULL_SCREEN_HEIGHT)/2 : 0; WINDOW* w_sokoban = newwin(FULL_SCREEN_HEIGHT, FULL_SCREEN_WIDTH, iOffsetY, iOffsetX); wborder(w_sokoban, LINE_XOXO, LINE_XOXO, LINE_OXOX, LINE_OXOX, LINE_OXXO, LINE_OOXX, LINE_XXOO, LINE_XOOX); parse_level(); mvwprintz(w_sokoban, 0, (FULL_SCREEN_WIDTH/2)-5, hilite(c_white), "Sokoban"); mvwprintz(w_sokoban, 1, FULL_SCREEN_WIDTH-10, c_ltgreen, "+"); wprintz(w_sokoban, c_white, " next"); mvwprintz(w_sokoban, 2, FULL_SCREEN_WIDTH-10, c_ltgreen, "-"); wprintz(w_sokoban, c_white, " prev"); mvwprintz(w_sokoban, 3, FULL_SCREEN_WIDTH-10, c_ltgreen, "r"); wprintz(w_sokoban, c_white, "eset"); mvwprintz(w_sokoban, 4, FULL_SCREEN_WIDTH-10, c_ltgreen, "q"); wprintz(w_sokoban, c_white, "uit"); mvwprintz(w_sokoban, 5, FULL_SCREEN_WIDTH-10, c_ltgreen, "u"); wprintz(w_sokoban, c_white, "ndo move"); int input = '.'; int iPlayerY = 0; int iPlayerX = 0; bool bNewLevel = true; bool bMoved = false; do { if (bNewLevel) { bNewLevel = false; iMoves = 0; vUndo.clear(); iPlayerY = mLevelInfo[iCurrentLevel]["PlayerY"]; iPlayerX = mLevelInfo[iCurrentLevel]["PlayerX"]; mLevel = vLevel[iCurrentLevel]; } print_score(w_sokoban, iScore, iMoves); if (check_win()) { //we won yay if (!mAlreadyWon[iCurrentLevel]) { iScore += 500; mAlreadyWon[iCurrentLevel] = true; } input = '+'; } else { draw_level(w_sokoban); wrefresh(w_sokoban); //Check input input = getch(); } bMoved = false; switch (input) { case KEY_UP: /* up */ iDirY = -1; iDirX = 0; bMoved = true; break; case KEY_DOWN: /* down */ iDirY = 1; iDirX = 0; bMoved = true; break; case KEY_LEFT: /* left */ iDirY = 0; iDirX = -1; bMoved = true; break; case KEY_RIGHT: /* right */ iDirY = 0; iDirX = 1; bMoved = true; break; case 'q': return iScore; break; case 'u': { int iPlayerYNew = 0; int iPlayerXNew = 0; bool bUndoSkip = false; //undo move if (vUndo.size() > 0) { //reset last player pos mLevel[iPlayerY][iPlayerX] = (mLevel[iPlayerY][iPlayerX] == "+") ? "." : " "; iPlayerYNew = vUndo[vUndo.size()-1].iOldY; iPlayerXNew = vUndo[vUndo.size()-1].iOldX; mLevel[iPlayerYNew][iPlayerXNew] = vUndo[vUndo.size()-1].sTileOld; vUndo.pop_back(); bUndoSkip = true; } if (bUndoSkip && vUndo.size() > 0) { iDirY = vUndo[vUndo.size()-1].iOldY; iDirX = vUndo[vUndo.size()-1].iOldX; if (vUndo[vUndo.size()-1].sTileOld == "$" || vUndo[vUndo.size()-1].sTileOld == "*") { mLevel[iPlayerY][iPlayerX] = (mLevel[iPlayerY][iPlayerX] == ".") ? "*" : "$"; mLevel[iPlayerY + iDirY][iPlayerX + iDirX] = (mLevel[iPlayerY + iDirY][iPlayerX + iDirX] == "*") ? "." : " "; vUndo.pop_back(); } } if (bUndoSkip) { iPlayerY = iPlayerYNew; iPlayerX = iPlayerXNew; } } break; case 'r': //reset level bNewLevel = true; break; case '+': //next level clear_level(w_sokoban); iCurrentLevel++; if (iCurrentLevel >= iNumLevel) { iCurrentLevel = 0; } bNewLevel = true; break; case '-': //prev level clear_level(w_sokoban); iCurrentLevel--; if (iCurrentLevel < 0) { iCurrentLevel = iNumLevel - 1; } bNewLevel = true; break; default: break; } if (bMoved) { //check if we can move the player std::string sMoveTo = mLevel[iPlayerY + iDirY][iPlayerX + iDirX]; bool bMovePlayer = false; if (sMoveTo != "#") { if (sMoveTo == "$" || sMoveTo == "*") { //Check if we can move the package std::string sMovePackTo = mLevel[iPlayerY + (iDirY * 2)][iPlayerX + (iDirX * 2)]; if (sMovePackTo == "." || sMovePackTo == " ") { //move both bMovePlayer = true; mLevel[iPlayerY + (iDirY * 2)][iPlayerX + (iDirX * 2)] = (sMovePackTo == ".") ? "*" : "$"; vUndo.push_back(cUndo(iDirY, iDirX, sMoveTo)); iMoves--; } } else { bMovePlayer = true; } if (bMovePlayer) { //move player vUndo.push_back(cUndo(iPlayerY, iPlayerX, mLevel[iPlayerY][iPlayerX])); mLevel[iPlayerY][iPlayerX] = (mLevel[iPlayerY][iPlayerX] == "+") ? "." : " "; mLevel[iPlayerY + iDirY][iPlayerX + iDirX] = (sMoveTo == "." || sMoveTo == "*") ? "+" : "@"; iPlayerY += iDirY; iPlayerX += iDirX; iMoves++; iTotalMoves++; } } } } while (true); return iScore; }
void change_level (char fromlevel, char tolevel, char rewrite_level) { struct level * thislevel = NULL; Player.sx = -1; Player.sy = -1; /* sanctuary effect dispelled */ thislevel = findlevel(Dungeon, tolevel); deepest[Current_Environment] = max(deepest[Current_Environment], tolevel); if (!thislevel) { thislevel = (level*) checkmalloc(sizeof(levtype)); clear_level(thislevel); Level = thislevel; Level->next = Dungeon; Dungeon = Level; } Level = thislevel; if ((!Level->generated) || rewrite_level) { initrand(Current_Environment, tolevel); Level->environment = Current_Environment; Level->depth = tolevel; Level->generated = true; switch (Current_Environment) { case E_CAVES: Level->level_width = CAVES_WIDTH; Level->level_length = CAVES_LENGTH; if ((0 == random_range(4)) && (tolevel < MaxDungeonLevels)) room_level(); else cavern_level(); break; case E_SEWERS: Level->level_width = SEWERS_WIDTH; Level->level_length = SEWERS_LENGTH; if ((0 == random_range(4)) && (tolevel < MaxDungeonLevels)) room_level(); else sewer_level(); break; case E_CASTLE: Level->level_width = CASTLE_WIDTH; Level->level_length = CASTLE_LENGTH; room_level(); break; case E_PALACE: /* PGM TODO */ Level->level_width = PALACE_WIDTH; Level->level_length = PALACE_LENGTH; room_level(); break; case E_ASTRAL: Level->level_width = ASTRAL_WIDTH; Level->level_length = ASTRAL_LENGTH; maze_level(); break; case E_VOLCANO: Level->level_width = VOLCANO_WIDTH; Level->level_length = VOLCANO_LENGTH; switch (random_range(3)) { case 0: cavern_level(); break; case 1: room_level(); break; case 2: maze_level(); break; } break; default: print3("This dungeon not implemented!"); assert(false); break; } install_traps(); install_specials(); make_stairs(fromlevel); make_stairs(fromlevel); initrand(E_RESTORE, 0); populate_level(Current_Environment); stock_level(); } find_stairs(fromlevel, tolevel); ScreenOffset = Player.y - (ScreenLength/2); show_screen(); screencheck(Player.x,Player.y); drawvision(Player.x,Player.y); /* synchronize with player on level change */ Player.click = (Tick+1)%60; roomcheck(); }
void game_shutdown(void) { DEBUG(1, "Shutting down game core\n"); clear_level(); }
/* loads the house level into Level*/ void load_house(int kind, int populate) { map *home; int i,j; char site; int stops; TempLevel = Level; initrand(Current_Environment, Player.x + Player.y + hour()*10); if (ok_to_free(TempLevel)) { #ifndef SAVE_LEVELS free_level(TempLevel); #endif TempLevel = NULL; } #ifndef SAVE_LEVELS Level = ((plv) checkmalloc(sizeof(levtype))); #else msdos_changelevel(TempLevel,0,-1); Level = &TheLevel; #endif clear_level(Level); switch(kind) { case E_HOUSE: home = map_open(MAP_house); break; case E_MANSION: home = map_open(MAP_mansion); break; default: case E_HOVEL: home = map_open(MAP_hovel); break; } Level->level_width=map_getWidth(home); Level->level_length=map_getLength(home); map_setLevel(home, 0); stops = 0; for(j=0;j<Level->level_length;j++) { for(i=0;i<Level->level_width;i++) { if (kind == E_HOVEL) Level->site[i][j].lstatus = SEEN; else Level->site[i][j].lstatus = 0; Level->site[i][j].roomnumber = RS_CORRIDOR; Level->site[i][j].p_locf = L_NO_OP; site = map_getSiteChar(home,i,j); switch(site) { case 'N': Level->site[i][j].locchar = FLOOR; Level->site[i][j].roomnumber = RS_BEDROOM; if (random_range(2) && populate) make_house_npc(i,j); break; case 'H': Level->site[i][j].locchar = FLOOR; Level->site[i][j].roomnumber = RS_BEDROOM; if (random_range(2) && populate) make_mansion_npc(i,j); break; case 'D': Level->site[i][j].locchar = FLOOR; Level->site[i][j].roomnumber = RS_DININGROOM; break; case '.': Level->site[i][j].locchar = FLOOR; if (stops) { lset(i,j,STOPS); stops = 0; } break; case 'c': Level->site[i][j].locchar = FLOOR; Level->site[i][j].roomnumber = RS_CLOSET; break; case 'G': Level->site[i][j].locchar = FLOOR; Level->site[i][j].roomnumber = RS_BATHROOM; break; case 'B': Level->site[i][j].locchar = FLOOR; Level->site[i][j].roomnumber = RS_BEDROOM; break; case 'K': Level->site[i][j].locchar = FLOOR; Level->site[i][j].roomnumber = RS_KITCHEN; break; case 'S': Level->site[i][j].locchar = FLOOR; Level->site[i][j].showchar = WALL; lset(i,j,SECRET); Level->site[i][j].roomnumber = RS_SECRETPASSAGE; break; case '3': Level->site[i][j].locchar = SAFE; Level->site[i][j].showchar = WALL; lset(i,j,SECRET); Level->site[i][j].p_locf = L_SAFE; break; case '^': Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = TRAP_BASE+random_range(NUMTRAPS); break; case 'P': Level->site[i][j].locchar = PORTCULLIS; Level->site[i][j].p_locf = L_PORTCULLIS; break; case 'R': Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_RAISE_PORTCULLIS; break; case 'p': Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_PORTCULLIS; break; case 'T': Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_PORTCULLIS_TRAP; break; case 'X': Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_HOUSE_EXIT; stops = 1; break; case '#': Level->site[i][j].locchar = WALL; switch (kind) { case E_HOVEL: Level->site[i][j].aux = 10; break; case E_HOUSE: Level->site[i][j].aux = 50; break; case E_MANSION: Level->site[i][j].aux = 150; break; } break; case '|': Level->site[i][j].locchar = OPEN_DOOR; Level->site[i][j].roomnumber = RS_CORRIDOR; lset(i,j,STOPS); break; case '+': Level->site[i][j].locchar = CLOSED_DOOR; Level->site[i][j].roomnumber = RS_CORRIDOR; Level->site[i][j].aux = LOCKED; lset(i,j,STOPS); break; case 'd': Level->site[i][j].locchar = FLOOR; Level->site[i][j].roomnumber = RS_CORRIDOR; if (populate) make_site_monster(i,j,DOBERMAN); break; case 'a': Level->site[i][j].locchar = FLOOR; Level->site[i][j].roomnumber = RS_CORRIDOR; Level->site[i][j].p_locf = L_TRAP_SIREN; break; case 'A': Level->site[i][j].locchar = FLOOR; Level->site[i][j].roomnumber = RS_CORRIDOR; if (populate) make_site_monster(i,j,AUTO_MINOR); /* automaton */ break; } Level->site[i][j].showchar = ' '; } } map_close(home); initrand(E_RESTORE, 0); }