fix infinite check bug
[rofl0r-oopoker.git] / io_terminal.cpp
blob353d2b2fe9778312aacdb370f62136e16a776522
1 /*
2 OOPoker
4 Copyright (c) 2010 Lode Vandevenne
5 All rights reserved.
7 This file is part of OOPoker.
9 OOPoker is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 OOPoker is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with OOPoker. If not, see <http://www.gnu.org/licenses/>.
23 #include "io_terminal.h"
25 #include "event.h"
26 #include "table.h"
27 #include "info.h"
30 #if defined(_WIN32)
33 #include <conio.h>
34 #include <windows.h>
35 #include <ctime>
37 int getChar()
39 return _getch();
42 void sleepMS(int milliSeconds)
44 Sleep(milliSeconds);
47 std::string getLine()
49 std::string result;
50 std::cin >> result;
51 return result;
54 int getCharNonBlocking()
56 if(kbhit()) return _getch();
57 else return 0;
60 std::string getDateString()
62 static const int SIZE = 256;
64 char buffer[SIZE];
66 // Get and print timestamp
67 time_t timestamp = time(NULL);
69 // Format string
70 const char* format = "%Y/%m/%d %H:%M:%S";
72 // Print time in my default timezone (NZDT)
73 std::strftime(buffer, SIZE, format, localtime(&timestamp));
75 std::string result = buffer;
77 return result;
81 ////////////////////////////////////////////////////////////////////////////////
82 ////////////////////////////////////////////////////////////////////////////////
83 ////////////////////////////////////////////////////////////////////////////////
84 ////////////////////////////////////////////////////////////////////////////////
85 ////////////////////////////////////////////////////////////////////////////////
86 ////////////////////////////////////////////////////////////////////////////////
87 ////////////////////////////////////////////////////////////////////////////////
88 ////////////////////////////////////////////////////////////////////////////////
91 #elif defined(linux) || defined(__linux) || defined(__linux__) || defined(__GNU__) || defined(__GLIBC__)
93 #include <iostream>
94 #include <string>
95 #include <stdio.h>
96 #include <termios.h>
97 #include <unistd.h>
98 #include <fcntl.h>
99 #include <time.h>
102 the intention of this function is the following:
103 ensure that after getLine(), the function getChar() will still work properly.
104 When doing std::cin, and later using getChar(), then getChar() immediatly returns char 10 (newline),
105 because that newline is still in the input buffer from the pressing enter after std::cin.
106 So flushcin should prevent that.
108 See documentation in io_terminal.h for more about getChar() and getLine()
110 void flushcin()
112 char nextChar = '0';
113 while( nextChar != '\n' && nextChar != EOF)
115 nextChar = std::cin.get();
120 Flush the buffer before doing mygetch, so that it gets only the keys pressed after the mygetch call.
122 See documentation in io_terminal.h for more about getChar() and getLine()
124 void termiosflush()
126 tcflush(STDIN_FILENO, TCIFLUSH);
129 int mygetch(bool echo)
131 struct termios oldt,
132 newt;
133 int ch;
134 tcgetattr( STDIN_FILENO, &oldt );
135 newt = oldt;
136 newt.c_lflag &= ~ICANON;
137 if(!echo) newt.c_lflag &= ~ECHO;
138 tcsetattr( STDIN_FILENO, TCSANOW, &newt );
139 ch = getchar();
140 tcsetattr( STDIN_FILENO, TCSANOW, &oldt );
141 return ch;
144 int getChar()
146 termiosflush();
147 return mygetch(false);
150 void sleepMS(int milliSeconds)
152 sleep(milliSeconds / 1000);
153 usleep((milliSeconds - (milliSeconds / 1000) * 1000) * 1000);
156 std::string getLine()
158 std::string result;
159 std::cin >> result;
161 flushcin();
162 return result;
165 int kbhit(void)
167 struct termios oldt, newt;
168 int ch;
169 int oldf;
171 tcgetattr(STDIN_FILENO, &oldt);
172 newt = oldt;
173 newt.c_lflag &= ~(ICANON | ECHO);
174 tcsetattr(STDIN_FILENO, TCSANOW, &newt);
175 oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
176 fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
178 ch = getchar();
180 tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
181 fcntl(STDIN_FILENO, F_SETFL, oldf);
183 if(ch != EOF)
185 ungetc(ch, stdin);
186 return 1;
189 return 0;
193 int getCharNonBlocking()
195 if(kbhit())
197 return mygetch(false);
199 return 0;
202 std::string getDateString()
204 static const int SIZE = 256;
206 char buffer[SIZE];
208 // Get and print timestamp
209 time_t timestamp = time(NULL);
211 // Format string
212 const char* format = "%Y/%m/%d %H:%M:%S";
214 // Print time in my default timezone (NZDT)
215 strftime(buffer, SIZE, format, localtime(&timestamp));
217 std::string result = buffer;
219 return result;
222 #endif
224 ////////////////////////////////////////////////////////////////////////////////
225 ////////////////////////////////////////////////////////////////////////////////
226 ////////////////////////////////////////////////////////////////////////////////
227 ////////////////////////////////////////////////////////////////////////////////
228 ////////////////////////////////////////////////////////////////////////////////
229 ////////////////////////////////////////////////////////////////////////////////
230 ////////////////////////////////////////////////////////////////////////////////
231 ////////////////////////////////////////////////////////////////////////////////
233 const std::string* getPokerTableStrings()
235 //234567891123456789212345678931234567894123456789512345678961234567897
236 static std::string s[56] = { "\
237 " , " " , " " , " \n\
238 " , " " , " " , " \n\
239 " , " " , " " , " \n\
240 ################################## \n\
241 ###" , " " , " " , "### \n\
242 " , " ## " , " " , " " , " ## " , " \n\
243 " , " ##" , " " , "## " , "\n\
244 " , " ## " , " O O P O K E R " , "## " , " \n\
245 ## "," "," "," "," "," ## \n\
246 " , " ## " , " " , "## " , "\n\
247 " , " ##" , " " , "## " , "\n\
248 " , " ## " , " " , " " , " ## " , " \n\
249 ### " , " " , " " , "### \n\
250 ################################## \n\
251 " , " " , " " , " \n\
252 " , " " , " " , " \n\
253 " , " " , " " , " \n\
254 " };
255 //234567890123456789012345678901234567890123456789012345678901234567890 --> each row is 71 characters including the newline
256 // 1 2 3 4 5 6 7
257 return s;
261 The sitting locations, in order of filling up for drawing the ascii art:
262 4 5 6
265 1 0 9
268 static void a(std::string& result, size_t& i, const std::string* s, const std::string& value)
270 result += s[i++];
271 result += value;
274 std::string centerString(const std::string& s, int num)
276 std::string result;
277 int space = num - s.size();
278 int left = space / 2;
279 int right = space - left;
280 for(int i = 0; i < left; i++) result += " ";
281 result += s;
282 for(int i = 0; i < right; i++) result += " ";
283 return result;
286 std::string getTableAsciiArt(const Info& info)
288 const std::vector<PlayerInfo>& players = info.players;
289 int dealer = info.dealer;
290 int current = info.current;
291 Round round = info.round;
293 const std::string* s = getPokerTableStrings();
294 std::string r;// = getPokerTableString();
296 std::string name[10];
297 std::string stack[10];
298 std::string wager[10];
299 std::string state[10]; //e.g. "folded", "(D)", ...
300 std::string hand[10];
301 std::string card[5];
304 for(size_t i = 0; i < 10; i++)
306 name[i] = " ";
307 stack[i] = " ";
308 wager[i] = " ";
309 state[i] = " ";
310 hand[i] = " ";
312 for(size_t i = 0; i < 5; i++)
314 card[i] = "..";
317 //for(size_t i = 0; i < 10; i++) name[i] = centerString(std::string("Player ") +(char)('0'+i), 13);
319 for(size_t i = 0; i < players.size(); i++)
321 std::string n = players[i].getName();
322 name[i] = centerString(n, 13);
324 std::stringstream ss;
326 ss.str("");
327 ss << "$" << players[i].stack;
328 stack[i] = centerString(ss.str(), 8);
330 ss.str("");
331 if(players[i].wager > 0)
333 ss << "$" << players[i].wager;
334 wager[i] = centerString(ss.str(), 8);
337 std::string st;
338 if((int)i == current) st = "Current";
339 else if(players[i].folded) st += "folded";
341 if(players.size() == 2)
343 if((int)i == info.wrap(dealer + 0)) st += " (D)";
344 if((int)i == info.wrap(dealer + 1)) st += " (B)";
346 else
348 if((int)i == info.wrap(dealer + 0)) st += " (D)";
349 if((int)i == info.wrap(dealer + 1)) st += " (S)";
350 if((int)i == info.wrap(dealer + 2)) st += " (B)";
353 if(i == (size_t)info.yourIndex) hand[i] = info.getHoleCards()[0].getShortNamePrintable() + " " + info.getHoleCards()[1].getShortNamePrintable();
354 if(players[i].showdown) hand[i] = players[i].holeCards[0].getShortNamePrintable() + " " + players[i].holeCards[1].getShortNamePrintable();
356 state[i] = centerString(st, 13);
360 if(round >= R_FLOP)
362 card[0] = info.boardCards[0].getShortNamePrintable();
363 card[1] = info.boardCards[1].getShortNamePrintable();
364 card[2] = info.boardCards[2].getShortNamePrintable();
366 if(round >= R_TURN)
368 card[3] = info.boardCards[3].getShortNamePrintable();
370 if(round >= R_RIVER)
372 card[4] = info.boardCards[4].getShortNamePrintable();
376 size_t i = 0;
378 a(r,i,s, state[4]); a(r,i,s, state[5]); a(r,i,s, state[6]);
379 a(r,i,s, name[4]); a(r,i,s, name[5]); a(r,i,s, name[6]);
380 a(r,i,s, stack[4]); a(r,i,s, stack[5]); a(r,i,s, stack[6]);
381 a(r,i,s, wager[4]); a(r,i,s, wager[5]); a(r,i,s, wager[6]);
382 a(r,i,s, state[3]); a(r,i,s, hand[4]); a(r,i,s, hand[5]); a(r,i,s, hand[6]); a(r,i,s, state[7]);
384 a(r,i,s, name[3]); a(r,i,s, wager[3]); a(r,i,s, wager[7]); a(r,i,s, name[7]);
385 a(r,i,s, stack[3]); a(r,i,s, hand[3]); a(r,i,s, hand[7]); a(r,i,s, stack[7]);
387 a(r,i,s, card[0]); a(r,i,s, card[1]); a(r,i,s, card[2]); a(r,i,s, card[3]); a(r,i,s, card[4]);
389 a(r,i,s, state[2]); a(r,i,s, hand[2]); a(r,i,s, hand[8]); a(r,i,s, state[8]);
390 a(r,i,s, name[2]); a(r,i,s, wager[2]); a(r,i,s, wager[8]); a(r,i,s, name[8]);
392 a(r,i,s, stack[2]); a(r,i,s, hand[1]); a(r,i,s, hand[0]); a(r,i,s, hand[9]);a(r,i,s, stack[8]);
393 a(r,i,s, wager[1]); a(r,i,s, wager[0]); a(r,i,s, wager[9]);
394 a(r,i,s, name[1]); a(r,i,s, name[0]); a(r,i,s, name[9]);
395 a(r,i,s, stack[1]); a(r,i,s, stack[0]); a(r,i,s, stack[9]);
396 a(r,i,s, state[1]); a(r,i,s, state[0]); a(r,i,s, state[9]);
398 return r;
401 void drawTable(const Info& info)
403 std::cout << getTableAsciiArt(info) << std::endl;
407 static std::string suitToAsciiArt(Suit suit)
409 switch(suit)
411 case S_CLUBS: return "\
412 .------.\n\
413 |? . |\n\
414 | / \\ |\n\
415 |(_ _) |\n\
416 | _|_ ?|\n\
417 '------'\n\
419 case S_DIAMONDS: return "\
420 .------.\n\
421 |? /\\ |\n\
422 | / \\ |\n\
423 | \\ / |\n\
424 | \\/ ?|\n\
425 '------'\n\
427 case S_HEARTS: return "\
428 .------.\n\
429 |?_ _ |\n\
430 |( \\/ )|\n\
431 | \\ / |\n\
432 | \\/ ?|\n\
433 '------'\n\
435 case S_SPADES: return "\
436 .------.\n\
437 |? _ |\n\
438 | ( ) |\n\
439 |(_ _) |\n\
440 | _|_ ?|\n\
441 '------'\n\
443 default: return "\
444 .------.\n\
445 |? |\n\
446 | |\n\
447 | |\n\
448 | ?|\n\
449 '------'\n\
454 static std::string cardToAsciiArt(Suit suit, int value)
456 char c = valueToSymbol(value);
457 std::string s = suitToAsciiArt(suit);
458 for(size_t i = 0; i < s.size(); i++) if(s[i] == '?') s[i] = c;
459 return s;
462 std::string cardsToAsciiArt(const std::vector<Card>& cards)
464 std::vector<std::string> strings(cards.size());
465 for(size_t i = 0; i < cards.size(); i++)
467 strings[i] = cardToAsciiArt(cards[i].suit, cards[i].value);
470 std::string result;
472 for(size_t j = 0; j < 6; j++)
474 for(size_t i = 0; i < cards.size(); i++)
476 for(size_t h = 0; h < 8; h++)
478 result += strings[i][j * 9 + h];
481 result += " ";
483 result += "\n";
486 return result;
489 bool pressAnyKeyOrQuit()
491 std::cout << "Press any key to continue (q to quit)" << std::endl;
493 int c = getChar();
495 return c == 'q';
498 void pressAnyKey()
500 std::cout << "Press any key to continue" << std::endl;
502 getChar();