/* main.c Copyright (C) 2010-2019 Amf This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef __WIN32__ #include #endif #include #include #include #include #include #include #include #include #include #include #include "chroma.h" #include "level.h" #include "menu.h" #include "display.h" #include "colours.h" #include "util.h" void editor(); void help(); void export(struct level*, int); extern int options_xor_mode; extern int options_xor_display; struct level* plevelcurrent = NULL; #ifdef __WIN32__ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { main(0, NULL); } #endif int main(int argc, char **argv) { struct menu* pmenu; struct menuentry* pentryplay; int result; int ok; char directory[FILENAME_MAX]; getfilename("locale", directory, 0, LOCATION_SYSTEM); setlocale(LC_ALL, ""); bindtextdomain("chroma", directory); textdomain("chroma"); display_init(); pmenu = menu_new(gettext("Chroma")); pmenu->logo = 1; pentryplay = menuentry_new(pmenu, gettext("Press any key to play"), MENU_KEY_ANY, MENU_CENTRE); menuentry_new(pmenu, "", 0, MENU_SPACE); menuentry_new(pmenu, gettext("How to Play"), 'H', 0); menuentry_new(pmenu, gettext("Editor"), 'E', 0); menuentry_new(pmenu, gettext("Display Options"), 'D', 0); menuentry_new(pmenu, gettext("Quit"), 'Q', 0); ok = 0; while(!ok) { pmenu->entry_selected = pentryplay; result = menu_process(pmenu); switch(result) { case MENU_SELECT: switch(pmenu->entry_selected->key) { case MENU_KEY_ANY: while(menu_levelselector(NULL, NULL, gettext("Choose a level"), LEVELMENU_MAIN | LEVELMENU_SAVED | LEVELMENU_SOLVED | LEVELMENU_GAME) != MENU_QUIT); break; case 'H': help(); break; case 'E': editor(); break; case 'D': display_options(); break; case 'Q': ok = 1; break; } break; case MENU_QUIT: ok = 1; break; default: break; } } exit(0); } void level_play(struct level* plevelgame) { struct menu* pmenu; struct menuentry* pentry; struct level* plevelrevert; struct level* plevelload; struct level *plevelreplay; int result; int quit; int ok; char filename[FILENAME_MAX]; char directory[FILENAME_MAX]; char menutitle[256]; plevelrevert = level_copy(plevelgame); plevelreplay = NULL; plevelcurrent = plevelgame; quit = 0; while(!quit) { display_play(plevelgame, plevelreplay); /* Has the replay finished? */ if(plevelreplay != NULL && plevelreplay->move_current == NULL) { level_delete(plevelreplay); plevelreplay = NULL; } ok = 0; while(!ok) { pmenu = menu_new(gettext("Game Options")); menuentry_new(pmenu, gettext("Return to Level"), 'Q', 0); menuentry_new(pmenu, gettext("Abort Level and Return to Selection"), 'A', 0); if(plevelrevert->moves != plevelgame->moves) menuentry_new(pmenu, gettext("Revert to Original Position"), 'V', 0); else { pentry = menuentry_new(pmenu, gettext("Revert to Original Position"), 'V', MENU_GREY); menuentry_extratext(pentry, gettext("(only after changes)"), NULL, NULL); } menuentry_new(pmenu, "", 0, MENU_SPACE); menuentry_new(pmenu, gettext("Load Position"), 'L', 0); if(plevelgame->mover_first == NULL) { menuentry_new(pmenu, gettext("Save Position"), 'S', 0); /* if(plevelgame->flags & LEVELFLAG_SOLVED) menuentry_new(pmenu, gettext("Export Solution"), 'E', 0); */ } else { pentry = menuentry_new(pmenu, gettext("Save Position"), 'S', MENU_GREY); menuentry_extratext(pentry, gettext("(not while pieces in motion)"), NULL, NULL); /* if(plevelgame->flags & LEVELFLAG_SOLVED) { pentry = menuentry_new(pmenu, gettext("Export Solution"), 'E', MENU_GREY); menuentry_extratext(pentry, gettext("(not while pieces in motion)"), NULL, NULL); } */ } menuentry_new(pmenu, "", 0, MENU_SPACE); if(plevelreplay == NULL) { if(plevelgame->moves == 0) { menuentry_new(pmenu, gettext("Replay Saved Position"), 'R', 0); menuentry_new(pmenu, "", 0, MENU_SPACE); } else { pentry = menuentry_new(pmenu, gettext("Replay Saved Position"), 'R', MENU_GREY); menuentry_extratext(pentry, gettext("(only at start of a level)"), NULL, NULL); menuentry_new(pmenu, "", 0, MENU_SPACE); } } else { menuentry_new(pmenu, gettext("Stop Replaying Position"), 'T', 0); menuentry_new(pmenu, "", 0, MENU_SPACE); } menuentry_new(pmenu, gettext("Display Options"), 'D', 0); menuentry_new(pmenu, gettext("Currently playing:"), 0, MENU_NOTE); if(plevelgame->title == NULL || strcmp(plevelgame->title, "") == 0) menuentry_new(pmenu, gettext("[untitled level]"), 0, MENU_NOTE | MENU_RIGHT); else menuentry_new(pmenu, gettext(plevelgame->title), 0, MENU_NOTE | MENU_RIGHT); result = menu_process(pmenu); if(result == MENU_QUIT) ok = 1; if(result == MENU_SELECT && pmenu->entry_selected != NULL) { switch(pmenu->entry_selected->key) { case 'Q': ok =1; break; case 'A': ok = 1; quit = 1; break; case 'S': /* Are there pieces still in motion? */ if(plevelgame->mover_first != NULL) break; if(plevelgame->flags & LEVELFLAG_SOLVED && !(plevelgame->flags & LEVELFLAG_FAILED)) { getfilename("solved", directory, 1, LOCATION_LOCAL); strcpy(menutitle, gettext("Save Solution")); } else { getfilename("saved", directory, 1, LOCATION_LOCAL); strcpy(menutitle, gettext("Save Position")); } if(menu_levelselector(directory, filename, menutitle, LEVELMENU_RETURN | LEVELMENU_NEW | LEVELMENU_DELETE | LEVELMENU_MOVES | LEVELMENU_FILTER) == MENU_SELECT) { if(strcmp(filename, "") == 0) sprintf(filename, "%s/%x.chroma", directory, (int)time(NULL)); level_save(plevelgame, filename, 0); level_delete(plevelrevert); plevelrevert = level_copy(plevelgame); ok = 1; } break; case 'L': getfilename("saved", directory, 0, LOCATION_LOCAL); if(menu_levelselector(directory, filename, gettext("Load Position"), LEVELMENU_RETURN | LEVELMENU_DELETE | LEVELMENU_MOVES | LEVELMENU_FILTER) == MENU_SELECT) { plevelload = level_load(filename, 0); if(plevelload != NULL) { if(plevelreplay != NULL) { level_delete(plevelreplay); plevelreplay = NULL; } level_delete(plevelgame); level_delete(plevelrevert); plevelrevert = plevelload; plevelgame = level_copy(plevelrevert); plevelcurrent = plevelgame; ok = 1; } } break; case 'E': /* Are there pieces still in motion? */ if(plevelgame->mover_first != NULL) break; export(plevelgame, 1); break; case 'V': if(plevelreplay != NULL) { level_delete(plevelreplay); plevelreplay = NULL; } level_delete(plevelgame); plevelgame = level_copy(plevelrevert); plevelcurrent = plevelgame; ok = 1; break; case 'R': getfilename("saved", directory, 0, LOCATION_LOCAL); if(menu_levelselector(directory, filename, gettext("Replay Saved Position"), LEVELMENU_RETURN | LEVELMENU_DELETE | LEVELMENU_MOVES | LEVELMENU_SOLVED | LEVELMENU_FILTER) == MENU_SELECT) { plevelreplay = level_load(filename, 0); plevelreplay->move_current = plevelreplay->move_first; ok = 1; } break; case 'T': level_delete(plevelreplay); plevelreplay = NULL; break; case 'D': display_options(); break; } } } menu_delete(pmenu); } if(plevelrevert != NULL) level_delete(plevelrevert); if(plevelreplay != NULL) level_delete(plevelreplay); if(plevelgame != NULL) level_delete(plevelgame); plevelcurrent = NULL; } void help() { struct menu* pmenu; char directory[FILENAME_MAX]; char filename[FILENAME_MAX]; char buffer[FILENAME_MAX]; char *locale; int ok; int i; pmenu = menu_new(gettext("How to Play")); menuentry_new(pmenu, gettext("Quit and return to previous menu"), 'Q', 0); menuentry_new(pmenu, gettext("Use [UP] and [DOWN] to scroll"), 0, MENU_NOTE | MENU_CENTRE); menuentry_new(pmenu, "", 0, MENU_TEXT); getfilename("help/README", directory, 0, LOCATION_SYSTEM); locale = setlocale(LC_MESSAGES, NULL); /* Given a locale of, say, en_GB.UTF-8, try help/README.en_GB.UTF-8, then help/README.en_GB and finally help/README.en before defaulting to just help/README - if we can't get even that, generate an error. */ ok = 0; if(locale != NULL) { i = 0; while(locale[i] != 0 && locale[i] != '/') { buffer[i] = locale[i]; i ++; } buffer[i] = 0; sprintf(filename, "%s.%s", directory, buffer); if(menu_addfile(pmenu, filename)) ok = 1; } else ok = 2; if(ok == 0) { i = 0; while(locale[i] != 0 && locale[i] != '/' && locale[i] != '.') { buffer[i] = locale[i]; i ++; } buffer[i] = 0; sprintf(filename, "%s.%s", directory, buffer); if(menu_addfile(pmenu, filename)) ok = 1; } if(ok == 0) { i = 0; while(locale[i] != 0 && locale[i] != '/' && locale[i] != '.' && locale[i] != '_') { buffer[i] = locale[i]; i ++; } buffer[i] = 0; sprintf(filename, "%s.%s", directory, buffer); if(menu_addfile(pmenu, filename)) ok = 1; } if(ok != 1) { strcpy(filename, directory); if(!menu_addfile(pmenu, filename)) menuentry_new(pmenu, "Unable to read help file!", 0, MENU_GREY | MENU_CENTRE); } menu_process(pmenu); } void export(struct level* plevel, int solution) { struct menu *pmenu; struct menuentry *pentry_filename; char filename[FILENAME_MAX]; int ok, result; int i, j; if(!solution) pmenu = menu_new(gettext("Export Level")); else pmenu = menu_new(gettext("Export Solution")); menuentry_new(pmenu, gettext("Quit and return to previous menu"), 'Q', 0); menuentry_new(pmenu, "", 0, MENU_SPACE); pentry_filename = menuentry_new(pmenu, gettext("Filename"), 'I', MENU_DOUBLE | MENU_EDITABLE); if(solution) { if(plevel->title != NULL && sscanf(plevel->title, "chroma %d.%d", &i, &j) == 2) sprintf(filename, "solution-%d-%02d", i, j); else strcpy(filename, "solution"); } else { if(plevel->title != NULL) strcpy(filename, plevel->title); else strcpy(filename, "level"); } menuentry_extratext(pentry_filename, NULL, NULL, filename); if(!solution) menuentry_new(pmenu, gettext("Export level"), 'E', 0); else menuentry_new(pmenu, gettext("Export solution"), 'E', 0); #ifdef __WIN32__ if(!solution) menuentry_new(pmenu, gettext("Exported levels are saved in \"My Documents\""), 0, MENU_NOTE | MENU_CENTRE); else menuentry_new(pmenu, gettext("Exported solutions are saved in \"My Documents\""), 0, MENU_NOTE | MENU_CENTRE); #else if(!solution) menuentry_new(pmenu, gettext("Exported levels are saved in your home directory"), 0, MENU_NOTE | MENU_CENTRE); else menuentry_new(pmenu, gettext("Exported solutions are saved in your home directory"), 0, MENU_NOTE | MENU_CENTRE); #endif ok = 0; while(!ok) { result = menu_process(pmenu); if(result == MENU_QUIT) ok = 1; if(result == MENU_SELECT && pmenu->entry_selected != NULL) { switch(pmenu->entry_selected->key) { case 'E': getfilename("", filename, 0, LOCATION_DOCUMENTS); i = 0; j = strlen(filename); while(pentry_filename->text4[i] != 0) { if(pentry_filename->text4[i] != '/' && pentry_filename->text4[i] != '\\') filename[j ++] = pentry_filename->text4[i ++]; } filename[j ++] = 0; if(!(strlen(filename) > 7 && strcmp(filename + strlen(filename) - 7, ".chroma") == 0)) strcat(filename, ".chroma"); level_save(plevel, filename, 1); #ifndef __WIN32__ if(solution) chmod(filename, 00600); #endif ok = 1; break; case 'Q': ok = 1; break; } } } menu_delete(pmenu); }