pass.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. //
  2. // File: pass.c
  3. // pass.c plays the password guessing game
  4. // @author Josh Bicking <josh1147582>
  5. // // // // // // // // // // // // // // // // // // // // // // //
  6. #define _BSD_SOURCE // for unistd.h
  7. #ifdef _WIN32
  8. # include <Windows.h>
  9. # include <curses.h>
  10. # define SLEEP(delay) Sleep(delay/1000)
  11. #else
  12. # include <ncurses.h>
  13. # include <unistd.h>
  14. # define SLEEP(delay) usleep(delay)
  15. #endif
  16. #include <time.h>
  17. #include <string.h>
  18. #include <stdlib.h>
  19. #include "pass.h"
  20. #include "print.h"
  21. #include "wordParse.h"
  22. #include "intro.h"
  23. #define OFFSET_LEFT 0
  24. #define OFFSET_RIGHT 20
  25. #define BIGSTRING_SIZE 408
  26. static int currentCharContains(char arr[],char c){
  27. int i;
  28. for(i=0; i<12; i++)
  29. if(arr[i]==c)
  30. return 1;
  31. return 0;
  32. }
  33. static int getCharLoc(int y, int x){
  34. // Left side
  35. if(x<19)
  36. return 12*(y-5)+(x-7);
  37. // Right side
  38. else
  39. return 12*(y-5)+(x-27+204);
  40. }
  41. void pass(){
  42. // Get the size of the terminal window.
  43. // The size of the game window is 53x22.
  44. int BUFF_Y = 0, BUFF_X = 0;
  45. int maxy, maxx;
  46. getmaxyx(stdscr, maxy, maxx);
  47. if(maxy > 22)
  48. BUFF_Y = maxy/2 - 22/2;
  49. if(maxx > 53)
  50. BUFF_X = maxx/2 - 53/2;
  51. // Clear the screen
  52. erase();
  53. // Intro text
  54. passPrint("ROBCO INDUSTRIES (TM) TERMLINK PROTOCOL", 0, BUFF_Y, BUFF_X);
  55. passPrint("ENTER PASSWORD NOW", 1, BUFF_Y, BUFF_X);
  56. passPrint("4 ATTEMPT(S) LEFT: * * * *", 3, BUFF_Y, BUFF_X);
  57. // Generate the hex values on the left sides
  58. int arbHex;
  59. arbHex = (rand() % 200) + 63744;
  60. // Generate the string to hold the bracket tricks and words
  61. char bigString [BIGSTRING_SIZE];
  62. char randValues[] = "!@#$%^*()_-=+\\|/[]{}?\"\':;,.<>";
  63. int i;
  64. for(i=0; i<BIGSTRING_SIZE; i++){
  65. // Fill bigString with random values
  66. bigString[i] = randValues[rand()%29];
  67. }
  68. char ** wordArr = getWordArr();
  69. int WORD_POOL_SIZE = getNumWords();
  70. int WORD_SIZE = getWordLength();
  71. int WORDS_CHOSEN = getWordsToChoose();
  72. // Place a word in the string total times, making sure it doesn
  73. // overwrite another word or get placed right next to it
  74. int place; // Current place for checking and word insertion
  75. int takenWords[WORDS_CHOSEN]; // Words already placed in bigString
  76. for(int i=0; i<WORDS_CHOSEN; i++)
  77. takenWords[i] = 0;
  78. int valid; // 1 if selected word is not already used a
  79. // does not conflict with other words, 0 otherwise */
  80. int pickedWord = 0; // Indicate whether or not we've chosen the correct word
  81. int left = WORDS_CHOSEN; // # of words that still need to be chosen
  82. char correctWord[WORD_SIZE]; // the correct word
  83. while(left>0){
  84. valid = 1;
  85. // Choose a random place in bigString
  86. place = rand()%(BIGSTRING_SIZE-WORD_SIZE);
  87. // Check of any characters there or around it are A-Z
  88. for(i=place-1; i<place+WORD_SIZE+1; i++){
  89. if(bigString[i] > 64 && bigString[i] < 91){
  90. valid = 0;
  91. break;
  92. }
  93. }
  94. if(valid){
  95. int wordLoc = rand()%WORD_POOL_SIZE;
  96. if(takenWords[wordLoc])
  97. valid=0;
  98. if(valid){
  99. takenWords[wordLoc] = 1;
  100. // Add the word to bigString
  101. for(i=place; i<place+WORD_SIZE; i++){
  102. bigString[i] = *(*(wordArr+wordLoc)+(i-place));
  103. // If this is the first word chosen, it is the correct word.
  104. if(!pickedWord)
  105. correctWord[i-place] = *(*(wordArr+wordLoc)+(i-place));
  106. }
  107. pickedWord = 1;
  108. left--;
  109. }
  110. }
  111. }
  112. // Create and fill an array to keep track of which brackets were used
  113. int usedBrackets[BIGSTRING_SIZE];
  114. for(i=0; i<BIGSTRING_SIZE; i++){
  115. usedBrackets[i] = 1;
  116. }
  117. // Print the hex and the filled bigString
  118. char temp[12];
  119. int current = 0;
  120. for(i=5; i<22; i++){
  121. // Print left side
  122. for(int j=0; j<12; j++){
  123. temp[j] = bigString[j+current];
  124. }
  125. printChoices(arbHex,temp,i, OFFSET_LEFT, BUFF_Y, BUFF_X);
  126. current = current + 12;
  127. arbHex = arbHex + 12;
  128. }
  129. for(i=5; i<22; i++){
  130. // Print right side
  131. for(int j=0; j<12; j++){
  132. temp[j] = bigString[j+current];
  133. }
  134. printChoices(arbHex,temp,i, OFFSET_RIGHT, BUFF_Y, BUFF_X);
  135. current = current + 12;
  136. arbHex = arbHex + 12;
  137. }
  138. mvprintw(BUFF_Y+21,BUFF_X+40,"%c",'>');
  139. move(5,7);
  140. char currentChar[12]; // Max length currentChar could be (total possible length of a bracket trick)
  141. currentChar[0] = (char)mvinch(5,7);
  142. int y,x,origy,origx,starty,startx; // values that keep track of current yx locations, and original ones
  143. int wordLength; // How long a word is
  144. int charStart; // where character counting starts for brackets
  145. int keyPress; // key pressed by user
  146. int charCounter; // counts currentChar - used for incrementing currentChar to print or change it
  147. int bracketLength; // length of a bracket trick
  148. char endBracket; // the end bracket that corresponds to currentChar[0];
  149. int bracketTricks=0; // Total number of bracket tricks used
  150. int needsClearing = 0; // Whether or not highlights need to be pur
  151. int needsClearingMultiLine = 0; // Whether or not a multi line highlight needs to be purged
  152. char output[13]; // Used for side terminal output
  153. int allowances = 4;
  154. // Get the key config
  155. int GO_LEFT, GO_RIGHT, GO_DOWN, GO_UP;
  156. switch(getKeyConfig()){
  157. case ARROWS:
  158. GO_LEFT = KEY_LEFT;
  159. GO_RIGHT = KEY_RIGHT;
  160. GO_UP = KEY_UP;
  161. GO_DOWN = KEY_DOWN;
  162. break;
  163. case WASD:
  164. GO_LEFT = 'a';
  165. GO_RIGHT = 'd';
  166. GO_UP = 'w';
  167. GO_DOWN = 's';
  168. break;
  169. case HJKL:
  170. GO_LEFT = 'h';
  171. GO_RIGHT = 'l';
  172. GO_UP = 'k';
  173. GO_DOWN = 'j';
  174. break;
  175. }
  176. // Get rid of all typed characters
  177. int ch = getch();
  178. while(ch != ERR)
  179. ch = getch();
  180. // Finally, set nodelay to false so we can wait for input
  181. nodelay(stdscr, 0);
  182. while(1){
  183. getyx(stdscr,y,x);
  184. // Get allowances left
  185. mvprintw(BUFF_Y+1,BUFF_X+0," ");
  186. mvprintw(BUFF_Y+3,BUFF_X+0," ");
  187. switch(allowances){
  188. case 1: mvprintw(BUFF_Y+3,BUFF_X+0,"1 ATTEMPT(S) LEFT: *");
  189. attron(A_BLINK);
  190. mvprintw(BUFF_Y+1,BUFF_X+0,"!!! WARNING: LOCKOUT IMNINENT !!!");
  191. attroff(A_BLINK);
  192. attron(A_BOLD);
  193. break;
  194. case 2: mvprintw(BUFF_Y+3,BUFF_X+0,"2 ATTEMPT(S) LEFT: * *");
  195. mvprintw(BUFF_Y+1,BUFF_X+0,"ENTER PASSWORD NOW");
  196. break;
  197. case 3: mvprintw(BUFF_Y+3,BUFF_X+0,"3 ATTEMPT(S) LEFT: * * *");
  198. mvprintw(BUFF_Y+1,BUFF_X+0,"ENTER PASSWORD NOW");
  199. break;
  200. case 4: mvprintw(BUFF_Y+3,BUFF_X+0,"4 ATTEMPT(S) LEFT: * * * *");
  201. mvprintw(BUFF_Y+1,BUFF_X+0,"ENTER PASSWORD NOW");
  202. break;
  203. case 0: clear();
  204. mvprintw(BUFF_Y+10,BUFF_X+20,"TERMINAL LOCKED");
  205. mvprintw(BUFF_Y+12,BUFF_X+12,"PLEASE CONTACT AN ADMINISTRATOR");
  206. refresh();
  207. SLEEP(3000000);
  208. endwin();
  209. if(strlen(getCompleteProg())> 2)
  210. system(getCompleteProg());
  211. freeAll();
  212. exit(EXIT_FAILURE);
  213. }
  214. refresh();
  215. move(y,x);
  216. // Check if highlights need to be purged
  217. if(needsClearing){
  218. charCounter = 0;
  219. while(charCounter!=bracketLength+1){
  220. currentChar[charCounter] = (char)mvinch(origy,charStart+charCounter);
  221. mvprintw(BUFF_Y+origy,BUFF_X+charStart+charCounter,"%c",(int)currentChar[charCounter]);
  222. charCounter++;
  223. }
  224. mvprintw(BUFF_Y+21,BUFF_X+41," ",currentChar[0]);
  225. needsClearing = 0;
  226. move(y,origx);
  227. }
  228. if(needsClearingMultiLine){
  229. charCounter = 0;
  230. while(charCounter!=wordLength){
  231. currentChar[charCounter] = (char)mvinch(starty,startx);
  232. mvprintw(BUFF_Y+starty,BUFF_X+startx,"%c",currentChar[charCounter]);
  233. charCounter++;
  234. startx++;
  235. if(startx==19 || startx==39){
  236. startx-=12;
  237. starty++;
  238. if(starty == 22) {
  239. starty = 5;
  240. startx+=20;
  241. }
  242. }
  243. }
  244. mvprintw(BUFF_Y+21,BUFF_X+41," ",currentChar[0]);
  245. needsClearingMultiLine = 0;
  246. move(y,x);
  247. }
  248. // Clear the char array
  249. for(i=0;i<12;i++)
  250. currentChar[i]=' ';
  251. currentChar[0] = (char) (char)mvinch(y,x);
  252. // Set the new y and x to origy and origx
  253. origy = y;
  254. origx = x;
  255. // Check for bracket tricks
  256. if((currentChar[0]=='(' || currentChar[0]=='<' || currentChar[0]=='[' || currentChar[0]=='{') && usedBrackets[getCharLoc(y,x)] && bracketTricks<WORDS_CHOSEN){
  257. charStart = x;
  258. bracketLength=0;
  259. while(x!=18 && x!=38){
  260. x++;
  261. endBracket = (char)mvinch(y,x);
  262. bracketLength++;
  263. if((endBracket == ')' && currentChar[0]=='(') ||
  264. (endBracket == '>' && currentChar[0]=='<') ||
  265. (endBracket == ']' && currentChar[0]=='[') ||
  266. (endBracket == '}' && currentChar[0]=='{')){
  267. // Reprint the bracket trick with highlight
  268. attron(A_STANDOUT);
  269. charCounter = 0;
  270. while(1){
  271. currentChar[charCounter] = (char)mvinch(y,charStart+charCounter);
  272. mvprintw(BUFF_Y+y,BUFF_X+charStart+charCounter,"%c",currentChar[charCounter]);
  273. if(currentChar[charCounter] == endBracket)
  274. break;
  275. charCounter++;
  276. }
  277. attroff(A_STANDOUT);
  278. // Print the bracket trick to output
  279. attron(A_BOLD);
  280. for(i=0;i<=charCounter;i++)
  281. mvprintw(BUFF_Y+21,BUFF_X+41+i,"%c",(int)currentChar[i]);
  282. // Notify that highlighting will need to be cleared next move
  283. needsClearing = 1;
  284. }
  285. }
  286. if(!((endBracket == ')' && currentChar[0]=='(') ||
  287. (endBracket == '>' && currentChar[0]=='<') ||
  288. (endBracket == ']' && currentChar[0]=='[') ||
  289. (endBracket == '}' && currentChar[0]=='{'))){
  290. mvprintw(BUFF_Y+21,BUFF_X+41,"%c",currentChar[0]);
  291. }
  292. }
  293. // Check for letters
  294. else if(currentChar[0]>64 && currentChar[0]<91){
  295. // Check for letter behind the current location
  296. int tempx = x;
  297. int tempy = y;
  298. while(bigString[getCharLoc(tempy,tempx)-1]>64 && bigString[getCharLoc(tempy,tempx)-1]<91){
  299. currentChar[0] = bigString[getCharLoc(tempy,tempx)];
  300. tempx--;
  301. if(tempx==6 || tempx==26){
  302. tempx+=12;
  303. tempy--;
  304. if(tempy == 4){
  305. tempy = 21;
  306. tempx-=20;
  307. }
  308. }
  309. }
  310. startx = tempx;
  311. starty = tempy; // We'll need the location of the first char for clean
  312. // And start there
  313. charCounter = 0;
  314. while(bigString[getCharLoc(tempy,tempx)+1]>64 && bigString[getCharLoc(tempy,tempx)+1]<91){
  315. currentChar[charCounter] = bigString[getCharLoc(tempy,tempx)];
  316. charCounter++;
  317. tempx++;
  318. if(tempx==19 || tempx==39){
  319. tempx-=12;
  320. tempy++;
  321. if(tempy == 22) {
  322. tempy = 5;
  323. tempx+=20;
  324. }
  325. }
  326. }
  327. // Now currentChar is the String, and charCounter+1 is the length
  328. wordLength = charCounter+1;
  329. // Reprint the word with highlight
  330. tempx = startx;
  331. tempy = starty;
  332. attron(A_STANDOUT);
  333. charCounter = 0;
  334. while(charCounter!=wordLength){
  335. currentChar[charCounter] = (char)mvinch(tempy,tempx);
  336. mvprintw(BUFF_Y+tempy,BUFF_X+tempx,"%c",currentChar[charCounter]);
  337. charCounter++;
  338. tempx++;
  339. if(tempx==19 || tempx==39){
  340. tempx-=12;
  341. tempy++;
  342. if(tempy == 22) {
  343. tempy = 5;
  344. tempx+=20;
  345. }
  346. }
  347. }
  348. attroff(A_STANDOUT);
  349. // Print the word to output
  350. attron(A_BOLD);
  351. for(i=0;i<charCounter;i++)
  352. mvprintw(BUFF_Y+21,BUFF_X+41+i,"%c",(int)currentChar[i]);
  353. // Notify that highlighting will need to be cleared next move
  354. needsClearingMultiLine = 1;
  355. }
  356. // Nothing was found, print current char
  357. else
  358. mvprintw(BUFF_Y+21,BUFF_X+41,"%c",currentChar[0]);
  359. move(origy,origx);
  360. refresh();
  361. keyPress = getch();
  362. getyx(stdscr,y,x);
  363. if(keyPress==GO_UP){
  364. if(y>5)
  365. move(y-1,x);
  366. }
  367. if(keyPress==GO_DOWN){
  368. if(y<21)
  369. move(y+1,x);
  370. }
  371. if(keyPress==GO_LEFT){
  372. if(x>7){
  373. if(x==27)
  374. move(y,18);
  375. else
  376. move(y,x-1);
  377. }
  378. }
  379. if(keyPress==GO_RIGHT){
  380. if(x<38){
  381. if(x==18)
  382. move(y,27);
  383. else
  384. move(y,x+1);
  385. }
  386. }
  387. if(keyPress==3) // Ctrl-C
  388. exit(0);
  389. if(keyPress=='\n'){ // Enter
  390. mvprintw(BUFF_Y+17,BUFF_X+40," ");
  391. mvprintw(BUFF_Y+18,BUFF_X+40," ");
  392. mvprintw(BUFF_Y+19,BUFF_X+40," ");
  393. // If the char is a left bracket
  394. if(((currentChar[0]=='(') && currentCharContains(currentChar,')')) ||
  395. (currentChar[0]=='<' && currentCharContains(currentChar,'>')) ||
  396. (currentChar[0]=='[' && currentCharContains(currentChar,']')) ||
  397. (currentChar[0]=='{' && currentCharContains(currentChar,'}'))){
  398. // Set the selected bracket as used
  399. usedBrackets[getCharLoc(y,x)] = 0;
  400. // Increment total bracket tricks used
  401. bracketTricks++;
  402. if(rand()%5==0){
  403. // 20% chance of allowance replenish
  404. sprintf(output,"Allowance ");
  405. mvprintw(BUFF_Y+18,BUFF_X+40,">");
  406. for(i=0;i<12;i++){
  407. mvprintw(BUFF_Y+18,BUFF_X+41+i,"%c",output[i]);
  408. }
  409. sprintf(output,"replenished.");
  410. mvprintw(BUFF_Y+19,BUFF_X+40,">");
  411. for(i=0;i<12;i++){
  412. mvprintw(BUFF_Y+19,BUFF_X+41+i,"%c",output[i]);
  413. }
  414. allowances = 4;
  415. }
  416. else{
  417. // Remove a dud
  418. int tempx,tempy;
  419. pickagain:do{
  420. if(rand()%2==0)
  421. tempx = (rand()%12)+7;
  422. else
  423. tempx = (rand()%12)+27;
  424. tempy = (rand()%17)+5;
  425. } while(!(bigString[getCharLoc(tempy,tempx)]>64 && bigString[getCharLoc(tempy,tempx)]<91));
  426. while(bigString[getCharLoc(tempy,tempx)-1]>64 && bigString[getCharLoc(tempy,tempx)-1]<91){
  427. tempx--;
  428. if(tempx==6 || tempx==26){
  429. tempx+=12;
  430. tempy--;
  431. }
  432. }
  433. startx = tempx;
  434. starty = tempy;
  435. charCounter = 0;
  436. while(bigString[getCharLoc(tempy,tempx)+1]>64 && bigString[getCharLoc(tempy,tempx)+1]<91){
  437. currentChar[charCounter] = bigString[getCharLoc(tempy,tempx)];
  438. charCounter++;
  439. tempx++;
  440. if(tempx==19 || tempx==39){
  441. tempx-=12;
  442. tempy++;
  443. }
  444. }
  445. // Check if currentChar = correctWord
  446. int allCorrect=1;
  447. for(i=0;i<WORD_SIZE;i++){
  448. if(currentChar[i]!=correctWord[i])
  449. allCorrect = 0;
  450. }
  451. if(allCorrect)
  452. goto pickagain;
  453. tempx = startx;
  454. tempy = starty;
  455. while(bigString[getCharLoc(tempy,tempx)]>64 && bigString[getCharLoc(tempy,tempx)]<91){
  456. mvprintw(BUFF_Y+tempy,BUFF_X+tempx,"%c",'.');
  457. bigString[getCharLoc(tempy,tempx)] = '.';
  458. tempx++;
  459. if(tempx==19 || tempx==39){
  460. tempx-=12;
  461. tempy++;
  462. }
  463. }
  464. sprintf(output,"Dud removed.");
  465. mvprintw(BUFF_Y+19,BUFF_X+40,">");
  466. for(i=0;i<12;i++){
  467. mvprintw(BUFF_Y+19,BUFF_X+41+i,"%c",output[i]);
  468. }
  469. }
  470. }
  471. // Else compare it to the correct word
  472. else{
  473. int rightLetters = WORD_SIZE;
  474. for(i=0;i<WORD_SIZE; i++){
  475. if(currentChar[i]!=correctWord[i])
  476. rightLetters--;
  477. }
  478. if(rightLetters==WORD_SIZE){
  479. mvprintw(BUFF_Y+15,BUFF_X+40,">");
  480. for(i=0;i<12;i++){
  481. mvprintw(BUFF_Y+15,BUFF_X+41+i,"%c",currentChar[i]);
  482. }
  483. sprintf(output,"Exact match!");
  484. mvprintw(BUFF_Y+16,BUFF_X+40,">");
  485. for(i=0;i<12;i++){
  486. mvprintw(BUFF_Y+16,BUFF_X+41+i,"%c",output[i]);
  487. }
  488. sprintf(output,"Please wait ");
  489. mvprintw(BUFF_Y+17,BUFF_X+40,">");
  490. for(i=0;i<12;i++){
  491. mvprintw(BUFF_Y+17,BUFF_X+41+i,"%c",output[i]);
  492. }
  493. sprintf(output,"while system");
  494. mvprintw(BUFF_Y+18,BUFF_X+40,">");
  495. for(i=0;i<12;i++){
  496. mvprintw(BUFF_Y+18,BUFF_X+41+i,"%c",output[i]);
  497. }
  498. sprintf(output,"is accessed.");
  499. mvprintw(BUFF_Y+19,BUFF_X+40,">");
  500. for(i=0;i<12;i++){
  501. mvprintw(BUFF_Y+19,BUFF_X+41+i,"%c",output[i]);
  502. }
  503. refresh();
  504. SLEEP(3000000);
  505. endwin();
  506. if(strlen(getVictoryProg()) > 2)
  507. system(getVictoryProg());
  508. else if(strlen(getCompleteProg())> 2)
  509. system(getCompleteProg());
  510. freeAll();
  511. exit(EXIT_SUCCESS);
  512. }
  513. else{
  514. mvprintw(BUFF_Y+17,BUFF_X+40,">");
  515. for(i=0;i<12;i++){
  516. mvprintw(BUFF_Y+17,BUFF_X+41+i,"%c",currentChar[i]);
  517. }
  518. sprintf(output,"Entry denied");
  519. mvprintw(BUFF_Y+18,BUFF_X+40,">");
  520. for(i=0;i<12;i++){
  521. mvprintw(BUFF_Y+18,BUFF_X+41+i,"%c",output[i]);
  522. }
  523. sprintf(output,"%d/%d correct.",rightLetters,WORD_SIZE);
  524. mvprintw(BUFF_Y+19,BUFF_X+40,">");
  525. for(i=0;i<12;i++){
  526. mvprintw(BUFF_Y+19,BUFF_X+41+i,"%c",output[i]);
  527. }
  528. allowances--;
  529. }
  530. }
  531. move(y,x);
  532. }
  533. refresh();
  534. }
  535. endwin();
  536. freeAll();
  537. exit(EXIT_SUCCESS);
  538. }