freg  0.3
Free-Roaming Elementary Game
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
CursedScreen.cpp
Go to the documentation of this file.
1  /* freg, Free-Roaming Elementary Game with open and interactive world
2  * Copyright (C) 2012-2014 Alexander 'mmaulwurff' Kromm
3  * mmaulwurff@gmail.com
4  *
5  * This file is part of FREG.
6  *
7  * FREG is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * FREG is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with FREG. If not, see <http://www.gnu.org/licenses/>. */
19 
20 /**\file CursedScreen.cpp
21  * \brief This file is related to curses screen for freg. */
22 
23 #include <QDir>
24 #include <QLocale>
25 #include <QMutexLocker>
26 #include "screens/CursedScreen.h"
27 #include "screens/IThread.h"
28 #include "Shred.h"
29 #include "blocks/Block.h"
30 #include "blocks/Inventory.h"
31 #include "Player.h"
32 
33 const char OBSCURE_BLOCK = ' ';
34 const int QUICK_INVENTORY_X_SHIFT = 36;
35 const int SHADOW_COLOR = COLOR_PAIR(BLACK_BLACK) | A_BOLD | A_REVERSE;
36 
37 const int MINIMAP_WIDTH = 11;
38 const int MINIMAP_HEIGHT = 7;
39 
40 void Screen::PrintVerticalDirection(WINDOW * const window, const int y,
41  const int x, const dirs direction)
42 {
43  mvwaddstr(window, y, x + 3, qPrintable(Block::DirString(direction)));
44 }
45 
46 void Screen::Arrows(WINDOW * const window, const int x, const int y,
47  const dirs direction)
48 const {
49  wcolor_set(window, WHITE_BLACK, nullptr);
50  if ( direction >= DOWN ) {
51  PrintVerticalDirection(window, 0, x, UP);
53  } else {
54  PrintVerticalDirection(window, 0, x, NORTH);
56  }
57  wcolor_set(window, WHITE_RED, nullptr);
58  mvwaddstr(window, 0, x, qPrintable(arrows[SOUTH]));
59  waddstr (window, qPrintable(arrows[SOUTH]));
60  mvwaddstr(window, SCREEN_SIZE+1, x, qPrintable(arrows[NORTH]));
61  waddstr (window, qPrintable(arrows[NORTH]));
62  HorizontalArrows(window, y, direction);
63  (void)wmove(window, y, x);
64 }
65 
66 void Screen::HorizontalArrows(WINDOW * const window, const int y,
67  const dirs direction)
68 const {
69  wcolor_set(window, WHITE_BLACK, nullptr);
70  const static QString dir_chars[] = {
71  QString(),
72  QString(),
73  Block::DirString(NORTH).left(1),
74  Block::DirString(SOUTH).left(1),
75  Block::DirString(EAST ).left(1),
76  Block::DirString(WEST ).left(1)
77  };
78  QString left, right;
79  switch ( direction ) {
80  case UP:
81  case DOWN:
82  case NORTH: left = dir_chars[WEST]; right = dir_chars[EAST]; break;
83  case SOUTH: left = dir_chars[EAST]; right = dir_chars[WEST]; break;
84  case EAST: left = dir_chars[NORTH]; right = dir_chars[SOUTH]; break;
85  case WEST: left = dir_chars[SOUTH]; right = dir_chars[NORTH]; break;
86  }
87  mvwaddstr(window, y-1, 0, qPrintable(left));
88  mvwaddstr(window, y-1, SCREEN_SIZE*2+1, qPrintable(right));
89 
90  wcolor_set(window, WHITE_RED, nullptr);
91  mvwaddstr(window, y, 0, qPrintable(arrows[EAST]));
92  mvwaddstr(window, y, SCREEN_SIZE*2+1, qPrintable(arrows[WEST]));
93 }
94 
96  clear();
97  static const QString action_strings[] = {
98  tr("[U] use, eat"),
99  tr("[T] throw"),
100  tr("[O] obtain"),
101  tr("[N] inscribe"),
102  tr("[B] build"),
103  tr("[C] craft"),
104  tr("[E] equipment"),
105  };
106  (void)wmove(actionWin, 0, 0);
107  for (int i=0; i<=ACTION_WIELD; ++i) {
108  waddstr(actionWin, qPrintable(action_strings[i]));
109  waddch(actionWin, '\n');
110  }
111  mvwchgat(actionWin, actionMode, 0, 20, A_NORMAL, BLACK_WHITE, nullptr);
112  refresh();
113  wrefresh(actionWin);
114  updated = false;
115 }
116 
117 void Screen::Update(int, int, int) { updated = false; }
118 void Screen::UpdatePlayer() { updated = false; }
119 void Screen::UpdateAround(int, int, int, int) { updated = false; }
120 void Screen::Move(int) { updated = false; }
121 bool Screen::IsScreenWide() { return COLS >= (SCREEN_SIZE*2+2)*2; }
122 
124  CleanFileToShow();
125  updated = false;
126 }
127 
128 void Screen::PassString(QString & str) const {
129  inputActive = true;
130  wattrset(notifyWin, A_UNDERLINE);
131  waddstr(notifyWin, qPrintable(tr("Enter input: ")));
132  char temp_str[MAX_NOTE_LENGTH + 1];
133  echo();
134  wgetnstr(notifyWin, temp_str, MAX_NOTE_LENGTH);
135  inputActive = false;
136  noecho();
137  lastNotification = str;
138  fprintf(notifyLog, "%lu: Command: %s\n", w->Time(), temp_str);
139  str = QString::fromUtf8(temp_str);
140 }
141 
142 char Screen::CharNumber(const int z) const {
143  if ( HEIGHT-1 == z ) { // sky
144  return ' ';
145  }
146  const int z_dif = ( UP==player->GetDir() ) ?
147  z - player->Z() : player->Z() - z;
148  return ( z_dif == 0 ) ?
149  ' ' : ( z_dif<0 ) ?
150  '-' : ( z_dif<10 ) ?
151  z_dif+'0' : '+';
152 }
153 
154 char Screen::CharNumberFront(const int i, const int j) const {
155  const int dist = (( NORTH==player->GetDir() || SOUTH==player->GetDir() ) ?
156  abs(player->Y()-j) :
157  abs(player->X()-i)) -1;
158  return ( dist>9 ) ?
159  '+' : ( dist>0 ) ?
160  dist+'0' : ' ';
161 }
162 
163 int Screen::RandomBlink() const { return RandomBit() ? 0 : A_REVERSE; }
164 bool Screen::RandomBit() const { return (randomBlink >>= 1) & 1; }
165 
166 int Screen::Color(const int kind, const int sub) const {
167  const int color = COLOR_PAIR(VirtScreen::Color(kind, sub));
168  switch ( kind ) { // foreground_background
169  case TELEGRAPH: return color | A_BOLD;
170  case LIQUID: switch ( sub ) {
171  case H_MEAT:
172  case A_MEAT:
173  case SUB_CLOUD: return color;
174  default: return color | RandomBlink();
175  case ACID: return color | RandomBlink() | A_BOLD;
176  case WATER: return RandomBit() ? color : COLOR_PAIR(BLUE_BLUE)|A_BOLD;
177  } break;
178  default: switch ( sub ) {
179  case GOLD: return color | RandomBlink();
180  case IRON:
181  case NULLSTONE:
182  case DIAMOND: return color | A_BOLD;
183  case ACID:
184  case SUB_DUST: return color | A_BOLD | A_REVERSE;
185  case FIRE: return color | A_BLINK | RandomBlink();
186  case SKY:
187  case STAR:
188  if ( w->GetEvernight() ) return COLOR_PAIR(BLACK_BLACK);
189  switch ( w->PartOfDay() ) {
190  case TIME_NIGHT: return
191  COLOR_PAIR(WHITE_BLACK) | ( RandomBit() ? A_BOLD : 0 );
192  case TIME_MORNING: return COLOR_PAIR(WHITE_BLUE);
193  case TIME_NOON: return COLOR_PAIR( CYAN_CYAN);
194  case TIME_EVENING: return COLOR_PAIR(WHITE_CYAN);
195  } break;
196  default: return color;
197  } break;
198  }
199 } // color_pairs Screen::Color(int kind, int sub)
200 
201 int Screen::ColorShred(const shred_type type) const {
202  switch ( type ) { // foreground_background
204  case SHRED_TESTSHRED:
205  case SHRED_EMPTY:
206  case SHRED_CHAOS: return COLOR_PAIR( WHITE_BLACK);
207  case SHRED_DEAD_FOREST: return COLOR_PAIR(YELLOW_BLACK);
208  case SHRED_DEAD_HILL: return COLOR_PAIR( BLACK_WHITE) | A_BOLD;
209  case SHRED_PYRAMID:
210  case SHRED_WASTE:
211  case SHRED_CASTLE:
212  case SHRED_MOUNTAIN: return Color(BLOCK, STONE);
213  case SHRED_PLAIN: return Color(BLOCK, GREENERY);
214  case SHRED_DESERT: return Color(BLOCK, SAND);
215  case SHRED_WATER: return Color(LIQUID, WATER);
216  case SHRED_LAVA_LAKE: return Color(LIQUID, STONE);
217  case SHRED_ACID_LAKE: return Color(LIQUID, ACID);
218  case SHRED_CRATER: return COLOR_PAIR( WHITE_WHITE) | A_BOLD;
219  case SHRED_FOREST: return COLOR_PAIR(YELLOW_GREEN);
220  case SHRED_HILL: return COLOR_PAIR( WHITE_GREEN);
221  case SHRED_NULLMOUNTAIN: return Color(BLOCK, NULLSTONE);
222  }
223  Q_UNREACHABLE();
224  return COLOR_PAIR(WHITE_BLACK);
225 }
226 
227 void Screen::MovePlayer(const dirs dir) {
228  if ( player->GetDir() == dir ) {
229  player->Move(dir);
230  } else {
231  player->SetDir(dir);
232  }
233 }
234 
235 void Screen::MovePlayerDiag(const dirs dir1, const dirs dir2) const {
236  player->SetDir(dir1);
237  static bool step_trigger = true;
238  player->Move(step_trigger ? dir1 : dir2);
239  step_trigger = !step_trigger;
240 }
241 
243 
244 void Screen::ControlPlayer(const int ch) {
245  if ( player->GetBlock() == nullptr ) return;
246  if ( ch != KEY_MOUSE ) {
247  CleanFileToShow();
248  }
249  /// \todo: ctrl-z (to background) support
250  // Q, ctrl-c, ctrl-d, ctrl-q, ctrl-x
251  if ( 'Q' == ch
252  || 3 == ch
253  || 4 == ch
254  || 17 == ch
255  || 24 == ch
256  || 'X' == ch
257  || KEY_F(10) == ch )
258  {
259  emit ExitReceived();
260  input->Stop();
261  return;
262  } // else:
263  if ( 'a'<=ch && ch<='z' ) { // actions with inventory
264  InventoryAction(ch-'a');
265  return;
266  } // else:
267  switch ( ch ) { // interactions with world
268  default:
269  Notify(tr("Unknown key. Press 'H' for help."));
270  #ifndef QT_NO_DEBUG
271  Notify(QString("Pressed key code: %1.").arg(ch));
272  #endif
273  break;
274  case 'W': case KEY_UP: case '8': MovePlayer(NORTH); break;
275  case 'S': case KEY_DOWN: case '2': MovePlayer(SOUTH); break;
276  case 'D': case KEY_RIGHT: case '6': MovePlayer(EAST); break;
277  case 'A': case KEY_LEFT: case '4': MovePlayer(WEST); break;
278  case KEY_END: case '5': player->Move(DOWN); break;
279  case '7': MovePlayerDiag(NORTH, WEST); break;
280  case '9': MovePlayerDiag(NORTH, EAST); break;
281  case '1': MovePlayerDiag(SOUTH, WEST); break;
282  case '3': MovePlayerDiag(SOUTH, EAST); break;
283  case '=':
284  case '0': MovePlayer(player->GetDir()); break;
285  case ' ': player->Jump(); break;
286  case '{': player->Move(World::TurnLeft (player->GetDir())); break;
287  case '}': player->Move(World::TurnRight(player->GetDir())); break;
288 
289  case '>': player->SetDir(World::TurnRight(player->GetDir())); break;
290  case '<': player->SetDir(World::TurnLeft (player->GetDir())); break;
291  case 'V':
292  case KEY_NPAGE: player->SetDir(DOWN); break;
293  case '^':
294  case KEY_PPAGE: player->SetDir(UP); break;
295 
296  case 'I':
297  case KEY_HOME: player->Backpack(); break;
298  case 8:
299  case KEY_F(8):
300  case KEY_DC: // delete
301  case KEY_BACKSPACE: player->Damage(); break;
302  case '\n':
303  case 13:
304  case KEY_F(2):
305  case 'F': player->Use(); break;
306  case '*':
307  case KEY_F(3):
308  case '?': player->Examine(); break;
309  case KEY_F(4):
310  case '~': player->Inscribe(); break;
311  case 27: /* esc */ player->StopUseAll(); break;
312 
313  case KEY_IC: player->Build(1); break; // insert
314  case 'B': SetActionMode(ACTION_BUILD); break;
315  case 'C': SetActionMode(ACTION_CRAFT); break;
316  case 'T': SetActionMode(ACTION_THROW); break;
317  case 'N': SetActionMode(ACTION_INSCRIBE); break;
318  case 'G':
319  case 'O': SetActionMode(ACTION_OBTAIN); break;
320  case 'E': SetActionMode(ACTION_WIELD); break;
321  case 'U': SetActionMode(ACTION_USE); break;
322  case '[':
324  ACTION_WIELD : static_cast<actions>(actionMode-1));
325  break;
326  case ']':
328  ACTION_USE : static_cast<actions>(actionMode+1));
329  break;
330  case 'Z':
331  if ( player->PlayerInventory() ) {
333  Notify(tr("Inventory reorganized."));
334  }
335  break;
336  case KEY_HELP:
337  case KEY_F(1):
338  case 'H': ProcessCommand("help"); break;
339  case KEY_F(5):
340  case 'R':
341  case 'L': RePrint(); break;
342 
343  case '-':
345  Notify(tr("%1 focus is set.").
346  arg(shiftFocus ? tr("Low") : tr("Normal")));
347  break; // move focus down
348  case '+':
350  Notify(tr("%1 focus is set.").
351  arg(shiftFocus ? tr("High") : tr("Normal")));
352  break;
353 
354  case KEY_F(12):
355  case '!': player->SetCreativeMode( not player->GetCreativeMode() ); break;
356  case KEY_F(9):
357  case '\\':
358  case ':':
359  case '/': PassString(previousCommand); // no break
360  case '.': ProcessCommand(previousCommand); break;
361 
362  case KEY_MOUSE: ProcessMouse(); break;
363  }
364  updated = false;
365 } // void Screen::ControlPlayer(int ch)
366 
367 void Screen::ExamineOnNormalScreen(int x, int y, int z, const int step) const {
368  World * const world = GetWorld();
369  x = (x-1)/2 + GetNormalStartX();
370  y = y-1 + GetNormalStartY();
371  for ( ; world->GetBlock(x, y, z)->Transparent() == INVISIBLE; z += step);
372  player->Examine(x, y, z);
373 }
374 
376  MEVENT mevent;
377  if ( getmouse(&mevent) == ERR ) return;
378  if ( wenclose(leftWin, mevent.y, mevent.x) ) { // left window
379  if ( not wmouse_trafo(leftWin, &mevent.y, &mevent.x, false) ) return;
380  if ( player->UsingSelfType() == USAGE_TYPE_OPEN ) {
381  Notify(tr("Your inventory."));
382  return;
383  }
384  if ( not (
385  0 < mevent.x && mevent.x < SCREEN_SIZE*2 + 1 &&
386  0 < mevent.y && mevent.y < SCREEN_SIZE ) )
387  {
388  Notify(tr("Left window, Down view."));
389  return;
390  }
391  ExamineOnNormalScreen(mevent.x, mevent.y, player->Z(), -1);
392  } else if ( wenclose(notifyWin, mevent.y, mevent.x) ) { // notify
393  Notify(tr("Notifications area."));
394  } else if ( wenclose(actionWin, mevent.y, mevent.x) ) { // actions
395  wmouse_trafo(actionWin, &mevent.y, &mevent.x, false);
396  SetActionMode(static_cast<actions>(mevent.y));
397  } else if ( wenclose(minimapWin, mevent.y, mevent.x) ) { // minimap
398  if (not wmouse_trafo(minimapWin, &mevent.y, &mevent.x, false)) return;
399  if ( not (
400  0 < mevent.x && mevent.x < MINIMAP_WIDTH-1 &&
401  0 < mevent.y && mevent.y < MINIMAP_HEIGHT-1 ) )
402  {
403  Notify(tr("Minimap."));
404  return;
405  }
406  const int shred_x = mevent.x/2 + GetMinimapStartX();
407  const int shred_y = mevent.y-1 + GetMinimapStartY();
408  Notify((0 <= shred_x && shred_x < w->NumShreds() &&
409  0 <= shred_y && shred_y < w->NumShreds() ) ?
410  tr("On minimap: %1").arg( Shred::ShredTypeName(
411  w->GetShredByPos(shred_x, shred_y)->GetTypeOfShred())) :
412  tr("You can't see that far.") );
413  } else if ( wenclose(hudWin, mevent.y, mevent.x) ) { // HUD
414  if ( not wmouse_trafo(hudWin, &mevent.y, &mevent.x, false) ) return;
415  mevent.x -= QUICK_INVENTORY_X_SHIFT;
416  mevent.x /= 2;
417  if ( not ( IsScreenWide() && 0 <= mevent.x && mevent.x <= 'z'-'a' ) ) {
418  Notify(tr("Information: left - player, right - focused thing."));
419  return;
420  }
421  Inventory * const inv = player->PlayerInventory();
422  if ( inv == nullptr ) return;
423  Notify( tr("In inventory at slot '%1': %2.").
424  arg(char(mevent.x + 'a')).
425  arg( inv->Number(mevent.x) ?
426  inv->InvFullName(mevent.x) :
427  tr("nothing") ) );
428  } else if ( wenclose(rightWin, mevent.y, mevent.x) ) { // right window
429  if ( not wmouse_trafo(rightWin, &mevent.y, &mevent.x, false) ) return;
430  if ( fileToShow != nullptr ) {
431  Notify(tr("Reading file: \"%1\".").arg(fileToShow->fileName()));
432  } else if (player->UsingType() == USAGE_TYPE_OPEN ) {
433  Notify(tr("Opened inventory."));
434  } else if ( not (
435  0 < mevent.x && mevent.x < SCREEN_SIZE*2 + 1 &&
436  0 < mevent.y && mevent.y < SCREEN_SIZE ) )
437  {
438  Notify(tr("Right window, %1 view.").
439  arg(Block::DirString(player->GetDir())));
440  } else {
441  switch ( player->GetDir() ) {
442  case UP:
443  ExamineOnNormalScreen(mevent.x, mevent.y, player->Z()+1, 1);
444  break;
445  case DOWN:
446  ExamineOnNormalScreen(mevent.x, mevent.y, player->Z()-1, -1);
447  break;
448  default:
449  PrintFront(player->GetDir(), mevent.x, mevent.y);
450  break;
451  }
452  }
453  } else {
454  Notify(tr("Nothing here. Click on something to get information."));
455  }
456 }
457 
458 void Screen::ProcessCommand(const QString command) {
459  if ( command.length()==1 && command.at(0)!='.' ) {
460  ControlPlayer(command.at(0).toLatin1());
461  return;
462  }
463  switch ( Player::UniqueIntFromString(qPrintable(command)) ) {
464  case Player::UniqueIntFromString("blink"):
465  blinkOn = not blinkOn;
466  Notify(tr("Block blink is now %1.").
467  arg(blinkOn ? tr("on") : tr("off")));
468  break;
469  case Player::UniqueIntFromString("size"):
470  Notify(tr("Terminal height: %1 lines, width: %2 chars.").
471  arg(LINES).arg(COLS));
472  break;
473  case Player::UniqueIntFromString("moo"):
474  Notify("^__^");
475  Notify("(oo)\\_______");
476  Notify("(__)\\ )\\/\\");
477  Notify(" ||----w |");
478  Notify(" || ||");
479  break;
480  default: player->ProcessCommand(command); break;
481  }
482 }
483 
484 void Screen::SetActionMode(const actions mode) {
485  mvwchgat(actionWin, actionMode, 0,20, A_NORMAL, WHITE_BLACK, nullptr);
486  mvwchgat(actionWin, actionMode=mode, 0,20, A_NORMAL, BLACK_WHITE, nullptr);
487  switch ( mode ) {
488  case ACTION_USE: Notify(tr("Action: use in inventory.")); break;
489  case ACTION_THROW: Notify(tr("Action: throw from inventory.")); break;
490  case ACTION_OBTAIN: Notify(tr("Action: obtain to inventory.")); break;
491  case ACTION_INSCRIBE: Notify(tr("Action: inscribe in inventory.")); break;
492  case ACTION_BUILD: Notify(tr("Action: build from inventory.")); break;
493  case ACTION_CRAFT: Notify(tr("Action: craft in inventory.")); break;
494  case ACTION_WIELD: Notify(tr("Action: organize equipment.")); break;
495  }
496  wrefresh(actionWin);
497  updated = false;
498 }
499 
500 void Screen::InventoryAction(const int num) const {
501  switch ( actionMode ) {
502  case ACTION_USE: player->Use (num); break;
503  case ACTION_THROW: player->Throw (num); break;
504  case ACTION_OBTAIN: player->Obtain (num); break;
505  case ACTION_INSCRIBE: player->Inscribe(num); break;
506  case ACTION_BUILD: player->Build (num); break;
507  case ACTION_CRAFT: player->Craft (num); break;
508  case ACTION_WIELD: player->Wield (num); break;
509  }
510 }
511 
512 void Screen::ActionXyz(int * x, int * y, int * z) const {
513  VirtScreen::ActionXyz(x, y, z);
514  if (
515  DOWN != player->GetDir() &&
516  UP != player->GetDir() &&
517  ( AIR==w->GetBlock(*x, *y, *z)->Sub() || AIR==w->GetBlock(
518  player->X(),
519  player->Y(),
520  player->Z()+shiftFocus)->Sub() ))
521  {
522  *z += shiftFocus;
523  }
524 }
525 
527  int x, y, z;
528  ActionXyz(&x, &y, &z);
529  return ( player->Visible(x, y, z) ) ?
530  GetWorld()->GetBlock(x, y, z) :
531  nullptr;
532 }
533 
534 char Screen::PrintBlock(const Block & block, WINDOW * const window) const {
535  const int kind = block.Kind();
536  const int sub = block.Sub();
537  wattrset(window, Color(kind, sub));
538  return CharName(kind, sub);
539 }
540 
542  if ( updated ) return;
543  updated = true;
544  w->Lock();
545  PrintHUD();
546  const dirs dir = player->GetDir();
547  if ( player->UsingSelfType() != USAGE_TYPE_OPEN ) { // left window
548  PrintNormal(leftWin, (UP==dir || DOWN==dir) ? NORTH : dir);
549  } else {
551  }
552  if ( fileToShow == nullptr ) { // right window
553  switch ( player->UsingType() ) {
554  default:
555  if ( dir <= DOWN ) {
556  PrintNormal(rightWin, dir);
557  } else if ( rightWin != nullptr ) {
558  PrintFront(dir);
559  }
560  break;
562  DisplayFile(QString(home_path + w->WorldName() + "/texts/"
564  player->GetUsingInInventory())->GetNote()));
566  break;
567  case USAGE_TYPE_READ: {
568  const Block * const focused = GetFocusedBlock();
569  if ( focused != nullptr ) {
570  DisplayFile(QString(home_path + w->WorldName()
571  + "/texts/" + GetFocusedBlock()->GetNote()));
573  }
574  } break;
575  case USAGE_TYPE_OPEN: {
576  Block * const focused = GetFocusedBlock();
577  if ( focused != nullptr ) {
578  PrintInv(rightWin, focused, focused->HasInventory());
579  }
580  } break;
581  }
582  }
583  w->Unlock();
584 } // void Screen::Print()
585 
587  werase(hudWin);
588  if ( player->GetCreativeMode() ) {
589  mvwaddstr (hudWin, 0, 0,
590  qPrintable(tr("Creative Mode\nxyz: %1, %2, %3. YX: %4, %5.")
591  .arg(player->GlobalX()).arg(player->GlobalY()).arg(player->Z())
592  .arg(player->GetLongitude()).arg(player->GetLatitude())) );
593  } else {
594  const int dur = player->GetBlock()->GetDurability();
595  if ( dur > 0 ) { // HitPoints line
596  static const int player_health_char = ascii ? '@' : 0x2665;
597  PrintBar(0,
598  (dur > MAX_DURABILITY/5) ?
599  COLOR_PAIR(RED_BLACK) : (COLOR_PAIR(BLACK_RED) | A_BLINK),
600  player_health_char, dur*100/MAX_DURABILITY);
601  }
602  const int breath = player->BreathPercent();
603  if ( breath != 100 ) {
604  static const int player_breath_char = ascii ? 'o' : 0x00b0;
605  PrintBar(16, COLOR_PAIR(BLUE_BLACK), player_breath_char, breath);
606  }
607  static const QString satiation_strings[] = {
608  tr("Hungry"),
609  tr("Content"),
610  satiation_strings[1],
611  tr("Full"),
612  tr("Gorged")
613  };
614  static const int satiation_colors[] = {
615  RED_BLACK,
616  WHITE_BLACK,
617  satiation_colors[1],
618  GREEN_BLACK,
619  BLUE_BLACK
620  };
621  const int satiation_state = player->SatiationPercent() / 25;
622  wcolor_set(hudWin, satiation_colors[satiation_state], nullptr);
623  mvwaddstr(hudWin, 1,1, qPrintable(satiation_strings[satiation_state]));
624  }
625  Block * const focused = GetFocusedBlock();
626  if ( focused && Block::GetSubGroup(focused->Sub()) != GROUP_AIR ) {
627  const int left_border = IsScreenWide() ?
628  (SCREEN_SIZE*2+2) * 2 :
629  SCREEN_SIZE*2+2 - 15;
630  PrintBar(left_border - 15,
631  Color(focused->Kind(), focused->Sub()),
632  (focused->IsAnimal() == nullptr) ? '+' : '*',
633  focused->GetDurability()*100/MAX_DURABILITY,
634  false);
635  const QString name = focused->FullName();
636  mvwaddstr(hudWin, 1, left_border-name.length() - 1,
637  qPrintable(focused->FullName()));
638  const QString note = focused->GetNote();
639  if ( not note.isEmpty() && IsScreenWide() ) {
640  const int width = qMin(36, note.length() + 2);
641  (void)wmove(hudWin, 2, left_border - width - 1);
642  if ( note.length()+2 <= width ) {
643  wprintw(hudWin, "~:%s", qPrintable(note));
644  } else {
645  wprintw(hudWin, "~:%s ...", qPrintable(note.left(width - 6)));
646  }
647  }
648  }
650  wrefresh(hudWin);
651  PrintMiniMap();
652 } // void Screen::PrintHUD()
653 
655  Inventory * const inv = player->PlayerInventory();
656  if ( inv!=nullptr && IsScreenWide() ) {
657  for (int i=inv->Size()-1; i>=0; --i) {
658  wstandend(hudWin);
659  const int x = QUICK_INVENTORY_X_SHIFT+i*2;
660  mvwaddch(hudWin, 0, x, 'a'+i);
661  switch ( inv->Number(i) ) {
662  case 0: break;
663  default: mvwaddch(hudWin, 2, x, inv->Number(i)+'0'); // no break;
664  case 1: mvwaddch(hudWin, 1, x,
665  PrintBlock(*inv->ShowBlock(i), hudWin));
666  break;
667  }
668  }
669  }
670 }
671 
673  return Shred::CoordOfShred(player->X()) - 2;
674 }
675 
677  return Shred::CoordOfShred(player->Y()) - 2;
678 }
679 
681  (void)wmove(minimapWin, 1, 0);
682  const int i_start = GetMinimapStartY();
683  const int j_start = GetMinimapStartX();
684  for (int i=i_start; i <= i_start+4; ++i, waddch(minimapWin, '\n'))
685  for (int j=j_start; j <= j_start+4; ++j) {
686  if ( i<0 || j<0 || i>=w->NumShreds() || j>=w->NumShreds() ) {
687  wstandend(minimapWin);
688  waddstr (minimapWin, " ");
689  } else {
690  Shred * const shred = w->GetShredByPos(j, i);
691  wattrset(minimapWin, ColorShred(shred->GetTypeOfShred()));
692  wprintw (minimapWin, " %c", shred->GetTypeOfShred());
693  }
694  }
695  wstandend(minimapWin);
696  box(minimapWin, 0, 0);
697  mvwaddstr(minimapWin, 0, 1, qPrintable(tr("Minimap")));
698  wrefresh(minimapWin);
699 }
700 
702  return ( player->X()/SHRED_WIDTH )*SHRED_WIDTH +
703  ( SHRED_WIDTH-SCREEN_SIZE )/2;
704 }
705 
707  return ( player->Y()/SHRED_WIDTH )*SHRED_WIDTH +
708  ( SHRED_WIDTH-SCREEN_SIZE )/2;
709 }
710 
711 void Screen::PrintNormal(WINDOW * const window, const dirs dir) const {
712  (void)wmove(window, 1, 1);
713  int k_start, k_step;
714  if ( UP == dir ) {
715  k_start = player->Z() + 1;
716  k_step = 1;
717  } else {
718  k_start = player->Z() - ( DOWN==dir );
719  k_step = -1;
720  }
721  const int start_x = GetNormalStartX();
722  const int start_y = GetNormalStartY();
723  const int end_x = start_x + SCREEN_SIZE;
724  const int end_y = start_y + SCREEN_SIZE;
725  for (int j=start_y; j<end_y; ++j, waddstr(window, "\n_")) {
726  randomBlink = blinkOn ? qrand() : 0;
727  for (int i=start_x; i<end_x; ++i ) {
728  Shred * const shred = w->GetShred(i, j);
729  const int i_in = Shred::CoordInShred(i);
730  const int j_in = Shred::CoordInShred(j);
731  int k = k_start;
732  for ( ; INVISIBLE == shred->GetBlock(i_in, j_in, k)->Transparent();
733  k += k_step);
734  if ( player->Visible(i, j, k) ) {
735  waddch(window,
736  PrintBlock(*shred->GetBlock(i_in, j_in, k), window));
737  waddch(window, CharNumber(k));
738  } else {
739  wattrset(window, SHADOW_COLOR);
740  waddch(window, OBSCURE_BLOCK);
741  waddch(window, ' ');
742  }
743  }
744  }
745 
746  if ( dir > DOWN ) {
747  const Block * const block = player->GetBlock();
748  wattrset(window, Color(block->Kind(), block->Sub()));
749  mvwaddstr(window, player->Y()-start_y+1, (player->X()-start_x)*2+2,
750  qPrintable(arrows[player->GetDir()]));
751  }
752 
753  wstandend(window);
754  box(window, 0, 0);
755  Arrows(window, (player->X()-start_x)*2+1, player->Y()-start_y+1, UP);
756  wrefresh(window);
757 } // void Screen::PrintNormal(WINDOW * window, int dir)
758 
759 void Screen::PrintFront(const dirs dir, const int block_x, const int block_y)
760 const {
761  const int pX = player->X();
762  const int begin_x = ( pX/SHRED_WIDTH )*SHRED_WIDTH +
763  ( SHRED_WIDTH-SCREEN_SIZE )/2;
764  const int pY = player->Y();
765  const int begin_y = ( pY/SHRED_WIDTH )*SHRED_WIDTH +
766  ( SHRED_WIDTH-SCREEN_SIZE )/2;
767  int x_step, z_step,
768  x_start, z_start,
769  x_end, z_end;
770  int * x, * z;
771  int i, j;
772  int arrow_X;
773  switch ( dir ) {
774  case NORTH:
775  x = &i;
776  x_step = 1;
777  x_start = begin_x;
778  x_end = x_start + SCREEN_SIZE;
779  z = &j;
780  z_step = -1;
781  z_start = pY - 1;
782  z_end = qMax(0, pY - SHRED_WIDTH*2);
783  arrow_X = (pX - begin_x)*2 + 1;
784  break;
785  case SOUTH:
786  x = &i;
787  x_step = -1;
788  x_start = SCREEN_SIZE - 1 + begin_x;
789  x_end = begin_x - 1;
790  z = &j;
791  z_step = 1;
792  z_start = pY + 1;
793  z_end = qMin(pY+SHRED_WIDTH*2, w->GetBound());
794  arrow_X = (SCREEN_SIZE - pX + begin_x)*2 - 1;
795  break;
796  case EAST:
797  x = &j;
798  x_step = 1;
799  x_start = begin_y;
800  x_end = SCREEN_SIZE + begin_y;
801  z = &i;
802  z_step = 1;
803  z_start = pX + 1;
804  z_end = qMin(pX + SHRED_WIDTH*2, w->GetBound());
805  arrow_X = (pY - begin_y)*2 + 1;
806  break;
807  case WEST:
808  x = &j;
809  x_step = -1;
810  x_start = SCREEN_SIZE - 1 + begin_y;
811  x_end = begin_y - 1;
812  z = &i;
813  z_step = -1;
814  z_start = pX - 1;
815  z_end = qMax(0, pX - SHRED_WIDTH*2);
816  arrow_X = (SCREEN_SIZE - pY + begin_y)*2 - 1;
817  break;
818  default:
819  Q_UNREACHABLE();
820  return;
821  }
822  const int k_start =
823  qBound(SCREEN_SIZE-1, player->Z()+SCREEN_SIZE/2, HEIGHT-1);
824  if ( block_x > 0 ) {
825  // ugly! use print function to get block by screen coordinates.
826  int k = k_start - block_y + 1;
827  *x = x_start + x_step * (block_x-1)/2;
828  for (*z=z_start; *z!=z_end && w->GetBlock(i, j, k)->
829  Transparent()==INVISIBLE;
830  *z += z_step);
831  player->Examine(i, j, k);
832  return;
833  }
834  const int sky_color = Color(BLOCK, SKY);
835  (void)wmove(rightWin, 1, 1);
836  for (int k=k_start; k>k_start-SCREEN_SIZE; --k, waddstr(rightWin, "\n_")) {
837  randomBlink = blinkOn ? qrand() : 0;
838  for (*x=x_start; *x!=x_end; *x+=x_step) {
839  for (*z=z_start; *z!=z_end && w->GetBlock(i, j, k)->
840  Transparent()==INVISIBLE;
841  *z += z_step);
842  if ( *z == z_end ) {
843  static const int sky_char = CharName(BLOCK, SKY);
844  wattrset(rightWin, sky_color);
845  waddch(rightWin, sky_char);
846  waddch(rightWin, ' ');
847  } else if ( player->Visible(i, j, k) ) {
848  waddch(rightWin, PrintBlock(*w->GetBlock(i, j, k), rightWin));
849  waddch(rightWin, CharNumberFront(i, j));
850  } else {
851  wattrset(rightWin, SHADOW_COLOR);
852  waddch(rightWin, OBSCURE_BLOCK);
853  waddch(rightWin, ' ');
854  }
855  }
856  }
857  wstandend(rightWin);
858  box(rightWin, 0, 0);
859  const int arrow_Y = k_start + 1 - player->Z();
860  if ( shiftFocus ) {
861  wattrset(rightWin, COLOR_PAIR(WHITE_BLUE));
862  const int ch = ( shiftFocus == 1 ) ? '^' : 'v';
863  for (int q=arrow_Y-shiftFocus; 0<q && q<=SCREEN_SIZE; q-=shiftFocus) {
864  mvwaddch(rightWin, q, 0, ch);
865  mvwaddch(rightWin, q, SCREEN_SIZE*2+1, ch);
866  }
867  }
868  Arrows(rightWin, arrow_X, arrow_Y, dir);
869  wrefresh(rightWin);
870 } // void Screen::PrintFront(dirs)
871 
872 void Screen::PrintInv(WINDOW * const window,
873  const Block * const block, const Inventory * const inv)
874 const {
875  if ( inv == nullptr ) return;
876  werase(window);
877  const int start = inv->Start();
878  int shift = 0; // to divide inventory sections
879  for (int i=0; i<inv->Size(); ++i) {
880  shift += ( start == i && i != 0 );
881  wstandend(window);
882  mvwprintw(window, 2+i+shift, 1, "%c) ", 'a'+i);
883  const int number = inv->Number(i);
884  if ( 0 == number ) {
885  wattrset(window, COLOR_PAIR(BLACK_BLACK) | A_BOLD);
886  waddstr(window, qPrintable(inv->InvFullName(i)));
887  continue;
888  }
889  const Block * const block = inv->ShowBlock(i);
890  wprintw(window, "[%c]%s",
891  PrintBlock(*block, window), qPrintable(inv->InvFullName(i)) );
892  if ( MAX_DURABILITY != block->GetDurability() ) {
893  wprintw(window, "{%d}", block->GetDurability()*100/MAX_DURABILITY);
894  }
895  const QString str = block->GetNote();
896  if ( not str.isEmpty() ) {
897  const int x = getcurx(window);
898  const int width = SCREEN_SIZE*2 - x - 3 - 8;
899  if ( str.length() <= width ) {
900  wprintw(window, " ~:%s", qPrintable(str));
901  } else {
902  wprintw(window, " ~:%s ...", qPrintable(str.left(width - 4)));
903  }
904  }
905  wstandend(window);
906  mvwprintw(window, 2+i+shift, 53, "%5hu mz", inv->GetInvWeight(i));
907  }
908  wstandend(window);
909  QString full_weight = tr("Full weight: %1 mz").
910  arg(inv->Weight(), 6, 10, QChar(' '));
911  mvwprintw(window, 2+inv->Size()+shift,
912  SCREEN_SIZE*2 + 1 - full_weight.length(), qPrintable(full_weight));
913  wattrset(window, Color(block->Kind(), block->Sub()));
914  box(window, 0, 0);
915  if ( start != 0 ) {
916  mvwhline(window, 2+start, 1, ACS_HLINE, SCREEN_SIZE*2);
917  }
918  mvwprintw(window, 0, 1, "[%c] %s", CharName( block->Kind(), block->Sub()),
919  qPrintable((player->PlayerInventory() == inv) ?
920  tr("Your inventory") : block->FullName()) );
921  wrefresh(window);
922 } // void Screen::PrintInv(WINDOW *, const Block *, const Inventory *)
923 
925  delete fileToShow;
926  fileToShow = nullptr;
927 }
928 
929 bool Screen::PrintFile(WINDOW * const window, QString const & file_name) {
930  CleanFileToShow();
931  fileToShow = new QFile(file_name);
932  if ( fileToShow->open(QIODevice::ReadOnly | QIODevice::Text) ) {
933  werase(window);
934  waddstr(window, qPrintable(
935  QString::fromLocal8Bit(fileToShow->readAll().constData())) );
936  wrefresh(window);
937  return true;
938  } else {
939  CleanFileToShow();
940  return false;
941  }
942 }
943 
944 void Screen::DisplayFile(QString path) {
945  wstandend(rightWin);
946  if ( not PrintFile(rightWin, path) ) {
947  Notify(tr("There is no such file."));
948  }
949 }
950 
951 void Screen::Notify(const QString str) const {
952  fputs(qPrintable(QString("%1 %2\n").arg(w->TimeOfDayStr()).arg(str)),
953  notifyLog);
954  if ( inputActive ) return;
955  wstandend(notifyWin);
956  switch ( str.at(str.size()-1).unicode() ) {
957  case '!': wcolor_set(notifyWin, RED_BLACK, nullptr); // no break;
958  case '*': if ( flashOn ) flash(); break;
959  case '^': if ( beepOn ) beep(); break;
960  }
961  static int notification_repeat_count = 1;
962  if ( str == lastNotification ) {
963  ++notification_repeat_count;
964  mvwprintw(notifyWin, getcury(notifyWin)-1, 0, "%s (x%d)\n",
965  qPrintable(str), notification_repeat_count);
966  } else {
967  notification_repeat_count = 1;
968  waddstr(notifyWin, qPrintable(lastNotification = str));
969  waddch(notifyWin, '\n');
970  }
971  wrefresh(notifyWin);
972 }
973 
975  werase(rightWin);
976  werase(hudWin);
977  wcolor_set(leftWin, WHITE_RED, nullptr);
978  if ( not PrintFile(leftWin, ":/texts/death.txt") ) {
979  waddstr(leftWin, qPrintable(tr("You die.\nWaiting for respawn...")));
980  }
981  box(leftWin, 0, 0);
982  wnoutrefresh(leftWin);
983  wnoutrefresh(rightWin);
984  wnoutrefresh(hudWin);
985  doupdate();
986  updated = true;
987 }
988 
990  World * const wor,
991  Player * const pl,
992  int & error,
993  bool _ascii)
994  :
995  VirtScreen(wor, pl),
996  lastNotification(),
997  input(new IThread(this)),
998  updated(),
999  notifyLog(fopen(qPrintable(home_path + "log.txt"), "at")),
1000  actionMode(ACTION_USE),
1001  shiftFocus(settings.value("focus_shift", 0).toInt()),
1002  fileToShow(nullptr),
1003  beepOn (settings.value("beep_on", false).toBool()),
1004  flashOn(settings.value("flash_on", true ).toBool()),
1005  ascii(_ascii && settings.value("ascii", true).toBool() ),
1006  blinkOn(not _ascii || settings.value("blink_on", true).toBool()),
1007  arrows{'.', 'x',
1008  ascii ? '^' : 0x2191,
1009  ascii ? 'v' : 0x2193,
1010  ascii ? '>' : 0x2192,
1011  ascii ? '<' : 0x2190
1012  },
1013  screen(newterm(nullptr, stdout, stdin)),
1014  randomBlink()
1015 {
1016  #ifndef Q_OS_WIN32
1017  set_escdelay(10);
1018  #endif
1019  start_color();
1020  nodelay(stdscr, FALSE);
1021  noecho(); // do not print typed symbols
1022  nonl();
1023  keypad(stdscr, TRUE); // use arrows
1024  mousemask(BUTTON1_CLICKED | BUTTON1_RELEASED, nullptr);
1025  memset(windows, 0, sizeof(windows));
1026  if ( LINES < 41 && IsScreenWide() ) {
1027  printf("Make your terminal height to be at least 41 lines.\n");
1028  error = HEIGHT_NOT_ENOUGH;
1029  return;
1030  } else if ( LINES < 39 ) {
1031  printf("Make your terminal height to be at least 39 lines.\n");
1032  error = HEIGHT_NOT_ENOUGH;
1033  }
1034  // all available color pairs (maybe some of them will not be used)
1035  const int colors[] = { // do not change colors order!
1036  COLOR_BLACK,
1037  COLOR_RED,
1038  COLOR_GREEN,
1039  COLOR_YELLOW,
1040  COLOR_BLUE,
1041  COLOR_MAGENTA,
1042  COLOR_CYAN,
1043  COLOR_WHITE
1044  };
1045  for (int i=BLACK_BLACK; i<=WHITE_WHITE; ++i) {
1046  init_pair(i, colors[(i-1)/8], colors[(i-1)%8]);
1047  }
1048  const int preferred_width = (SCREEN_SIZE*2+2)*2;
1049  if ( IsScreenWide() ) {
1050  const int left_border = COLS/2-SCREEN_SIZE*2-2;
1051  rightWin = newwin(SCREEN_SIZE+2, SCREEN_SIZE*2+2, 0, COLS/2);
1052  leftWin = newwin(SCREEN_SIZE+2, SCREEN_SIZE*2+2, 0, left_border);
1053  hudWin = newwin(3, preferred_width, SCREEN_SIZE+2, left_border);
1054  notifyWin = newwin(0, 0, SCREEN_SIZE+5,left_border+33);
1055  minimapWin =
1056  newwin(MINIMAP_HEIGHT, MINIMAP_WIDTH, SCREEN_SIZE+5, left_border);
1057  actionWin = newwin(7, 20, SCREEN_SIZE+5, left_border+12);
1058  } else if ( COLS >= preferred_width/2 ) {
1059  const int left_border = COLS/2-SCREEN_SIZE-1;
1060  leftWin = newwin(SCREEN_SIZE+2, SCREEN_SIZE*2+2, 0, left_border);
1061  hudWin = newwin(2,SCREEN_SIZE*2+2-15, SCREEN_SIZE+2,left_border+15);
1062  notifyWin = newwin(0, 0, SCREEN_SIZE+2+2, left_border+15);
1063  actionWin = newwin(7, 15, SCREEN_SIZE+2, left_border);
1064  } else {
1065  puts(qPrintable(tr("Set your terminal width at least %1 chars.").
1066  arg(SCREEN_SIZE*2+2)));
1067  error = WIDTH_NOT_ENOUGH;
1068  return;
1069  }
1070  scrollok(notifyWin, TRUE);
1071 
1072  if ( not PrintFile(stdscr, ":/texts/splash.txt") ) {
1073  addstr("Free-Roaming Elementary Game\nby mmaulwurff\n");
1074  }
1075  addstr(qPrintable(tr("\nVersion %1.\n\nPress any key.").arg(VER)));
1076  qsrand(getch());
1077  CleanFileToShow();
1078  RePrint();
1079  SetActionMode(static_cast<actions>
1080  (settings.value("action_mode", ACTION_USE).toInt()));
1081  Print();
1082  Notify(tr("--- Game started. Press 'H' for help. ---"));
1083  if ( not IsScreenWide() ) {
1084  Notify(tr("For better gameplay set your"));
1085  Notify(tr("terminal width at least %1 chars.").arg(preferred_width));
1086  }
1087 
1088  input->start();
1089  connect(wor, SIGNAL(UpdatesEnded()), SLOT(Print()), Qt::DirectConnection);
1090 } // Screen::Screen(World * wor, Player * pl)
1091 
1093  w->Lock();
1094  disconnect(w, SIGNAL(UpdatesEnded()), this, SLOT(Print()));
1095  w->Unlock();
1096 
1097  input->Stop();
1098  input->wait();
1099  delete input;
1100 
1101  for (ulong i=0; i<sizeof(windows)/sizeof(windows[0]); ++i) {
1102  delwin(windows[i]);
1103  }
1104  endwin();
1105  delscreen(screen);
1106  if ( notifyLog ) {
1107  fclose(notifyLog);
1108  }
1109  delete fileToShow;
1110  settings.setValue("focus_shift", shiftFocus);
1111  settings.setValue("action_mode", actionMode);
1112  settings.setValue("last_command", previousCommand);
1113  settings.setValue("beep_on", beepOn);
1114  settings.setValue("flash_on", flashOn);
1115  settings.setValue("blink_on", blinkOn);
1116  settings.setValue("ascii", ascii);
1117 }
1118 
1119 void Screen::PrintBar(const int x, const int attr, const int ch,
1120  const int percent, const bool value_position_right)
1121 {
1122  wstandend(hudWin);
1123  mvwprintw(hudWin, 0, x,
1124  value_position_right ? "[..........]%hd" : "%3hd[..........]",percent);
1125  wattrset(hudWin, attr);
1126  mvwaddstr(hudWin, 0, x + (value_position_right ? 1 : 4),
1127  qPrintable(QString(10, QChar(ch)).left(percent/10)));
1128 }
int GetNormalStartY() const
void DisplayFile(QString path) override
Screen(World *, Player *, int &error, bool ascii)
bool Obtain(int src, int dest=0, int num=1)
Tries to get block number num from outer inventory.
Definition: Player.cpp:257
const int MAX_DURABILITY
10 bits to store durability in file, signed.
Definition: World.h:43
IThread *const input
Definition: CursedScreen.h:138
virtual QString FullName() const
Definition: Block.cpp:88
void SetUsingTypeNo()
Definition: Player.cpp:53
static dirs TurnRight(dirs dir)
Definition: World.cpp:165
QString previousCommand
Definition: VirtScreen.h:192
void Print() override
const int MINIMAP_HEIGHT
int GetMinimapStartX() const
const char OBSCURE_BLOCK
void UpdateAround(int, int, int, int) override
static int CoordInShred(const int x)
Get local coordinate.
Definition: Shred.h:100
const bool beepOn
Definition: CursedScreen.h:145
static char CharName(int kind, int sub)
Definition: VirtScreen.cpp:131
virtual void ActionXyz(int *x, int *y, int *z) const
Used to get player focus coordinates from screen.
Definition: VirtScreen.cpp:70
bool Damage() const
Returns true if xyz are in world bounds.
Definition: Player.cpp:414
int GetUsingInInventory() const
Definition: Player.cpp:54
3
Definition: header.h:90
const QString home_path
Definition: main.cpp:50
void PrintNormal(WINDOW *, dirs) const
void DeathScreen()
bool PrintFile(WINDOW *, QString const &file_name)
Returns false when file does not exist, otherwise true.
const bool flashOn
Definition: CursedScreen.h:145
29
Definition: header.h:189
Player *const player
Definition: VirtScreen.h:190
int Number(int i) const
Definition: Inventory.cpp:28
void PrintQuickInventory()
void ExamineOnNormalScreen(int x, int y, int z, int step) const
World * world
Definition: World.cpp:32
SCREEN *const screen
Definition: CursedScreen.h:149
shred_type GetTypeOfShred() const
Definition: Shred.cpp:65
28
Definition: header.h:188
World provides global physics and shred connection.
Definition: World.h:52
void ControlPlayer()
void Shake()
Stacks items in inventory if possible.
Definition: Inventory.cpp:234
~Screen() override
volatile bool updated
Definition: CursedScreen.h:139
long GetLatitude() const
Definition: Player.cpp:56
short Z() const
Definition: Xyz.cpp:30
int shiftFocus
Can be -1, 0, 1 for low, normal, and high focus.
Definition: CursedScreen.h:143
void PrintHUD()
char PrintBlock(const Block &, WINDOW *) const
long GlobalX() const
Definition: Player.cpp:44
void SetDir(dirs)
Definition: Player.cpp:408
actions
Definition: CursedScreen.h:41
World * GetWorld() const
Definition: VirtScreen.cpp:74
0
Definition: header.h:87
void Examine()
Definition: Player.cpp:95
const int SHADOW_COLOR
void PassString(QString &) const override
4
Definition: header.h:164
Block * GetFocusedBlock() const
Returns nullptr if block is not player->Visible().
int Transparent() const
Definition: Block.h:143
WINDOW * windows[6]
Definition: CursedScreen.h:130
21
Definition: header.h:181
2
Definition: header.h:89
int BreathPercent() const
This returns player breath reserve. On error returns -100.
Definition: Player.cpp:72
Shred * GetShredByPos(int x, int y) const
Definition: World.cpp:44
long GetLongitude() const
Definition: Player.cpp:55
char CharNumber(int z) const
static int Color(int kind, int sub)
Definition: VirtScreen.cpp:76
const QChar arrows[WEST+1]
Definition: CursedScreen.h:148
0
Definition: header.h:115
void PrintMiniMap()
void ProcessCommand(QString command)
void SetCreativeMode(bool turn)
Definition: Player.cpp:60
char CharNumberFront(int x, int y) const
static sub_groups GetSubGroup(int sub)
Definition: Block.cpp:275
Provides curses (text-based graphics interface) screen for freg.
4
Definition: header.h:91
dirs GetDir() const
This returns current player direction (see enum dirs in header.h)
Definition: Player.cpp:49
virtual Inventory * HasInventory()
Definition: Block.cpp:224
int GetInvWeight(int i) const
Definition: Inventory.cpp:154
static void PrintVerticalDirection(WINDOW *, int y, int x, dirs)
Block * ShowBlock(int slot) const
Definition: Inventory.cpp:182
FILE *const notifyLog
Definition: CursedScreen.h:140
Definition: Shred.h:32
World *const w
Definition: VirtScreen.h:189
int Color(int kind, int sub) const
int RandomBlink() const
void UpdatePlayer() override
const int MINIMAP_WIDTH
7 (hominid meat)
Definition: header.h:167
virtual int Start() const
Definition: Inventory.cpp:26
const int HEIGHT
Definition: header.h:40
Inventory * PlayerInventory() const
Returns nullptr if there is no inventory, otherwise returns inventory.
Definition: Player.cpp:80
int Y() const
Definition: Player.cpp:40
int SatiationPercent() const
Can be > 100 if player is gorged. On error returns -100.
Definition: Player.cpp:74
Keyboard input thread for curses screen for freg.
Definition: IThread.h:33
int UsingType() const
This returns how player is using something now.
Definition: Player.cpp:50
int Size() const
Definition: Inventory.cpp:27
void ActionXyz(int *x, int *y, int *z) const override
void Craft(int num)
Definition: Player.cpp:312
int GetNormalStartX() const
void Lock()
Definition: World.cpp:161
bool Visible(int x, int y, int z) const
This returns true if block at (x, y, z) is visible to player.
Definition: Player.cpp:402
WINDOW *& minimapWin
Definition: CursedScreen.h:135
bool GetCreativeMode() const
Definition: Player.cpp:57
void Build(int num)
Definition: Player.cpp:298
ulong Time() const
Returns time in seconds since world creation.
Definition: World.cpp:61
void StopUseAll()
Closes backpack, chests, etc.
Definition: Player.cpp:51
QSettings settings
Definition: VirtScreen.h:191
3
Definition: header.h:163
Block * GetBlock(int x, int y, int z) const
Definition: World.cpp:204
void SetActionMode(actions mode)
Provides declaration for class Inventory for freg.
WINDOW *& rightWin
Definition: CursedScreen.h:132
void Wield(int num)
Definition: Player.cpp:270
void ProcessCommand(QString command)
Definition: Player.cpp:329
void Move(int) override
int randomBlink
Definition: CursedScreen.h:151
void Inscribe() const
Definition: Player.cpp:180
shred_type
Definition: header.h:59
void ProcessMouse()
virtual Animal * IsAnimal()
Definition: Block.cpp:225
const int SCREEN_SIZE
Definition: CursedScreen.h:39
static QString ShredTypeName(shred_type)
Definition: Shred.cpp:32
bool GetEvernight() const
Definition: World.cpp:64
void ExitReceived()
This is emitted when input receives exit key.
void HorizontalArrows(WINDOW *, int y, dirs) const
static constexpr quint64 UniqueIntFromString(const char *const chars)
Definition: Player.h:131
2
Definition: header.h:162
void RePrint()
void MovePlayerDiag(dirs dir1, dirs dir2) const
QString lastNotification
Definition: CursedScreen.h:137
static QString DirString(dirs)
Definition: Block.cpp:75
void Unlock()
Definition: World.cpp:163
int Kind() const
Definition: Block.h:145
int Sub() const
Definition: Block.h:144
bool RandomBit() const
long GlobalY() const
Definition: Player.cpp:45
void InventoryAction(int num) const
void UpdateAll() override
12
Definition: header.h:172
WINDOW *& leftWin
Definition: CursedScreen.h:131
QString TimeOfDayStr() const
Definition: World.cpp:82
WINDOW *& hudWin
Definition: CursedScreen.h:134
19
Definition: header.h:179
const Block * GetBlock() const
Definition: Player.cpp:58
const bool ascii
Definition: CursedScreen.h:146
QString GetNote() const
Definition: Block.cpp:234
int GetBound() const
Definition: World.cpp:126
times_of_day PartOfDay() const
Definition: World.cpp:78
void PrintFront(dirs direction, int x=-1, int y=0) const
void Notify(QString) const override
5
Definition: header.h:165
void CleanFileToShow()
void Arrows(WINDOW *, int x, int y, dirs) const
13
Definition: header.h:173
25
Definition: header.h:185
virtual int Weight() const
Definition: Inventory.cpp:169
void PrintBar(int x, int color, int ch, int percent, bool value_position_right=true)
Can print health, breath and other bars on hudWin.
1
Definition: header.h:88
int GetMinimapStartY() const
dirs
Definition: header.h:85
static bool IsScreenWide()
Provides block ability to contain other blocks inside.
Definition: Inventory.h:33
This class provides base for all screens for freg.
Definition: VirtScreen.h:104
0
Definition: header.h:160
Shred * GetShred(int i, int j) const
Definition: World.cpp:40
bool inputActive
Definition: CursedScreen.h:150
int UsingSelfType() const
This returns how player is using himself.
Definition: Player.cpp:52
bool blinkOn
Definition: CursedScreen.h:147
void Backpack()
Tries to switch usingSelfType from NO to OPEN.
Definition: Player.cpp:155
Block * GetBlock(const int x, const int y, const int z) const
Definition: Shred.h:61
QFile * fileToShow
Definition: CursedScreen.h:144
int GetDurability() const
Definition: Block.cpp:232
const int MAX_NOTE_LENGTH
Definition: World.h:44
int NumShreds() const
Definition: World.cpp:58
int ColorShred(shred_type) const
void PrintInv(WINDOW *, const Block *, const Inventory *) const
static int CoordOfShred(const int x)
Get shred coordinate in loaded zone (from 0 to numShreds).
Definition: Shred.h:103
5
Definition: header.h:120
actions actionMode
Definition: CursedScreen.h:141
WINDOW *& notifyWin
Definition: CursedScreen.h:133
void Jump()
Definition: Player.cpp:133
15
Definition: header.h:175
const int SHRED_WIDTH
Definition: header.h:38
void Update(int, int, int) override
This class contains information specific to player and interface for manipulating him...
Definition: Player.h:34
Block without special physics and attributes.
Definition: Block.h:89
5
Definition: header.h:92
WINDOW *& actionWin
Definition: CursedScreen.h:136
void MovePlayer(dirs dir)
30
Definition: header.h:145
const int QUICK_INVENTORY_X_SHIFT
8 (animal meat)
Definition: header.h:168
void Use()
Definition: Player.cpp:163
virtual QString InvFullName(int num) const
Definition: Inventory.cpp:145
static dirs TurnLeft(dirs dir)
Definition: World.cpp:178
void Stop()
Definition: IThread.cpp:34
int X() const
Definition: Player.cpp:36
Provides definition for class Block.
30
Definition: header.h:190
14
Definition: header.h:174
QString WorldName() const
Definition: World.cpp:65
void Throw(int src, int dest=0, int num=1)
Tries to throw (drop out) block number num from inventory.
Definition: Player.cpp:249
void Move(dirs)
Definition: Player.cpp:145