diff --git a/achievement.cpp b/achievement.cpp index 7cf87e59..22185b09 100644 --- a/achievement.cpp +++ b/achievement.cpp @@ -1,4 +1,4 @@ -#define NUMLEADER 26 +#define NUMLEADER 40 #define SCORE_UNKNOWN (-1) #define NO_SCORE_YET (-2) @@ -8,11 +8,21 @@ int currentscore[NUMLEADER]; const char* leadernames[NUMLEADER] = { "Score", "Diamonds", "Gold", "Spice", "Rubies", "Elixirs", "Shards", "Totems", "Daisies", "Statues", "Feathers", "Sapphires", - "Hyperstones", "Time to Win", "Turns to Win", - "Time to 10 Hyperstones-62", "Turns to 10 Hyperstones-62", "Orbs of Yendor", + "Hyperstones", "Time to Win-71", "Turns to Win-71", + "Time to 10 Hyperstones-73", "Turns to 10 Hyperstones-73", "Orbs of Yendor", "Fern Flowers", "Royal Jellies", "Powerstones", "Silver", "Wine", "Emeralds", "Grimoires", - "Holy Grails" + "Holy Grails", "Red Gems", "Pirate Treasures", + "Shmup Score", "Shmup Time to Win", "Shmup Knife to Win", + "Bomberbird Eggs", // 31 + "Ambers", // 32 + "Pearls", // 33 + "Hypersian Rugs", // 34 + "Garnets", // 35 + "Princess Challenge", // 36 + "Ivory Figurines", // 37 + "Elemental Gems", // 38 + "Onyxes" // 39 }; bool haveLeaderboard(int id); @@ -23,9 +33,11 @@ string achievementMessage[3]; int achievementTimer; // vector achievementsReceived; -void achievement_log(const char* s, bool euclideanAchievement) { +void achievement_log(const char* s, bool euclideanAchievement, bool shmupAchievement) { if(cheater) return; if(euclid != euclideanAchievement) return; + if(shmup::on != shmupAchievement) return; + if(randomPatternsMode) return; for(int i=0; i= 5) achievement_gain("GOLEM2"); if(s == "GOLEM" && current >= 10) @@ -204,6 +267,7 @@ int specific_what = 0; void improve_score(int i, eItem what) { #ifdef HAVE_ACHIEVEMENTS + if(haveLeaderboard(i)) updateHi(what, currentscore[i]); if(items[what] && haveLeaderboard(i)) { if(items[what] > currentscore[i] && currentscore[i] != SCORE_UNKNOWN) { specific_improved++; specific_what = what; @@ -215,14 +279,16 @@ void improve_score(int i, eItem what) { #endif } -void achievement_final(bool really_final) { +void achievement_score(int cat, int number) { #ifdef HAVE_ACHIEVEMENTS if(cheater) return; if(euclid) return; - int total_improved = 0; - specific_improved = 0; - specific_what = 0; - + if(randomPatternsMode) return; + upload_score(cat, number); +#endif + } + +void improveItemScores() { for(int i=1; i<=12; i++) improve_score(i, eItem(i)); improve_score(17, itOrbYendor); improve_score(18, itFernFlower); @@ -233,14 +299,39 @@ void achievement_final(bool really_final) { improve_score(23, itEmerald); improve_score(24, itGrimoire); improve_score(25, itHolyGrail); + improve_score(26, itRedGem); + improve_score(27, itPirate); + improve_score(31, itBombEgg); + improve_score(32, itCoast); + improve_score(33, itWhirlpool); + improve_score(34, itPalace); + improve_score(35, itFjord); + + improve_score(37, itEdge); + improve_score(38, itElemental); + improve_score(39, itZebra); + } + +void achievement_final(bool really_final) { +#ifdef HAVE_ACHIEVEMENTS + if(cheater) return; + if(euclid) return; + if(randomPatternsMode) return; + int total_improved = 0; + specific_improved = 0; + specific_what = 0; + + if(!shmup::on) improveItemScores(); + + int sid = shmup::on ? 28 : 0; int tg = gold(); - if(tg && haveLeaderboard(0)) { - if(tg > currentscore[0] && currentscore[0] != SCORE_UNKNOWN) { - if(currentscore[0] < 0) total_improved += 2; - total_improved++; currentscore[0] = tg; + if(tg && haveLeaderboard(sid)) { + if(tg > currentscore[sid] && currentscore[sid] != SCORE_UNKNOWN) { + if(currentscore[sid] < 0) total_improved += 2; + total_improved++; currentscore[sid] = tg; } - upload_score(0, tg); + upload_score(sid, tg); } if(total_improved >= 2) { @@ -264,11 +355,13 @@ void achievement_victory(bool hyper) { #ifdef HAVE_ACHIEVEMENTS if(cheater) return; if(euclid) return; + if(randomPatternsMode) return; + if(hyper && shmup::on) return; int t = savetime + time(NULL) - timerstart; - int ih1 = hyper ? 15 : 13; - int ih2 = hyper ? 16 : 14; + int ih1 = hyper ? 15 : shmup::on ? 29 : 13; + int ih2 = hyper ? 16 : shmup::on ? 30 : 14; int improved = 0; if(currentscore[ih1] == NO_SCORE_YET || currentscore[ih2] == NO_SCORE_YET) @@ -291,12 +384,20 @@ void achievement_victory(bool hyper) { addMessage(XLAT("This has been recorded in the " LEADERFULL ".")); addMessage(XLAT("The faster you get here, the better you are!")); } - else if(improved >= 3) - addMessage(XLAT("You have improved both your real time and turn count. Congratulations!")); + else if(improved >= 3) { + if(shmup::on) + addMessage(XLAT("You have improved both your real time and knife count. Congratulations!")); + else + addMessage(XLAT("You have improved both your real time and turn count. Congratulations!")); + } else if(improved == 1) addMessage(XLAT("You have used less real time than ever before. Congratulations!")); - else if(improved == 2) - addMessage(XLAT("You have used less turns than ever before. Congratulations!")); + else if(improved == 2) { + if(shmup::on) + addMessage(XLAT("You have used less knives than ever before. Congratulations!")); + else + addMessage(XLAT("You have used less turns than ever before. Congratulations!")); + } } upload_score(ih1, t); diff --git a/cell.cpp b/cell.cpp index 0c5fa128..b640e99a 100644 --- a/cell.cpp +++ b/cell.cpp @@ -4,6 +4,7 @@ // cells the game is played on int fix6(int a) { return (a+96)% 6; } +int fix7(int a) { return (a+84)% 7; } struct cell : gcell { char type; // 6 for hexagons, 7 for heptagons @@ -12,6 +13,8 @@ struct cell : gcell { cell *mov[7]; // meaning very similar to heptagon::move }; +int fixdir(int a, cell *c) { a %= c->type; if(a<0) a += c->type; return a; } + int cellcount = 0; void initcell(cell *c); // from game.cpp @@ -116,6 +119,16 @@ cell *createMov(cell *c, int d) { return c->mov[d]; } +cell *createMovR(cell *c, int d) { + d %= 42; d += 42; d %= c->type; + return createMov(c, d); + } + +cell *getMovR(cell *c, int d) { + d %= 42; d += 42; d %= c->type; + return c->mov[d]; + } + // similar to heptspin from heptagon.cpp struct cellwalker { cell *c; @@ -132,6 +145,10 @@ bool cwstepcreates(cellwalker& cw) { return cw.c->mov[cw.spin] == NULL; } +cell *cwpeek(cellwalker cw, int dir) { + return createMov(cw.c, (cw.spin+42+dir) % cw.c->type); + } + void cwstep(cellwalker& cw) { createMov(cw.c, cw.spin); int nspin = cw.c->spn[cw.spin]; @@ -188,7 +205,9 @@ cell*& euclideanAtCreate(eucoord x, eucoord y) { void initcells() { origin.s = hsOrigin; - origin.fjordval = 98; + origin.emeraldval = 98; + origin.zebraval = 40; + origin.fiftyval = 0; for(int i=0; i<7; i++) origin.move[i] = NULL; origin.alt = NULL; origin.distance = 0; @@ -197,7 +216,7 @@ void initcells() { else origin.c7 = newCell(7, &origin); - // origin.fjordval = + // origin.emeraldval = } #define DEBMEM(x) // { x fflush(stdout); } @@ -287,9 +306,26 @@ bool ishept(cell *c) { else return c->type == 7; } +bool ishex1(cell *c) { + // EUCLIDEAN + if(euclid) { + eucoord x, y; + decodeMaster(c->master, x, y); + short z = (short(y+2*x))%3; + if(z<0) z += 3; + return z == 1; + } + else return c->type == 7; + } + void clearMemory() { extern void clearGameMemory(); clearGameMemory(); + if(shmup::on) shmup::clearMemory(); + cleargraphmemory(); +#ifndef MOBILE + mapeditor::clearModelCells(); +#endif // EUCLIDEAN if(euclid) { for(int y=0; y<256; y++) for(int x=0; x<256; x++) @@ -307,15 +343,15 @@ void clearMemory() { DEBMEM ( printf("ok\n"); ) } -int fjordval(cell *c) { +int emeraldval(cell *c) { if(euclid) return 0; if(c->type == 7) - return c->master->fjordval >> 3; + return c->master->emeraldval >> 3; else { - return fjord_hexagon( - fjordval(createMov(c,0)), - fjordval(createMov(c,2)), - fjordval(createMov(c,4)) + return emerald_hexagon( + emeraldval(createMov(c,0)), + emeraldval(createMov(c,2)), + emeraldval(createMov(c,4)) ); } } @@ -348,6 +384,8 @@ int celldist(cell *c) { #define ALTDIST_BOUNDARY 99999 #define ALTDIST_UNKNOWN 99998 +#define ALTDIST_ERROR 90000 + // defined in 'game' int euclidAlt(short x, short y); @@ -373,3 +411,231 @@ int celldistAlt(cell *c) { #define GRAIL_FOUND 0x4000 #define GRAIL_RADIUS_MASK 0x3FFF + +int dirfromto(cell *cfrom, cell *cto) { + for(int i=0; itype; i++) if(cfrom->mov[i] == cto) return i; + return -1; + } + +// === FIFTYVALS === + +unsigned bitmajority(unsigned a, unsigned b, unsigned c) { + return (a&b) | ((a^b)&c); + } + +int fiftyval(cell *c) { + if(euclid) return 0; + if(c->type == 7) + return c->master->fiftyval; + else { + return bitmajority( + fiftyval(createMov(c,0)), + fiftyval(createMov(c,2)), + fiftyval(createMov(c,4))) + 512; + } + } + +int cdist50(cell *c) { + if(euclid) { + eucoord x, y; + decodeMaster(c->master, x, y); + int ix = short(x) + 99999 + short(y); + int iy = short(y) + 99999; + char palacemap[3][10] = { + "012333321", + "112322232", + "222321123" + }; + ix += (iy/3) * 3; + iy %= 3; ix %= 9; + return palacemap[iy][ix] - '0'; + } + if(c->type == 7) return cdist50(fiftyval(c)); + int a0 = cdist50(createMov(c,0)); + int a1 = cdist50(createMov(c,2)); + int a2 = cdist50(createMov(c,4)); + if(a0 == 0 || a1 == 0 || a2 == 0) return 1; + return a0+a1+a2-5; + } + +int land50(cell *c) { + if(c->type == 7) return land50(fiftyval(c)); + else { + if(cdist50(createMov(c,0)) < 3) return land50(createMov(c,0)); + if(cdist50(createMov(c,2)) < 3) return land50(createMov(c,2)); + if(cdist50(createMov(c,4)) < 3) return land50(createMov(c,4)); + return 0; + } + } + +int polara50(cell *c) { + if(c->type == 7) return polara50(fiftyval(c)); + else { + if(cdist50(createMov(c,0)) < 3) return polara50(createMov(c,0)); + if(cdist50(createMov(c,2)) < 3) return polara50(createMov(c,2)); + if(cdist50(createMov(c,4)) < 3) return polara50(createMov(c,4)); + return 0; + } + } + +int polarb50(cell *c) { + if(euclid) return true; + if(c->type == 7) return polarb50(fiftyval(c)); + else { + if(cdist50(createMov(c,0)) < 3) return polarb50(createMov(c,0)); + if(cdist50(createMov(c,2)) < 3) return polarb50(createMov(c,2)); + if(cdist50(createMov(c,4)) < 3) return polarb50(createMov(c,4)); + return 0; + } + } + +int elhextable[28][3] = { + {0,1,2}, {1,2,9}, {1,9,-1}, {1,8,-1}, {1,-1,-1} + }; + +int fiftyval049(cell *c) { + if(c->type == 7) return fiftyval(c) / 32; + else { + int a[3], qa=0; + int pa = polara50(c), pb = polarb50(c); + for(int i=0; i<6; i+=2) { + cell *c2 = c->mov[i]; + if(polara50(c2) == pa && polarb50(c2) == pb) + a[qa++] = fiftyval049(c2); + } + // 0-1-2 + sort(a, a+qa); + if(qa == 1) return 43+a[0]-1; + if(qa == 2 && a[1] == a[0]+7) return 36+a[0]-1; + if(qa == 2 && a[1] != a[0]+7) return 29+a[0]-1; + if(a[1] == 1 && a[2] == 7) + return 15 + 6; + if(a[2] >= 1 && a[2] <= 7) + return 15 + a[1]-1; + if(a[0] == 1 && a[1] == 7 && a[2] == 8) + return 22; + if(a[1] <= 7 && a[2] >= 8) + return 22 + a[1]-1; + return 0; + } + } + +/* +{0,1,2} 15+0..15+6 +{1,2,9},22+0..22+6 +{1,9} 29+0..29+6 +{1,8} 36+0..36+6 +{1} 43+0..43+6 +*/ + +// zebraval + +int zebra40(cell *c) { + if(c->type == 7) return (c->master->zebraval/10); + else { + int ii[3], z; + ii[0] = (c->mov[0]->master->zebraval/10); + ii[1] = (c->mov[2]->master->zebraval/10); + ii[2] = (c->mov[4]->master->zebraval/10); + for(int r=0; r<2; r++) + if(ii[1] < ii[0] || ii[2] < ii[0]) + z = ii[0], ii[0] = ii[1], ii[1] = ii[2], ii[2] = z; + for(int i=0; i<28; i++) + if(zebratable6[i][0] == ii[0] && zebratable6[i][1] == ii[1] && + zebratable6[i][2] == ii[2]) { + int ans = 16+i; + // if(ans >= 40) ans ^= 2; + // if(ans >= 4 && ans < 16) ans ^= 2; + return ans; + } + return 0; + } + } + +int zebra3(cell *c) { + if(c->type == 7) return (c->master->zebraval/10)/4; + else { + int ii[3]; + ii[0] = (c->mov[0]->master->zebraval/10)/4; + ii[1] = (c->mov[2]->master->zebraval/10)/4; + ii[2] = (c->mov[4]->master->zebraval/10)/4; + if(ii[0] == ii[1]) return ii[0]; + if(ii[1] == ii[2]) return ii[1]; + if(ii[2] == ii[0]) return ii[2]; + return 0; + } + } + +bool randpattern(cell *c, int rval) { + int i, sw=0; + switch(rval & 3) { + case 0: + return rand() < rval; + case 1: + i = zebra40(c); + if(i&1) { if(rval&4) sw^=1; i &= ~1; } + if(i&2) { if(rval&8) sw^=1; i &= ~2; } + i >>= 2; + i--; i /= 3; + if(rval & (16<type; i++) { + if(randpatternMajority(createMov(c,i), ival, iterations-1)) + z++; + else + z--; + } + if(z!=0) memo = (z>0); + else memo = randpattern(c, rval); + // printf("%p] rval = %X code = %d iterations = %d result = %d\n", c, rval, code, iterations, memo); + return memo; + } diff --git a/classes.cpp b/classes.cpp index 2b871aee..e5d5ea85 100644 --- a/classes.cpp +++ b/classes.cpp @@ -1,56 +1,57 @@ + // --- help --- -#define MC -#define M - const char *wormdes = -MC"These huge monsters normally live below the sand, but your movements have " -MC"disturbed them. They are too big to be slain with your " -MC"weapons, but you can defeat them by making them unable to move. " -M "This also produces some Spice. They move two times slower than you."; + "These huge monsters normally live below the sand, but your movements have " + "disturbed them. They are too big to be slain with your " + "weapons, but you can defeat them by making them unable to move. " + "This also produces some Spice. They move two times slower than you."; const char *cocytushelp = -M "This frozen lake is a hellish version of the Icy Land. Now, your body heat melts the floor, not the walls."; + "This frozen lake is a hellish version of the Icy Land. Now, your body heat melts the floor, not the walls."; const char *tentdes = -MC"The tentacles of Cthulhu are like sandworms, but longer. " -M "They also withdraw one cell at a time, instead of exploding instantly."; + "The tentacles of Cthulhu are like sandworms, but longer. " + "They also withdraw one cell at a time, instead of exploding instantly."; const char *gameboardhelp = -MC"Ever wondered how some boardgame would look on the hyperbolic plane? " -MC"I wondered about Go, so I have created this feature. Now you can try yourself!\n" -MC"Enter = pick up an item (and score), space = clear an item\n" -M "Other keys place orbs and terrain features of various kinds\n" + "Ever wondered how some boardgame would look on the hyperbolic plane? " + "I wondered about Go, so I have created this feature. Now you can try yourself!\n" + "Enter = pick up an item (and score), space = clear an item\n" + "Other keys place orbs and terrain features of various kinds\n" "In the periodic editor, press 0-4 to switch walls in different ways\n" ; const char *ivydes = -MC"A huge plant growing in the Jungle. Each Ivy has many branches, " -MC"and one branch grows per each of your moves. Branches grow in a clockwise " -M "order. The root itself is vulnerable."; + "A huge plant growing in the Jungle. Each Ivy has many branches, " + "and one branch grows per each of your moves. Branches grow in a clockwise " + "order. The root itself is vulnerable."; const char *slimehelp = -MC"The Alchemists produce magical potions from pools of blue and red slime. You " -MC"can go through these pools, but you cannot move from a blue pool to a red " -MC"pool, or vice versa. Pools containing items count as colorless, and " -MC"they change color to the PC's previous color when the item is picked up. " -MC"Slime beasts also have to keep to their own color, " -MC"but when they are killed, they explode, destroying items and changing " -M "the color of the slime and slime beasts around them."; + "The Alchemists produce magical potions from pools of blue and red slime. You " + "can go through these pools, but you cannot move from a blue pool to a red " + "pool, or vice versa. Pools containing items count as colorless, and " + "they change color to the PC's previous color when the item is picked up. " + "Slime beasts also have to keep to their own color, " + "but when they are killed, they explode, destroying items and changing " + "the color of the slime and slime beasts around them."; const char *gdemonhelp = -MC "These creatures are slow, but very powerful... more powerful than you. " -MC "You need some more experience in demon fighting before you will be able to defeat them. " -MC "Even then, you will be able to slay this one, but more powerful demons will come...\n\n" -MC "Each 10 lesser demons you kill, you become powerful enough to kill all the greater " -M "demons on the screen, effectively turning them into lesser demons."; + "These creatures are slow, but very powerful... more powerful than you. " + "You need some more experience in demon fighting before you will be able to defeat them. " + "Even then, you will be able to slay this one, but more powerful demons will come...\n\n" + "Each 10 lesser demons you kill, you become powerful enough to kill all the greater " + "demons on the screen, effectively turning them into lesser demons."; const char *ldemonhelp = -M "These creatures are slow, but they often appear in large numbers."; + "These creatures are slow, but they often appear in large numbers."; const char *trollhelp = -MC"A big monster from the Living Caves. A dead Troll will be reunited " -M "with the rocks, causing some walls to grow around its body."; + "A big monster from the Living Caves. A dead Troll will be reunited " + "with the rocks, causing some walls to grow around its body."; + +const char *trollhelp2 = + " Additionally, all items around the killed Troll will be destroyed."; const char *camelothelp = "The Knights of the Round Table are the greatest warriors of these lands. " @@ -71,14 +72,14 @@ const char *templehelp = "infinite, and there is an infinite number of them."; const char *barrierhelp = -M "Huge, impassable walls which separate various lands."; + "Huge, impassable walls which separate various lands."; const char *cavehelp = -MC"This cave contains walls which are somehow living. After each turn, each cell " -MC"counts the number of living wall and living floor cells around it, and if it is " -MC"currently of a different type than the majority of cells around it, it switches. " -MC"Items count as three floor cells, and dead Trolls count as five wall cells. " -M "Some foreign monsters also count as floor or wall cells.\n"; + "This cave contains walls which are somehow living. After each turn, each cell " + "counts the number of living wall and living floor cells around it, and if it is " + "currently of a different type than the majority of cells around it, it switches. " + "Items count as three floor cells, and dead Trolls count as five wall cells. " + "Some foreign monsters also count as floor or wall cells.\n"; const char *vinehelp = "The Vineyard is filled with vines. A very dense pattern of straight lines here...\n\n" @@ -94,11 +95,11 @@ const char *deadcavehelp = "Somehow, this cave has not received the spark of Life yet."; const char *foresthelp = -MC"This forest is quite dry. Beware the bushfires!\n" -MC"Trees catch fire on the next turn. The temperature of the grass cells " -MC"rises once per turn for each fire nearby, and becomes fire itself " -MC"when its temperature has risen 10 times.\n" -M "You can also cut down the trees. Big trees take two turns to cut down."; + "This forest is quite dry. Beware the bushfires!\n" + "Trees catch fire on the next turn. The temperature of the grass cells " + "rises once per turn for each fire nearby, and becomes fire itself " + "when its temperature has risen 10 times.\n" + "You can also cut down the trees. Big trees take two turns to cut down."; const char *hivehelp = "The Hive is filled with Hyperbugs. They are huge insects which look a bit like " @@ -107,9 +108,60 @@ const char *hivehelp = "including you and enemy Hyperbugs. Will you manage to get to the " "heart of such a nest, and get the precious Royal Jelly?"; +const char *redrockhelp = + "This land contains high rock formations. Most of the valley is at level 0, " + "while items are found at level 3. It is impossible to gain two or more levels, " + "or to lose three levels, in a single move, (attacks are possible at any " + "difference, though). Kill Red Trolls and Rock Snakes to make a cell higher."; + +const char *caribbeanhelp = + "This dangerous sea contains nasty sharks and pirates. "; + +const char *cislandhelp = + "The islands of Caribbean are infinite and circular, and " + "the pirates probably have hidden their treasures somewhere far from the coast."; + +const char *redsnakedes = + "Rock snakes are similar to Sandworms, but they move each turn. However, they " + "only move on the hexagonal cells. They are also somewhat longer than the Sandworms."; + +const char *minedesc = + "This minefield has been created by the Bomberbirds to protect their valuable eggs. " + "Mines explode when they are stepped on, creating fire all around them " + "(this fire never expires in the Minefield). If you don't step on a mine, you " + "know the number of mines in cells around you. These numbers are marked with " + "color codes on the cells you have visited."; + +const char *palacedesc = + "So better just to concentrate on collecting treasure. " + "Beware the traps, and the guards, who are hard to kill!"; + +const char *gatedesc = + "Green pressure plates open all gates in radius 3 around them. " + "Similarly, red pressure plates close all gates in this radius."; + +const char *princessdesc = + "A mouse squeaks at you. It seems that it wants you to go somewhere. " + "That's interesting, what could you find here?\n\n" + "Note: in the part of the Palace that you are exploring during this " + "quest, the distribution of monsters, pressure plates, and items has been " + "changed somewhat, to make it a bit more suitable for less " + "experienced players. The number of monsters does not depend on the " + "number of Hypersian Rugs you have collected, and there are more " + "opening plates.\n\n" + "However, even with the normal distribution, it appears that it should be " + "always possible to reach your goal. If you want this challenge, " + "select it from the special game modes menu."; + +const char *elemdesc = + "The Elemental Planes are divided into four subzones: Planes of Fire, Water, Air, and Earth. " + "You need to collect a Shard from each Plane to construct an Elemental Gem. " + "It is dangerous to collect too many Shards of the same type without constructing a Gem."; + +const char *NODESC = "No description yet."; // --- monsters --- -const int motypes = 67; +const int motypes = 102; struct monstertype { char glyph; @@ -120,116 +172,124 @@ struct monstertype { #define BUGCOLORS 3 +const char* tamebomberdesc = + "This bomberbird will follow you at some distance, and attack your enemies. " + "You can kill it to place a mine."; + +const char *gargdesc = + "A being made of stone, who likes high buildings. It becomes normal stone when " + "killed, but only if next to something stable -- otherwise it falls."; + monstertype minf[motypes] = { { 0, 0, "none" , NULL}, { 'Y', 0x4040FF, "Yeti" , -M "A big and quite intelligent monster living in the Icy Land." + "A big and quite intelligent monster living in the Icy Land." }, { 'W', 0xD08040, "Icewolf" , -MC "A nasty predator from the Icy Land. Contrary to other monsters, " -M "it tracks its prey by their heat." + "A nasty predator from the Icy Land. Contrary to other monsters, " + "it tracks its prey by their heat." }, { 'W', 0xD08040, "Icewolf" , ""}, { 'R', 0xFF8000, "Ranger" , -MC "Rangers take care of the magic mirrors in the Land of Mirrors. " -MC "They know that rogues like to break these mirrors... so " -M "they will attack you!" + "Rangers take care of the magic mirrors in the Land of Mirrors. " + "They know that rogues like to break these mirrors... so " + "they will attack you!" }, { 'T', 0xD0D0D0, "Rock Troll", trollhelp}, { 'G', 0x20D020, "Goblin", -MC "A nasty creature native to the Living Caves. They don't like you " -M "for some reason." + "A nasty creature native to the Living Caves. They don't like you " + "for some reason." }, { 'S', 0xE0E040, "Sand Worm", wormdes }, { 's', 0x808000, "Sand Worm Tail", wormdes }, { 'S', 0x808000, "Sand Worm W", wormdes }, { 'H', 0x80FF00, "Hedgehog Warrior", -MC "These warriors of the Forest wield exotic weapons called hedgehog blades. " -MC "These blades protect them from a frontal attack, but they still can be 'stabbed' " -M "easily by moving from one place next to them to another." + "These warriors of the Forest wield exotic weapons called hedgehog blades. " + "These blades protect them from a frontal attack, but they still can be 'stabbed' " + "easily by moving from one place next to them to another." }, { 'M', 0x806050, "Desert Man", -M "A tribe of men native to the Desert. They have even tamed the huge Sandworms, who won't attack them."}, + "A tribe of men native to the Desert. They have even tamed the huge Sandworms, who won't attack them."}, { 'C', 0x00FFFF, "Ivy Root", ivydes}, { 'C', 0xFFFF00, "Active Ivy", ivydes}, { 'C', 0x40FF00, "Ivy Branch", ivydes}, { 'C', 0x006030, "Dormant Ivy", ivydes}, - { 'C', 0x800000, "Ivy N", ivydes}, - { 'C', 0x800000, "Ivy D", ivydes}, + { 'C', 0x804000, "Dead Ivy", ivydes}, + { 'C', 0x800000, "Dead Ivy", ivydes}, { 'M', 0x804000, "Giant Ape", -M "This giant ape thinks that you are an enemy."}, + "This giant ape thinks that you are an enemy."}, { 'B', 0x909000, "Slime Beast", slimehelp}, { '@', 0x8080FF, "Mirror Image", -M "A magical being which copies your movements." + "A magical being which copies your movements." }, { '@', 0xFF8080, "Mirage", -MC "A magical being which copies your movements. " -M "You feel that it would be much more useful in an Euclidean space." + "A magical being which copies your movements. " + "You feel that it would be much more useful in an Euclidean space." }, { '@', 0x509050, "Golem", -M "You can summon these friendly constructs with a magical process." + "You can summon these friendly constructs with a magical process." }, { '@', 0x509050, "Golem", -M "You can summon these friendly constructs with a magical process." + "You can summon these friendly constructs with a magical process." }, { 'E', 0xD09050, "Eagle", -M "A majestic bird, who is able to fly very fast." + "A majestic bird, who is able to fly very fast." }, { 'S', 0xFF8080, "Seep", -M "A monster who is able to live inside the living cave wall." + "A monster who is able to live inside the living cave wall." }, { 'Z', 0x804000, "Zombie", -M "A typical Graveyard monster." + "A typical Graveyard monster." }, { 'G', 0xFFFFFF, "Ghost", -M "A typical monster from the Graveyard, who moves through walls.\n\n" + "A typical monster from the Graveyard, who moves through walls.\n\n" "There are also wandering Ghosts. They will appear " "if you do not explore any new places for a long time (about 100 turns). " "They can appear anywhere in the game." }, { 'N', 0x404040, "Necromancer", -M "Necromancers can raise ghosts and zombies from fresh graves." + "Necromancers can raise ghosts and zombies from fresh graves." }, { 'S', 0x404040, "Shadow", -M "A creepy monster who follows you everywhere in the Graveyard." + "A creepy monster who follows you everywhere in the Graveyard." }, { 'T', 0x40E040, "Tentacle", tentdes }, { 't', 0x008000, "Tentacle Tail", tentdes }, { 'T', 0x008000, "Tentacle W", tentdes }, { 'z', 0xC00000, "Tentacle (withdrawing)", tentdes }, { 'P', 0xFF8000, "Cultist", -M "People worshipping Cthulhu. They are very dangerous." + "People worshipping Cthulhu. They are very dangerous." }, { 'P', 0xFFFF00, "Fire Cultist", -MC "People worshipping Cthulhu. This one is especially dangerous, " -M "as he is armed with a weapon which launches fire from afar." + "People worshipping Cthulhu. This one is especially dangerous, " + "as he is armed with a weapon which launches fire from afar." }, { 'D', 0xFF0000, "Greater Demon", gdemonhelp}, { 'D', 0x800000, "Greater Demon", gdemonhelp}, { 'd', 0xFF2020, "Lesser Demon", ldemonhelp}, { 'd', 0x802020, "Lesser Demon", ldemonhelp}, { 'S', 0x2070C0, "Ice Shark", -M "This dangerous predator has killed many people, and has been sent to Cocytus." + "This dangerous predator has killed many people, and has been sent to Cocytus." }, { 'W', 0xFFFFFF, "Running Dog", -MC "This white dog is able to run all the time. It is the only creature " -M "able to survive and breed in the Land of Eternal Motion." + "This white dog is able to run all the time. It is the only creature " + "able to survive and breed in the Land of Eternal Motion." }, { 'S', 0xC00040, "Demon Shark", -MC "Demons of Hell do not drown when they fall into the lake in Cocytus. " -M "They turn into demonic sharks, enveloped in a cloud of steam." + "Demons of Hell do not drown when they fall into the lake in Cocytus. " + "They turn into demonic sharks, enveloped in a cloud of steam." }, { 'S', 0xC00040, "Fire Fairy", -MC "These fairies would rather burn the forest, than let you get some Fern Flowers. " -MC "The forest is infinite, after all...\n\n" -M "Fire Fairies transform into fires when they die." + "These fairies would rather burn the forest, than let you get some Fern Flowers. " + "The forest is infinite, after all...\n\n" + "Fire Fairies transform into fires when they die." }, { 'C', 0x4000C0, "Crystal Sage", -MC "This being radiates an aura of wisdom. " -MC "It is made of a beautiful crystal, you would love to take it home. " -MC "But how is it going to defend itself? Better not to think of it, " -MC "thinking causes your brain to go hot...\n\n" -M "Crystal Sages melt at -30 °C, and they can rise the temperature around you from afar." + "This being radiates an aura of wisdom. " + "It is made of a beautiful crystal, you would love to take it home. " + "But how is it going to defend itself? Better not to think of it, " + "thinking causes your brain to go hot...\n\n" + "Crystal Sages melt at -30 °C, and they can rise the temperature around you from afar." }, { 'P', 0x4040C0, "Pikeman", "When Pikemen move, they attack all cells which are now adjacent to them. " @@ -251,7 +311,7 @@ M "Crystal Sages melt at -30 °C, and they can rise the temperature around you "A beast made of vines!\n\n" "Vine Beasts turn into vines when they die." }, - { 'V', 0x003000, "Vine Spirit", + { 'V', 0xFFC0C0, "Vine Spirit", "A spirit living in the vines!\n\n" "Vine Spirits destroy the vines when they die." }, @@ -302,6 +362,71 @@ M "Crystal Sages melt at -30 °C, and they can rise the temperature around you "Illusions are targetted " "by most monsters, just like yourself, Thumpers, and your friends." }, + { 'P', 0xD00000, "Pirate", + "Just a typical hyperbolic pirate." }, + { 'S', 0x8080C0, "Shark", "Just a nasty shark."}, + { 'P', 0x0000FF, "Parrot", "Parrots feel safe in the forests of Caribbean, so they " + "never leave them. But they will help the Pirates by attacking the intruders."}, + { 'S', 0xE09000, "Rock Snake", redsnakedes }, + { 's', 0xE09000, "Rock Snake Tail", redsnakedes }, + { 'T', 0xC02020, "Red Troll", "A kind of Troll native to the Red Rock Valley."}, + { 'B', 0xA00000, "Bomberbird", + "Dark red birds who have created the minefield.\n\n" + "They create a mine on the spot where they are killed, provided " + "that the terrain is suitable. Also note that mines are triggered " + "by dead birds falling on them." + }, + { 'A', 0xFFFFFF, "Albatross", + "Those large seabirds attack you for some reason. At least they are not " + "as fast as Eagles..." + }, + { 'B', 0x40C000, "Tame Bomberbird", tamebomberdesc}, + { 'B', 0x40C000, "Tame Bomberbird", tamebomberdesc}, // bomberbird moved + { 'G', 0xFF0000, "Palace Guard", + "You have to hit Palace Guards several times to kill them. After each hit, they " + "are pushed away and stunned for some time." + }, + { 'G', 0xC06000, "Fat Guard", "Fat guards are too heavy to be pushed away by your hits."}, + { 'G', 0xFFFFFF, "Skeleton", + "Skeletons work similar to Palace Guards, but they won't die no matter how many " + "times you hit them. Well, you have to be more creative...\n\n" + "Skeletons attacked outside of their native land, Palace, are stunned for a longer time." + }, + { 'G', 0xC000C0, "Vizier", + "Viziers are neither pushed away nor stunned. However, you attack them automatically when " + "escaping from them."}, + { 'V', 0xC0C0C0, "Viking", "Mighty warriors from the Fjord, who can use boats."}, + { 'T', 0x00FFFF, "Fjord Troll", + "Fjord Trolls leave a wall when they die, causing the living fjord to rise around it. " + "Contrary to Rock Trolls, items around are not destroyed." + }, + { 'E', 0x0000FF, "Water Elemental", + "Wherever this powerful being goes, the living fjord " + "sinks below water, non-magical boats are destroyed, and fires are extinguished.\n\n" + "As a special case, you can attack the Water Elemental from the water, without drowning immediately." + }, + { 'M', 0xD0D0D0, "Mouse", princessdesc}, + { 'M', 0xD0D0D0, "Mouse", princessdesc}, + { 'P', 0xFF80FF, "Prince", princessdesc}, + { 'P', 0xFF80FF, "Princess", princessdesc}, + { 'P', 0xFF80FF, "Prince", princessdesc}, + { 'P', 0xFF80FF, "Princess", princessdesc}, + { 'S', 0xC0C0C0, "Servant", "A simple servant of the master of the Ivory Tower."}, + { 'B', 0x707070, "Gargoyle", gargdesc}, + { 'E', 0xFF0000, "Fire Elemental", + "This monster leaves a trail of fire behind."}, + { 'E', 0xC0C0FF, "Air Elemental", "An Air Elemental looks like a live tornado. Once you are three (or less) cells from it, " + "it is impossible to move closer, due to strong winds. You can stand and wait, though. " + "This also affects most monsters."}, + { 'D', 0xC06000, "Striped Dog", "A predator native to the Zebra."}, + { 'G', 0xFFFFFF, "Tentacle+Ghost", tentdes }, + // shmup specials + { '@', 0xC0C0C0, "Rogue", "In the Shoot'em Up mode, you are armed with thrown Knives."}, + { '*', 0xC0C0C0, "Knife", "A simple, but effective, missile, used by rogues."}, + { '*', 0xFF0000, "Flail", "This attack is likely to hit the attacker."}, + { '*', 0xFFFF00, "Fireball", "This magical missile burns whatever it hits."}, + { '*', 0xFFFF00, "Tongue", "Some monsters have long tongues, which allow them to attack enemies in nearby cells."}, + { '*', 0xFFFFFF, "Airball", "This magical missile pushes back whatever it hits."} }; enum eMonster { @@ -327,15 +452,25 @@ enum eMonster { moWitch, moWitchSpeed, moWitchFlash, moWitchFire, moWitchWinter, moWitchGhost, moEvilGolem, moKnight, moCultistLeader, moSlimeNextTurn, moKnightMoved, moIllusion, + moPirate, moCShark, moParrot, + moHexSnake, moHexSnakeTail, moRedTroll, moBomberbird, moAlbatross, + moTameBomberbird, moTameBomberbirdMoved, + moPalace, moFatGuard, moSkeleton, moVizier, + moViking, moFjordTroll, moWaterElemental, + moMouse, moMouseMoved, + moPrincess, moPrincessMoved, + moPrincessArmed, moPrincessArmedMoved, + moEdgeMonkey, moGargoyle, moFireElemental, moAirElemental, + moOrangeDog, moTentacleGhost, + // shmup specials + moPlayer, moBullet, moFlailBullet, moFireball, moTongue, moAirball, // temporary - moDeadBug, moLightningBolt + moDeadBug, moLightningBolt, moDeadBird }; -#define NUMWITCH 7 - // --- items ---- -const int ittypes = 40; +const int ittypes = 67; struct itemtype { char glyph; @@ -347,87 +482,87 @@ struct itemtype { itemtype iinf[ittypes] = { { 0, 0, "none", NULL}, { '*', 0xFFFFFF, "Ice Diamond", -M "Cold white gems, found in the Icy Land." + "Cold white gems, found in the Icy Land." }, { '$', 0xFFD700, "Gold", -MC "An expensive metal from the Living Caves. For some reason " -M "gold prevents the living walls from growing close to it." + "An expensive metal from the Living Caves. For some reason " + "gold prevents the living walls from growing close to it." }, { ';', 0xFF4000, "Spice", -MC "A rare and expensive substance found in the Desert. " -M "It is believed to extend life and raise special psychic powers." + "A rare and expensive substance found in the Desert. " + "It is believed to extend life and raise special psychic powers." }, { '*', 0xC00000, "Ruby", -M "A beautiful gem from the Jungle." + "A beautiful gem from the Jungle." }, { '!', 0xFFFF00, "Elixir of Life", -MC "A wonderful beverage, apparently obtained by mixing red and blue slime. You definitely feel more " -M "healthy after drinking it, but you still fell that one hit of a monster is enough to kill you."}, + "A wonderful beverage, apparently obtained by mixing red and blue slime. You definitely feel more " + "healthy after drinking it, but you still fell that one hit of a monster is enough to kill you."}, { '%', 0xFF00FF, "Shard", -MC "A piece of a magic mirror, or a mirage cloud, that can be used for magical purposes. Only mirrors and clouds " -M "in the Land of Mirrors leave these."}, + "A piece of a magic mirror, or a mirage cloud, that can be used for magical purposes. Only mirrors and clouds " + "in the Land of Mirrors leave these."}, { '/', 0xFF8000, "Necromancer's Totem", -M "These sinister totems contain valuable gems."}, + "These sinister totems contain valuable gems."}, { '%', 0x00D000, "Demon Daisy", -M "These star-shaped flowers native to Hell are a valuable alchemical component."}, + "These star-shaped flowers native to Hell are a valuable alchemical component."}, { '/', 0x00FF00, "Statue of Cthulhu", -M "This statue is made of materials which cannot be found in your world."}, + "This statue is made of materials which cannot be found in your world."}, { '*', 0xFF8000, "Phoenix Feather", -M "One of few things that does not cause the floor in the Land of Eternal Motion to collapse. Obviously they are quite valuable." + "One of few things that does not cause the floor in the Land of Eternal Motion to collapse. Obviously they are quite valuable." }, { '*', 0x8080FF, "Ice Sapphire", -M "Cold blue gems, found in the Cocytus." + "Cold blue gems, found in the Cocytus." }, { '*', 0xEEFF20, "Hyperstone", -M "These bright yellow gems can be found only by those who have mastered the Crossroads." + "These bright yellow gems can be found only by those who have mastered the Crossroads." }, { '[', 0x8080FF, "Key", -MC "That's all you need to unlock the Orb of Yendor! Well... as long as you are able to return to the Orb that this key unlocks...\n\n" -M "Each key unlocks only the Orb of Yendor which led you to it." + "That's all you need to unlock the Orb of Yendor! Well... as long as you are able to return to the Orb that this key unlocks...\n\n" + "Each key unlocks only the Orb of Yendor which led you to it." }, { 'o', 0x306030, "Dead Orb", -MC "These orbs can be found in the Graveyard. You think that they were once powerful magical orbs, but by now, their " -M "power is long gone. No way to use them, you could as well simply drop them...\n\n" + "These orbs can be found in the Graveyard. You think that they were once powerful magical orbs, but by now, their " + "power is long gone. No way to use them, you could as well simply drop them...\n\n" }, { 'o', 0xFF20FF, "Orb of Yendor", -MC "This wonderful Orb can only be collected by those who have truly mastered this hyperbolic universe, " -MC "as you need the right key to unlock it. Luckily, your psychic abilities will let you know " -M "where the key is after you touch the Orb." }, + "This wonderful Orb can only be collected by those who have truly mastered this hyperbolic universe, " + "as you need the right key to unlock it. Luckily, your psychic abilities will let you know " + "where the key is after you touch the Orb." }, { 'o', 0xFFFF00, "Orb of Storms", -M "This orb can be used to invoke the lightning spell, which causes lightning bolts to shoot from you in all directions."}, + "This orb can be used to invoke the lightning spell, which causes lightning bolts to shoot from you in all directions."}, { 'o', 0xFFFFFF, "Orb of Flash", -M "This orb can be used to invoke a flash spell, which destroys almost everything in radius of 2."}, + "This orb can be used to invoke a flash spell, which destroys almost everything in radius of 2."}, { 'o', 0x8080FF, "Orb of Winter", -M "This orb can be used to invoke a wall of ice. It also protects you from fires."}, + "This orb can be used to invoke a wall of ice. It also protects you from fires."}, { 'o', 0xFF6060, "Orb of Speed", -M "This orb can be used to move faster for some time."}, + "This orb can be used to move faster for some time."}, { 'o', 0x90B090, "Orb of Life", -M "This orb can be used to summon friendly golems. It is used instantly when you pick it up."}, + "This orb can be used to summon friendly golems. It is used instantly when you pick it up."}, { 'o', 0x60D760, "Orb of Shielding", -M "This orb can protect you from damage."}, + "This orb can protect you from damage."}, { 'o', 0x606060, "Orb of Earth", -M "This orb lets you go through living walls. It also has powers in some of the other lands."}, + "This orb lets you go through living walls. It also has powers in some of the other lands."}, { 'o', 0x20FFFF, "Orb of Teleport", -MC "This orb lets you instantly move to another location on the map. Just click a location which " -M "is not next to you to teleport there. " + "This orb lets you instantly move to another location on the map. Just click a location which " + "is not next to you to teleport there. " }, { 'o', 0xA0FF40, "Orb of Safety", -MC "This orb lets you instantly move to a safe faraway location. Knowing the nature of this strange world, you doubt " -MC "that you will ever find the way back...\n\n" -MC "Your game will be saved if you quit the game while the Orb of Safety is still powered.\n\n" -M "Technical note: as it is virtually impossible to return, this Orb recycles memory used for the world so far (even if you do not use it to save the game). " + "This orb lets you instantly move to a safe faraway location. Knowing the nature of this strange world, you doubt " + "that you will ever find the way back...\n\n" + "Your game will be saved if you quit the game while the Orb of Safety is still powered.\n\n" + "Technical note: as it is virtually impossible to return, this Orb recycles memory used for the world so far (even if you do not use it to save the game). " }, { 'o', 0x40C000, "Orb of Thorns", -M "This orb allows attacking Hedgehog Warriors directly, as well as stabbing other monsters.\n" + "This orb allows attacking Hedgehog Warriors directly, as well as stabbing other monsters.\n" }, { '%', 0x0000FF, "Fern Flower", -M "This flower brings fortune to the person who finds it.\n" + "This flower brings fortune to the person who finds it.\n" }, { '!', 0x900000, "Wine", -M "Wine grown under hyperbolic sun would be extremely prized in your home location." + "Wine grown under hyperbolic sun would be extremely prized in your home location." }, { 'o', 0x706070, "Orb of Aether", -M "This orb allows one to pass through all kinds of walls and chasms." + "This orb allows one to pass through all kinds of walls and chasms." }, { '$', 0xFFFFC0, "Silver", "A precious metal from the Dead Caves." @@ -473,6 +608,91 @@ M "This orb allows one to pass through all kinds of walls and chasms." "If you have both Orb of Teleport and Orb of Trickery, Illusion is cast " "first -- you can then teleport on your Illusion to switch places with it." }, + { 'x', 0xFF0000, "Pirate Treasure", "Ye wonder where did th' Pirates find all these riches..."}, + { '?', 0xFFFFFF, "Compass", + "The hyperbolic pirates have no use for treasure maps. However, they have found " + "out that a compass points to the center of the island. So they just go as " + "far towards the center as they can, and hide their treasure there." + }, + { '*', 0xFF8080, "Red Gem", "A gem from the Red Rock Valley."}, + { 'o', 0x6060FF, "Orb of Time", + "Normally, the power of most Orbs slowly fades away, even when " + "you are not actively using them. This Orb prevents this.\n\n" + + "When you have the Orb of Time, Orbs which are not active won't lose their power. " + "Orbs are considered active if they have a continuous power which has actually " + "affected something in the last turn.\n\n" + + "Orbs of Shielding remain active after being activated (even if you are no longer " + "attacked), and Orbs of Time have a bigger cap inside their native Caribbean than " + "outside." + }, + { 'o', 0x40C0C0, "Orb of Space", + "This Orb is able to bring faraway items to your location, even if there are " + "monsters or barriers on the way. The cost of " + "bringing an item (in charges) equals the square of its distance to you. Contrary " + "to some other Orbs, usage is not allowed if you have not enough power left.", + }, + { '!', 0xFF8080, "Bomberbird Egg", + "Bomberbird eggs are big and tasty, and thus valuable. " + "They can hatch when left alone for some time (but this will never happen " + "if you are watching)." + }, + { '*', 0xFFBF00, "Amber", + "When the tide is away, beautiful ambers can be found on the hyperbolic beaches. " + "Perhaps there used to be a forest here?" + }, + { '$', 0xFFFFFF, "Pearl", + "You do not know exactly why, but there are valuable pearls on many boats " + "in the whirlpool." + }, + { 'o', 0x306000, "Orb of Friendship", + "This Orb summons a friendly Bomberbird." + }, + { 'o', 0x000060, "Orb of Water", + "This Orb allows your boat to go against the current, " + "and also to go into the land, creating water on the way." + }, + { 'o', 0xC00060, "Orb of Air", + "This Orb allows you to blow your enemies away.\n\n" + "Click a monster to blow it one cell away. It cannot be used against mimics, ghosts, sharks and other monsters restricted to a specific terrain, and multi-tile monsters." + }, + { '?', 0x802000, "Hypersian Rug", + "Nice, a hyperbolic rug! It will not fit very well on your flat Euclidean floor, but who cares?"}, + { 'o', 0x60A060, "Orb of the Frog", + "This Orb lets you jump to a place which is two cell away from you, in a single turn. " + "You can jump over water, chasms and fire, but not over walls."}, + { '*', 0x800000, "Garnet", "Vikings believe that garnets improve their strength."}, + { 'o', 0x0070C0, "Orb of the Fish", + "This Orb lets you dive into the water. While diving, you are able to see and collect underwater treasures, " + "while being invisible to monsters yourself. You are afraid of jumping into the water straight from a boat, so usually you won't do it." + }, + { 'o', 0xC00000, "Orb of Discord", + "Causes most monsters to attack other monsters, not only you and your friends."}, + { 'P', 0x00FF00, "SAVE", princessdesc}, + { 'o', 0xFF208F, "Orb of Love", + "Love takes time, but it heals all wounds, and transcends time and space.\n\n" + "The Orb of Love is worth 30$$$, if you end the game with it.\n" + }, + { '/', 0xFFFFE0, "Ivory Figurine", + "A beautiful figurine, made of ivory. Figurines close to the base of the Tower " + "tend do disappear after you have collected many of them." + }, + { '*', 0x606060, "Onyx", "A black gem with white stripes. It is beautiful."}, + { '%', 0xFF8000, "Fire Shard", elemdesc}, + { '%', 0x8080C0, "Air Shard", elemdesc}, + { '%', 0x80C080, "Earth Shard", elemdesc}, + { '%', 0x0000C0, "Water Shard", elemdesc}, + { '*', 0xF0F0F0, "Elemental Gem", elemdesc}, + { 'o', 0x309060, "Orb of Summoning", + "This orb allows you to summon monsters. Usually, they are either Elementals or " + "native creatures. While the monsters do not like being summoned, and will " + "attack you once they recover from summoning sickness, such summoning " + "often has its uses." + }, + { 'o', 0x306090, "Orb of Matter", + "This Orb allows to temporarily create impassable matter, either to block paths or " + "to build bridges across chasms and waters."} }; enum eItem { itNone, itDiamond, itGold, itSpice, itRuby, itElixir, itShard, itBone, itHell, itStatue, @@ -484,12 +704,23 @@ enum eItem { itNone, itDiamond, itGold, itSpice, itRuby, itElixir, itShard, itBo itWine, itOrbGhost, itSilver, itOrbPsi, itRoyalJelly, itEmerald, itOrbInvis, itPower, itOrbFire, itHolyGrail, itGrimoire, - itOrbDragon, itOrbIllusion + itOrbDragon, itOrbIllusion, + itPirate, itCompass, + itRedGem, itOrbPreserve, itOrbTelekinesis, + itBombEgg, itCoast, itWhirlpool, + itOrbFriend, itOrbWater, itOrbAir, + itPalace, itOrbFrog, + itFjord, itOrbFish, + itOrbDiscord, + itSavedPrincess, itOrbLove, + itEdge, itZebra, + itFireShard, itAirShard, itEarthShard, itWaterShard, + itElemental, itOrbSummon, itOrbMatter }; // --- wall types --- -const int walltypes = 37; +const int walltypes = 69; struct walltype { char glyph; @@ -500,10 +731,14 @@ struct walltype { const char *lakeDesc = "Hell has these lakes everywhere... They are shaped like evil stars, and filled with burning sulphur."; +const char *thumpdesc = "A device that attracts sandworms and other enemies. You need to activate it."; + +const char *twdesc = "This structure will disappear after some time."; + walltype winf[walltypes] = { { '.', 0xFF00FF, "none", NULL}, { '#', 0x8080FF, "ice wall", -M "Ice Walls melt after some time has passed." + "Ice Walls melt after some time has passed." }, { '#', 0xC06000, "great wall", barrierhelp}, { '+', 0x900030, "red slime", slimehelp }, @@ -512,39 +747,38 @@ M "Ice Walls melt after some time has passed." { '.', 0x306060, "living floor",cavehelp}, { '#', 0xD03030, "dead troll", trollhelp}, { '#', 0xCDA98F, "sand dune", -M "A natural terrain feature of the Desert." + "A natural terrain feature of the Desert." }, { '%', 0xC0C0FF, "Magic Mirror", -M "You can go inside the Magic Mirror, and produce some mirror images to help you." + "You can go inside the Magic Mirror, and produce some mirror images to help you." }, { '%', 0xFFC0C0, "Cloud of Mirage", -MC "Tiny droplets of magical water. You see images of yourself inside them. " -M "Go inside the cloud, to make these images help you."}, - { '^', 0x8D694F, "Thumper", -M "A device that attracts sandworms and other enemies. You need to activate it."}, - { '^', 0x804000, "Bonfire", -M "A heap of wood that can be used to start a fire. Everything is already here, you just need to touch it to fire it." + "Tiny droplets of magical water. You see images of yourself inside them. " + "Go inside the cloud, to make these images help you."}, + { '^', 0x8D694F, "Thumper", thumpdesc}, + { '^', 0x804000, "Fire", + "This cell is on fire. Most beings and items cannot survive." }, { '+', 0xC0C0C0, "ancient grave", -M "An ancient grave." + "An ancient grave." }, { '+', 0xD0D080, "fresh grave", -M "A fresh grave. Necromancers like those." + "A fresh grave. Necromancers like those." }, { '#', 0x00FFFF, "column", -M "A piece of architecture typical to R'Lyeh." + "A piece of architecture typical to R'Lyeh." }, { '=', 0xFFFF00, "lake of sulphur", lakeDesc }, { '=', 0xFFFF00, "lake of sulphur", lakeDesc }, { '=', 0x000080, "lake", -M "An impassable lake in Cocytus." + "An impassable lake in Cocytus." }, { '_', 0x000080, "frozen lake", cocytushelp }, { '>', 0x101010, "chasm", -M "It was a floor... until something walked on it." + "It was a floor... until something walked on it." }, { '>', 0x101010, "chasmD", -M "It was a floor... until something walked on it." + "It was a floor... until something walked on it." }, { '#', 0x60C000, "big tree", foresthelp}, { '#', 0x006000, "tree", foresthelp}, @@ -573,24 +807,86 @@ M "It was a floor... until something walked on it." "valuable anyway. Most monsters will never go through them... they probably have " "their reasons. But you can go! When you move into the cell containing " "a statue, you push the statue to the cell you left.\n" - } + }, + { '=', 0x0000A0, "sea", caribbeanhelp}, + { '+', 0x0000A0, "boat", + "Hyperbolic pirates do not need huge ships, since so many lands to conquest " + "are so close. These small boats are enough for them.\n\n" + "Boats allow you to go through water. If you are in a boat, you can move into " + "a water cell (and the boat will come with you)." + }, + { '.', 0x00FF00, "island", cislandhelp}, + { '.', 0x80C000, "island", cislandhelp}, + { '#', 0x006000, "tree", + "The forests of Caribbean are too dense to be traversed by humans, " + "and they are hard to burn. Many colorful parrots can be found there." + }, + { ',', 0x800000, "rock I", redrockhelp}, + { ':', 0xC00000, "rock II", redrockhelp}, + { ';', 0xFF0000, "rock III", redrockhelp}, + { '.', 0xD0D0D0, "minefield", minedesc}, + { '.', 0xD0D0D0, "minefield", minedesc}, + { '.', 0x909090, "cell without mine", minedesc}, + { '+', 0x808000, "stranded boat", + "This boat cannot go through the sand. But if you sit inside and " + "wait for the tide, you will be able to use it to travel through the Ocean." + }, + { '#', 0xFFD500, "palace wall", palacedesc }, + { '+', 0xFFFFFF, "closed gate", gatedesc }, + { '-', 0x404040, "open gate", gatedesc }, + { '_', 0xC00000, "closing plate", gatedesc }, + { '_', 0x00C000, "opening plate", gatedesc }, + { '_', 0x202020, "trapdoor", "This floor will fall after someone goes there. Go quickly!" }, + { '+', 0xFF0000, "giant rug", + "This is the biggest Hypersian Rug you have ever seen! " + "Unfortunately, it is too large to take it as a trophy." }, + { '#', 0xfffff0, "platform", "You can stand here."}, + { '#', 0x909090, "stone gargoyle", gargdesc}, + { '.', 0x909090, "stone gargoyle floor", gargdesc}, + { '.', 0x909090, "rubble", "Some rubble."}, + { '+', 0x804000, "ladder", + "You can use this ladder to climb the Tower." + }, + { '#', 0xC0C0C0, "limestone wall", "Simply a wall. Mostly."}, + { '^', 0x804000, "Bonfire", + "A heap of wood that can be used to start a fire. Everything is already here, you just need to touch it to fire it." + }, + { '^', 0x8D694F, "Thumper", + "A device that attracts sandworms and other enemies. You need to activate it."}, + { '^', 0x804000, "Eternal Fire", + "This fire never burns out." + }, + { '.', 0x909090, "stone gargoyle bridge", gargdesc}, + { '#', 0x309060, "temporary wall", twdesc}, + { '.', 0x309060, "temporary floor", twdesc}, + { '.', 0x309060, "temporary bridge", twdesc} }; enum eWall { waNone, waIcewall, waBarrier, waFloorA, waFloorB, waCavewall, waCavefloor, waDeadTroll, waDune, - waMirror, waCloud, waThumper, waBonfire, waAncientGrave, waFreshGrave, waColumn, waSulphurC, waSulphur, + waMirror, waCloud, waThumperOff, waFire, waAncientGrave, waFreshGrave, waColumn, waSulphurC, waSulphur, waLake, waFrozenLake, waChasm, waChasmD, waDryTree, waWetTree, waVinePlant, waVineHalfA, waVineHalfB, waPartialFire, waDeadwall, waDeadfloor, waDeadfloor2, waWaxWall, waGlass, waCamelot, waRoundTable, waCamelotMoat, waBigStatue, + waSea, waBoat, waCIsland, waCIsland2, waCTree, + waRed1, waRed2, waRed3, + waMineUnknown, waMineMine, waMineOpen, + waStrandedBoat, + waPalace, waClosedGate, waOpenGate, waClosePlate, waOpenPlate, waTrapdoor, + waGiantRug, + waPlatform, waGargoyle, waGargoyleFloor, waRubble, waLadder, waStone, + waBonfireOff, waThumperOn, waEternalFire, + waGargoyleBridge, + waTempWall, waTempFloor, waTempBridge, // temporary walls for various purposes - waTemporary, waEarthD + waTemporary, waEarthD, waElementalTmp, waElementalD }; // --- land types --- -const int numLands = 20; -const int landtypes = numLands + 3; +const int numLands = 35; +const int landtypes = numLands + 6; struct landtype { int color; @@ -602,46 +898,46 @@ landtype linf[landtypes] = { { 0xFF00FF, "???" , ""}, { 0xC06000, "Great Wall" , ""}, { 0xFF0000, "Crossroads" , -MC "This land is a quick gateway to other lands. It is very easy to find other lands " -MC "from the Crossroads. Which means that you find monsters from most other lands here!\n\n" -MC "As long as you have found enough treasure in their native lands, you can " -MC "find magical items in the Crossroads. Mirror Land brings mirrors and clouds, " -MC "and other land types bring magical orbs.\n\n" -MC "A special treasure, Hyperstone, can be found on the Crossroads, but only " -MC "after you have found 10 of every other treasure." + "This land is a quick gateway to other lands. It is very easy to find other lands " + "from the Crossroads. Which means that you find monsters from most other lands here!\n\n" + "As long as you have found enough treasure in their native lands, you can " + "find magical items in the Crossroads. Mirror Land brings mirrors and clouds, " + "and other land types bring magical orbs.\n\n" + "A special treasure, Hyperstone, can be found on the Crossroads, but only " + "after you have found 10 of every other treasure." }, { 0xCDA98F, "Desert", -M "A hot land, full of sand dunes, mysterious Spice, and huge and dangerous sand worms." + "A hot land, full of sand dunes, mysterious Spice, and huge and dangerous sand worms." }, { 0x8080FF, "Icy Land", -MC "A very cold land, full of ice walls. Your mere presence will cause these ice walls to " -M "melt, even if you don't want it." + "A very cold land, full of ice walls. Your mere presence will cause these ice walls to " + "melt, even if you don't want it." }, { 0x306060, "Living Cave", cavehelp}, { 0x00C000, "Jungle", -M "A land filled with huge ivy plants and dangerous animals." + "A land filled with huge ivy plants and dangerous animals." }, { 0x900090, "Alchemist Lab", slimehelp}, { 0x704070, "Mirror Land", -M "A strange land which contains mirrors and mirages, protected by Mirror Rangers."}, + "A strange land which contains mirrors and mirages, protected by Mirror Rangers."}, { 0x404070, "Graveyard", -MC "All the monsters you kill are carried to this strange land, and buried. " -M "Careless Rogues are also carried here..." + "All the monsters you kill are carried to this strange land, and buried. " + "Careless Rogues are also carried here..." }, { 0x00FF00, "R'Lyeh", -M "An ancient sunken city which can be reached only when the stars are right.\n\n" + "An ancient sunken city which can be reached only when the stars are right.\n\n" "You can find Temples of Cthulhu in R'Lyeh once you collect five Statues of Cthulhu." }, { 0xC00000, "Hell", -M "A land filled with demons and molten sulphur. Abandon all hope ye who enter here!" + "A land filled with demons and molten sulphur. Abandon all hope ye who enter here!" }, { 0x00FF00, "Cocytus", cocytushelp }, { 0xFFFF00, "Land of Eternal Motion", -MC "A land where you cannot stop, because every piece of floor is extremely unstable. Only monsters who " -MC "can run forever are able to survive there, and only phoenix feathers are so light that they do not disturb " -M "the floor.\n" + "A land where you cannot stop, because every piece of floor is extremely unstable. Only monsters who " + "can run forever are able to survive there, and only phoenix feathers are so light that they do not disturb " + "the floor.\n" }, { 0x008000, "Dry Forest", foresthelp}, { 0x0000C0, "Emerald Mine", @@ -659,38 +955,107 @@ M "the floor.\n" "Witches are allowed to use all the powers of the " "basic orbs against intruders. These powers never expire, but a Witch " "can use only one power at a time (not counting Orbs of Life).\n\n" - "Witches and Golems don't pursue you into other Lands. Also, most Orb powers" + "Witches and Golems don't pursue you into other Lands. Also, most Orb powers " "are drained when you leave the Land of Power." }, { 0xD0D0D0, "Camelot", camelothelp }, { 0xD000D0, "Temple of Cthulhu", templehelp }, - { 0xE08020, "Game Board", gameboardhelp} + { 0xFF8000, "Crossroads II", + "An alternate layout of the Crossroads. It is more dense and more regular, " + "although you won't find the castle of Camelot here." + }, + { 0x0000FF, "Caribbean", caribbeanhelp}, + { 0x400000, "Red Rock Valley", redrockhelp }, + { 0xD0D0D0, "Minefield", minedesc}, + { 0x2020FF, "Ocean", + "You can collect some valuable Ambers on the coast, but beware the tides!\n\n" + "You can also take one of the boats and venture into the Ocean, " + "to find other coasts, dangerous whirlpools, and islands inhabited by Pirates." + }, + { 0x0000C0, "Whirlpool", + "Many lost boats are spinning in this whirlpool. Some of them contain treasures " + "and Pirates.\n\n" + "Unmanned boats will go one cell clockwise in each turn. Sharks and manned boats " + "are only allowed to go with the current, that is, towards the center, or clockwise." + }, + { 0xFFD500, "Palace", palacedesc }, + { 0xC0C000, "Living Fjord", + "A coastal area, from where you can get both to the inland worlds and to the Ocean. " + "Each turn, each cell will become water or earth, based on the majority of cells around it. " + "Contrary to the Living Caves, this process is not affected by most items and monsters, " + "but elementals, dead Trolls, and cells outside of the Living Fjord have " + "a very powerful effect." + }, + { 0xFFFFE0, "Ivory Tower", "Powerful wizards claimed this part of the world, to perform their magical " + "experiments in peace and solitude. They have changed the direction of gravity, " + "to make it even harder for intruders to reach them.\n\n" + "Gravity works as follows: cells are unstable if they are empty, and there is " + "no cell immediately below them which contains a wall. It is impossible to move " + "from one unstable cell to another, except if moving down."}, + { 0x606060, "Zebra", "Everything in this Land has black and white stripes."}, + { 0xC08080, "Plane of Fire", elemdesc}, + { 0x808080, "Plane of Air", elemdesc}, + { 0x80C080, "Plane of Earth", elemdesc}, + { 0x8080C0, "Plane of Water", elemdesc}, + { 0x4040FF, "Crossroads III", + "An alternate layout of the Crossroads. Great Walls cross here at right angles." + }, + { 0x4040C0, "Sea Border", "Border between seas."}, + { 0x4040C0, "Elemental Planes", elemdesc}, + { 0xE08020, "Canvas", "A fake Land with colored floors."}, + { 0x00C000, "Palace Quest", princessdesc}, // this is fake }; enum eLand { laNone, laBarrier, laCrossroads, laDesert, laIce, laCaves, laJungle, laAlchemist, laMirror, laGraveyard, - laRlyeh, laHell, laCocytus, laMotion, laDryForest, laFjord, laWineyard, laDeadCaves, - laHive, laPower, laCamelot, laTemple, laGameBoard }; + laRlyeh, laHell, laCocytus, laMotion, laDryForest, laEmerald, laWineyard, laDeadCaves, + laHive, laPower, laCamelot, laTemple, + laCrossroads2, laCaribbean, laRedRock, laMinefield, laOcean, laWhirlpool, + laPalace, laLivefjord, + laEdge, laZebra, laEFire, laEAir, laEEarth, laEWater, laCrossroads3, + laOceanWall, laElementalWall, laCanvas, laPrincessQuest }; // cell information for the game struct gcell { - // 8 bits - eLand land : 5; - unsigned mondir : 3; - // 8 bits - eMonster monst : 7; - unsigned ligon : 1; - // 16 bits - eWall wall : 6; - eLand barleft : 5, barright : 5; - // 16 bits - eItem item : 6; - unsigned cpdist : 5, mpdist : 5; - // 14 bits - unsigned pathdist : 10, bardir : 4; - short tmp; - float heat; + + // main fields + eLand land : 8; + eWall wall : 8; + eMonster monst : 8; + eItem item : 8; + + // if this is a barrier, what lands on are on the sides? + eLand barleft : 8, barright : 8; + + unsigned ligon : 1; // is it sparkling with lightning? + + unsigned + pathdist : 5, // player distance wrt usual movement + cpdist : 5, mpdist : 5; // current/minimum player distance + + unsigned mondir : 3, // monster direction, for multi-tile monsters and graphics + bardir : 4, // barrier direction + stuntime : 4, // stun time left (for Palace Guards and Skeletons) + hitpoints : 3, // hitpoints left (for Palace Guards) + landflags : 2; // extra flags for land + + char wparam; // wall parameter, used for remaining power of Bonfires and Thumpers + + // 'tmp' is used for: + // pathfinding algorithm used by monsters with atypical movement (which do not use pathdist) + // bugs' pathfinding algorithm + short aitmp; + + // 'landparam' is used for: + // heat in Icy/Cocytus; + // heat in Dry (0..10); + // CR2 structure; + // hive Weird Rock color / pheromones; + // Ocean/coast depth + union { int32_t landpar; float heat; } LHU; }; +#define landparam LHU.landpar + #define NODIR 7 #define NOBARRIERS 8 diff --git a/direntx.h b/direntx.h new file mode 100644 index 00000000..3abedfaf --- /dev/null +++ b/direntx.h @@ -0,0 +1,143 @@ +/* + * DIRENT.H (formerly DIRLIB.H) + * This file has no copyright assigned and is placed in the Public Domain. + * This file is a part of the mingw-runtime package. + * No warranty is given; refer to the file DISCLAIMER within the package. + * + */ +#ifndef _DIRENT_H_ +#define _DIRENT_H_ + +/* All the headers include this file. */ +#include <_mingw.h> + +#include + +#ifndef RC_INVOKED + +#ifdef __cplusplus +extern "C" { +#endif + +struct dirent +{ + long d_ino; /* Always zero. */ + unsigned short d_reclen; /* Always zero. */ + unsigned short d_namlen; /* Length of name in d_name. */ + + /* The following exactly mimic the layout of _finddata_t ... + */ + unsigned d_type; /* File attributes */ + time_t d_time_create; + time_t d_time_access; /* always midnight local time */ + time_t d_time_write; + _fsize_t d_size; + /* + * ...so that we may map a union of _finddata_t at the + * location of d_type (corresponding to _finddata_t.attrib), + * and thus map this directly to the _findfirst/_findnext + * returned field. + */ + char d_name[FILENAME_MAX]; /* File name. */ +}; + +/* + * This opaque data type represents the private structure + * through which a directory stream is referenced. + */ +typedef union __dirstream_t DIR; + +DIR* __cdecl __MINGW_NOTHROW opendir (const char*); +struct dirent* __cdecl __MINGW_NOTHROW readdir (DIR*); +int __cdecl __MINGW_NOTHROW closedir (DIR*); +void __cdecl __MINGW_NOTHROW rewinddir (DIR*); +long __cdecl __MINGW_NOTHROW telldir (DIR*); +void __cdecl __MINGW_NOTHROW seekdir (DIR*, long); + + +/* wide char versions */ + +struct _wdirent +{ + long d_ino; /* Always zero. */ + unsigned short d_reclen; /* Always zero. */ + unsigned short d_namlen; /* Length of name in d_name. */ + + /* The following exactly mimic the layout of _wfinddata_t ... + */ + unsigned d_type; /* File attributes */ + time_t d_time_create; /* -1 for FAT file systems */ + time_t d_time_access; /* -1 for FAT file systems */ + time_t d_time_write; + _fsize_t d_size; + /* + * ...so that we may map a union of _wfinddata_t at the + * location of d_type (corresponding to _wfinddata_t.attrib), + * and thus map this directly to the _wfindfirst/_wfindnext + * returned field. + */ + wchar_t d_name[FILENAME_MAX]; /* File name. */ +}; + +/* + * This opaque data type represents the private structure + * through which a wide directory stream is referenced. + */ +typedef union __wdirstream_t _WDIR; + +_WDIR* __cdecl __MINGW_NOTHROW _wopendir (const wchar_t*); +struct _wdirent* __cdecl __MINGW_NOTHROW _wreaddir (_WDIR*); +int __cdecl __MINGW_NOTHROW _wclosedir (_WDIR*); +void __cdecl __MINGW_NOTHROW _wrewinddir (_WDIR*); +long __cdecl __MINGW_NOTHROW _wtelldir (_WDIR*); +void __cdecl __MINGW_NOTHROW _wseekdir (_WDIR*, long); + + +#ifdef __cplusplus +} +#endif + +#if defined(_BSD_SOURCE) || defined(_WIN32) +/* + * BSD-ish systems define manifest constants for the d_type field; + * although probably only DT_REG and DT_DIR are useful on Win32, we + * try to map them as best we can from the _finddata.attrib field. + * + * The relevant Microsoft manifest values are: + * + * _A_NORMAL (0x0000) normal file: best fit for DT_REG + * _A_RDONLY (0x0001) read-only: no BSD d_type equivalent + * _A_HIDDEN (0x0002) hidden entity: no BSD equivalent + * _A_SYSTEM (0x0004) system entity: no BSD equivalent + * _A_VOLID (0x0008) volume label: no BSD equivalent + * _A_SUBDIR (0x0010) directory: best fit for DT_DIR + * _A_ARCH (0x0020) "dirty": no BSD equivalent + * + * Thus, we may immediately define: + */ +#define DT_REG _A_NORMAL +#define DT_DIR _A_SUBDIR + +/* The remaining BSD d_type manifest values have no Win32 equivalents; + * we will define them artificially, and then we will ensure that our + * opendir()/readdir() implementation will never assign them; (we will + * substitute DT_UNKNOWN, but it would be unwise to simply make these + * equivalent to that, since an application is likely to simply check + * for d_type equal to any one of these defined types, and thus could + * mistakenly identify DT_UNKNOWN as being of the tested type): + */ +#define DT_BLK (((_A_SUBDIR) << 4) | DT_UNKNOWN) +#define DT_CHR (((_A_SUBDIR) << 5) | DT_UNKNOWN) +#define DT_FIFO (((_A_SUBDIR) << 6) | DT_UNKNOWN) +#define DT_LNK (((_A_SUBDIR) << 7) | DT_UNKNOWN) +#define DT_SOCK (((_A_SUBDIR) << 8) | DT_UNKNOWN) + +/* No file system entity can ever be simultaneously a volume label + * and a directory; we will exploit this to unambiguously define: + */ +#define DT_UNKNOWN (_A_VOLID | _A_SUBDIR) + +#endif /* _BSD_SOURCE */ +#endif /* ! RC_INVOKED */ + +#endif /* !defined _DIRENT_H_ */ diff --git a/game.cpp b/game.cpp index c285d339..a215972c 100644 --- a/game.cpp +++ b/game.cpp @@ -15,6 +15,26 @@ int turncount; int lastexplore; eLand lastland; +bool hardcore = false; +int hardcoreAt; + +bool randomPatternsMode = false; +int randompattern[landtypes]; + +#define RANDLANDS 14 +eLand randlands[14] = { + laIce, laDesert, laCaves, laAlchemist, laGraveyard, laPower, laLivefjord, laZebra, + laRlyeh, laDryForest, laEmerald, laWineyard, laDeadCaves, laRedRock + }; + +bool seenSevenMines = false; + +#define PUREHARDCORE_LEVEL 10 + +bool pureHardcore() { return hardcore && hardcoreAt < PUREHARDCORE_LEVEL; } + +bool canmove = true; + int sagephase = 0; // number of Grails collected, to show you as a knight @@ -25,7 +45,9 @@ bool safety = false; int showid = 0; bool lifebrought = false; // was Life brought to the Dead Caves? -bool invismove = false; // last move was invisible +bool escaped = false; // escaped the Whirlpool? + +bool invismove = false, invisfish = false; // last move was invisible [due to Fish] int currentLocalTreasure; @@ -44,7 +66,8 @@ extern void DEBT(const char *buf); bool eq(short a, short b) { return a==b; } // game state -int items[ittypes], kills[motypes], explore[10], exploreland[10][landtypes], landcount[landtypes]; +int items[ittypes], hiitems[ittypes], kills[motypes], explore[10], exploreland[10][landtypes], landcount[landtypes]; +bool orbused[ittypes], lastorbused[ittypes]; bool playerdead = false; // obsolete bool playermoved = true; // center on the PC? bool flipplayer = true; // flip the player image after move, do not flip after attack @@ -59,12 +82,14 @@ int cheater = 0; // did the player cheat? vector dcal; // queue for cpdist vector pathq; // queue for pathdist +vector offscreen; // offscreen cells to take care off + vector pathqm; // list of monsters to move (pathq restriced to monsters) vector targets; // list of monster targets // monsters of specific types to move -vector worms, ivies, ghosts, golems, mirrors, mirrors2; +vector worms, ivies, ghosts, golems, mirrors, mirrors2, hexsnakes; vector temps; // temporary changes during bfs vector tempval; // restore temps @@ -82,42 +107,112 @@ int first7; // the position of the first monster at distance 7 in dcal cellwalker cwt; // player character position +// heat <-> Celsius calculations: + +bool isIcyLand(eLand l) { + return l == laIce || l == laCocytus; + } + bool isIcyLand(cell *c) { - return c->land == laIce || c->land == laCocytus; + return isIcyLand(c->land); + } + +inline float& HEAT(cell *c) { + return c->LHU.heat; + } + +#include "mtrand.cpp" + +MTRand_int32 r; + +void shrand(int i) { + r.seed(i); + } + +int hrand(int i) { + return r() % i; + } + +double absheat(cell *c) { + if(c->land == laCocytus) return HEAT(c) -.6; + if(c->land == laIce) return HEAT(c) -.4; + return 0; + } + +double celsius(cell *c) { return absheat(c) * 60; } + +// watery + +bool isWatery(cell *c) { + return c->wall == waCamelotMoat || c->wall == waSea || c->wall == waLake; + } + +bool isWateryOrBoat(cell *c) { + return isWatery(c) || c->wall == waBoat; + } + +bool boatStrandable(cell *c) { + return c->wall == waNone && (c->land == laLivefjord || c->land == laOcean); } void initcell(cell *c) { c->mpdist = INFD; // minimum distance from the player, ever c->cpdist = INFD; // current distance from the player c->pathdist = INFD; // current distance from the player, along paths (used by yetis) - c->heat = 0; + c->landparam = 0; c->landflags = 0; c->wall = waNone; c->item = itNone; c->monst = moNone; c->bardir = NODIR; c->land = laNone; - c->tmp = -1; c->ligon = 0; - lastexplore = turncount; + c->stuntime = 0; + lastexplore = shmup::on ? shmup::curtime : turncount; } // 0 = basic treasure, 1 = something else, 2 = power orb #define IC_TREASURE 0 #define IC_OTHER 1 #define IC_ORB 2 + +bool isElementalShard(eItem i) { + return + i == itFireShard || i == itAirShard || i == itEarthShard || i == itWaterShard; + } + +eMonster elementalOf(eLand l) { + if(l == laEFire) return moFireElemental; + if(l == laEWater) return moWaterElemental; + if(l == laEAir) return moAirElemental; + if(l == laEEarth) return moEarthElemental; + return moNone; + } + int itemclass(eItem i) { if(i == 0) return -1; if(i < itKey || i == itFernFlower || i == itWine || i == itSilver || i == itEmerald || i == itRoyalJelly || i == itPower || - i == itGrimoire) + i == itGrimoire || i == itPirate || i == itRedGem || i == itBombEgg || + i == itCoast || i == itWhirlpool || i == itPalace || i == itFjord || + i == itElemental || i == itZebra || i == itEdge) return IC_TREASURE; - if(i == itKey || i == itOrbYendor || i == itGreenStone || i == itHolyGrail) - return IC_OTHER; + if(i == itKey || i == itOrbYendor || i == itGreenStone || i == itHolyGrail || i == itCompass || + i == itSavedPrincess || isElementalShard(i)) + return IC_OTHER; return IC_ORB; } +bool itemHidden(cell *c) { + return isWatery(c); + } + +bool itemHiddenFromSight(cell *c) { + return isWatery(c) && !items[itOrbInvis] && !(items[itOrbFish] && isWatery(cwt.c)); + } + int puregold() { int i = items[itOrbYendor] * 50 + items[itHolyGrail] * 10; + if(items[itOrbLove]) i += 30; for(int t=0; t= 10; + return false; + } + + switch(l) { + case laIce: case laJungle: case laCaves: case laDesert: + case laMotion: case laCrossroads: + return true; + + case laMirror: case laMinefield: case laAlchemist: case laPalace: + case laOcean: case laLivefjord: + return gold() >= 30; + + case laCaribbean: case laWhirlpool: + return exploreland[0][laOcean] || items[itCoast] || items[itStatue]; + + case laRlyeh: case laDryForest: case laWineyard: case laCrossroads2: + return gold() >= 60; + + case laDeadCaves: + return gold() >= 60 && items[itGold] >= 10; + + case laGraveyard: + return tkills() >= 100; + + case laHive: + return tkills() >= 100 && gold() >= 60; + + case laRedRock: + return gold() >= 60 && items[itSpice] >= 10; + + case laEmerald: + return (items[itFernFlower] >= 5 && items[itGold] >= 5) || kills[moVizier]; + + case laCamelot: + return items[itEmerald] >= 5; + + case laHell: case laCrossroads3: + return hellUnlocked(); + + case laCocytus: case laPower: + return items[itHell] >= 10; + + case laTemple: + return items[itStatue] >= 5; + + case laEdge: return gold() >= 60; + case laZebra: return gold() >= 30 && items[itFeather] >= 10; + + case laEAir: case laEEarth: case laEWater: case laEFire: case laElementalWall: + return + kills[moFireElemental] || kills[moWaterElemental] || + kills[moEarthElemental] || kills[moAirElemental]; + + case laBarrier: case laNone: case laOceanWall: case laCanvas: + return false; + + case laPrincessQuest: return kills[moVizier]; + } + return false; + } + +int numplayers() { + if(shmup::on) return shmup::players; + return 1; + } + +cell *playerpos(int i) { + if(!shmup::on) return cwt.c; + return shmup::playerpos(i); + } + +bool isPlayerOn(cell *c) { + if(!shmup::on) return c == cwt.c; + for(int i=0; iwall == waBoat || c->wall == waStrandedBoat); + for(int i=0; iwall == waBoat || c->wall == waStrandedBoat || shmup::playerInBoat(i) + )) + return true; + return false; + } + +bool playerInPower() { + if(!shmup::on) return cwt.c->land == laPower; + for(int i=0; iland == laPower) + return true; + return false; + } + eItem localTreasureType() { lastland = cwt.c->land; return treasureType(lastland); @@ -168,22 +585,44 @@ void countLocalTreasure() { currentLocalTreasure = i ? items[i] : 0; } -bool hellUnlocked() { +int orbsUnlocked() { int i = 0; for(int t=0; t= 10) i++; - return i >= 9; + return i; } -bool hyperstonesUnlocked() { +bool hellUnlocked() { + return orbsUnlocked() >= 9; + } + +void countHyperstoneQuest(int& i1, int& i2) { + i1 = 0; i2 = 0; for(int t=1; t= 10) i1++; } + } + +bool hyperstonesUnlocked() { + int i1, i2; + countHyperstoneQuest(i1, i2); + return i1 == i2; + } + +bool markOrb(eItem it) { + if(!items[it]) return false; + orbused[it] = true; return true; } +bool markOrb2(eItem it) { + if(!items[it]) return false; + orbused[it] = true; + return items[it] > 1; + } + int gold() { return puregold(); } @@ -214,32 +653,159 @@ int tkills() { kills[moDarkTroll] + kills[moEarthElemental] + kills[moWitch] + kills[moEvilGolem] + kills[moWitchFlash] + kills[moWitchFire] + kills[moWitchWinter] + kills[moWitchSpeed] + - kills[moCultistLeader]; + kills[moCultistLeader] + + kills[moPirate] + kills[moCShark] + kills[moParrot] + + kills[moHexSnake] + kills[moRedTroll] + + kills[moPalace] + kills[moSkeleton] + kills[moFatGuard] + kills[moVizier] + + kills[moViking] + kills[moFjordTroll] + kills[moWaterElemental] + + kills[moAlbatross] + + kills[moAirElemental] + kills[moFireElemental] + + kills[moGargoyle] + kills[moEdgeMonkey] + kills[moOrangeDog] + ; } -bool passable(cell *w, cell *from, bool monster_passable, bool mirror_passable) { - if(w->wall == waFloorA && from && from->wall == waFloorB && !w->item && !from->item) - return false; - if(w->wall == waFloorB && from && from->wall == waFloorA && !w->item && !from->item) - return false; - if(w->wall == waMirror || w->wall == waCloud) return mirror_passable; - if((w->wall == waVineHalfA || w->wall == waVineHalfB) && from && from->wall == w->wall) - return false; - if(w->wall == waNone || w->wall == waFloorA || w->wall == waFloorB || - w->wall == waCavefloor || w->wall == waFrozenLake || w->wall == waVineHalfA || - w->wall == waVineHalfB || w->wall == waDeadfloor || w->wall == waDeadfloor2) { - if(w->monst) return monster_passable; - return true; - } - return false; +// monster/wall types + +bool isFire(cell *w) { + return w->wall == waFire || w->wall == waPartialFire || w->wall == waEternalFire; + } + +bool isThumper(eWall w) { + return w == waThumperOff || w == waThumperOn; + } + +bool isThumper(cell *c) { + return isThumper(c->wall); + } + +bool isActivable(cell *c) { + return c->wall == waThumperOff || c->wall == waBonfireOff; + } + +bool hasTimeout(cell *c) { + return c->wall == waThumperOn || c->wall == waFire || c->wall == waPartialFire || + c->wall == waTempWall || c->wall == waTempFloor || c->wall == waTempBridge; + } + +bool isMimic(eMonster m) { + return m == moMirror || m == moMirage; + } + +bool isMimic(cell *c) { + return isMimic(c->monst); + } + +bool isPrincess(eMonster m) { + return + m == moPrincess || m == moPrincessMoved || + m == moPrincessArmed || m == moPrincessArmedMoved; + } + +bool isGolemOrKnight(eMonster m) { + return + m == moGolem || m == moGolemMoved || + m == moKnight || m == moKnightMoved || + m == moTameBomberbird || m == moTameBomberbirdMoved || + m == moMouse || m == moMouseMoved || + isPrincess(m); + } + +bool isGolemOrKnight(cell *c) { return isGolemOrKnight(c->monst); } + +bool isNonliving(eMonster m) { + return + m == moMirage || m == moMirror || m == moGolem || m == moGolemMoved || + m == moZombie || m == moGhost || m == moShadow || m == moSkeleton || + m == moEvilGolem || m == moIllusion || m == moEarthElemental || + m == moWaterElemental; + } + +bool isStunnable(eMonster m) { + return m == moPalace || m == moFatGuard || m == moSkeleton || isPrincess(m); + } + +bool hasHitpoints(eMonster m) { + return m == moPalace || m == moFatGuard || m == moVizier || isPrincess(m); + } + +bool isFriendly(eMonster m) { + return isMimic(m) || isGolemOrKnight(m) || m == moIllusion; + } + +bool isFriendly(cell *c) { return isFriendly(c->monst); } + +bool isBug(eMonster m) { + return m >= moBug0 && m < moBug0+BUGCOLORS; + } + +bool isBug(cell *c) { + return isBug(c->monst); + } + +bool isKillable(cell *c); +bool isKillableSomehow(cell *c); + +bool isFriendlyOrBug(cell *c) { // or killable discord! + // do not attack the stunned Princess + if(isPrincess(c->monst) && c->stuntime) return false; + return isFriendly(c) || isBug(c) || (c->monst && markOrb(itOrbDiscord) && isKillable(c) && !c->stuntime); + } + +bool isFriendlyOrBugS(cell *c) { // or killable discord! + // do not attack the stunned Princess + if(isPrincess(c->monst) && c->stuntime) return false; + return isFriendly(c) || isBug(c) || (c->monst && markOrb(itOrbDiscord) && isKillableSomehow(c) && !c->stuntime); + } + +bool isIvy(eMonster m) { + return m == moIvyRoot || m == moIvyHead || m == moIvyBranch || m == moIvyWait || + m == moIvyNext || m == moIvyDead; + } + +bool isIvy(cell *c) { + return isIvy(c->monst); + } + +bool isDemon(eMonster m) { + return m == moLesser || m == moLesserM || m == moGreater || m == moGreaterM; + } + +bool isDemon(cell *c) { + return isDemon(c->monst); + } + +bool isWorm(eMonster m) { + return m == moWorm || m == moWormtail || m == moWormwait || + m == moTentacle || m == moTentacletail || m == moTentaclewait || + m == moTentacleEscaping || m == moTentacleGhost || + m == moHexSnake || m == moHexSnakeTail; + } + +bool isWorm(cell *c) { + return isWorm(c->monst); + } + +bool isWitch(eMonster m) { + // evil golems don't count + return m >= moWitch && m < moWitch+NUMWITCH-1; + } + +bool isOnCIsland(cell *c) { + return (c->wall == waCIsland || c->wall == waCTree || c->wall == waCIsland2); } bool cellUnstable(cell *c) { - return c->land == laMotion && c->wall == waNone; + return (c->land == laMotion && c->wall == waNone) || c->wall == waTrapdoor; + } + +bool ignoresPlates(eMonster m) { + return m == moMouse; } bool cellUnstableOrChasm(cell *c) { - return c->land == laMotion && (c->wall == waNone || c->wall == waChasm); + return + (c->land == laMotion && c->wall == waNone) || + c->wall == waChasm || c->wall == waTrapdoor; } bool cellHalfvine(cell *c) { @@ -247,7 +813,436 @@ bool cellHalfvine(cell *c) { } bool thruVine(cell *c, cell *c2) { - return cellHalfvine(c) && c2->wall == c->wall; + return cellHalfvine(c) && c2->wall == c->wall && c2 != c; + } + +// === MOVEMENT FUNCTIONS === + +bool againstWind(cell *c2, cell *c1); + +// w = from->mov[d] +bool againstCurrent(cell *w, cell *from) { + if(from->land != laWhirlpool) return false; + if(againstWind(from, w)) return false; // wind is stronger than current + if(!euclid && (!from->master->alt || !w->master->alt)) return false; + int dfrom = celldistAlt(from); + int dw = celldistAlt(w); + if(dw < dfrom) return false; + if(dfrom < dw) return true; + for(int d=0; dtype; d++) + if(from->mov[d] == w) { + cell *c3 = from->mov[(d+from->type-1) % from->type]; + if(!c3) return false; + return celldistAlt(c3) < dfrom; + } + return false; + } + +bool boatGoesThrough(cell *c) { + if(c->land == laEdge) return false; + return + (c->wall == waNone && c->land != laMotion && c->land != laZebra) || + c->wall == waFloorA || c->wall == waFloorB || + c->wall == waCavefloor || c->wall == waFrozenLake || + c->wall == waDeadfloor || c->wall == waCIsland || c->wall == waCIsland2 || + c->wall == waMineUnknown || c->wall == waMineMine || c->wall == waMineOpen || + c->wall == waBonfireOff || c->wall == waFire || c->wall == waPartialFire; + } + +void placeWater(cell *c, cell *c2) { + if(isWatery(c)) ; + else if(c2 && (c2->wall == waFloorA || c2->wall == waFloorB)) + c->wall = c2->wall; + else if(isIcyLand(c)) + c->wall = waLake; + else + c->wall = waSea; + } + +bool realred(eWall w) { + return w == waRed1 || w == waRed2 || w == waRed3; + } + +int snakelevel(eWall w) { + if(w == waRed1 || w == waDeadfloor2 || w == waRubble || w == waGargoyleFloor || + w == waGargoyleBridge || w == waTempFloor || w == waTempBridge) + return 1; + if(w == waRed2) return 2; + if(w == waRed3) return 3; + return 0; + } + +int snakelevel(cell *c) { return snakelevel(c->wall); } + +int incline(cell *cfrom, cell *cto) { + return snakelevel(cto) - snakelevel(cfrom); + } + +bool inclineInRange(cell *cfrom, cell *cto) { + int i = incline(cfrom, cto); + return i <= 1 && i >= -2; + } + +bool cellEdgeUnstable(cell *c); +int coastval(cell *c); + +bool passable(cell *w, cell *from, bool monster_passable, bool mirror_passable, bool revdir) { + + if(from && !(revdir ? inclineInRange(w, from) : inclineInRange(from, w))) return false; + + if(from && cellEdgeUnstable(w) && cellEdgeUnstable(from) && + coastval(w) != coastval(from) + (revdir?1:-1)) return false; + + if(from && (revdir ? againstWind(from,w) : againstWind(w, from))) return false; + + if(revdir && from && w->monst && passable(from, w, false, mirror_passable, false)) + return true; + + if(w->wall == waFloorA && from && from->wall == waFloorB && !w->item && !from->item) + return false; + if(w->wall == waFloorB && from && from->wall == waFloorA && !w->item && !from->item) + return false; + if(w->wall == waMirror || w->wall == waCloud) return mirror_passable; + + if(from && thruVine(from, w)) return false; + if(w->wall == waNone || w->wall == waFloorA || w->wall == waFloorB || + w->wall == waCavefloor || w->wall == waFrozenLake || w->wall == waVineHalfA || + w->wall == waVineHalfB || w->wall == waDeadfloor || w->wall == waDeadfloor2 || + w->wall == waRubble || w->wall == waGargoyleFloor || w->wall == waGargoyleBridge || + w->wall == waTempFloor || w->wall == waTempBridge || + w->wall == waBoat || w->wall == waCIsland || w->wall == waCIsland2 || + w->wall == waRed1 || w->wall == waRed2 || w->wall == waRed3 || + w->wall == waMineUnknown || w->wall == waMineMine || w->wall == waMineOpen || + w->wall == waStrandedBoat || w->wall == waOpenGate || w->wall == waClosePlate || + w->wall == waOpenPlate || w->wall == waTrapdoor || w->wall == waGiantRug || + w->wall == waLadder) { + if(w->monst) return monster_passable; + return true; + } + return false; + } + +bool blowable0(cell *c2, cell *c) { + return + passable(c2, NULL, false, false, false) || + c2->wall == waCamelotMoat || isFire(c2) || c2->wall == waChasm || + c2->wall == waSea || c2->wall == waLake || c2->wall == waPartialFire || + c2->wall == waTrapdoor || c2->wall == waSulphur || c2->wall == waSulphurC; + } + +bool blowable(cell *c2, cell *c) { + if(c2->monst) return false; + return blowable0(c2, c); + } + +bool jumpable(cell *c2, cell *c) { + if(c2->monst && c2->monst != moMouse) return false; + return blowable0(c2, c); + } + +bool player_passable(cell *w, cell *from, bool mon); + +bool jumpable2(cell *c, cell *c2) { + if(!c->monst && c->wall == waNone && c->land == laEdge && c2->wall == waNone) + return true; + return player_passable(c, c2, false); + } + +extern bool haveair; +int airdir; + +int airdist(cell *c) { + if(!haveair) return 3; + if(!c) return 3; + if(c->monst == moAirElemental) + return 0; + if(!blowable(c, c)) return 3; + for(int i=0; itype; i++) { + cell *c2 = c->mov[i]; + if(c2 && c2->monst == moAirElemental) { + airdir = c->spn[i] * 42 / c2->type; + return 1; + } + } + for(int i=0; itype; i++) { + cell *c2 = c->mov[i]; + if(!c2) continue; + if(!blowable(c2, c)) continue; + if(!blowable(c, c2)) continue; + for(int i=0; itype; i++) { + cell *c3 = c2->mov[i]; + if(c3 && c3->monst == moAirElemental) { + airdir = c2->spn[i] * 42 / c3->type; + return 2; + } + } + } + return 3; + } + +bool againstWind(cell *c2, cell *c1) { + if(!c1 || !c2) return false; + return airdist(c2) < airdist(c1); + } + +bool player_passable(cell *w, cell *from, bool mon) { + if(w->monst && !isFriendly(w)) return false; + if(isFire(w) && markOrb(itOrbWinter)) return true; + if(isWatery(w) && !(from && isWatery(from) && againstCurrent(w, from)) && markOrb(itOrbFish)) return true; + if(isWatery(w) && from && from->wall == waBoat) { + if(againstCurrent(w, from)) + return !items[itOrbWater]; + return true; + } + if(w->wall == waRoundTable && from && from->wall != waRoundTable) + return true; + if(passable(w, from, mon, true, false)) return true; + return markOrb(itOrbGhost); + return false; + } + +bool isAngryBird(eMonster m) { + return m == moEagle || m == moAlbatross || m == moBomberbird || m == moGargoyle || + m == moAirElemental; + } + +bool isBird(eMonster m) { + return isAngryBird(m) || m == moTameBomberbird || m == moTameBomberbirdMoved; + } + +bool normalMover(eMonster m) { + return + m == moYeti || m == moRanger || m == moGoblin || m == moTroll || m == moDesertman || + m == moMonkey || m == moZombie || m == moNecromancer || m == moCultist || + m == moLesser || m == moGreater || m == moRunDog || m == moPyroCultist || + m == moFireFairy || m == moCrystalSage || m == moHedge || + m == moVineBeast || m == moLancer || m == moFlailer || + m == moMiner || m == moDarkTroll || + (playerInPower() && ( + (isWitch(m) && m != moWitchGhost && m != moWitchWinter) || m == moEvilGolem + )) || + m == moRedTroll || + m == moPalace || m == moFatGuard || m == moSkeleton || m == moVizier || + m == moFjordTroll || m == moEdgeMonkey || + m == moFireElemental || m == moOrangeDog; + } + +// eagles can go through lakes, chasms, and slime +// todo vines? +bool eaglepassable(cell *w, cell *from) { + if(w->monst) return false; + if(isPlayerOn(w)) return true; + if(againstWind(w, from)) return false; + return + w->wall == waNone || w->wall == waFloorA || w->wall == waFloorB || + w->wall == waCavefloor || w->wall == waFrozenLake || w->wall == waLake || + w->wall == waDeadfloor || w->wall == waDeadfloor2 || w->wall == waCamelotMoat || + w->wall == waRubble || w->wall == waGargoyleFloor || w->wall == waGargoyleBridge || + w->wall == waTempFloor || w->wall == waTempBridge || + w->wall == waSulphur || w->wall == waSulphurC || w->wall == waChasm || + w->wall == waRed1 || w->wall == waRed2 || w->wall == waRed3 || + w->wall == waSea || w->wall == waCIsland || w->wall == waCIsland2 || + w->wall == waMineMine || w->wall == waMineOpen || w->wall == waMineUnknown || + w->wall == waClosePlate || w->wall == waOpenPlate || w->wall == waOpenGate || + w->wall == waTrapdoor || w->wall == waGiantRug || w->wall == waLadder; + } + +bool earthpassable(cell *c, cell *from) { + // cannot go through Living Caves... + if(c->wall == waCavefloor) return false; + if(isPlayerOn(c)) return true; + // but can dig through... + if(c->wall == waDeadwall || c->wall == waDune || c->wall == waStone) + return true; + if(c->wall == waSea && c->land == laLivefjord) + return true; + return passable(c, from, true, false, false); + } + +// from-to + +bool isGhost(eMonster m) { + return m == moGhost || m == moTentacleGhost; + } + +bool ghostmove(eMonster m, cell* to, cell* from) { + if(to->monst && !(to->monst == moTentacletail && isGhost(m))) + return false; + if((m == moWitchGhost || m == moWitchWinter) && to->land != laPower) + return false; + if(isGhost(m)) + for(int i=0; itype; i++) + if(to->mov[i] && to->mov[i] != from && isGhost(to->mov[i]->monst)) + return false; + if(isGhost(m) || m == moWitchGhost) return true; + if(m == moGreaterShark) return isWatery(to); + if(m == moWitchWinter) return isFire(to) || passable(to, from, false, false, false); + if(isPlayerOn(to)) return true; + return false; + } + +bool isGhostMover(eMonster m) { + return m == moGhost || m == moGreaterShark || m == moTentacleGhost || + (playerInPower() && (m == moWitchGhost || m == moWitchWinter)); + } + +bool isSlimeMover(eMonster m) { + return + m == moSlime || m == moSeep || m == moShark || + m == moVineSpirit || m == moCShark || m == moParrot; + } + +bool isBlowableMonster(eMonster m) { + return m && !( + isWorm(m) || isIvy(m) || isSlimeMover(m) || m == moGhost || m == moGreaterShark || + m == moWaterElemental || m == moWitchGhost || isMimic(m) + ); + } + +bool isSlimeMover(cell *c) { + return isSlimeMover(c->monst); + } + +int slimegroup(cell *c) { + if(c->wall == waCavewall || c->wall == waDeadwall) + return 1; + if(isWatery(c)) + return 2; + if(c->wall == waFloorA) + return 3; + if(c->wall == waFloorB) + return 4; + if(c->wall == waVinePlant || cellHalfvine(c)) + return 5; + if(c->wall == waCTree) + return 6; + return 0; + } + +bool slimepassable(cell *w, cell *c) { + int u = dirfromto(c, w); + if(w == c) return true; + if(isPlayerOn(w)) return true; + int group = slimegroup(c); + if(!group) return false; + int ogroup = slimegroup(w); + if(!ogroup) return false; + bool hv = (group == ogroup); + + // don't go against the current + if(isWateryOrBoat(w) && isWateryOrBoat(c)) + return !againstCurrent(w, c); + + if(w->item) return false; + + // only travel to halfvines correctly + if(cellHalfvine(c)) { + int i=0; + for(int t=0; ttype; t++) if(c->mov[t] && c->mov[t]->wall == c->wall) i=t; + int z = i-u; if(z<0) z=-z; z%=6; + if(z>1) return false; + hv=true; + } + // only travel from halfvines correctly + if(cellHalfvine(w)) { + int i=0; + for(int t=0; ttype; t++) if(w->mov[t] && w->mov[t]->wall == w->wall) i=t; + int z = i-c->spn[u]; if(z<0) z=-z; z%=6; + if(z>1) return false; + hv=true; + } + if(!hv) return false; + return true; + } + +bool canPushStatueOn(cell *c) { + return passable(c, NULL, true, false, false) && c->wall != waBoat && !snakelevel(c); + } + +bool boatpassable(cell *c, cell *from) { + return + from->wall == waBoat && isWatery(c) && !againstCurrent(c, from); + } + +void moveBoat(cell *to, cell *from) { + eWall x = to->wall; to->wall = from->wall; from->wall = x; + to->mondir = neighborId(to, from); + moveItem(from, to, false); + } + +void moveBoatIfUsingOne(cell *to, cell *from) { + if(from->wall == waBoat && isWatery(to)) moveBoat(to, from); + } + +bool leaderpassable(cell *c, cell *from) { + if(isPlayerOn(c)) return true; + if(c->monst) return false; + if(isWateryOrBoat(c) && isWateryOrBoat(from) && (c->wall != waBoat || from->wall != waBoat)) + return !againstCurrent(c, from); + if(c->wall == waBigStatue) return canPushStatueOn(from); + return passable(c, from, false, false, false); + } + +bool isLeader(eMonster m) { + return m == moPirate || m == moCultistLeader || m == moViking; + } + +bool waterpassable(cell *w, cell *from) { + return isWatery(w) || boatGoesThrough(w) || w->wall == waDeadTroll || isPlayerOn(w); + } + +bool passable_for(eMonster m, cell *w, cell *from, bool monster_passable) { + if(w->monst && !monster_passable) + return false; + if(m == moWolf) { + return isIcyLand(w) && (isPlayerOn(w) || passable(w, from, monster_passable, false, false)); + } + if(normalMover(m) || isBug(m) || isDemon(m)) { + if((isWitch(m) || m == moEvilGolem) && w->land != laPower) + return false; + return isPlayerOn(w) || passable(w, from, monster_passable, false, false); + } + if(isSlimeMover(m)) + return slimepassable(w, from); + if(m == moEarthElemental) + return earthpassable(w, from); + if(m == moWaterElemental) + return waterpassable(w, from); + if(m == moGreaterShark) + return isWatery(w) || w->wall == waBoat || w->wall == waFrozenLake; + if(isGhostMover(m)) + return ghostmove(m, w, from); + // for the purpose of Shmup this is correct + if(isBird(m)) + return eaglepassable(w, from); + if(isLeader(m)) + return leaderpassable(w, from); + if(isPrincess(m)) + return passable(w, from, monster_passable, false, false) || boatpassable(w, from); + if(isGolemOrKnight(m)) + return passable(w, from, monster_passable, false, false); + return false; + } + +eMonster movegroup(eMonster m) { + if(isWitch(m) || m == moEvilGolem) { + if(m == moWitchGhost) return moWitchGhost; + if(m == moWitchWinter) return moWitchWinter; + return moWitch; + } + if(normalMover(m)) return moYeti; + if(isSlimeMover(m)) return moSlime; + if(m == moEarthElemental) return moEarthElemental; + if(isLeader(m)) return moPirate; + if(isAngryBird(m)) return moEagle; + if(isBird(m)) return moTameBomberbird; + if(m == moGhost) return moGhost; + if(m == moGreaterShark) return moGreaterShark; + if(m == moWolf) return moWolf; + if(isDemon(m)) return moLesser; + if(isBug(m)) return m; + if(m == moWaterElemental) return moWaterElemental; + return moNone; } bool itemBurns(eItem it) { @@ -263,90 +1258,37 @@ bool attackingForbidden(cell *c, cell *c2) { return thruVine(c, c2) && !attackThruVine(c2->monst) && !attackThruVine(c->monst); } -bool isFire(cell *w) { - return w->wall == waBonfire || w->wall == waPartialFire; - } - -// eagles can go through lakes, chasms, and slime -// todo vines? -bool eaglepassable(cell *w) { - if(w->monst) return false; - return - w->wall == waNone || w->wall == waFloorA || w->wall == waFloorB || - w->wall == waCavefloor || w->wall == waFrozenLake || w->wall == waLake || - w->wall == waDeadfloor || w->wall == waDeadfloor2 || w->wall == waCamelotMoat || - w->wall == waSulphur || w->wall == waSulphurC || w->wall == waChasm; - } - -bool isActiv(cell *c) { - return c->wall == waThumper || c->wall == waBonfire || c->wall == waPartialFire; - } - -bool isMimic(eMonster m) { - return m == moMirror || m == moMirage; - } - -bool isMimic(cell *c) { - return isMimic(c->monst); - } - -bool isGolemOrKnight(cell *c) { - return - c->monst == moGolem || c->monst == moGolemMoved || - c->monst == moKnight ||c->monst == moKnightMoved; - } - -bool isFriendly(cell *c) { - return isMimic(c->monst) || isGolemOrKnight(c) || c->monst == moIllusion; - } - -bool isBug(eMonster m) { - return m >= moBug0 && m < moBug0+BUGCOLORS; - } - -bool isBug(cell *c) { - return isBug(c->monst); - } - -bool isFriendlyOrBug(cell *c) { - return isFriendly(c) || isBug(c); - } - -bool isIvy(cell *c) { - return c->monst == moIvyRoot || c->monst == moIvyHead || c->monst == moIvyBranch || c->monst == moIvyWait || - c->monst == moIvyNext || c->monst == moIvyDead; - } - -bool isDemon(cell *c) { - return c->monst == moLesser || c->monst == moLesserM || - c->monst == moGreater || c->monst == moGreaterM; - } - -bool isWorm(cell *c) { - return c->monst == moWorm || c->monst == moWormtail || c->monst == moWormwait || - c->monst == moTentacle || c->monst == moTentacletail || c->monst == moTentaclewait || - c->monst == moTentacleEscaping; - } - void useup(cell *c) { - c->tmp--; - if(c->tmp == 0) c->wall = waNone; + c->wparam--; + if(c->wparam == 0) { + if(c->wall == waTempFloor) + c->wall = waChasm; + else if(c->wall == waTempBridge) + placeWater(c, c); + else + c->wall = c->land == laCaribbean ? waCIsland2 : waNone; + } } -bool isInactiveEnemy(cell *w) { - if(w->monst == moWormtail || w->monst == moWormwait || w->monst == moTentacletail || w->monst == moTentaclewait) +bool isInactiveEnemy(cell *w, bool forpc) { + if(w->monst == moWormtail || w->monst == moWormwait || w->monst == moTentacletail || w->monst == moTentaclewait || w->monst == moHexSnakeTail) return true; if(w->monst == moLesserM || w->monst == moGreaterM) return true; if(w->monst == moIvyRoot || w->monst == moIvyWait || w->monst == moIvyNext || w->monst == moIvyDead) return true; + if((forpc ? w->stuntime : w->stuntime > 1) && !isFriendly(w)) + return true; return false; } -bool isActiveEnemy(cell *w, cell *killed) { +// forpc = true (for PC), false (for golems) +bool isActiveEnemy(cell *w, cell *killed, bool forpc) { + if((forpc ? w->stuntime : w->stuntime > 1)) + return false; if(w->monst == moNone || w == killed) return false; if(isFriendly(w)) return false; - if(isInactiveEnemy(w)) return false; + if(isInactiveEnemy(w, forpc)) return false; if(w->monst == moIvyHead || w->monst == moIvyBranch) { while(w != killed && w->mondir != NODIR) w = w->mov[w->mondir]; return w != killed; @@ -354,17 +1296,14 @@ bool isActiveEnemy(cell *w, cell *killed) { return true; } -bool isArmedEnemy(cell *w, cell *killed) { - return w->monst != moCrystalSage && isActiveEnemy(w, killed); +bool isUnarmed(eMonster m) { + return + m == moMouse || m == moMouseMoved || m == moPrincess || m == moPrincessMoved || + m == moCrystalSage; } -bool player_passable(cell *w, cell *from, bool mon) { - if(w->monst && !isFriendly(w)) return false; - if(isFire(w) && items[itOrbWinter]) return true; - if(w->wall == waRoundTable && from->wall != waRoundTable) - return true; - if(items[itOrbGhost] > 1) return true; - return passable(w, from, mon, true); +bool isArmedEnemy(cell *w, cell *killed, bool forpc) { + return w->monst != moCrystalSage && isActiveEnemy(w, killed, forpc); } bool isHive(eLand l) { @@ -372,14 +1311,15 @@ bool isHive(eLand l) { } bool isKillable(cell *c) { - return c->monst != moShadow && !isWorm(c) && c->monst != moGreater && c->monst != moGreaterM - && c->monst != moHedge && c->monst != moFlailer; + return c->monst != moShadow && (!isWorm(c) || c->monst == moTentacleGhost) && c->monst != moGreater && c->monst != moGreaterM + && c->monst != moHedge && c->monst != moFlailer && !(c->monst == moVizier && c->hitpoints > 1); // && !isBug(c->monst); } bool isKillableSomehow(cell *c) { return isKillable(c) - || c->monst == moHedge || c->monst == moLancer || c->monst == moFlailer; + || c->monst == moHedge || c->monst == moLancer || c->monst == moFlailer || + c->monst == moVizier; } bool isNeighbor(cell *c1, cell *c2) { @@ -387,6 +1327,11 @@ bool isNeighbor(cell *c1, cell *c2) { return false; } +int neighborId(cell *c1, cell *c2) { + for(int i=0; itype; i++) if(c1->mov[i] == c2) return i; + return -1; + } + // how many monsters are near eMonster which; @@ -407,7 +1352,7 @@ bool flashWouldKill(cell *c, bool friendly) { if(isWorm(c3)) continue; // immune to Flash if(c3->monst == moEvilGolem) continue; // evil golems don't count if(c3 != c && c3->monst) { - bool b = isFriendly(c3) || isBug(c3); + bool b = isFriendlyOrBugS(c3); if(friendly ? b: !b) return true; } } @@ -415,12 +1360,13 @@ bool flashWouldKill(cell *c, bool friendly) { return false; } -int monstersnear(cell *c, cell *nocount = NULL, bool shielded = true) { +int monstersnear(cell *c, cell *nocount = NULL, eMonster who = moNone) { + if(hardcore && !who) return 0; int res = 0; bool fast = false; - if(shielded) { - if(items[itOrbShield] > 1) return 0; - fast = (items[itOrbSpeed] && !(items[itOrbSpeed] & 1)); + + if(!who) { + fast = (items[itOrbSpeed] && !(items[itOrbSpeed] & 1)); } for(int t=0; ttype; t++) { @@ -439,8 +1385,8 @@ int monstersnear(cell *c, cell *nocount = NULL, bool shielded = true) { if(c3->monst != moWitchSpeed && fast) continue; // cannot attack if the immediate cell is impassable (except flashwitches) if(c3->monst != moWitchFlash) { - if(!passable(c2, c3, !isArmedEnemy(c2, nocount), false)) continue; - if(c2 == cwt.c && items[itOrbFire]) continue; + if(!passable(c2, c3, !isArmedEnemy(c2, nocount, true), false, false)) continue; + if(isPlayerOn(c2) && items[itOrbFire]) continue; } // flashwitches cannot attack if it would kill another enemy if(c3->monst == moWitchFlash && flashWouldKill(c3, false)) continue; @@ -449,7 +1395,7 @@ int monstersnear(cell *c, cell *nocount = NULL, bool shielded = true) { } // consider normal monsters - if(c2 && isArmedEnemy(c2, nocount) && c2->monst != moLancer) { + if(c2 && isArmedEnemy(c2, nocount, !who) && (c2->monst != moLancer || isUnarmed(who))) { if(fast && c2->monst != moWitchSpeed) continue; // they cannot attack through vines if(attackingForbidden(c, c2)) @@ -459,26 +1405,33 @@ int monstersnear(cell *c, cell *nocount = NULL, bool shielded = true) { // do not include stabbed enemies if( (c2->monst == moHedge || (isKillable(c2) && items[itOrbThorns])) - && c2->cpdist == 1 && c != cwt.c) + && c2->cpdist == 1 && !isPlayerOn(c)) continue; res++, which = c2->monst; } } + if(!who && res && markOrb2(itOrbShield)) + res = 0; + return res; } // reduce c->mpdist to d; also generate the landscape -bool checkBarriersBack(cellwalker& bb, int q=5); +bool buggyGeneration = false; + + +bool checkBarriersBack(cellwalker bb, int q=5, bool cross = false); + +bool checkBarriersFront(cellwalker bb, int q=5, bool cross = false) { -bool checkBarriersFront(cellwalker& bb, int q=5) { if(bb.c->mpdist < BARLEV) return false; if(bb.c->mpdist == BUGLEV) return false; if(bb.c->bardir != NODIR) return false; if(bb.spin == 0) {q--; if(!q) return true; } - if(1) for(int i=0; i<7; i++) { + if(!cross) for(int i=0; i<7; i++) { cellwalker bb2 = bb; cwspin(bb2, i); cwstep(bb2); if(bb2.c->bardir != NODIR) return false; @@ -490,14 +1443,16 @@ bool checkBarriersFront(cellwalker& bb, int q=5) { return checkBarriersBack(bb, q); } -bool checkBarriersBack(cellwalker& bb, int q) { +bool checkBarriersBack(cellwalker bb, int q, bool cross) { // printf("back, %p, s%d\n", bb.c, bb.spin); + if(bb.c->mpdist < BARLEV) return false; if(bb.c->mpdist == BUGLEV) return false; if(bb.c->bardir != NODIR) return false; + // if(bb.spin == 0 && bb.c->mpdist == INFD) return true; - if(1) for(int i=0; i<7; i++) { + if(!cross) for(int i=0; i<7; i++) { cellwalker bb2 = bb; cwspin(bb2, i); cwstep(bb2); if(bb2.c->bardir != NODIR) return false; @@ -512,9 +1467,37 @@ bool checkBarriersBack(cellwalker& bb, int q) { return checkBarriersFront(bb, q); } +bool isSealand(eLand l) { + return l == laOcean || l == laCaribbean || l == laWhirlpool || l == laLivefjord || + l == laOceanWall; + } + +bool isElemental(eLand l) { + return l == laEAir || l == laEWater || l == laEEarth || l == laEFire || + l == laElementalWall; + } + +eWall getElementalWall(eLand l) { + if(l == laEAir) return waChasm; + if(l == laEEarth) return waStone; + if(l == laEFire) return waEternalFire; + if(l == laEWater) return waSea; + return waNone; + } + void setbarrier(cell *c) { - c->wall = waBarrier; - c->land = laBarrier; + if(isSealand(c->barleft) && isSealand(c->barright)) { + c->wall = c->type == 7 ? waBarrier : waSea; + c->land = laOceanWall; + } + else if(isElemental(c->barleft) && isElemental(c->barright)) { + c->land = laElementalWall; + c->wall = getElementalWall(c->barleft); + } + else { + c->wall = waBarrier; + c->land = laBarrier; + } /*if(isHive(c->barleft) && isHive(c->barright)) c->wall = waWaxWall, c->land = c->barleft; */ } @@ -537,7 +1520,7 @@ int buildIvy(cell *c, int children, int minleaf) { int leafchild = 0; for(int i=0; itype; i++) { createMov(c, i); - if(passable(c->mov[i], c, false, false)) { + if(passable(c->mov[i], c, false, false, false)) { if(children && !child) child = c->mov[i], leafchild = buildIvy(c->mov[i], children-1, 5); else @@ -559,14 +1542,10 @@ bool isIcyWall(cell *c) { return c->wall == waNone || c->wall == waIcewall || c->wall == waFrozenLake || c->wall == waLake; } -bool destroyHalfvine(cell *c, eWall newwall = waNone, int tval = 6); - -void killMonster(cell *c); - void prespill(cell* c, eWall t, int rad) { // these monsters block spilling if(c->monst == moSeep || c->monst == moVineSpirit || c->monst == moShark || - c->monst == moGreaterShark) + c->monst == moGreaterShark || c->monst == moParrot || c->monst == moCShark) return; // turn statues into Slimes! if(c->wall == waBigStatue && t != waNone) { @@ -579,17 +1558,22 @@ void prespill(cell* c, eWall t, int rad) { } // these walls block spilling completely if(c->wall == waIcewall || c->wall == waBarrier || c->wall == waDeadTroll || - c->wall == waDune || c->wall == waAncientGrave || c->wall == waThumper || + c->wall == waDune || c->wall == waAncientGrave || + c->wall == waThumperOff || c->wall == waThumperOn || c->wall == waFreshGrave || c->wall == waColumn || c->wall == waPartialFire || c->wall == waDeadwall || c->wall == waWaxWall || c->wall == waCamelot || c->wall == waRoundTable || - c->wall == waBigStatue) + c->wall == waBigStatue || c->wall == waRed1 || c->wall == waRed2 || c->wall == waRed3 || + c->wall == waPalace || c->wall == waOpenGate || c->wall == waClosedGate || + c->wall == waPlatform || c->wall == waStone || c->wall == waTempWall || + c->wall == waTempFloor || c->wall == waTempBridge) return; // these walls block further spilling if(c->wall == waCavewall || cellUnstable(c) || c->wall == waSulphur || c->wall == waSulphurC || c->wall == waLake || c->wall == waChasm || c->wall == waDryTree || c->wall == waWetTree || c->wall == waTemporary || - c->wall == waVinePlant || c->wall == waBonfire || c->wall == waVineHalfA || c->wall == waVineHalfB || - c->wall == waCamelotMoat) + c->wall == waVinePlant || isFire(c) || c->wall == waBonfireOff || c->wall == waVineHalfA || c->wall == waVineHalfB || + c->wall == waCamelotMoat || c->wall == waSea || c->wall == waCTree || + c->wall == waRubble || c->wall == waGargoyleFloor || c->wall == waGargoyle) t = waTemporary; if(c->wall == waSulphur) { @@ -628,32 +1612,445 @@ void degradeDemons() { achievement_gain("DEMONSLAYER"); if(c->monst == moGreaterM) c->monst = moLesserM; if(c->monst == moGreater) c->monst = moLesser; + shmup::degradeDemons(); } } void ivynext(cell *c); -void earthFloor(cell *c) { - if(c->monst) return; - if(c->wall == waDeadwall) c->wall = waDeadfloor; - if(c->wall == waDune) c->wall = waNone; - if(c->wall == waAncientGrave || c->wall == waFreshGrave) c->wall = waNone; +bool earthFloor(cell *c) { + if(c->monst) return false; + if(c->wall == waDeadwall) { c->wall = waDeadfloor; return true; } + if(c->wall == waDune) { c->wall = waNone; return true; } + if(c->wall == waStone) { c->wall = waNone; return true; } + if(c->wall == waAncientGrave || c->wall == waFreshGrave) { + c->wall = waNone; + return true; + } + if((c->wall == waSea || c->wall == waNone) && c->land == laOcean) { + c->wall = waCIsland; + return true; + } + if(c->wall == waSea && c->land == laCaribbean) { + c->wall = waCIsland; + return true; + } + return false; } -void earthWall(cell *c) { +bool earthWall(cell *c) { if(c->wall == waDeadfloor || c->wall == waDeadfloor2 || c->wall == waEarthD) { c->item = itNone; c->wall = waDeadwall; + return true; } if(c->wall == waNone && c->land == laDesert) { c->item = itNone; c->wall = waDune; + return true; + } + if(c->wall == waNone && isElemental(c->land)) { + c->item = itNone; + c->wall = waStone; + return true; + } + if(c->wall == waNone && c->land == laRedRock) { + c->item = itNone; + c->wall = waRed3; + return true; + } + if(c->wall == waCIsland || c->wall == waCIsland2 || (c->wall == waNone && c->land == laOcean)) { + c->item = itNone; + c->wall = waSea; + if(c->land == laOcean) c->landparam = 40; + return true; + } + return false; + } + +void snakepile(cell *c) { + if(c->wall == waRed1 || c->wall == waOpenGate) c->wall = waRed2; + else if(c->wall == waRed2) c->wall = waRed3; + else if(c->wall == waNone || c->wall == waFloorA || c->wall == waFloorB || + c->wall == waCIsland || c->wall == waCIsland2 || + (c->wall == waSea && c->land == laOcean) || + (c->wall == waSea && c->land == laLivefjord) || + c->wall == waOpenPlate || c->wall == waClosePlate || + c->wall == waMineUnknown || c->wall == waMineOpen) + c->wall = waRed1; + else if(c->wall == waDeadfloor) + c->wall = waDeadfloor2; + else if(c->wall == waDeadfloor2) + c->wall = waDeadwall; + else if(c->wall == waRubble || c->wall == waGargoyleFloor || c->wall == waGargoyleBridge || + c->wall == waTempFloor || c->wall == waTempBridge) + c->wall = waRed2; + else if(c->wall == waCavefloor) c->wall = waCavewall; + else if(c->wall == waSea) c->wall = waCIsland; + else if(isWateryOrBoat(c) || c->wall == waFrozenLake) c->wall = waNone; + else if(isWateryOrBoat(c) || c->wall == waFrozenLake) c->wall = waNone; + else if(cellHalfvine(c)) { + destroyHalfvine(c, waRed1); } } -bool isWitch(eMonster m) { - // evil golems don't count - return m >= moWitch && m < moWitch+NUMWITCH-1; +bool eternalFire(cell *c) { + return c->land == laDryForest || c->land == laPower || c->land == laMinefield || + c->land == laEFire || c->land == laElementalWall; + } + +void explodeMine(cell *c); + +bool makeflame(cell *c, int timeout, bool checkonly) { + if(itemBurns(c->item)) { + if(checkonly) return true; + addMessage(XLAT("%The1 burns!", c->item)), c->item = itNone; + } + if(cellUnstable(c)) { + if(checkonly) return true; + c->wall = waChasm; + } + else if(c->wall == waChasm || c->wall == waOpenGate || c->wall == waRed2 || c->wall == waRed3) + return false; + else if(c->wall == waBoat) { + if(checkonly) return true; + placeWater(c, c); + addMessage(XLAT("%The1 burns!", winf[c->wall].name)); + if(isIcyLand(c)) HEAT(c) += 1; + } + else if(c->wall == waNone && c->land == laCocytus) { + if(checkonly) return true; + c->wall = waLake, HEAT(c) += 1; + } + else if(c->wall == waFrozenLake && c->land == laCocytus) { + if(checkonly) return true; + c->wall = waLake, HEAT(c) += 1; + } + else if(c->wall == waIcewall) { + if(checkonly) return true; + c->wall = waNone; + } + else if(c->wall == waMineMine) { + if(checkonly) return true; + explodeMine(c); + } + else if(c->wall != waCTree && c->wall != waDryTree && c->wall != waWetTree && + c->wall != waVinePlant && !passable(c, NULL, true, true, false)) return false; + else { + eWall w = eternalFire(c) ? waEternalFire : waFire; + if(w == c->wall) return false; + if(checkonly) return true; + destroyHalfvine(c); + if(!isFire(c)) c->wparam = 0; + c->wall = w; + c->wparam = max(c->wparam, (char) timeout); + } + return true; + } + +void explodeMine(cell *c) { + if(c->wall != waMineMine) + return; + + c->wall = waMineOpen; + makeflame(c, 20, false); + + for(int i=0; itype; i++) if(c->mov[i]) { + cell *c2 = c->mov[i]; + if(c2->wall == waRed2 || c2->wall == waRed3) + c2->wall = waRed1; + else if(c2->wall == waDeadTroll || c2->wall == waGargoyle) { + c2->wall = waNone; + makeflame(c2, 10, false); + } + else if(c2->wall == waPalace || c2->wall == waOpenGate || c2->wall == waClosedGate) { + c2->wall = waNone; + makeflame(c2, 10, false); + } + else makeflame(c2, 20, false); + } + } + +void stunMonster(cell *c2) { + if(c2->monst != moSkeleton) + c2->hitpoints--; + c2->stuntime = ( + c2->monst == moFatGuard ? 2 : + c2->monst == moSkeleton && c2->land != laPalace ? 7 : + 3); + } + +bool attackJustStuns(cell *c2) { + return isStunnable(c2->monst) && c2->hitpoints > 1; + } + +void killOrStunMonster(cell *c2) { + if(attackJustStuns(c2)) + stunMonster(c2); + else + killMonster(c2); + } + +void moveEffect(cell *ct, cell *cf, eMonster m); + +namespace princess { + +#define EPX 39 +#define EPY 21 + +#define OUT_OF_PRISON 200 +#define OUT_OF_PALACE 250 + + bool generating = false; + bool challenge = false; + bool saved = false; + bool everSaved = false; + bool everGotYendorVictory = false; + + bool forceVizier = false; + bool forceMouse = false; + + int saveHP = 0, saveArmedHP = 0; + + struct info { + int id; // id of this info + cell *prison; // where was the Princess locked + heptagon *alt; // alt of the prison + int bestdist; // best dist achieved + int bestnear; // best dist achieved, by the player + int value; // number of Rugs at 120 + cell *princess; // where is the Princess currently + }; + + vector infos; + + void assign(info *i) { + if(i->alt) i->alt->emeraldval = i->id; + } + + void newInfo(cell *c) { + info *i = new info; + i->prison = c; + i->princess = c; + i->alt = c->master->alt; + i->id = size(infos); + i->bestdist = 0; + i->bestnear = OUT_OF_PRISON; + infos.push_back(i); + assign(i); + } + + void newFakeInfo(cell *c) { + info *i = new info; + i->prison = NULL; + i->princess = c; + i->alt = NULL; + i->id = size(infos); + i->bestdist = OUT_OF_PALACE; + i->bestnear = 0; + infos.push_back(i); + assign(i); + } + + info *getPrisonInfo(cell *c) { + if(euclid) return NULL; + if(c->land != laPalace) return NULL; + if(!c->master->alt) return NULL; + return infos[c->master->alt->emeraldval]; + } + + info *getPrincessInfo(cell *c) { + for(int i=0; iprincess == c) { + while(i) { + infos[i]->id = i-1; assign(infos[i]); + infos[i-1]->id = i; assign(infos[i-1]); + i--; + } + return infos[i]; + } + return NULL; + } + + int dist(cell *c) { + if(c->land != laPalace) return OUT_OF_PALACE; + else if(euclid) return celldistAlt(c); + else if(!c->master->alt) return OUT_OF_PRISON; + else return celldistAlt(c); + } + + void clear() { + for(int i=0; imonst = moPrincessArmed; + c->stuntime = 0; + c->hitpoints = palaceHP(); + drawFlash(c); + + info *inf = NULL; + for(int i=0; iprincess && infos[i]->bestdist == OUT_OF_PALACE) + inf = infos[i]; + + if(inf) { inf->princess->monst = moNone; inf->princess = c; } + else newFakeInfo(c); + return true; + } + + void bringBack() { + if(bringBackAt(cwt.c->mov[cwt.spin])) return; + for(int i=1; iprincess = ct; + int newdist = dist(ct); + // printf("newdist = %d (vs %d)\n", newdist, i->bestdist); + if(newdist < ALTDIST_ERROR && newdist > i->bestdist) { + i->bestdist = newdist; +// printf("Improved dist to %d\n", newdist); + if(newdist == OUT_OF_PALACE) { + if(!princess::saved) + achievement_gain("PRINCESS1"); + princess::saved = true; + princess::everSaved = false; + items[itSavedPrincess]++; + } + if(newdist == OUT_OF_PRISON && princess::challenge) { + addMessage(XLAT("Congratulations! Your score is %1.", its(i->value))); + achievement_gain("PRINCESS2"); + if(!cheater) achievement_score(36, i->value); + showMissionScreen(); + } + } + } + } + + void mouseSqueak(cell *c) { + eMonster m = c->monst; + info *i = getPrisonInfo(c); + int d = dist(c); + + if(!i) + addMessage(XLAT("%The1 squeaks in a confused way.", m)); + else if(i->bestdist >= 6) + addMessage(XLAT("%The1 squeaks gratefully!", m)); + else if(!i->princess) + addMessage(XLAT("%The1 squeaks hopelessly.", m)); + else if(d > 120) + addMessage(XLAT("%The1 squeaks in despair.", m)); + else if(d > 90) + addMessage(XLAT("%The1 squeaks sadly.", m)); + else if(d > 60) + addMessage(XLAT("%The1 squeaks with hope!", m)); + else if(d > 30) + addMessage(XLAT("%The1 squeaks happily!", m)); + else + addMessage(XLAT("%The1 squeaks excitedly!", m)); + } + + void line(cell *c) { + int d = (euclid || c->master->alt) ? celldistAlt(c) : 200; + eMonster m = c->monst; + + static int msgid = 0; + + retry: + if(msgid >= 32) msgid = 0; + + if(msgid == 0 && d < 20 && c->land == laPalace) { + addMessage(XLAT("%The1 kisses you, and begs you to bring %him1 away from here.", m)); + } + else if(msgid == 1 && d >= 20 && c->land == laPalace) { + if(m == moPrincess) + addMessage(XLAT("\"I want my revenge. Stun a guard and leave him for me!\"", m)); + else + addMessage(XLAT("\"That felt great. Thanks!\"", m)); + } + else if(msgid == 2 && d >= 70 && c->land == laPalace) { + addMessage(XLAT("\"Bring me out of here please!\"", m)); + } + else if(msgid == 3 && c->land != laPalace) { + addMessage(XLAT("%The1 kisses you, and thanks you for saving %him1.", m)); + } + else if(msgid == 4 && c->land != laPalace && m == moPrincess) { + addMessage(XLAT("\"I have been trained to fight with a Hypersian scimitar, you know?\"", m)); + } + else if(msgid == 5 && c->land != laPalace) { + addMessage(XLAT("\"I would love to come to your world with you!\"", m)); + } + else if(msgid == 6 && c->land != laPalace) { + addMessage(XLAT("\"Straight lines stay close to each other forever, this is so romantic!\"", m)); + } + else if(msgid == 7 && c->land != laPalace) { + addMessage(XLAT("\"Maps... Just like the world, but smaller... how is that even possible?!\"", m)); + } + else { + msgid++; goto retry; + } + + msgid++; + } + + void playernear(cell *c) { + info *i = getPrisonInfo(c); + int d = dist(c); + // if(i) printf("d=%d bn=%d\n", d, i->bestnear); + if(i && d < i->bestnear) { + if(i->bestnear > 100 && d <= 100) { + i->value = items[itPalace]; + if(princess::challenge) + addMessage(XLAT("Hardness frozen at %1.", its(i->value))); + } + i->bestnear = d; + } + } + + } + +bool grailWasFound(cell *c) { + if(euclid) return items[itHolyGrail]; + return c->master->alt->alt->emeraldval & GRAIL_FOUND; + } + +int euclidAlt(short x, short y) { + if(euclidland == laTemple) { + return max(int(x), x+y); + } + else if(euclidland == laCaribbean || euclidland == laWhirlpool) { + return + min( + min(max(int(-x), -x-y) + 3, + max(int(x+y), int(y)) + 3), + max(int(x), int(-y)) + 3 + ); + } + else if(euclidland == laPrincessQuest) + return eudist(x-EPX, y-EPY); + else return eudist(x-20, y-10); + } + +void flameHalfvine(cell *c, int val) { + if(itemBurns(c->item)) { + c->item = itNone; + addMessage(XLAT("%The1 burns!", c->item)), c->item = itNone; + } + c->wall = waPartialFire; + c->wparam = val; } void killMonster(cell *c) { @@ -661,7 +2058,7 @@ void killMonster(cell *c) { eMonster m = c->monst; if(!m) return; - if(isWorm(c)) return; + if(isWorm(c) && m != moTentacleGhost) return; if(m == moShadow) return; if(m == moGolemMoved) m = moGolem; if(m == moKnightMoved) m = moKnight; @@ -669,14 +2066,52 @@ void killMonster(cell *c) { if(m == moLesserM) m = moLesser; if(m == moGreater) m = moLesser; if(m == moGreaterM) m = moLesser; + if(isPrincess(m)) m = moPrincess; + if(m == moTentacleGhost) m = moGhost; kills[m]++; - if(m == moTroll) { + if(m == moPrincess) { + princess::info *i = princess::getPrincessInfo(c); + if(i) { + i->princess = NULL; + if(i->bestdist == OUT_OF_PALACE) items[itSavedPrincess]--; + if(princess::challenge) showMissionScreen(); + } + } + + if(m == moGargoyle && c->wall != waMineMine) { + bool connected = false; + + if(c->land == laEdge) { + for(int i=0; itype; i++) { + cell *c2 = c->mov[i]; + if(c2->wall == waPlatform || c2->wall == waGargoyle || c2->wall == waBarrier || + c2->wall == waDeadTroll) + connected = true; + } + } + else { + for(int i=0; itype; i++) { + cell *c2 = c->mov[i]; + if(!cellUnstableOrChasm(c2) && !isWatery(c2)) connected = true; + } + } + + if(connected) { + destroyHalfvine(c); + if(cellUnstableOrChasm(c)) c->wall = waGargoyleFloor; + else if(isWatery(c)) c->wall = waGargoyleBridge; + else c->wall = waGargoyle; + c->item = itNone; + } + } + + if(m == moTroll || m == moFjordTroll) { destroyHalfvine(c); c->wall = cellUnstableOrChasm(c) ? waChasm : waDeadTroll; c->item = itNone; for(int i=0; itype; i++) if(c->mov[i]) { - c->mov[i]->item = itNone; + if(m == moTroll) c->mov[i]->item = itNone; if(c->mov[i]->wall == waDeadwall || c->mov[i]->wall == waDeadfloor2) c->mov[i]->wall = waCavewall; if(c->mov[i]->wall == waDeadfloor) c->mov[i]->wall = waCavefloor; } @@ -684,7 +2119,7 @@ void killMonster(cell *c) { if(m == moMiner) { destroyHalfvine(c); c->wall = cellUnstableOrChasm(c) ? waChasm : waNone; - for(int i=0; itype; i++) if(passable(c->mov[i], c, true, true)) { + for(int i=0; itype; i++) if(passable(c->mov[i], c, true, true, false)) { destroyHalfvine(c->mov[i]); c->mov[i]->wall = cellUnstableOrChasm(c) ? waChasm : waNone; if(c->mov[i]->monst == moSlime || c->mov[i]->monst == moSlimeNextTurn) @@ -696,34 +2131,70 @@ void killMonster(cell *c) { c->wall = cellUnstableOrChasm(c) ? waChasm : waVinePlant; c->item = itNone; } + if(isBird(m)) moveEffect(c, c, moDeadBird); + if(m == moBomberbird || m == moTameBomberbird) { + if(c->wall == waNone || c->wall == waMineUnknown || c->wall == waMineOpen || + c->wall == waCavefloor || c->wall == waDeadfloor || c->wall == waDeadfloor2 || + c->wall == waRubble || c->wall == waGargoyleFloor || + c->wall == waCIsland || c->wall == waCIsland2 || + c->wall == waStrandedBoat || c->wall == waRed1 || c->wall == waGiantRug) + c->wall = waMineMine; + else if(c->wall == waFrozenLake) + c->wall = waLake; + else if(c->wall == waGargoyleBridge) + placeWater(c, c); + else if(c->wall == waRed3 || c->wall == waRed2) { + c->wall = waRed1; + for(int i=0; itype; i++) if(c->mov[i]->wall == waRed3) + c->mov[i]->wall = waRed2; + c->item = itNone; + } + if(isFire(c)) { + c->wall = waMineMine; + explodeMine(c); + } + } if(m == moVineSpirit) { destroyHalfvine(c); - c->wall = waNone; + if(!isFire(c)) c->wall = waNone; } - if(isWitch(m) && (c->wall == waBonfire || passable(c, NULL, true, false)) && !c->item) { + if(m == moRedTroll) snakepile(c); + if(isWitch(m) && (isFire(c) || passable(c, NULL, true, false, false)) && !c->item) { if(m == moWitchFire) c->item = itOrbFire; if(m == moWitchFlash) c->item = itOrbFlash; if(m == moWitchGhost) c->item = itOrbGhost; if(m == moWitchWinter) c->item = itOrbWinter; if(m == moWitchSpeed) c->item = itOrbSpeed; - if(c->wall == waBonfire && itemBurns(c->item)) + if(isFire(c) && itemBurns(c->item)) c->item = itNone; } - if(m == moFireFairy) { - c->wall = cellUnstableOrChasm(c) ? waChasm : waBonfire; - c->item = itNone, c->tmp = 50; - } + if(m == moFireFairy) + makeflame(c, 50, false); if(m == moPyroCultist && c->item == itNone && c->wall != waChasm) { // a reward for killing him before he shoots! c->item = itOrbDragon; } + // note: an Orb appears underwater! + if(m == moWaterElemental && c->item == itNone) + c->item = itOrbWater; + + if(m == moPirate && isOnCIsland(c) && c->item == itNone && (euclid||c->master->alt) && celldistAlt(c) <= -5) { + bool toomany = false; + for(int i=0; itype; i++) { + cell *c2 = c->mov[i]; + if(c2) for(int j=0; jtype; j++) + if(c2->mov[j] && c2->mov[j]->item == itCompass) + toomany = true; + } + if(!toomany) c->item = itCompass; + } if(m == moSlime) { c->monst = moNone; spill(c, c->wall, 2); } // if(c->monst == moShark) c->heat += 1; // if(c->monst == moGreaterShark) c->heat += 10; if(isIcyLand(c)) { - if(m == moCultist) c->heat += 3; - if(m == moPyroCultist) c->heat += 6; - if(m == moLesser) c->heat += 10; + if(m == moCultist) HEAT(c) += 3; + if(m == moPyroCultist) HEAT(c) += 6; + if(m == moLesser) HEAT(c) += 10; } if(m == moLesser && !(kills[m] % 10)) degradeDemons(); @@ -750,76 +2221,256 @@ void killMonster(cell *c) { } } } + else if(c->monst == moTentacleGhost) + c->monst = moTentacletail; else c->monst = moNone; if(m == moEarthElemental) earthWall(c); } -void burnMonstersAndItems(cell *c, int val, eWall firetype = waBonfire) { - if(itemBurns(c->item)) - addMessage(XLAT("%The1 burns!", c->item)), c->item = itNone; - if(c->monst && c->monst != moGhost && !isWorm(c) && c->monst != moShadow) { - addMessage(XLAT("%The1 burns!", c->monst)); +void killWithMessage(cell *c, bool orStun = false) { + eMonster m = c->monst; + int tk = tkills(); + if(orStun) + killOrStunMonster(c); + else killMonster(c); + int ntk = tkills(); + + if(tk == 0 && ntk > 0) + addMessage(XLAT("That was easy, but groups could be dangerous.")); + + if(tk < 10 && ntk >= 10) + addMessage(XLAT("Good to know that your fighting skills serve you well in this strange world.")); + + if(tk < 50 && ntk >= 50) + addMessage(XLAT("You wonder where all these monsters go, after their death...")); + + if(tk < 100 && ntk >= 100) + addMessage(XLAT("You feel that the souls of slain enemies pull you to the Graveyard...")); + + if(m == moVizier && c->monst != moVizier && kills[moVizier] == 1) { + addMessage(XLAT("Hmm, he has been training in the Emerald Mine. Interesting...")); + princess::forceMouse = true; } - c->tmp = val; - c->wall = firetype; + + if(m == moIvyRoot && ntk>tk) + achievement_gain("IVYSLAYER"); } -void flameHalfvine(cell *c, int val) { - burnMonstersAndItems(c, val); - c->wall = waPartialFire; +void pushMonster(cell *ct, cell *cf) { + moveMonster(ct, cf); } bool destroyHalfvine(cell *c, eWall newwall, int tval) { if(cellHalfvine(c)) { for(int t=0; ttype; t++) if(c->mov[t]->wall == c->wall) { - if(newwall == waPartialFire) burnMonstersAndItems(c->mov[t], tval, newwall); + if(newwall == waPartialFire) flameHalfvine(c->mov[t], tval); + else if(newwall == waRed1) c->mov[t]->wall = waVinePlant; else c->mov[t]->wall = newwall; } - if(newwall == waPartialFire) burnMonstersAndItems(c, tval, newwall); + if(newwall == waPartialFire) flameHalfvine(c, tval); else c->wall = newwall; return true; } return false; } +bool isCrossroads(eLand l) { + return l == laCrossroads || l == laCrossroads2 || l == laCrossroads3; + } + +/* bool orbChance(cell *c, eLand usual, int chthere, int chcross) { - if(c->land == usual) return chthere && rand() % chthere == 0; - if(chcross && c->land == laCrossroads) { + if(usual == laElementalWall && isElementalLand(c->land)) + usual = c->land; + if(c->land == usual) return chthere && hrand(chthere) == 0; + if(chcross && isCrossroads(c->land)) { chcross = (chcross / 50) * (50 + items[itHyperstone]); - return rand() % chcross == 0; + return hrand(chcross) == 0; + } + if(chcross && c->land == laOcean && c->wall == waBoat && c->landparam > 25) { + return hrand(chcross) < 20; } return false; } -void buildBarrier(cell *c) { - // printf("build barrier at %p", c); - if(c->wall == waBarrier) { - // printf("-> ready\n"); - return; +void placeOrbs(cell *c) { + + if(c->land == laZebra && c->wall == waTrapdoor) return; + if(c->land == laEdge && cellEdgeUnstable(c)) return; + + for(int i=0; i= 10) + c->item = oi.orb; + if(oi.orb == itOrbWater && c->land != laOcean) c->wall = waStrandedBoat; } -// if(c->wall == waWaxWall) return; - if(c->mpdist > BARLEV) { - // printf("-> too far\n"); - return; // == INFD) return; + + } +*/ + +void buildPrizeMirror(cell *c) { + if(c->type == 7) return; + if(items[itShard] < 25) return; + c->wall = hrand(2) ? waCloud : waMirror; + } + +void placePrizeOrb(cell *c) { + eLand l = c->land; + if(isElemental(l)) l = laElementalWall; + + // these two lands would have too much orbs according to normal rules + if(l == laPalace && hrand(100) >= 20) return; + if(l == laGraveyard && hrand(100) >= 15) return; + if(l == laLivefjord && hrand(100) >= 35) return; + if(l == laMinefield && hrand(100) >= 25) return; + if(l == laElementalWall && hrand(100) >= 25) return; + + if(l == laPalace && princess::dist(c) < OUT_OF_PRISON) + l = laPrincessQuest; + for(int i=0; i= 60) continue; + if(oi.orb == itOrbWater && c->land != laOcean) { + if(cellHalfvine(c)) continue; + c->wall = waStrandedBoat; + return; + } + c->item = oi.orb; } + + // printf("land: %s orb: %s\n", dnameof(l), dnameof(c->item)); + } + +#define PRIZEMUL 7 + +void placeLocalOrbs(cell *c) { + eLand l = c->land; + if(l == laZebra && c->wall == waTrapdoor) return; + if(l == laEdge && cellEdgeUnstable(c)) return; + if(isElemental(l)) l = laElementalWall; + + for(int i=0; i= 10) { + // printf("local orb\n"); + c->item = oi.orb; + if(oi.orb == itOrbWater && c->land != laOcean) c->wall = waStrandedBoat; + return; + } + else if(oi.gchance && ch == 1 && getOLR(itShard, l) == olrPrize25 && l != laRedRock) + buildPrizeMirror(c); + else if(oi.gchance && (ch >= 2 && ch < 2+PRIZEMUL)) + placePrizeOrb(c); + } + } + +void placeCrossroadOrbs(cell *c) { + for(int i=0; i= 50) continue; + c->item = oi.orb; + if(oi.orb == itOrbWater && c->land != laOcean) c->wall = waStrandedBoat; + } + } + +void placeOceanOrbs(cell *c) { + for(int i=0; i= 20) continue; + c->item = oi.orb; + } + } + +bool errorReported = false; + +void describeCell(cell *c) { + if(!c) { printf("NULL\n"); return; } + printf("describe %p: ", c); + printf("%-15s", linf[c->land].name); + printf("%-15s", winf[c->wall].name); + printf("%-15s", iinf[c->item].name); + printf("%-15s", iinf[c->monst].name); + printf("%3d", c->landparam); + printf("%3d", c->mpdist); + printf("\n"); + } + +void raiseBuggyGeneration(cell *c, const char *s) { + + printf("procgen error in: %s\n", s); + + if(!errorReported) { + addMessage(string("something strange happened in: ") + s); + errorReported = true; + } + // return; + + describeCell(c); + for(int i=0; itype; i++) describeCell(c->mov[i]); + + z: + c->item = itPirate; + for(int i=0; itype; i++) if(c->mov[i] && c->mov[i]->mpdist < c->mpdist) { + c = c->mov[i]; + goto z; + } + + buggyGeneration = true; return; + } + +void setland(cell *c, eLand l) { + if(c->land != l) + c->landparam = 0; + c->land = l; + } + +void buildBarrier(cell *c); + +bool buildBarrier4(cell *c, int d, int mode, eLand ll, eLand lr); + +void buildBarrierFront(cell *c) { + int ht = c->landparam; cellwalker bb(c, c->bardir); setbarrier(bb.c); cwstep(bb); - bb.c->barleft = c->barright; - bb.c->barright = c->barleft; + bb.c->barleft = c->barleft; + bb.c->barright = c->barright; + bb.c->landparam = (ht-4); +//printf("[A heat %d]\n", ht-4); setbarrier(bb.c); - cwspin(bb, 2); cwstep(bb); bb.c->land = c->barleft; cwstep(bb); - cwspin(bb, 2); cwstep(bb); bb.c->land = c->barright; cwstep(bb); + cwspin(bb, 2); cwstep(bb); setland(bb.c, c->barleft); cwstep(bb); + cwspin(bb, 2); cwstep(bb); setland(bb.c, c->barright); cwstep(bb); cwspin(bb, 2); cwspin(bb, 3); cwstep(bb); + bb.c->landparam = (ht-4)^2; +//printf("[B heat %d]\n", (ht-4)^2); bb.c->barleft = c->barright; bb.c->barright = c->barleft; setbarrier(bb.c); cwspin(bb, 3); cwstep(bb); + bb.c->landparam = ht ^ 2; +//printf("[C heat %d]\n", (ht)^2); bb.c->bardir = bb.spin; bb.c->barleft = c->barright; bb.c->barright = c->barleft; @@ -828,18 +2479,75 @@ void buildBarrier(cell *c) { for(int a=-3; a<=3; a++) if(a) { bb.c = c; bb.spin = c->bardir; cwspin(bb, a); cwstep(bb); - bb.c->land = a > 0 ? c->barright : c->barleft; + setland(bb.c, a > 0 ? c->barright : c->barleft); } + } - bb.c = c; bb.spin = c->bardir; - cwspin(bb, 3); cwstep(bb); cwspin(bb, 4); bb.c->land = c->barright; cwstep(bb); cwspin(bb, 3); +void buildBarrierBack(cell *c) { + int ht = c->landparam; + + cellwalker bb(c, c->bardir); setbarrier(bb.c); + cwspin(bb, 3); cwstep(bb); cwspin(bb, 4); setland(bb.c, c->barright); cwstep(bb); cwspin(bb, 3); bb.c->bardir = bb.spin; bb.c->barleft = c->barright; bb.c->barright = c->barleft; + bb.c->landparam = ht ^ 11; +//printf("[D heat %d]\n", (ht^11)); + + // needed for CR2 to work + cwstep(bb); + bb.c->barleft = c->barright; + bb.c->barright = c->barleft; + bb.c->landparam = (ht^11)-4; + cwstep(bb); +//printf("[E heat %d]\n", (ht^11)); + // printf("#2\n"); buildBarrier(bb.c); } +eLand oppositeElement(eLand l) { + if(l == laEFire) return laEWater; + if(l == laEWater) return laEFire; + if(l == laEAir) return laEEarth; + if(l == laEEarth) return laEAir; + return l; + } + +void buildBarrier(cell *c) { + if(buggyGeneration) return; + + // printf("build barrier at %p", c); + if(c->wall == waBarrier || c->land == laElementalWall) { + // printf("-> ready\n"); + return; + } +// if(c->wall == waWaxWall) return; + if(c->mpdist > BARLEV) { + // printf("-> too far\n"); + return; // == INFD) return; + } + + if(((c->barleft == laCrossroads3 || c->barright == laCrossroads3) && hrand(100) < 66) || + (isElemental(c->barleft) && isElemental(c->barright) && hrand(100) < 25)) { + cellwalker cw(c, c->bardir); + cwspin(cw, 3); cwstep(cw); + cell *cp = cwpeek(cw, 4); + if(cp->wall != waBarrier && cp->land != laElementalWall) { + cwspin(cw, 2); cwstep(cw); + bool b = buildBarrier4(cw.c, cw.spin, 2, oppositeElement(c->barleft), c->barright); + if(b) return; + } + else { + bool b = buildBarrier4(c, c->bardir, 1, c->barleft, c->barright); + if(b) return; + } + } + + buildBarrierFront(c); + buildBarrierBack(c); + } + void chasmify(cell *c) { c->wall = waChasm; c->item = itNone; int q = 0; @@ -847,7 +2555,7 @@ void chasmify(cell *c) { for(int i=0; itype; i++) if(c->mov[i] && c->mov[i]->mpdist > c->mpdist && cellUnstable(c->mov[i])) c2[q++] = c->mov[i]; if(q) { - cell *c3 = c2[rand() % q]; + cell *c3 = c2[hrand(q)]; c3->wall = waChasmD; } } @@ -865,7 +2573,7 @@ void chasmifyEarth(cell *c) { } if(!q) printf("no further move!\n"); if(q) { - int d = d2[rand() % q]; + int d = d2[hrand(q)]; cell *c3 = c->mov[d]; c3->wall = waEarthD; for(int i=0; itype; i++) { @@ -877,40 +2585,151 @@ void chasmifyEarth(cell *c) { earthWall(c); c->item = itNone; } +void chasmifyElemental(cell *c) { + int q = 0; + int d2[10]; + for(int i=2; i<=c->type-2; i++) { + int j = (i+c->mondir)%c->type; + cell *c2 = c->mov[j]; + if(c2 && c2->mpdist > c->mpdist && c2->land == c->land) + d2[q++] = j; + } + if(q) { + int d = d2[hrand(q)]; + cell *c3 = c->mov[d]; + c3->wall = waElementalD; + for(int i=0; itype; i++) { + cell *c4 = createMov(c3, i); + c4->wall = waNone; + } + c3->mondir = c->spn[d]; + } + c->wall = getElementalWall(c->land); + c->wparam = 100; c->item = itNone; + } + +bool incompatible1(eLand l1, eLand l2) { + if(isCrossroads(l1) && isCrossroads(l2)) return true; + if(l1 == laJungle && l2 == laMotion) return true; + if(l1 == laMirror && l2 == laMotion) return true; + if(l1 == laPower && l2 == laWineyard) return true; + if(l1 == laPower && l2 == laDryForest) return true; + if(l1 == laEFire && l2 == laWineyard) return true; + if(l1 == laEFire && l2 == laDryForest) return true; + if(l1 == laGraveyard && l2 == laDryForest) return true; + if(l1 == laGraveyard && l2 == laRedRock) return true; + if(l1 == laGraveyard && l2 == laEmerald) return true; + if(l1 == laDeadCaves && l2 == laEmerald) return true; + if(l1 == laDeadCaves && l2 == laCaves) return true; + if(isElemental(l1) && isElemental(l2)) return true; + return false; + } + +eLand randomElementalLand() { + int i = hrand(4); + eLand t[4] = { laEFire, laEWater, laEAir, laEEarth }; + return t[i]; + } + +bool incompatible(eLand nw, eLand old) { + return (nw == old) || incompatible1(nw, old) || incompatible1(old, nw); + } + +extern bool generatingEquidistant; + +bool rlyehComplete() { + return items[itStatue] >= 10 || items[itGrimoire] >= 10; + } + +bool lchance() { return hrand(100) < 90; } + +eLand pickLandRPM(eLand old) { + while(true) { + eLand n = randlands[hrand(RANDLANDS)]; + if(incompatible(n, old)) continue; + if(n == laIce || n == laCaves || n == laDesert) + return n; + if(hiitems[treasureType(n)] < 10) + continue; + return n; + } + } + eLand getNewLand(eLand old) { - eLand tab[32]; + + if(randomPatternsMode) return pickLandRPM(old); + + if(old == laCaribbean) + return laOcean; + + if(old == laEEarth && lchance()) return hrand(2) ? laEWater : laEFire; + if(old == laEAir && lchance()) return hrand(2) ? laEWater : laEFire; + if(old == laEWater && lchance()) return hrand(2) ? laEEarth : laEAir; + if(old == laEFire && lchance()) return hrand(2) ? laEEarth : laEAir; + + if(old == laLivefjord && hrand(2)) + return laOcean; + + if(old == laOcean && !generatingEquidistant) + return hrand(2) ? laCaribbean : laLivefjord; + + if(old == laOcean && gold() >= 60 && hrand(100) < 75 && !rlyehComplete()) + return laRlyeh; + + if(old == laRlyeh && !rlyehComplete()) + return laOcean; + + eLand tab[256]; int cnt = 0; -/* if(isHive(old) && rand() % 100 < 90) { +/* if(isHive(old) && hrand(100) < 90) { eLand n = old; - while(n == old) n = eLand(laHive0 + rand() % 3); + while(n == old) n = eLand(laHive0 + hrand(3)); return n; } */ - // return (rand() % 2) ? laMotion : laJungle; + // return (hrand(2)) ? laMotion : laJungle; // the basic lands, always available tab[cnt++] = laCrossroads; tab[cnt++] = laIce; tab[cnt++] = laDesert; tab[cnt++] = laJungle; + tab[cnt++] = laMotion; if(old != laDeadCaves) tab[cnt++] = laCaves; - // the advanced lands + // the intermediate lands if(gold() >= 30) { tab[cnt++] = laCrossroads; tab[cnt++] = laAlchemist; tab[cnt++] = laMirror; - tab[cnt++] = laMotion; + tab[cnt++] = laOcean; + tab[cnt++] = laLivefjord; + tab[cnt++] = laMinefield; + tab[cnt++] = laPalace; + if(kills[moVizier]) tab[cnt++] = laEmerald; + if(items[itFeather] >= 10) tab[cnt++] = laZebra; } + // the advanced lands if(gold() >= 60) { - tab[cnt++] = laCrossroads; - tab[cnt++] = laRlyeh; - if(old != laDeadCaves && items[itGold] >= 5 && items[itFernFlower] >= 5) tab[cnt++] = laFjord; - if(old != laPower) tab[cnt++] = laDryForest; - if(old != laPower) tab[cnt++] = laWineyard; - if(old != laCaves && old != laFjord && items[itGold] >= 10) tab[cnt++] = laDeadCaves; + // REMOVETHIS + tab[cnt++] = laEdge; + tab[cnt++] = laCrossroads2; + if(rlyehComplete()) tab[cnt++] = laRlyeh; + if(old == laCrossroads || old == laCrossroads2) tab[cnt++] = laOcean; + if(old == laOcean) tab[cnt++] = laCrossroads; + if(items[itGold] >= 5 && items[itFernFlower] >= 5 && !kills[moVizier]) + tab[cnt++] = laEmerald; + tab[cnt++] = laDryForest; + tab[cnt++] = laWineyard; + if(items[itGold] >= 10) tab[cnt++] = laDeadCaves; + // tab[cnt++] = laCaribbean; + if(items[itSpice] >= 10) { + tab[cnt++] = laRedRock; + if(old == laDesert) tab[cnt++] = laRedRock; + } + if(old == laRedRock) tab[cnt++] = laDesert; } if(tkills() >= 100) { @@ -918,18 +2737,31 @@ eLand getNewLand(eLand old) { if(gold() >= 60) tab[cnt++] = laHive; } + if(kills[moWaterElemental] + kills[moEarthElemental] + kills[moFireElemental] + kills[moAirElemental]) + tab[cnt++] = randomElementalLand(); + if(hellUnlocked()) { - tab[cnt++] = laCrossroads; + tab[cnt++] = laCrossroads3; tab[cnt++] = laHell; } if(items[itHell] >= 10) { tab[cnt++] = laCocytus; - if(old != laWineyard && old != laDryForest) tab[cnt++] = laPower; + if(old == laHell || old == laIce) tab[cnt++ ] = laCocytus; + if(old == laCocytus) { tab[cnt++] = laIce; tab[cnt++] = laHell; } + tab[cnt++] = laPower; + if(old == laCrossroads || old == laCrossroads2) tab[cnt++] = laOcean; + if(old == laOcean) tab[cnt++] = laCrossroads2; } + // for(int i=0; i<20; i++) tab[cnt++] = laRedRock; + // for(int i=0; i<20; i++) tab[cnt++] = laCaribbean; + // for(int i=0; i<20; i++) tab[cnt++] = laCocytus; + + // for(int i=0; i<20; i++) tab[cnt++] = laCrossroads; + eLand n = old; - while(n == old) n = tab[rand() % cnt]; + while(incompatible(n, old)) n = tab[hrand(cnt)]; return n; } @@ -938,21 +2770,21 @@ bool notDippingFor(eItem i) { int v = items[i] - currentLocalTreasure; if(v <= 10) return true; if(v >= 20) return false; - return v >= rand() % 10 + 10; + return v >= hrand(10) + 10; } bool notDippingForExtra(eItem i, eItem x) { int v = items[i] - min(items[x], currentLocalTreasure); if(v <= 10) return true; if(v >= 20) return false; - return v >= rand() % 10 + 10; + return v >= hrand(10) + 10; } eLand euland[65536]; eLand switchable(eLand nearland, eLand farland, eucoord c) { if(nearland == laCrossroads) { - if(rand() % 4 == 0 && (short(c)%3==0)) + if(hrand(4) == 0 && (short(c)%3==0)) return laBarrier; return laCrossroads; } @@ -960,7 +2792,7 @@ eLand switchable(eLand nearland, eLand farland, eucoord c) { return getNewLand(farland); } else { - if(rand() % 20 == 0 && (short(c)%3==0)) + if(hrand(20) == 0 && (short(c)%3==0)) return laBarrier; return nearland; } @@ -979,55 +2811,572 @@ eLand getEuclidLand(eucoord c) { return euland[c] = laCrossroads; } -void createBugArmy(cell *c); - int newRoundTableRadius() { return 28 + 2 * items[itHolyGrail]; } int roundTableRadius(cell *c) { if(euclid) return 28; - return c->master->alt->alt->fjordval & GRAIL_RADIUS_MASK; - } - -bool grailWasFound(cell *c) { - if(euclid) return items[itHolyGrail]; - return c->master->alt->alt->fjordval & GRAIL_FOUND; - } - -int euclidAlt(short x, short y) { - if(euclidland == laTemple) { - return max(int(x), x+y); - } - else return eudist(x-20, y-10); + return c->master->alt->alt->emeraldval & GRAIL_RADIUS_MASK; } int celldistAltRelative(cell *c) { return celldistAlt(c) - roundTableRadius(c); } -heptagon *createAlternateMap(cell *c, int rad, hstate firststate); - -void generateAlts(heptagon *h); - void buildCamelotWall(cell *c) { c->wall = waCamelot; for(int i=0; itype; i++) { cell *c2 = createMov(c, i); - if(c2->wall == waNone && celldistAlt(c2) > celldistAlt(c) && c2->monst == moNone) + if(c2->wall == waNone && (euclid || (c2->master->alt && c->master->alt)) && celldistAlt(c2) > celldistAlt(c) && c2->monst == moNone) c2->wall = waCamelotMoat; } } // This function generates all lands. Warning: it's very long! + +void buildBarrier(cell *c, int d) { + d %= 7; + cellwalker bb(c, d); + + if(checkBarriersFront(bb) && checkBarriersBack(bb)) { + c->bardir = d; + eLand oldland = c->land; + eLand newland = getNewLand(oldland); + if(showoff) newland = showlist[(showid++) % 10]; + landcount[newland]++; + + if(d == 5) c->barleft = oldland, c->barright = newland; + else c->barleft = newland, c->barright = oldland; + c->landparam = 40; + } + } + +bool buildBarrier4(cell *c, int d, int mode, eLand ll, eLand lr) { + d %= 7; + cellwalker b1(c, d); + + cellwalker b2(c, d); + cwstep(b2); cwspin(b2, 3); cwstep(b2); cwspin(b2, 3); cwstep(b2); + + cellwalker b3(c, d); + cwstep(b3); cwspin(b3, 4); cwstep(b3); cwspin(b3, 4); + + cellwalker b4(c, d); + cwstep(b4); cwspin(b4, -4); cwstep(b4); cwspin(b4, -4); + + if(mode == 0) { + if(!((checkBarriersBack(b1) && checkBarriersBack(b2)))) return false; + if(!((checkBarriersFront(b3) && checkBarriersFront(b4)))) return false; + } + + if(mode == 1) { + if(!(checkBarriersFront(b3, 5, true) && checkBarriersFront(b4, 5, true))) + return false; + } + + if(mode == 2) { + if(!((checkBarriersBack(b1, 5, true) && checkBarriersBack(b2, 5, true)))) + return false; + } + + eLand xl = oppositeElement(ll); + eLand xr = oppositeElement(lr); + + c->bardir = d, c->barleft = ll, c->barright = lr; buildBarrierBack(c); + + c= b2.c; d=b2.spin; + c->bardir = d, c->barleft = xl, c->barright = xr; buildBarrierBack(c); + + c= b3.c; d=b3.spin; + c->bardir = d, c->barleft = xl, c->barright = lr; buildBarrierFront(c); + + c= b4.c; d=b4.spin; + c->bardir = d, c->barleft = ll, c->barright = xr; buildBarrierFront(c); + + for(int a=-3; a<=3; a++) if(a) { + setland(cwpeek(b1, a), a > 0 ? lr : ll); + setland(cwpeek(b2, a), a > 0 ? xr : xl); + setland(cwpeek(b3, a), a > 0 ? lr : xl); + setland(cwpeek(b4, a), a > 0 ? xr : ll); + } + + cell *cp; + cp = cwpeek(b1, 0); + cp->barleft = ll; cp->barright = lr; setbarrier(cp); + cp = cwpeek(b2, 0); + cp->barleft = xl; cp->barright = xr; setbarrier(cp); + + return true; + } + +void buildBarrierStrong(cell *c, int d, bool oldleft) { + d %= 7; + cellwalker bb(c, d); + + c->bardir = d; + eLand oldland = c->land; + eLand newland = getNewLand(oldland); + if(showoff) newland = showlist[(showid++) % 10]; + landcount[newland]++; + + if(oldleft) c->barleft = oldland, c->barright = newland; + else c->barleft = newland, c->barright = oldland; + } + +void buildCrossroads2(cell *c) { + + if(buggyGeneration) return; + + if(!c) return; + + for(int i=0; itype; i++) + if(c->mov[i] && !c->mov[i]->landparam && c->mov[i]->mpdist < c->mpdist) + buildCrossroads2(c->mov[i]); + + if(c->bardir != NODIR && c->bardir != NOBARRIERS) + buildBarrier(c); + + if(c->land != laCrossroads2) return; + + if(!c->landparam) { + for(int i=0; itype; i++) { + cell *c2 = createMov(c, i); + if(c2 && c2->landparam) { + for(int j=0; jtype; j++) { + createMov(c2, j); + cell *c3 = c2->mov[j]; + if(c3 && c3->landparam) { + int h2 = c2->landparam; + int h3 = c3->landparam; + + // ambiguous + if(h2/4 == 1 && h3/4 == 3) continue; + if(h2/4 == 3 && h3/4 == 1) continue; + + for(int d=0; dtype; d++) + if(emeraldtable[h2][d] == h3) { + int nh = emeraldtable[h2][(42+d + c->spn[i] - j) % c2->type]; + if(c->landparam>0 && c->landparam != nh) printf("CONFLICT\n"); + c->landparam = nh; + } + + if(c->landparam == 0) + printf("H2 = %d H3=%d\n", c2->landparam, c3->landparam); + } + } + if(c->landparam == 0) { + printf("H2 = %d\n", c2->landparam); + describeCell(c2); + for(int i=0; itype; i++) describeCell(c2->mov[i]); +// halted = true; +// c->heat = -1; + c2->item = itCompass; + return; + } + } + } + + if(c->landparam) { +// for(int i=0; itype; i++) { +// cell *c2 = c->mov[i]; +// buildCrossroads2(c2); +// } + } + else { + raiseBuggyGeneration(c, "buildCrossroads2"); + return; + } + } + + int h = c->landparam; + + if(h/4 >= 8 && h/4 <= 11) { + for(int i=0; itype; i++) { + createMov(c, i)->land = laCrossroads2; + if(!c->mov[i]->landparam) buildCrossroads2(c->mov[i]); + } + if(h/4 == 8 || h/4 == 10) + for(int i=0; itype; i++) { + if(c->mov[i] && c->mov[i]->landparam == h-4) { + bool oldleft = true; + for(int j=1; j<=3; j++) + if(c->mov[(i+j)%7] && c->mov[(i+j)%7]->mpdist < c->mpdist) + oldleft = false; + + buildBarrierStrong(c, i, oldleft); + c->landparam = h; + buildBarrier(c); + } + } + } + } + +extern bool bugtrack; + +bool generatingEquidistant = false; + +void buildAnotherEquidistant(cell *c) { + // printf("building another coast\n"); + + int gdir = -1; + for(int i=0; itype; i++) { + if(c->mov[i] && c->mov[i]->mpdist < c->mpdist) gdir = i; + } + if(!gdir) return; + + generatingEquidistant = true; + + cellwalker cw(c, (gdir+3) % c->type); + vector coastpath; + while(coastpath.size() < 30 || cw.c->type != 7) { + coastpath.push_back(cw.c); + cwstep(cw); cwspin(cw, 3); + if(cw.c->type == 7 && hrand(2) == 0) cwspin(cw, 1); + } + coastpath.push_back(cw.c); + // printf("setdists\n"); + for(int i=1; ibardir != NODIR && c2->bardir != NOBARRIERS) + buildBarrier(c2); + // printf("setdisting\n"); + for(int i=size(coastpath)-2; i>=0; i--) { + for(int j=BARLEV; j>=6; j--) + setdist(coastpath[i], j, NULL); + // buildEquidistant(coastpath[i]); + // printf("i=%d heat=%f\n", i, coastpath[i]->heat); + // coastpath[i]->item = itCoast; + } + generatingEquidistant = false; + } + +bool bugtrack = false, bugfound = false; + +#define UNKNOWN 65535 + +int coastval(cell *c) { + if(!c) return UNKNOWN; + if(c->land == laNone) return UNKNOWN; + if(c->land == laOceanWall || c->land == laCaribbean || c->land == laWhirlpool || + c->land == laLivefjord) + return 30; + if(c->land != laOcean && c->land != laEdge) { + return 0; + } + if(!c->landparam) return UNKNOWN; + return c->landparam; + } + +bool cellEdgeUnstable(cell *c) { + if(c->land != laEdge || c->wall != waNone) return false; + int d = coastval(c); + for(int i=0; itype; i++) + if(coastval(c->mov[i]) == d-1) { + if(againstWind(c->mov[i], c)) return false; + if(!passable(c->mov[i], NULL, true, false, false) && + !isFire(c->mov[i])) + return false; + if(isWorm(c->mov[i])) + return false; + } + return true; + } + +eMonster crossroadsMonster() { + + static eMonster weak[9] = { + moYeti, moGoblin, moRanger, moOrangeDog, moRunDog, moMonkey, moZombie, + moDesertman, moCultist + }; + + if(hrand(10) == 0) return weak[hrand(9)]; + + static eMonster m[24] = { + moWorm, moTentacle, + moTroll, moEagle, + moLesser, moGreater, moPyroCultist, moGhost, + moFireFairy, moIvyRoot, moHedge, + moLancer, moFlailer, moVineBeast, + moBomberbird, moAlbatross, moRedTroll, + moWaterElemental, moAirElemental, moFireElemental, + moFatGuard, moMiner, moPalace, moVizier + }; + return m[hrand(24)]; + } + +eMonster wanderingCrossroadsMonster() { + while(true) { + eMonster m = crossroadsMonster(); + if(!isIvy(m) && m != moTentacle) return m; + } + } + +void buildEquidistant(cell *c) { + if(!c) return; + if(c->landparam) return; + int mcv = UNKNOWN; + + // find the lowest coastval + for(int i=0; itype; i++) { + int cv = coastval(c->mov[i]); + if(cv < mcv) mcv = cv; + } + + int mcv2 = 0; + + if(bugfound) { mcv = 1; c->landparam = 10; } + + else if(mcv == 0) { + // if(generatingEquidistant) printf("mcv=0\n"); + c->landparam = 1; + } + else { + // if it appears twice, increase it + int qcv = 0; + int sid = 0; + for(int i=0; itype; i++) + if(coastval(c->mov[i]) == mcv) + qcv++, sid = i; + + // if(generatingEquidistant) printf("qcv=%d mcv=%d\n", qcv, mcv); + if(qcv >= 2) c->landparam = mcv+1; + else { + // if(qcv != 1) { printf("qcv = %d\n", qcv); exit(1); } + cell *c2 = c->mov[sid]; + int bsid = c->spn[sid]; + for(int j=0; j<7; j++) { + int q = (bsid+j+42) % c2->type; + cell *c3 = c2->mov[q]; + if(coastval(c3) < mcv) { + cell *c4 = createMovR(c2, bsid+1); + buildEquidistant(c4); + mcv2 = coastval(c4); + break; + } + q = (bsid-j+42) % c2->type; + c3 = c2->mov[q]; + if(coastval(c3) < mcv) { + cell *c4 = createMovR(c2, bsid-1); + buildEquidistant(c4); + mcv2 = coastval(c4); + break; + } + } + if(bugfound) c->item = itSapphire; + if(mcv2 > mcv) mcv2 = mcv; + if(mcv2 == 0) mcv2 = mcv; + c->landparam = mcv2+1; + + /* if(c->heat < 3) + raiseBuggyGeneration(c, "low heat"); */ + + } + } + + if(!c->landparam) { + // int z = int(c->heat); + if(c->item || c->monst) + printf("building coast over %s/%s, mpdist = %d\n", iinf[c->item].name, minf[c->monst].name, + c->mpdist); + if(c->land == laOcean) c->wall = waSea; + } + + if(c->landparam > 30 && c->land == laOcean && !generatingEquidistant && hrand(10) < 5) + buildAnotherEquidistant(c); + } + +void beCIsland(cell *c) { + int i = hrand(3); + if(i == 0) c->wall = waCIsland; + if(i == 1) c->wall = waCIsland2; + if(i == 2) c->wall = waCTree; + return; + } + +void generateTreasureIsland(cell *c) { + if(!euclid) generateAlts(c->master); + if(isOnCIsland(c)) return; + + bool src = hrand(100) < 10; + if(src) { + beCIsland(c); + if(c->wall == waCTree) return; + } + cell* ctab[7]; + int qc = 0, qlo, qhi; + for(int i=0; itype; i++) { + cell *c2 = createMov(c, i); + if((euclid || (c->master->alt && c2->master->alt)) && celldistAlt(c2) < celldistAlt(c)) { + ctab[qc++] = c2; + qlo = i; qhi = i; + while(true) { + qlo--; + c2 = createMovR(c, qlo); + if(!c2->master->alt) break; + if(celldistAlt(c2) >= celldistAlt(c)) break; + ctab[qc++] = c2; + } + while(true) { + qhi++; + c2 = createMovR(c, qhi); + if(!c2->master->alt) break; + if(celldistAlt(c2) >= celldistAlt(c)) break; + ctab[qc++] = c2; + } + break; + } + } + if(!qc) { printf("NO QC\n"); c->wall = waSea; return; } + cell* c2 = createMovR(c, (qlo+qhi)/2); + generateTreasureIsland(c2); + if(!src) { + c->wall = c2->wall; + if(c->wall != waCTree && hrand(100) < 15) + c->wall = (c->wall == waCIsland ? waCIsland2 : waCIsland); + } + if(src && c2->wall == waCTree && (euclid||c->master->alt) && celldistAlt(c) <= -10) { + bool end = true; + for(int i=0; iwall != waCTree) + end = false; + } + // printf("%p: end=%d, qc=%d, dist=%d\n", c, end, qc, celldistAlt(c)); + if(end) c->item = itPirate; + else c->item = itCompass; + } + } + +#define ROCKSNAKELENGTH 50 + +void buildRedWall(cell *c, int gemchance) { + if(c->monst) return; + int ki = kills[moHexSnake] + kills[moRedTroll]; + c->wall = waRed3; + if(hrand(100+ki) < gemchance + ki) + c->item = itRedGem; + if(items[itRedGem] >= 10 && hrand(18000) < gemchance) + c->item = itOrbTelekinesis; + } + +bool generatingYendor = false; +bool yendorPath = false; + +int palaceHP() { + if(items[itPalace] < 3) // 1+2 + return 2; + else if(items[itPalace] < 10) // 1+2+3+4 + return 3; + else if(items[itPalace] < 21) // 1+2+3+4+5+6 + return 4; + else if(items[itPalace] < 35) + return 5; + else if(items[itPalace] < 50) + return 6; + else return 7; + } + +bool havemouse; + +cell *randomDown(cell *c) { + cell *tab[7]; + int q=0; + for(int i=0; itype; i++) + if(c->mov[i] && coastval(c->mov[i]) < coastval(c)) + tab[q++] = c->mov[i]; + if(!q) return NULL; + if(q==1) return tab[0]; + return tab[hrand(q)]; + } + +// which=1 => right, which=-1 => left +// set which=1,bonus=1 to get right neighbor on level + +cell *chosenDown(cell *c, int which, int bonus) { + int d = coastval(c)-1; + for(int i=0; itype; i++) { + if(!c->mov[i]) createMov(c, i); + if(c->mov[i]->mpdist > BARLEV) setdist(c->mov[i], BARLEV, c); + + if(coastval(c->mov[i]) == d) { + int i2 = (i+which+42)%c->type; + if(coastval(c->mov[i2]) == d) + return createMovR(c, i2+bonus); + else return createMovR(c, i+bonus); + } + } + // printf("nothing down here\n"); + return NULL; + } + +int edgeDepth(cell *c) { + if(c->land == laEdge) return coastval(c); + else if(c->land != laBarrier) { + for(int i=0; itype; i++) if(c->mov[i] && c->mov[i]->land == laBarrier) + return -20+c->cpdist; + } + return 0; + } + +int towerval(cell *c) { + if(c->land != laEdge) return 0; + cell *cp1 = chosenDown(c, 1, 1); + if(!cp1) return 0; + /* cell *cp2 = chosenDown(cp1, 1, 1); + if(!cp2) return 0; + cell *cm1 = chosenDown(c, -1, -1); + if(!cm1) return 0; + cell *cm2 = chosenDown(cm1, -1, -1); + if(!cm2) return 0; */ + + /* return + (c->type-6) + + 2*(cp1->type-6) + 4*(cp2->type-6) + + 8*(cm1->type-6) +16*(cm2->type-6); */ + + int under = 0; + for(int i=0; itype; i++) if(c->mov[i]->landparam < c->landparam) + under++; + return (c->type-6) + 2*(cp1->type-6) + 4*under; + } + +int hivehard() { + return items[itRoyalJelly] + 5 * items[itOrbYendor] * (items[itOrbYendor] * 3 - 2); + // 0, 5, 40, 135 + } + +eMonster randomHyperbug() { + int h = hivehard(); + if(hrand(200) < h) + return moBug2; + return eMonster(moBug0 + hrand(BUGCOLORS)); + // 50: 25/25/50 + // 100: + } + +#define RANDPATC(c) (randpattern(c,randompattern[c->land])) +#define RANDPAT (randpattern(c,randompattern[c->land])) +#define RANDPAT3(i) (randpatternMajority(c,i,RANDITER)) +#define RANDPATV(x) (randpattern(c,randompattern[x])) + void setdist(cell *c, int d, cell *from) { DEB("setdist"); + if(buggyGeneration) return; if(signed(c->mpdist) <= d) return; c->mpdist = d; if(d >= BARLEV) { - if(!c->land) c->land = from->land; + if(!c->land && from->land != laElementalWall) c->land = from->land; if(c->land == laTemple) c->land = laRlyeh; + if(c->land == laWhirlpool) c->land = laOcean; if(c->land == laCamelot) c->land = laCrossroads; if(euclid) { @@ -1037,96 +3386,370 @@ void setdist(cell *c, int d, cell *from) { decodeMaster(c->master, x, y); c->land = getEuclidLand(y+2*x); } + if(euclidland == laWhirlpool) { + c->land = laOcean; + c->landparam = 99; + } + if(euclidland == laPrincessQuest) + c->land = laPalace; + if(euclidland == laOcean) { + eucoord x, y; + decodeMaster(c->master, x, y); + int y0 = y; if(y>50000) y0 -= 65536; y0 += 10; + if(y0 == 0) + {c->land = laBarrier; if(ishept(c)) c->land = laRlyeh; } + else if(y0<0) c->land = laRlyeh; + else c->landparam = y0; + } + if(euclidland == laEdge) { + eucoord x, y; + decodeMaster(c->master, x, y); + int y0 = y; if(y>50000) y0 -= 65536; y0 = -y0; y0 -= 5; + if(y0 == 0) + {c->land = laBarrier; if(ishept(c)) c->land = laAlchemist; } + else if(y0<0) c->land = laAlchemist; + else { + c->landparam = y0; + } + } + if(euclidland == laElementalWall) { + eucoord x, y; + decodeMaster(c->master, x, y); + int y0 = y; if(y>32768) y0 -= 65536; + int x0 = x +y/2; + + int id = 0; + if(y0&16) id += 2; + if(x0&16) id += 1; + + x0 += 8; y0 += 8; + + y0--; x0++; + int id2 = 0; + if(y0&16) id2 += 2; + if(x0&16) id2 += 1; + + c->land = eLand(laEFire + id); + + if(((y0&15) == 15 && (x0&1)) || ((x0&15) == 0 && ((y0+1)&1))) { + if(c->land == laEFire) c->wall = waEternalFire; + if(c->land == laEWater) c->wall = waSea; + if(c->land == laEAir) c->wall = waChasm; + if(c->land == laEEarth) c->wall = waStone; + c->barright = c->land; + c->barleft = eLand(laEFire+id2); + c->land = laElementalWall; + } + } + if(euclidland == laCrossroads3) { + eucoord x, y; + decodeMaster(c->master, x, y); + int y0 = y; if(y>32768) y0 -= 65536; + int x0 = x +y/2; + + x0 += 24; y0 += 8; + + int id = 0; + if(y0&16) id ^= 1; + if(x0&16) id ^= 1; + + c->land = id ? laCrossroads3 : laDesert; + + if(((y0&15) == 15 && (x0&1)) || ((x0&15) == 0 && ((y0+1)&1))) { + c->wall = waBarrier; + c->land = laBarrier; + } + } } } - if(d == BARLEV && !euclid) { - - if(c->type == 7 && rand() % 10000 < ( - showoff ? (cwt.c->mpdist > 7 ? 0 : 10000) : - c->land == laCrossroads ? 5000 : 50) && - c->land != laGameBoard) { - - int bd = 2 + (rand() % 2) * 3; - - cellwalker bb(c, bd); - cellwalker bb2 = bb; +#ifndef MOBILE + if(d == BARLEV && c->land == laCanvas) + c->landparam = mapeditor::generateCanvas(c); +#endif - if(checkBarriersFront(bb) && checkBarriersBack(bb2)) { - c->bardir = bd; - eLand oldland = c->land; - eLand newland = getNewLand(oldland); - if(showoff) newland = showlist[(showid++) % 10]; - landcount[newland]++; - - if(bd == 5) c->barleft = oldland, c->barright = newland; - else c->barleft = newland, c->barright = oldland; + if(d == BARLEV && !euclid && c != cwt.c) { + + bool deepOcean = false; + + if(c->land == laOcean) { + if(!from) deepOcean = true; + else for(int i=0; itype; i++) { + cell *c2 = from->mov[i]; + if(c2 && c2->landparam > 30) + deepOcean = true; } } + + if(generatingEquidistant) deepOcean = false; + + if(c->land == laCrossroads2) + buildCrossroads2(c); + + else if(c->type == 7 && hrand(10000) < ( + showoff ? (cwt.c->mpdist > 7 ? 0 : 10000) : + princess::challenge ? 0 : + c->land == laCrossroads3 ? 10000 : + isElemental(c->land) ? 4000 : + c->land == laCrossroads ? 5000 : + c->land == laCaribbean ? 500 : + c->land == laCanvas ? 0 : + c->land == laOcean ? (deepOcean ? 1000 : 0) : + c->land == laEdge ? 0 : + 50)) + { + + int bd = 2 + hrand(2) * 3; + + buildBarrier(c, bd); + + /* int bd = 2; + buildBarrier4(c, bd, 0, getNewLand(c->land), c->land); */ + } - if(c->land == laCrossroads && c->type == 7 && rand() % 2000 < 200 && items[itEmerald] >= 5) { + if(c->land == laCrossroads && c->type == 7 && hrand(2000) < 200 && items[itEmerald] >= 5) { int rtr = newRoundTableRadius(); heptagon *alt = createAlternateMap(c, rtr+14, hsOrigin); if(alt) { - alt->fjordval = rtr; + alt->emeraldval = rtr; } } - if(c->land == laRlyeh && c->type == 7 && rand() % 2000 < 100 && items[itStatue] >= 5) - createAlternateMap(c, 2, hsA); + if(true) { + if(c->land == laRlyeh && c->type == 7 && hrand(2000) < 100 && items[itStatue] >= 5 && !randomPatternsMode) + createAlternateMap(c, 2, hsA); - if(c->bardir != NODIR && c->bardir != NOBARRIERS) - buildBarrier(c); + if(c->land == laOcean && c->type == 7 && hrand(2000) < 500 && deepOcean) + createAlternateMap(c, 2, hsA); + + if(c->land == laCaribbean && c->type == 7) + createAlternateMap(c, 2, hsA); + + if(c->land == laPalace && c->type == 7 && !princess::generating && !shmup::on && + (princess::forceMouse ? (from && from->pathdist != INF) : (hrand(2000) < 20)) && + !c->master->alt && + (princess::challenge || kills[moVizier])) + createAlternateMap(c, 141, hsOrigin, waPalace); + + if(c->bardir != NODIR && c->bardir != NOBARRIERS) + buildBarrier(c); + } } if(d < 10) { explore[d]++; exploreland[d][c->land]++; - if(d < BARLEV) - for(int i=0; itype; i++) { - createMov(c, i); - setdist(c->mov[i], d+1, c); + if(d == BARLEV-2 && c->land == laOcean) { + buildEquidistant(c); + } + + if(d < BARLEV) for(int i=0; itype; i++) { + setdist(createMov(c, i), d+1, c); } - if(d==8 && c->land == laFjord) { + if(d == 8 && c->land == laEdge) { + buildEquidistant(c); + } + + if(d == 8 && c->land == laEdge && !euclid) { + + if(hrand(1000) < 75 && // chosenDown(c, 1, 0)->landflags != 3 && chosenDown(c,-1,0)->landflags != 3 && + (c->landparam&1) ) { + c->landflags = 3; + } + else c->landflags = 0; + } + + if(d == 7 && c->land == laEdge) { + /* if(int(c->landparam) % 5 == 0) + c->wall = waCamelot; + */ + if(euclid) { + eucoord x, y; + decodeMaster(c->master, x, y); + string tab[] = { + ".####...", + "L...L...", + ".L..L...", + "L...L...", + "........", + "........" + }; + int y0 = y; if(y>32768) y0 -= 65536; + + y0 += 5; y0 %= 12; if(y0<0) y0+=12; + + if(y0 >= 6) { y0 -= 6; x += 4; } + + char ch = tab[y0][(x+(y+1)/2)&7]; + + if(ch == '#') + c->wall = waPlatform; + else if(ch == 'L') + c->wall = waLadder; + } + + else if(true) { + + cell *c2 = c; + cell *c3 = c; + + bool rdepths[5]; + for(int i=0; i<5; i++) { + if(coastval(c2) == 0) { + rdepths[i++] = false; + } + else { + cell *c4 = c2; + if(c2 != c3 && !isNeighbor(c2, c3)) { + for(int i=0; itype; i++) if(c2->mov[i] && isNeighbor(c2->mov[i], c3)) + c4 = c2->mov[i]; + } + rdepths[i] = c2 && c3 && c4 && (c2->landflags == 3 || c3->landflags == 3 || c4->landflags == 3); + c2 = chosenDown(c2, 1, 0); + c3 = chosenDown(c3, -1, 0); + } + } + + if(rdepths[3]) { + c->wall = waPlatform; +// if(!c4->item) c4->item = itPalace; + } + else if(!rdepths[2] && !rdepths[4] && !rdepths[1]) { + c2 = c; + c3 = c; + cell *c4 = chosenDown(c, 1, 1); + cell *c5 = chosenDown(c, -1, -1); + for(int i=0; i<3; i++) { + if(coastval(c2) == 0) break; + if(c2 && c4 && c4->landflags == 3 && c2->landflags != 3 && c4 == chosenDown(c2, 1, 1)) + c->wall = waLadder; + if(c3 && c5 && c5->landflags == 3 && c3->landflags != 3 && c5 == chosenDown(c3, -1, -1)) + c->wall = waLadder; + buildEquidistant(c4); buildEquidistant(c5); + if(c2) c2 = chosenDown(c2, 1, 0); + if(c3) c3 = chosenDown(c3, -1, 0); + if(c4) c4 = chosenDown(c4, 1, 0); + if(c5) c5 = chosenDown(c5, -1, 0); + } + } + } + else c->wall = waCIsland; + } + + if(d == 9 && c->land == laPalace) { + +/* ELEMENTAL: + items[itOrbGhost] = 999; + int h = fiftyval(c); + eWall colorwalls[8] = { + waNone, waSea, waCIsland, waFloorA, waColumn, waDryTree, waChasm, waMirror + }; + c->wall = colorwalls[h&7]; +*/ + + if(cdist50(c) == 3 && polarb50(c) == 1) + c->wall = waPalace; + } + + if(d == 8 && c->land == laPalace) { + + // note: Princess Challenge brings back the normal Palace generation + bool lookingForPrincess = !euclid && c->master->alt && !princess::challenge; + + if(cdist50(c) == 3 && polarb50(c) == 1) { + int q = 0, s = 0; + if(!ishept(c)) for(int i=0; i<6; i++) + if(cdist50(c->mov[i]) == 3 && polarb50(c->mov[i]) == 1 && !ishept(c->mov[i])) + q++, s += i; + if(q == 1 && c->mov[s]->land == laPalace) { + switch(princess::generating ? 0 : hrand(2)) { + case 0: + c->wall = waClosedGate; + c->mov[s]->wall = waClosedGate; + break; + case 1: + c->wall = waOpenGate; + c->mov[s]->wall = waOpenGate; + break; + } + } + } + else if((hrand(100) < (lookingForPrincess ? 7 : 5) && cdist50(c)) || + (cdist50(c) == 0 && polarb50(c) && hrand(100) < 60)) { + c->wall = hrand(100) < (lookingForPrincess ? 30:50) ? waClosePlate : waOpenPlate; + } + else if(hrand(100) < (lookingForPrincess ? 3 : 5)) + c->wall = waTrapdoor; + } + + if(d==8 && c->land == laEmerald) { + if(randomPatternsMode) + c->wall = RANDPAT3(0) ? waCavewall : waCavefloor; + else if(euclid) { eucoord x, y; decodeMaster(c->master, x, y); if(((y-2)&7) < 4) c->wall = waCavewall; else c->wall = waCavefloor; } else { - int v = fjordval(c); + int v = emeraldval(c); if((v&3) >= 2) c->wall = waCavewall; else c->wall = waCavefloor; } } + if(d == 8 && isIcyLand(c)) c->landparam = 0; + if(d == 8 && c->land == laDryForest) c->landparam = 0; + if(d==8 && c->land == laPower) { int v; - if(euclid) { + if(randomPatternsMode) + v = RANDPAT ? 24 : 0; + else if(euclid) { eucoord x, y; decodeMaster(c->master, x, y); int y0 = ((short)y) % 6; if(y0<0) y0+=6; if(y0 == 3 || y0 == 4) v=24; else v=0; } - else v = fjordval(c); + else v = emeraldval(c); v &= ~3; if((v == 24 || v == 32 || v == 56)) - c->wall = waBonfire, c->tmp = 9; - else if(rand() % 100 < 10) { + c->wall = waEternalFire; + else if(hrand(100) < 10) { c->wall = waGlass; - eItem protectedItems[17] = { + eItem protectedItems[18] = { itPower, itPower, itPower, itPower, itPower, itPower, itOrbLightning, itOrbLightning, itOrbThorns, itOrbThorns, itOrbInvis, itOrbInvis, itOrbShield, itOrbTeleport, itOrbPsi, - itOrbDragon, itOrbIllusion + itOrbDragon, itOrbIllusion, itOrbPreserve }; - c->item = protectedItems[rand() % 17]; + c->item = protectedItems[hrand(18)]; + } + } + + if(d==8 && c->land == laZebra) { + if(euclid) { + eucoord x, y; + decodeMaster(c->master, x, y); + if(y&1) c->wall = waTrapdoor; + else c->wall = waNone; + } + else + c->wall = (randomPatternsMode ? RANDPAT : (zebra40(c)&2)) ? waTrapdoor : waNone; + } + + if(d==8 && isElemental(c->land)) { + if(hrand(c->land == laEAir ? 6 : 25) == 0) { + if(c->land == laEFire) c->wall = waEternalFire; + else if(c->land == laEWater) c->wall = waSea; + else if(c->land == laEAir) c->wall = waChasm; + else if(c->land == laEEarth) c->wall = waStone; } } @@ -1138,9 +3761,10 @@ void setdist(cell *c, int d, cell *from) { if(dy == 1) c->wall = waVinePlant; } else { - int v = fjordval(c); + int v = emeraldval(c); int w = v / 4; - if(w == 9 || w == 10 || w == 7 || w == 8) { + if(randomPatternsMode) c->wall = RANDPAT ? waVinePlant : waNone; + else if(w == 9 || w == 10 || w == 7 || w == 8) { c->wall = waVinePlant; } else if(v == 24 || v == 58 || v == 26 || v == 56) @@ -1165,73 +3789,95 @@ void setdist(cell *c, int d, cell *from) { // if(c->land == laIce && ((celldist(c) % 10) + 10) % 10 == 5) // c->wall = waColumn; - if(c->land == laIce) if(rand() % 100 < 5 && c->wall != waBarrier) { - c->wall = waIcewall; - for(int i=0; itype; i++) if(rand() % 100 < 50) { - createMov(c, i); - setdist(c->mov[i], d+1, c); - cell *c2 = c->mov[i]; - if(c2->wall == waBarrier || c2->land != laIce) continue; - c2->wall = waIcewall; - for(int j=0; jtype; j++) if(rand() % 100 < 20) { - createMov(c2, j); - setdist(c->mov[i], d+2, c); - cell *c3 = c2->mov[j]; - if(c3->wall == waBarrier || c3->land != laIce) continue; - c3->wall = waIcewall; + if(c->land == laIce) { + if(randomPatternsMode) c->wall = RANDPAT ? waIcewall : waNone; + else if(hrand(100) < 5 && c->wall != waBarrier) { + c->wall = waIcewall; + for(int i=0; itype; i++) if(hrand(100) < 50) { + cell *c2 = createMov(c, i); + setdist(c2, d+1, c); + if(c2->wall == waBarrier || c2->land != laIce) continue; + c2->wall = waIcewall; + for(int j=0; jtype; j++) if(hrand(100) < 20) { + cell *c3 = createMov(c2, j); + setdist(c->mov[i], d+2, c); + if(c3->wall == waBarrier || c3->land != laIce) continue; + c3->wall = waIcewall; + } } } } - if(c->land == laIce || c->land == laCocytus) if(c->wall == waIcewall && items[itDiamond] >= 5 && rand() % 200 == 1) - c->wall = waBonfire, c->tmp = -1;; + if(c->land == laIce || c->land == laCocytus) if(c->wall == waIcewall && items[itDiamond] >= 5 && hrand(200) == 1) + c->wall = waBonfireOff; if(c->land == laCaves) - c->wall = rand() % 100 < 55 ? waCavewall : waCavefloor; + c->wall = (randomPatternsMode ? RANDPAT3(1) : hrand(100) < 55) ? waCavewall : waCavefloor; + + if(c->land == laLivefjord) { + int die = (randomPatternsMode ? (RANDPAT3(2)?100:0) : hrand(100)); + if(die < 50) + c->wall = waSea; + else + c->wall = waNone; + } if(c->land == laDeadCaves) { - int i = rand() % 100; - if(i<50) c->wall = waDeadwall; - else if(i<55) c->wall = waDeadfloor2; + int die = (randomPatternsMode ? (RANDPAT?100:0) : hrand(100)); + if(die<50) c->wall = waDeadwall; + else if(die<55) c->wall = waDeadfloor2; else c->wall = waDeadfloor; } if(c->land == laAlchemist) - c->wall = rand() % 2 ? waFloorA : waFloorB; + c->wall = (randomPatternsMode ? RANDPAT : hrand(2)) ? waFloorA : waFloorB; - if(c->land == laDryForest) - c->wall = rand() % 100 < 50 ? (rand() % 100 < 50 ? waDryTree : waWetTree) : - waNone; + if(c->land == laDryForest) { + if(randomPatternsMode) + c->wall = RANDPAT ? waNone : RANDPATV(laHell) ? waDryTree : waWetTree; + else + c->wall = + (hrand(100) < 50) ? (hrand(100) < 50 ? waDryTree : waWetTree) : waNone; + } - if(c->land == laGraveyard && ishept(c)) - c->wall = rand() % 5 ? waAncientGrave : waFreshGrave; + if(c->land == laGraveyard) { + if(randomPatternsMode) + c->wall = RANDPAT ? ((RANDPATV(laCrossroads) || RANDPATV(laCrossroads2)) ? waAncientGrave : waFreshGrave) : waNone; + else if(ishept(c)) + c->wall = hrand(5) ? waAncientGrave : waFreshGrave; + } if(c->land == laRlyeh) { - if(rand() % 500 < 5) { - for(int i=0; itype; i++) { - createMov(c, i); - setdist(c->mov[i], d+1, c); - if(c->mov[i] && c->mov[i]->land == laRlyeh) - c->mov[i]->wall = waColumn; - } - - for(int j=0; j<2; j++) { - int i = rand() % c->type; - if(c->mov[i] && c->mov[i]->land == laRlyeh) - c->mov[i]->wall = waNone; - } + if(randomPatternsMode) { + c->wall = RANDPAT ? waColumn : waNone; + } + else { + if(hrand(500) < 5) { + for(int i=0; itype; i++) { + cell *c2 = createMov(c, i); + setdist(c2, d+1, c); + if(c2 && c2->land == laRlyeh) + c2->wall = waColumn; + } + + for(int j=0; j<2; j++) { + int i = hrand(c->type); + if(c->mov[i] && c->mov[i]->land == laRlyeh) + c->mov[i]->wall = waNone; + } + } + if(ishept(c) && hrand(2)) c->wall = waColumn; } - if(ishept(c) && rand() % 2) c->wall = waColumn; } if(c->land == laHell) { - if(rand() % 100 < 4) { + if(hrand(1000) < 36) { for(int i=0; itype; i++) { - createMov(c, i); - setdist(c->mov[i], d+1, c); - if(c->mov[i] && c->mov[i]->land == laHell) - if(c->mov[i]->wall != waSulphurC) - c->mov[i]->wall = waSulphur; + cell *c2 = createMov(c, i); + setdist(c2, d+1, c); + if(c2 && c2->land == laHell) + if(c2->wall != waSulphurC) + c2->wall = waSulphur; } c->wall = waSulphurC; @@ -1240,24 +3886,29 @@ void setdist(cell *c, int d, cell *from) { if(c->land == laCocytus) { if(c->wall == waNone) c->wall = waFrozenLake; - if(rand() % 100 < 5) { + if(hrand(100) < 5) { for(int i=0; itype; i++) { - createMov(c, i); - setdist(c->mov[i], d+1, c); - if(c->mov[i] && c->mov[i]->land == laCocytus) - c->mov[i]->wall = waLake; + cell *c2 = createMov(c, i); + setdist(c2, d+1, c); + if(c2 && c2->land == laCocytus) + c2->wall = waLake; } c->wall = waLake; - if(rand() % 500 < 100 + 2 * (items[itSapphire])) + if(hrand(500) < 100 + 2 * (items[itSapphire])) c->monst = moShark; } } - if(isHive(c->land) && rand() % 2000 < 2) + if(isHive(c->land) && hrand(2000) < 2) createBugArmy(c); + if(c->land == laPalace && !euclid && c->master->alt) { + int d = celldistAlt(c); + if(d <= 150) generateAlts(c->master); + } + if((c->land == laCrossroads && !euclid) || c->land == laCamelot) if(euclid || c->master->alt) { int d = celldistAltRelative(c); @@ -1265,7 +3916,7 @@ void setdist(cell *c, int d, cell *from) { eucoord x,y; decodeMaster(c->master, x, y); } - if(d <= 14) { + if(d <= 14 && roundTableRadius(c) > 20) { if(!euclid) generateAlts(c->master); c->bardir = NOBARRIERS; int d = celldistAltRelative(c); @@ -1291,13 +3942,13 @@ void setdist(cell *c, int d, cell *from) { } if(d == 0) c->wall = waRoundTable; if(celldistAlt(c) == 0) c->item = itHolyGrail; - if(d < 0 && rand() % 7000 <= 10 + items[itHolyGrail] * 5) { + if(d < 0 && hrand(7000) <= 10 + items[itHolyGrail] * 5) { eMonster m[3] = { moHedge, moLancer, moFlailer }; - c->monst = m[rand() % 3]; + c->monst = m[hrand(3)]; } if(d == 1) { // roughly as many knights as table cells - if(rand() % 1720 < 1000) + if(hrand(1720) < 1000) c->monst = moKnight; if(!euclid) for(int i=0; i<7; i++) generateAlts(c->master->move[i]); for(int i=0; itype; i++) @@ -1332,18 +3983,52 @@ void setdist(cell *c, int d, cell *from) { } } } + + if(c->land == laOcean || c->land == laWhirlpool) { + if(euclid || (c->master->alt && c->master->alt->distance <= 2)) { + if(!euclid) generateAlts(c->master); + c->bardir = NOBARRIERS; + int dd = celldistAlt(c); + if(dd <= 0) { + c->land = laWhirlpool, c->wall = waSea, c->monst = moNone, c->item = itNone; + } + } + } - if(isHive(c->land) && rand() % 2000 < 100 && !c->wall && !c->item && !c->monst) { + if(c->land == laCaribbean) { + if(!euclid) { + if(c->master->alt && c->master->alt->distance <= 2) { + if(!euclid) generateAlts(c->master); + c->bardir = NOBARRIERS; + int d = celldistAlt(c); + if(d <= 0) + // c->wall = waChasm; + generateTreasureIsland(c); + else + c->wall = waSea; + } + else c->wall = waSea; + } + else { + int d = celldistAlt(c); + if(d <= 0) + generateTreasureIsland(c); + else + c->wall = waSea; + } + } + + if(isHive(c->land) && hrand(2000) < 100 && !c->wall && !c->item && !c->monst) { int nww = 0; for(int i=0; itype; i++) if(c->mov[i] && c->mov[i]->wall == waWaxWall) nww++; if(nww == 0) { c->wall = waWaxWall; c->monst = moNone; - c->heat = rand() & 0xFFFFFF; + c->landparam = rand() & 0xFFFFFF; } /* for(int i=0; itype; i++) { - if(rand() % 6 < 5) { + if(hrand(6) < 5) { createMov(c,i); cell *c2 = c->mov[i]; c2->wall = waWaxWall; @@ -1353,37 +4038,149 @@ void setdist(cell *c, int d, cell *from) { } if(c->land == laDesert) { - if(rand() % 100 < 5) { - for(int i=0; itype; i++) { - createMov(c, i); - setdist(c->mov[i], d+1, c); - if(c->mov[i] && c->mov[i]->land == laDesert) - c->mov[i]->wall = waDune; - } - - for(int j=0; j<2; j++) { - int i = rand() % c->type; - if(c->mov[i] && c->mov[i]->land == laDesert) - c->mov[i]->wall = waNone; + if(randomPatternsMode) + c->wall = RANDPAT ? waDune : waNone; + else { + if(hrand(100) < 5) { + for(int i=0; itype; i++) { + cell *c2 = createMov(c, i); + setdist(c2, d+1, c); + if(c2 && c2->land == laDesert) + c2->wall = waDune; + } + + for(int j=0; j<2; j++) { + int i = hrand(c->type); + if(c->mov[i] && c->mov[i]->land == laDesert) + c->mov[i]->wall = waNone; + } } } + + if(hrand(300) == 1 && items[itSpice] >= 5) c->wall = waThumperOff; + } - if(rand() % 300 == 1 && items[itSpice] >= 5) - c->wall = waThumper, c->tmp = -1; + if(c->land == laRedRock) { + if(randomPatternsMode) { + c->wall = waNone; + if(!ishept(c)) { if(RANDPAT) buildRedWall(c, 20); } + else { + int k = 0; + for(int i=0; i<20; i++) + if(RANDPATC(c->mov[i%7]) && !RANDPATC(c->mov[(i+1)%7])) + k++; + if(k>=4) buildRedWall(c, 20); + } + } + else if(ishept(c) && hrand(100) < 8 && !c->monst) { + buildRedWall(c, 80); + int i = hrand(7); + buildRedWall(createMovR(c, i), 33); + if(hrand(2) == 0) + buildRedWall(createMovR(createMovR(c, i), c->spn[i]+(hrand(2)?2:4)), 20); + i += 3 + hrand(2); + if(hrand(6) < 4) + buildRedWall(createMovR(c, i), 33); + if(hrand(2) == 0) + buildRedWall(createMovR(createMovR(c, i), c->spn[i]+(hrand(2)?2:4)), 20); + } } } - if(d == 7 && c->land == laCaves && c->wall == waCavewall && rand() % 5000 < items[itGold]) + if(d == 8 && c->land == laCaribbean && !euclid) { + int mindist = 9; + for(int i=0; itype; i++) { + cell *c2 = c->mov[i]; + if((euclid || c2->master->alt) && celldistAlt(c2) < mindist) + mindist = celldistAlt(c2); + } + if(mindist == 0) beCIsland(c); + } + + if(d == 7 && c->land == laRedRock && c->wall == waNone && hrand(1000) == 0) + buildPrizeMirror(c); + + if(d == 7 && c->land == laCaribbean && c->wall == waSea) { + bool coast = false; + for(int i=0; itype; i++) { + cell *c2 = c->mov[i]; + if(passable(c2, c, false, false, false) && c2->wall != waBoat) coast = true; + } + if(coast && hrand(10) < 5) { + c->wall = waBoat; + if(items[itPirate] >= 10 && hrand(100) < 2) + c->item = itOrbPreserve; + else if(hrand(100) < 2*PRIZEMUL) + placePrizeOrb(c); + } + } + + if(d == 7 && c->land == laCaves && c->wall == waCavewall && hrand(5000) < items[itGold]) c->monst = moSeep; - if(d == 7 && c->land == laFjord && c->wall == waCavewall && rand() % 5000 < items[itEmerald]) + if(d == 7 && c->land == laLivefjord && c->wall == waSea && hrand(5000) < 15 + items[itFjord]) { + if(items[itFjord] >= 5 && hrand(100) < 20) + c->monst = moWaterElemental; + else { + c->monst = moViking; + c->wall = waBoat; + } + } + + if(d == 7 && c->land == laLivefjord && hrand(2000) < 50 + kills[moViking] && notDippingFor(itFjord)) { + c->item = itFjord; + } + + if(d == 7 && c->land == laLivefjord && items[itFjord] >= 10 && hrand(2000) < 2) + c->item = itOrbFish; + + if(d == 7 && c->land == laLivefjord && hrand(2000) < 2*PRIZEMUL) + placePrizeOrb(c); + + if(d == 7 && c->land == laLivefjord && hrand(2000) < 2) + buildPrizeMirror(c); + + if(d == 7 && c->land == laEmerald && c->wall == waCavewall && hrand(5000) < items[itEmerald]) c->monst = moSeep; - if(d == 7 && c->land == laDeadCaves && c->wall == waDeadwall && rand() % 1000 < items[itSilver]) + if(d == 7 && c->land == laDeadCaves && c->wall == waDeadwall && hrand(1000) < items[itSilver]) c->monst = moSeep; - if(d == 7 && c->wall == waVinePlant && rand() % 100 < 10) + if(d == 7 && c->wall == waVinePlant && hrand(100) < (randomPatternsMode ? 2 : 10)) c->monst = moVineSpirit; + + if(d == 7 && c->land == laOcean && !safety) { + if(c->landparam >= 1 && c->landparam <= 25) { + if(hrand(1000) < 5) + c->wall = waBoat; + if(hrand(1000) < 50 + kills[moAlbatross]/2) + c->item = itCoast; + if(hrand(15000) < 10 + 2 * items[itCoast]) + c->monst = moAlbatross; + if(items[itCoast] >= 10 && hrand(10000) < 5) + c->item = itOrbAir; + if(hrand(10000) < 5*PRIZEMUL) + placePrizeOrb(c); + if(hrand(10000) < 5) + buildPrizeMirror(c); + } + else if(c->landparam > 25) { + if(hrand(30000) < 10) { + c->wall = waBoat; + c->monst = moPirate; + // orbs are possible! + placeOceanOrbs(c); + } + else if(hrand(30000) < 10) + c->monst = moCShark; + } + } + + if(d == 7 && c->land == laCaribbean && c->wall == waSea && hrand(10000) < 20 + items[itPirate]) + c->monst = moCShark; + + if(d == 7 && c->wall == waCTree && hrand(5000) < 100 + items[itPirate]) + c->monst = moParrot; // repair the buggy walls flowing in from another land, like ice walls flowing into the Caves if(d == 7 && c->land == laCaves && c->wall != waCavewall && c->wall != waCavefloor) @@ -1399,6 +4196,44 @@ void setdist(cell *c, int d, cell *from) { if(d == 7 && c->land == laAlchemist && c->wall != waFloorA && c->wall != waFloorB) c->wall = waFloorA; + if(d == 3 && c->land == laMinefield && safety && c->wall == waMineMine) + c->wall = waMineOpen; + + if(d == 7 && c->land == laMinefield) { + c->wall = waMineUnknown; + // 250: rare mines + // 1250: at 25 + int minefreq = 0; + int treas = items[itBombEgg]; + if(treas <= 10) minefreq = 250 + 30 * treas; + if(treas <= 110) minefreq = 550 + 10 * (treas-10); + else minefreq = 1550 + (treas - 110); + + // experimentation says that 600 is slightly too hard to find the Orb of Yendor + if(generatingYendor || yendorPath) + if(minefreq < 550) + minefreq = 550; + + int tfreq = + treas < 10 ? 50 + 5 * treas : + treas < 25 ? 100 + (treas-10) * 2: + treas < 50 ? 150 + (treas-25) : + 175; + + if(hrand(5000) < minefreq) + c->wall = waMineMine; + else if(hrand(5000) < tfreq && !safety) { + c->item = itBombEgg; + c->landparam = items[itBombEgg] + 5 + hrand(11); + } + else if(hrand(5000) < treas - 20 + items[itOrbYendor] * 5 && !safety) + c->monst = moBomberbird; + else if(treas >= 10 && hrand(5000) < 10 && !safety) + c->item = itOrbFriend; + else if(hrand(5000) < 10*PRIZEMUL && !safety) + placePrizeOrb(c); + } + if(d == 7 && c->wall == waIcewall && c->land != laIce && c->land != laCocytus) c->wall = waNone; @@ -1410,6 +4245,10 @@ void setdist(cell *c, int d, cell *from) { chasmifyEarth(c); } + if(d == 7 && c->wall == waElementalD) { + chasmifyElemental(c); + } + // seal entrances to the Land of Power. if(d == 7 && c->land == laPower && c->type == 7) { bool onwall = false; @@ -1419,37 +4258,144 @@ void setdist(cell *c, int d, cell *from) { cell *c2 = c->mov[i]; cell *c3 = c2->mov[(c->spn[i] + 3) % 6]; if(c3->land != laPower && c3->land != laBarrier) - if(c2->wall != waBonfire && c2->wall != waGlass) { - if(c->wall == waBonfire) c->monst = moWitchWinter; + if(c2->wall != waFire && c2->wall != waGlass) { + if(c->wall == waFire) c->monst = moWitchWinter; else if(c->wall == waGlass) c->monst = moWitchGhost; else c->monst = moEvilGolem; } } } - if(d == 7 && passable(c, NULL, false, false)) { + if(d == 7 && passable(c, NULL, false, false, false)) { if(c->land == laBarrier) c->wall = waBarrier; + if(c->land == laOceanWall) c->wall = c->type == 7 ? waBarrier : waSea; } - if(d == 7 && passable(c, NULL, false, false) && !safety) { + if(d == 7 && c->land == laWhirlpool) + whirlGenerate(c); + + if(c->land == laPalace && princess::generating) { + // no Opening Plates nearby + if(d <= 7 && c->wall == waOpenPlate) + c->wall = waNone; + // no monsters nearby + if(d>0) c->monst = moNone; + // no Plates or Trapdoors in the Princess cell + if(d < 3 && (c->wall == waClosePlate || c->wall == waOpenPlate || c->wall == waTrapdoor)) + c->wall = waNone; + if(d > 1) c->item = itNone; + // the Princess herself + if(d == 0) { + c->monst = moPrincess; + c->hitpoints = palaceHP(); + c->wall = waGiantRug; + cell *c2 = NULL; + for(int i=0; itype; i++) { + cellwalker cw(c, i); + cwstep(cw); + cwspin(cw, 4); + cwstep(cw); + cwspin(cw, 2); + cwstep(cw); + cwspin(cw, 4); + cwstep(cw); + cwspin(cw, 2 + hrand(3)); + cwstep(cw); + if(!c2) c2 = cw.c; + else if(celldist(cw.c) > celldist(c2)) c2 = cw.c; + cw.c->monst = moMouse; + } + c2->wall = waOpenPlate; + } + + } + + if(d == 7 && passable(c, NULL, false, false, false) && !safety) { int hard = items[itOrbYendor] * 5; + if(c->land == laEdge) { + if(hrand(20000) < 20 + items[itEdge]) { + if(cellEdgeUnstable(c)) + c->monst = moGargoyle; + else + c->monst = moEdgeMonkey; + } + else if(c->landparam >= 14 && hrand(2000) < 50+kills[moGargoyle]+kills[moEdgeMonkey] && !cellEdgeUnstable(c) ) { + c->item = itEdge; + } + } + if(c->land == laIce) { - if(rand() % 5000 < 100 + 2 * (kills[moYeti] + kills[moWolf]) && notDippingFor(itDiamond)) + if(hrand(5000) < 100 + 2 * (kills[moYeti] + kills[moWolf]) && notDippingFor(itDiamond)) c->item = itDiamond; - if(rand() % 8000 < 2 * (items[itDiamond] + hard)) - c->monst = rand() % 2 ? moYeti : moWolf; + if(hrand(8000) < 2 * (items[itDiamond] + hard)) + c->monst = hrand(2) ? moYeti : moWolf; + } + if(c->land == laPalace) { + bool lookingForPrincess0 = !euclid && c->master->alt; + bool lookingForPrincess = lookingForPrincess0 && !princess::challenge; + int hardness = lookingForPrincess ? 5 : items[itPalace] + hard; + + if(hrand(5000) < 100 + 2 * (kills[moPalace] + kills[moFatGuard] + kills[moVizier] + kills[moSkeleton]) && notDippingFor(itPalace) && + c->wall != waOpenGate && !lookingForPrincess0) + c->item = itPalace; + if(items[itPalace] >= 10 && hrand(5000) < 16 && c->wall != waOpenGate) + c->item = hrand(100) < 80 ? itOrbFrog : itOrbDiscord; + if(hrand(5000) < 20*PRIZEMUL && c->wall != waOpenGate) + placePrizeOrb(c); + if(hrand(5000) < 20 && c->wall == waNone) + buildPrizeMirror(c); + if(c->land == laPalace && (euclid || c->master->alt) && celldistAlt(c) <= 150 && !havemouse && !princess::generating && + (euclid || (princess::getPrisonInfo(c)->bestdist < 6 && princess::getPrisonInfo(c)->princess))) { + c->monst = moMouse; + addMessage(XLAT("You hear a distant squeak!")); + drawFlash(c); +/* { + cell *c2= c; + z: + c2->item = itPirate; + printf("AT %p\n", c2); + for(int i=0; itype; i++) if(c2->mov[i] && c2->mov[i]->mpdist < c2->mpdist) { + c2 = c2->mov[i]; + goto z; + } + } */ + havemouse = true; + } + else if(hrand(15000) < 10 + hardness) { + c->monst = moPalace; + c->hitpoints = palaceHP(); + if(hrand(10 + items[itPalace]) >= 14 && !lookingForPrincess) + c->monst = moSkeleton; + } + else if(hrand(20000) < hardness) { + c->monst = moFatGuard; + c->hitpoints = palaceHP(); + } + else if(hrand(20000) < hardness - 7) { + c->monst = moVizier; + c->hitpoints = palaceHP(); + } + else if(princess::forceVizier && from->pathdist != INF) { + c->monst = moVizier; + c->hitpoints = palaceHP(); + princess::forceVizier = false; + } } if(c->land == laCaves) { - if(rand() % 5000 < 100 + 2 * (kills[moTroll] + kills[moGoblin]) && notDippingFor(itGold)) + if(hrand(5000) < 100 + 2 * min(kills[moTroll] + kills[moGoblin], 150) && notDippingFor(itGold)) c->item = itGold; - if(rand() % 8000 < 10 + 2 * (items[itGold] + hard)) - c->monst = rand() % 2 ? moTroll : moGoblin; + if(hrand(8000) < 10 + 2 * (items[itGold] + hard)) + c->monst = hrand(2) ? moTroll : moGoblin; + } + if(c->land == laLivefjord) { + if(hrand(16000) < 10 + 2 * (items[itFjord] + hard)) + c->monst = moFjordTroll; } if(c->land == laDeadCaves) { - if(rand() % 5000 < 100 + 2 * (kills[moDarkTroll] + kills[moEarthElemental]) && notDippingFor(itSilver)) + if(hrand(5000) < 100 + 2 * (kills[moDarkTroll] + kills[moEarthElemental]) && notDippingFor(itSilver)) c->item = itSilver; - if(rand() % 16000 < (items[itSilver] + hard)) { + if(hrand(16000) < (items[itSilver] + hard)) { c->monst = moEarthElemental; for(int i=0; itype; i++) { cell *c2 = c->mov[i]; @@ -1458,111 +4404,161 @@ void setdist(cell *c, int d, cell *from) { for(int i=0; itype; i++) if(c->mov[i]->mpdist < c->mpdist) c->mondir = i; chasmifyEarth(c); c->wall = waDeadfloor2; } - else if(rand() % 8000 < 60 + 8 * (items[itSilver] + hard)) { - if(rand() % 100 < 25) { + else if(hrand(8000) < 60 + 8 * (items[itSilver] + hard)) { + if(hrand(100) < 25) { } - else c->monst = rand() % 2 ? moDarkTroll : moGoblin; + else c->monst = hrand(2) ? moDarkTroll : moGoblin; } } if(c->land == laDesert) { - if(rand() % 5000 < 100 + 2 * (kills[moWorm] + kills[moDesertman]) && notDippingFor(itSpice)) + if(hrand(5000) < 100 + 2 * (kills[moWorm] + kills[moDesertman]) && notDippingFor(itSpice)) c->item = itSpice; - if(rand() % 8000 < 10 + 2 * (items[itSpice] + hard)) - c->monst = rand() % 2 ? moWorm : moDesertman, + if(hrand(8000) < 10 + 2 * (items[itSpice] + hard)) + c->monst = hrand(2) ? moWorm : moDesertman, + c->mondir = NODIR; + } + if(c->land == laRedRock) { + if(hrand(16000) < 30+items[itRedGem] && !ishept(c)) { + int i = -1; + for(int t=0; t<6; t++) if(c->mov[t]->mpdist > c->mpdist && !ishept(c->mov[t])) + i = t; + if(i != -1) { + c->monst = moHexSnake; + c->bardir = NOBARRIERS; + int len = ROCKSNAKELENGTH; + cell *c2 = c; + while(--len) { + c2->bardir = NOBARRIERS; + c2->mondir = i; + createMov(c2, i); + int j = c2->spn[i]; + c2 = c2->mov[i]; + c2->monst = moHexSnakeTail; + if(c2->bardir != NODIR) return; + i = (j + (len%2 ? 2 : 4)) % 6; + } + c2->mondir = NODIR; + } + } + else if(hrand(16000) < 50+items[itRedGem] && !ishept(c)) + c->monst = moRedTroll, c->mondir = NODIR; } if(c->land == laWineyard) { - if(rand() % 5000 < 100 + 2 * (kills[moVineBeast] + kills[moVineSpirit]) && notDippingFor(itWine)) + if(hrand(5000) < 100 + 2 * (kills[moVineBeast] + kills[moVineSpirit]) && notDippingFor(itWine)) c->item = itWine; - if(rand() % 8000 < 12 * (items[itWine] + hard)) + if(hrand(8000) < 12 * (items[itWine] + hard)) c->monst = moVineBeast; } - if(c->land == laFjord) { - if(rand() % 1000 < 100 + 2 * (kills[moMiner] + kills[moLancer] + kills[moFlailer]) && notDippingFor(itEmerald)) { + if(c->land == laZebra) { + if(c->wall == waNone && hrand(2500) < 100 + 2 * (kills[moOrangeDog]) && notDippingFor(itZebra)) + c->item = itZebra; + if(hrand(10000) < 40 + 2*(items[itZebra] + hard)) + c->monst = moOrangeDog; + } + if(isElemental(c->land) && c->land != laElementalWall) { + eItem localshard = eItem(itFireShard + (c->land - laEFire)); + int danger = 5 * items[localshard] * items[localshard]; + eMonster elof = elementalOf(c->land); + int elkills = kills[elof]; + + if(hrand(8000) < 12 + (items[itElemental] + danger + hard)) { + c->monst = elof; + if(c->land != laEAir) chasmifyElemental(c); + c->wall = waNone; + if(c->land == laEWater) c->wall = waSea; + } + else if(hrand(5000) < 100 + elkills*3 && notDippingFor(itElemental)) + c->item = localshard; + else if(hrand(5000) < 10 && items[itElemental] >= 10) + c->item = itOrbSummon; + else if(hrand(5000) < 10*PRIZEMUL) + placePrizeOrb(c); + } + if(c->land == laEmerald) { + if(hrand(1000) < 100 + 2 * (kills[moMiner] + kills[moLancer] + kills[moFlailer]) && notDippingFor(itEmerald)) { // do not destroy walls! bool ok = true; for(int i=0; itype; i++) if(c->mov[i]->wall == waCavewall) ok = false; if(ok) c->item = itEmerald; } - if(rand() % 8000 < 50 + 10 * (items[itEmerald] + hard)) { - static eMonster fjordmonsters[4] = { moHedge, moLancer, moFlailer, moMiner }; - c->monst = fjordmonsters[rand() % 4]; + if(hrand(8000) < 50 + 10 * (items[itEmerald] + hard)) { + static eMonster emeraldmonsters[4] = { moHedge, moLancer, moFlailer, moMiner }; + c->monst = emeraldmonsters[hrand(4)]; } } if(c->land == laJungle) { - if(rand() % 5000 < 25 + 2 * (kills[moIvyRoot] + kills[moMonkey]) && notDippingFor(itRuby)) + if(hrand(5000) < 25 + 2 * (kills[moIvyRoot] + kills[moMonkey]) && notDippingFor(itRuby)) c->item = itRuby; - if(rand() % 15000 < 5 + 1 * (items[itRuby] + hard)) + if(hrand(15000) < 5 + 1 * (items[itRuby] + hard)) c->monst = moMonkey; - else if(rand() % 80000 < 5 + items[itRuby] + hard) + else if(hrand(80000) < 5 + items[itRuby] + hard) c->monst = moEagle; - else if(ishept(c) && rand() % 4000 < 300 + items[itRuby]) { - bool hard = rand() % 100 < 25; + else if(ishept(c) && hrand(4000) < 300 + items[itRuby]) { + bool hard = hrand(100) < 25; if(hard ? buildIvy(c, 1, 9) : buildIvy(c, 0, c->type)) c->item = itRuby; } } if(c->land == laAlchemist) { - if(rand() % 5000 < 25 + min(kills[moSlime], 200) && notDippingFor(itElixir)) + if(hrand(5000) < 25 + min(kills[moSlime], 200) && notDippingFor(itElixir)) c->item = itElixir; - else if(rand() % 3500 < 10 + items[itElixir] + hard) + else if(hrand(3500) < 10 + items[itElixir] + hard) c->monst = moSlime; } if(c->land == laPower) { - if(rand() % (5000+50*items[itPower]) < 1200) { + if(hrand(5000+50*items[itPower]) < 1200) { eItem powerorbs[6] = { itOrbFlash, itOrbSpeed, itOrbFire, itOrbWinter, itOrbGhost, itOrbLife}; - c->item = powerorbs[rand() % 6]; + c->item = powerorbs[hrand(6)]; } - else if(c->type == 6 && rand() % 5000 < 10) - c->wall = rand() % 2 ? waMirror : waCloud; - else if(rand() % 1000 < 10 + (items[itPower] ? 10:0) + (items[itPower] + hard)) - c->monst = eMonster(moWitch + rand() % NUMWITCH); + else if(c->type == 6 && hrand(5000) < 10) + c->wall = hrand(2) ? waMirror : waCloud; + else if(hrand(1000) < 10 + (items[itPower] ? 10:0) + (items[itPower] + hard)) + c->monst = eMonster(moWitch + hrand(NUMWITCH)); } - if(c->land == laCrossroads) { - if(c->type == 6 && rand() % 8000 < 120 && items[itShard] >= 10) - c->wall = rand() % 2 ? waMirror : waCloud; - else if(hyperstonesUnlocked() && rand() % 5000 < tkills() && notDippingFor(itHyperstone)) - c->item = itHyperstone; - else if(rand() % 4000 < items[itHyperstone] + 2 * items[itHolyGrail]) { - // only interesting monsters here! - static eMonster m[14] = { - moWorm, moTroll, moEagle, - moLesser, moGreater, moPyroCultist, moGhost, - moFireFairy, moIvyRoot, moTentacle, moHedge, - moLancer, moFlailer, moVineBeast - }; - eMonster cm = m[rand() % 14]; - if(cm == moIvyRoot) buildIvy(c, 0, c->type); - else c->monst = cm; - if(cm == moWorm || cm == moTentacle) - c->mondir = NODIR; + if(isCrossroads(c->land)) { + if(c->type == 6 && hrand(8000) < 120 && items[itShard] >= 10) + c->wall = hrand(2) ? waMirror : waCloud; + else { + if(hyperstonesUnlocked() && hrand(25000) < tkills() && notDippingFor(itHyperstone)) + c->item = itHyperstone; + if(hrand(4000) < items[itHyperstone] + 2 * items[itHolyGrail]) { + // only interesting monsters here! + eMonster cm = crossroadsMonster(); + if(cm == moIvyRoot) buildIvy(c, 0, c->type); + else c->monst = cm; + if(cm == moWorm || cm == moTentacle) + c->mondir = NODIR; + } } } if(c->land == laMirror) { - if(c->type == 6 && rand() % 5000 < 120 && notDippingFor(itShard)) - c->wall = rand() % 2 ? waMirror : waCloud; - if(rand() % 12000 < 8 + items[itShard] + hard) + if(c->type == 6 && hrand(5000) < 120 && notDippingFor(itShard)) + c->wall = hrand(2) ? waMirror : waCloud; + else if(c->type == 7 && hrand(5000) < 10 * PRIZEMUL) + placePrizeOrb(c); + else if(hrand(12000) < 8 + items[itShard] + hard) c->monst = moRanger; - else if(rand() % 60000 < 8 + items[itShard] + hard) + else if(hrand(60000) < 8 + items[itShard] + hard) c->monst = moEagle; } if(c->land == laGraveyard) { - if(rand() % 5000 < 30 + 2 * (kills[moZombie] + kills[moGhost] + kills[moNecromancer]) && notDippingFor(itBone)) + if(hrand(5000) < 30 + 2 * (kills[moZombie] + kills[moGhost] + kills[moNecromancer]) && notDippingFor(itBone)) c->item = itBone; - if(rand() % 20000 < 10 + items[itBone] + hard + (kills[moZombie] + kills[moGhost] + kills[moNecromancer])/60) { + if(hrand(20000) < 10 + items[itBone] + hard + (kills[moZombie] + kills[moGhost] + kills[moNecromancer])/60) { eMonster grm[6] = { moZombie, moZombie, moZombie, moGhost, moGhost, moNecromancer}; - c->monst = grm[rand() % 6]; + c->monst = grm[hrand(6)]; } } if(c->land == laRlyeh) { - if(rand() % 5000 < 30 + 2 * (kills[moCultist] + kills[moTentacle] + kills[moPyroCultist]) && notDippingFor(itStatue)) + if(hrand(5000) < 30 + 2 * (kills[moCultist] + kills[moTentacle] + kills[moPyroCultist]) && notDippingFor(itStatue)) c->item = itStatue; - if(rand() % 8000 < 5 + items[itStatue] + hard) + if(hrand(8000) < 5 + items[itStatue] + hard) c->monst = moTentacle, c->item = itStatue, c->mondir = NODIR; - else if(rand() % 12000 < 5 + items[itStatue] + hard) - c->monst = rand() % 3 ? ((rand() % 40 < items[itStatue]-25) ? moCultistLeader : moCultist) : moPyroCultist; - else if(rand() % 8000 < 5 + items[itStatue] + hard && c->type == 6) { + else if(hrand(12000) < 5 + items[itStatue] + hard) + c->monst = hrand(3) ? ((hrand(40) < items[itStatue]-25) ? moCultistLeader : moCultist) : moPyroCultist; + else if(hrand(8000) < 5 + items[itStatue] + hard && c->type == 6) { for(int t=0; ttype; t++) { if(c->mov[t] && c->mov[t]->monst == moNone && (c->wall == waNone || c->wall == waColumn)) c->mov[t]->wall = ishept(c->mov[t]) ? waColumn : waNone; @@ -1574,56 +4570,56 @@ void setdist(cell *c, int d, cell *from) { } if(c->land == laTemple) { // depth! - int d = celldistAlt(c); + int d = (euclid || c->master->alt) ? celldistAlt(c) : 10; // remember: d is negative if(d % TEMPLE_EACH == 0) { - if(rand() % 5000 < 20 - 2*d) + if(hrand(5000) < 20 - 2*d) c->monst = moTentacle, c->mondir = NODIR; } else { - int d0 = d % TEMPLE_EACH; - if(d0<0) d0=-d0; - if(rand() % 100 < 30) // && d0 != 1 && d0 != TEMPLE_EACH-1) + // int d0 = d % TEMPLE_EACH; + // if(d0<0) d0=-d0; + if(hrand(100) < 30) // && d0 != 1 && d0 != TEMPLE_EACH-1) c->wall = waBigStatue; - else if(rand() % 20000 < -d) - c->monst = rand() % 3 ? moCultist : moPyroCultist; - else if(rand() % 100000 < -d) + else if(hrand(20000) < -d) + c->monst = hrand(3) ? moCultist : moPyroCultist; + else if(hrand(100000) < -d) c->monst = moCultistLeader; - else if(rand() % 5000 < 250) + else if(hrand(5000) < 250) c->item = itGrimoire; - else if(rand() % 5000 < 10 && -d > TEMPLE_EACH * 10) + else if(hrand(5000) < 10 && -d > TEMPLE_EACH * 10) c->item = itOrbDragon; } } if(c->land == laDryForest) { - if(rand() % 5000 < 100 + 2 * (kills[moFireFairy]*2 + kills[moHedge]) && notDippingFor(itFernFlower)) + if(hrand(5000) < 100 + 2 * (kills[moFireFairy]*2 + kills[moHedge]) && notDippingFor(itFernFlower)) c->item = itFernFlower; - if(rand() % 4000 < 40 + items[itFernFlower] + hard) + if(hrand(4000) < 40 + items[itFernFlower] + hard) c->monst = moHedge; - else if(rand() % 8000 < 2 * items[itFernFlower] + hard) + else if(hrand(8000) < 2 * items[itFernFlower] + hard) c->monst = moFireFairy; } if(c->land == laHell) { - if(rand() % 1500 < 30 + (kills[moCultist] + kills[moTentacle]) && notDippingFor(itHell)) + if(hrand(6000) < 120 + (kills[moLesser]) && notDippingFor(itHell)) c->item = itHell; - if(rand() % 8000 < 40 + items[itHell] + hard) + if(hrand(8000) < 40 + items[itHell] + hard) c->monst = moLesser; - else if(rand() % 24000 < 40 + items[itHell] + hard) + else if(hrand(24000) < 40 + items[itHell] + hard) c->monst = moGreater; } if(c->land == laCocytus) { - if(rand() % 5000 < 100 + 2 * (kills[moShark] + kills[moGreaterShark] + kills[moCrystalSage]) && notDippingFor(itSapphire)) + if(hrand(5000) < 100 + 2 * (kills[moShark] + kills[moGreaterShark] + kills[moCrystalSage]) && notDippingFor(itSapphire)) c->item = itSapphire; - if(rand() % 5000 < 2 * (items[itSapphire] + hard)) { + if(hrand(5000) < 2 * (items[itSapphire] + hard)) { eMonster ms[3] = { moYeti, moGreaterShark, moCrystalSage }; - c->monst = ms[rand() % 3]; + c->monst = ms[hrand(3)]; if(c->monst == moGreaterShark) c->wall = waLake; } } if(c->land == laMotion) { - if(rand() % 1500 < 30 + (kills[moRunDog]) && notDippingFor(itFeather)) + if(hrand(1500) < 30 + (kills[moRunDog]) && notDippingFor(itFeather)) c->item = itFeather; - if(rand() % 20000 < 25 + items[itFeather] + hard) { + if(hrand(20000) < 25 + items[itFeather] + hard) { c->monst = moRunDog; // preset the movement direction // this will make the dog go in the direction of the center, @@ -1632,68 +4628,37 @@ void setdist(cell *c, int d, cell *from) { c->mondir = (d+3) % c->type; } chasmify(c); + c->wall = shmup::on ? waNone : waChasm; } } if(c->land == laHive) { - if(isHive(c->land) && rand() % 6000 < (items[itRoyalJelly] + hard-15)) - c->monst = eMonster(moBug0 + rand() % BUGCOLORS); + if(isHive(c->land) && hrand(6000) < (hivehard() - 15)) + c->monst = randomHyperbug(); - /* if(rand() % 1500 < 30 + (kills[moBug0] + kills[moBug1] + kills[moBug2]) && notDippingFor(itRoyalJelly)) + /* if(hrand(1500) < 30 + (kills[moBug0] + kills[moBug1] + kills[moBug2]) && notDippingFor(itRoyalJelly)) c->item = itRoyalJelly; */ - /* if(rand() % 2000 < 2) - c->monst = eMonster(moBug0 + rand() % 3); */ + /* if(hrand(2000) < 2) + c->monst = eMonster(moBug0 + hrand(3)); */ + } + if(c->land == laCaribbean) { +// if(hrand(1500) < 60 && celldistAlt(c) <= -5) +// c->item = itCompass; + if(hrand(16000) < 40 + (items[itPirate] + hard)) + c->monst = moPirate; } if(!c->item && c->wall != waCloud && c->wall != waMirror) { - if(orbChance(c, laJungle, 1200, 1500) && items[itRuby] >= 10) - c->item = itOrbLightning; - if(orbChance(c, laIce, 2000, 1500) && items[itDiamond] >= 10) - c->item = itOrbFlash; - if(orbChance(c, laCaves, 1800, 2000) && items[itGold] >= 10) - c->item = itOrbLife; - if(orbChance(c, laAlchemist, 600, 800) && items[itElixir] >= 10) - c->item = itOrbSpeed; - if(orbChance(c, laGraveyard, 200, 200) && items[itBone] >= 10) - c->item = itGreenStone; - if(orbChance(c, laDesert, 2500, 600) && items[itSpice] >= 10) - c->item = itOrbShield; - if(orbChance(c, laHell, 2000, 1000) && items[itHell] >= 10) - c->item = itOrbYendor; - if(orbChance(c, laRlyeh, 1500, 1000) && items[itStatue] >= 10) - c->item = itOrbTeleport; - if(orbChance(c, laMotion, 2000, 700) && items[itFeather] >= 10) { - c->item = itOrbSafety; - } - - if(orbChance(c, laIce, 1500, 0) && items[itDiamond] >= 10) - c->item = itOrbWinter; - if(orbChance(c, laDryForest, 2500, 0) && items[itFernFlower] >= 10) - c->item = itOrbWinter; - if(orbChance(c, laCocytus, 1500, 1500) && items[itSapphire] >= 10) - c->item = itOrbWinter; - if(orbChance(c, laCaves, 1200, 0) && items[itGold] >= 10) - c->item = itOrbDigging; - if(orbChance(c, laDryForest, 500, 2000) && items[itFernFlower] >= 10) - c->item = itOrbThorns; - - if(orbChance(c, laDeadCaves, 1800, 0) && items[itSilver] >= 10) - c->item = itGreenStone; - if(orbChance(c, laDeadCaves, 1800, 1000) && items[itSilver] >= 10) - c->item = itOrbDigging; - if(orbChance(c, laFjord, 1500, 2500) && items[itEmerald] >= 10) - c->item = itOrbPsi; - if(orbChance(c, laWineyard, 900, 1200) && items[itWine] >= 10) - c->item = itOrbGhost; - if(orbChance(c, laHive, 800, 1200) && items[itRoyalJelly] >= 10) - c->item = itOrbInvis; - if(orbChance(c, laPower, 0, 1500) && items[itPower] >= 10) - c->item = itOrbFire; - if(orbChance(c, laTemple, 0, 2500) && items[itGrimoire] >= 10) - c->item = itOrbDragon; - if(orbChance(c, laCamelot, 1000, 1500) && items[itHolyGrail]) - c->item = itOrbIllusion; + if(isCrossroads(c->land)) + placeCrossroadOrbs(c); + else + placeLocalOrbs(c); } } } + +#ifndef MOBILE + if(d >= 7 && mapeditor::whichPattern) + mapeditor::applyModelcell(c); +#endif } // find worms and ivies @@ -1708,7 +4673,10 @@ void findWormIvy(cell *c) { worms.push_back(c); settemp(c); break; } - else if(c->monst == moWormtail) { + else if(c->monst == moHexSnake) { + hexsnakes.push_back(c); settemp(c); + } + else if(c->monst == moWormtail || c->monst == moHexSnakeTail) { bool bug = true; for(int i=0; itype; i++) { cell* c2 = c->mov[i]; @@ -1744,32 +4712,100 @@ void findWormIvy(cell *c) { } } -bool isGhostMover(eMonster m) { - return m == moGhost || m == moGreaterShark || - (cwt.c->land == laPower && (m == moWitchGhost || m == moWitchWinter)); - } - -bool havebugs, haveearth, haveeagles, haveleader; +bool havebugs, haveearth, haveeagles, haveleader, havehex, havewhirlpool, havewater, + haveair; bool bugsfighting; +bool keepLightning = false; + +int statuecount; + +int tidalphase; + +int tidalsize, tide[200]; + +void calcTidalPhase() { + if(!tidalsize) { + for(int i=0; i<5; i++) tide[tidalsize++] = 1; + + for(int i=1; i<4; i++) for(int j=0; j<3; j++) + tide[tidalsize++] = i; + + for(int i=4; i<7; i++) for(int j=0; j<2; j++) + tide[tidalsize++] = i; + + for(int i=7; i<20; i++) + tide[tidalsize++] = i; + + for(int i=20; i<23; i++) for(int j=0; j<2; j++) + tide[tidalsize++] = i; + + for(int i=23; i<26; i++) for(int j=0; j<3; j++) + tide[tidalsize++] = i; + + for(int i=0; i+iland == laOcean) { + if(c->wall == waStrandedBoat || c->wall == waBoat) + c->wall = c->landparam >= tidalphase ? waBoat : waStrandedBoat; + if(c->wall == waSea || c->wall == waNone) + c->wall = c->landparam >= tidalphase ? waSea : waNone; + if(isFire(c) && c->landparam >= tidalphase) + c->wall = waSea; + } + } + // calculate cpdist and pathdist -void bfs() { +void bfs(bool tick = true) { + + calcTidalPhase(); + + checkOnYendorPath(); int dcs = size(dcal); for(int i=0; icpdist = INFD; worms.clear(); ivies.clear(); ghosts.clear(); golems.clear(); mirrors.clear(); - temps.clear(); tempval.clear(); targets.clear(); havebugs = false; - haveearth = false; haveeagles = false; haveleader = false; - - dcal.clear(); dcal.push_back(cwt.c); - reachedfrom.clear(); reachedfrom.push_back(rand() % cwt.c->type); + temps.clear(); tempval.clear(); targets.clear(); + statuecount = 0; + hexsnakes.clear(); + havebugs = false; + haveearth = false; haveeagles = false; haveleader = false; havehex = false; + havemouse = false; + havewater = false; + havewhirlpool = false; + haveair = false; + dcal.clear(); reachedfrom.clear(); + int pqs = size(pathq); for(int i=0; ipathdist = INFD; - pathq.clear(); if(!invismove) targets.push_back(cwt.c); + pathq.clear(); + + for(int i=0; icpdist == 0) continue; + c->cpdist = 0; + checkTide(c); + dcal.push_back(c); + reachedfrom.push_back(hrand(c->type)); + if(!invismove) targets.push_back(c); + } - cwt.c->cpdist = 0; int qb = 0; while(true) { int i, fd = reachedfrom[qb] + 3; @@ -1779,6 +4815,11 @@ void bfs() { for(int j=0; jtype; j++) if(i = (fd+j) % c->type, c->mov[i]) { // printf("i=%d cd=%d\n", i, c->mov[i]->cpdist); cell *c2 = c->mov[i]; + + if((c->wall == waBoat || c->wall == waSea) && + (c2->wall == waSulphur || c2->wall == waSulphurC)) + c2->wall = waSea; + if(c2 && signed(c2->cpdist) > d+1) { c2->cpdist = d+1; @@ -1786,60 +4827,84 @@ void bfs() { if(c2->item && c2->cpdist == 7 && itemclass(c2->item) == IC_TREASURE && items[c2->item] >= 20 + currentLocalTreasure) c2->item = itNone; + + if(c2->item == itBombEgg && c2->cpdist == 7 && items[itBombEgg] >= c2->landparam) { + c2->item = itNone; + if(!c2->monst) c2->monst = moBomberbird; + } + + if(c2->item == itEdge && c2->cpdist == 7 && items[itEdge] >= c2->landparam) { + c2->item = itNone; + } - c2->ligon = 0; + if(!keepLightning) c2->ligon = 0; dcal.push_back(c2); reachedfrom.push_back(c->spn[i]); + + checkTide(c2); + + if(c2->wall == waBigStatue && c2->land != laTemple) + statuecount++; + + if(c2->land == laWhirlpool) havewhirlpool = true; + if(c2->monst) { - if(isWorm(c2) || isIvy(c2)) findWormIvy(c2); + if(c2->monst == moHexSnake || c2->monst == moHexSnakeTail) { + havehex = true; + if(c2->monst == moHexSnake) hexsnakes.push_back(c2); + else findWormIvy(c2); + } else if(isGhostMover(c2->monst)) ghosts.push_back(c2); + else if(isWorm(c2) || isIvy(c2)) findWormIvy(c2); else if(isBug(c2)) { havebugs = true; targets.push_back(c2); } else if(isFriendly(c2)) { - targets.push_back(c2); + if(c2->monst != moMouse) targets.push_back(c2); if(c2->monst == moGolem) golems.push_back(c2); if(c2->monst == moKnight) golems.push_back(c2); + if(c2->monst == moTameBomberbird) golems.push_back(c2); + if(c2->monst == moMouse) { golems.push_back(c2); havemouse = true; } + if(c2->monst == moPrincess || c2->monst == moPrincessArmed) golems.push_back(c2); if(c2->monst == moIllusion) { if(items[itOrbIllusion]) items[itOrbIllusion]--; else c2->monst = moNone; } if(isMimic(c2)) mirrors.push_back(c2); } - else if(c2->monst == moEagle) haveeagles = true; + else if(isAngryBird(c2->monst)) haveeagles = true; + else if(isLeader(c2->monst)) haveleader = true; else if(c2->monst == moEarthElemental) haveearth = true; - else if(c2->monst == moCultistLeader) haveleader = true; + else if(c2->monst == moWaterElemental) havewater = true; + if(c2->monst == moAirElemental) haveair = true; } // pheromones! - if(c2->land == laHive && c2->heat >= 50 && c2->wall != waWaxWall) + if(c2->land == laHive && c2->landparam >= 50 && c2->wall != waWaxWall) havebugs = true; - if(c2->wall == waThumper && c2->tmp > 0) { - useup(c2); + if(c2->wall == waThumperOn) targets.push_back(c2); - } } } } - + + reachedfrom.clear(); for(int i=0; ipathdist = (targets[i] == cwt.c) ? 0 : 1; + targets[i]->pathdist = isPlayerOn(targets[i]) ? 0 : 1; pathq.push_back(targets[i]); + reachedfrom.push_back(hrand(targets[i]->type)); } int qtemp = size(temps); for(int i=0; imonst = tempval[i]; pathqm.clear(); - reachedfrom.clear(); reachedfrom.push_back(rand() % cwt.c->type); qb = 0; for(qb=0; qb < size(pathq); qb++) { int fd = reachedfrom[qb] + 3; cell *c = pathq[qb]; - eucoord x, y; - decodeMaster(c->master, x, y); if(c->monst && !isBug(c) && !isFriendly(c)) { pathqm.push_back(c); continue; // no paths going through monsters @@ -1850,7 +4915,7 @@ void bfs() { int i = (fd+j) % c->type; // printf("i=%d cd=%d\n", i, c->mov[i]->cpdist); if(c->mov[i] && c->mov[i]->pathdist == INFD && !thruVine(c, c->mov[i]) && - (c->mov[i]->monst || passable(c->mov[i], (d==0)?NULL:c, true, false))) { + passable(c->mov[i], d==0?NULL:c, true, false, true)) { c->mov[i]->pathdist = d+1; pathq.push_back(c->mov[i]); reachedfrom.push_back(c->spn[i]); } @@ -1858,45 +4923,81 @@ void bfs() { } } -extern void cleargraphmemory(); - // initialize the game void initgame() { + + if(firstland == laNone || firstland == laBarrier) + firstland = laCrossroads; + + if(firstland == laOceanWall) firstland = laOcean; + if(firstland == laEdge) firstland = laCrossroads; + if(firstland == laElementalWall) firstland = randomElementalLand(); + cwt.c = origin.c7; cwt.spin = 0; cwt.c->land = euclid ? euclidland : firstland; createMov(cwt.c, 0); for(int i=0; i<65536; i++) euland[i] = laNone; + + if(euclid && euclidland == laPrincessQuest) { + cell *c = euclideanAtCreate(EPX, EPY); + princess::generating = true; + c->land = laPalace; + for(int j=BARLEV; j>=0; j--) setdist(c, j, NULL); + princess::generating = false; + } + + if(cwt.c->land == laCrossroads2) { + cwt.c->landparam = 12; + createMov(cwt.c, 0)->landparam = 44; + } // extern int sightrange; sightrange = 9; // cwt.c->land = laHell; items[itHell] = 10; - for(int i=9; i>=0; i--) { + for(int i=BARLEV; i>=0; i--) { setdist(cwt.c, i, NULL); verifycells(&origin); } if(cwt.c->land == laCocytus) cwt.c->wall = waFrozenLake; - else if(cwt.c->land == laAlchemist || cwt.c->land == laGameBoard) + else if(cwt.c->land == laAlchemist || cwt.c->land == laCanvas) ; - else if(cwt.c->land == laCaves || cwt.c->land == laFjord) + else if(cwt.c->land == laCaves || cwt.c->land == laEmerald) cwt.c->wall = waCavefloor; else if(cwt.c->land == laDeadCaves) cwt.c->wall = waDeadfloor2; + else if(cwt.c->land == laCaribbean || cwt.c->land == laOcean || cwt.c->land == laWhirlpool || cwt.c->land == laLivefjord) + cwt.c->wall = waBoat; // , cwt.c->item = itOrbYendor; + else if(cwt.c->land == laMinefield) + cwt.c->wall = waMineOpen; else cwt.c->wall = waNone; cwt.c->item = itNone; cwt.c->monst = moNone; - - cleargraphmemory(); + + if(shmup::on) shmup::init(); if(!safety) { - timerstart = time(NULL); turncount = 0; sagephase = 0; + timerstart = time(NULL); turncount = 0; + sagephase = 0; hardcoreAt = 0; timerstopped = false; savecount = 0; savetime = 0; cheater = 0; - if(firstland != laIce) cheater++; + if(!randomPatternsMode) { + if(firstland != (princess::challenge ? laPalace : laIce)) cheater++; + } + if(princess::challenge) { + kills[moVizier] = 1; + princess::forceMouse = true; + if(princess::everGotYendorVictory) + items[itGreenStone] = 99; + addMessage(XLAT("Welcome to %the1 Challenge!", moPrincess)); + addMessage(XLAT("The more Hypersian Rugs you collect, the harder it is.", moPrincess)); + } + } + else { + safety = false; } - else safety = false; // items[itGreenStone] = 100; // items[itOrbTeleport] = 100; @@ -1937,28 +5038,194 @@ void initgame() { bfs(); } -void firetrail(cell *c) { - if(!passable(c, NULL, true, true)) return; - destroyHalfvine(c); - c->item = itNone; - if(c->wall == waFrozenLake) - c->wall = waLake; - if(cellUnstableOrChasm(c)) - return; - c->wall = waBonfire, c->tmp = 10; +void toggleGates(cell *ct, eWall type, int rad) { + if(!ct) return; + if(ct->wall == waOpenGate && type == waClosePlate) { + bool onWorm = false; + if(isWorm(ct)) onWorm = true; + for(int i=0; itype; i++) + if(ct->mov[i] && ct->mov[i]->wall == waOpenGate && isWorm(ct->mov[i])) onWorm = true; + if(!onWorm) { + ct->wall = waClosedGate, rad = 1; + if(ct->item) { + addMessage(XLAT("%The1 is crushed!", ct->item)); + ct->item = itNone; + } + } + } + if(ct->wall == waClosedGate && type == waOpenPlate) + ct->wall = waOpenGate, rad = 1; + if(rad) for(int i=0; itype; i++) + toggleGates(ct->mov[i], type, rad-1); + } + +// effect of moving monster m from cf to ct +// this is called from moveMonster, or separately from moveIvy/moveWorm, +// or when a dead bird falls (then m == moDeadBird) + +void moveEffect(cell *ct, cell *cf, eMonster m) { + + if(!survivesMine(m)) + explodeMine(ct); + + if(!ignoresPlates(m) && !survivesMine(m) && (ct->wall == waClosePlate || ct->wall == waOpenPlate)) + toggleGates(ct, ct->wall, 3); + + if(isPrincess(m)) princess::move(ct, cf); + } + +void updateHi(eItem it, int v) { + if(v > hiitems[it]) hiitems[it] = v; + } + +void gainItem(eItem it) { + int g = gold(); + items[it]++; updateHi(it, items[it]); + achievement_collection(it, gold(), g); + } + +void playerMoveEffects(cell *c2) { + bool nomine = (c2->wall == waMineMine || c2->wall == waMineUnknown) && markOrb(itOrbGhost); + + if(!nomine) { + uncoverMines(c2, + items[itBombEgg] < 10 && hiitems[itBombEgg] < 25 ? 0 : + items[itBombEgg] < 20 ? 1 : + items[itBombEgg] < 30 ? 2 : + 3 + ); + explodeMine(c2); + } + + if((c2->wall == waClosePlate || c2->wall == waOpenPlate) && !markOrb(itOrbGhost)) + toggleGates(c2, c2->wall, 3); + + princess::playernear(c2); + + if(c2->wall == waGlass && items[itOrbGhost] > 2) { + addMessage(XLAT("Your Aether powers are drained by %the1!", c2->wall)); + items[itOrbGhost] = 2; + } + + if(c2->wall == waMirror && !markOrb(itOrbGhost)) { + invismove = false; + addMessage(XLAT("The mirror shatters!")); + if(c2->land == laMirror) gainItem(itShard); + c2->wall = waNone; + createMirrors(cwt.c, cwt.spin, moMirage); + } + + if(c2->wall == waCloud && !markOrb(itOrbGhost)) { + invismove = false; + addMessage(XLAT("The cloud turns into a bunch of images!")); + if(c2->land == laMirror) gainItem(itShard); + c2->wall = waNone; + createMirages(cwt.c, cwt.spin, moMirage); + } + + if(cellUnstable(c2) && !markOrb(itOrbGhost)) + c2->wall = waChasm; + + if(c2->wall == waStrandedBoat && markOrb(itOrbWater)) + c2->wall = waBoat; + + if(c2->land == laOcean && c2->wall == waBoat && c2->landparam < 30 && markOrb(itOrbWater)) + c2->landparam = 40; + } + +void moveMonster(cell *ct, cell *cf) { + eMonster m = cf->monst; + moveEffect(ct, cf, m); + if(m == moTentacleGhost) { + cf->monst = moTentacletail; + m = moGhost; + } + else cf->monst = moNone; + if(ct->monst == moTentacletail && m == moGhost) { + ct->monst = moTentacleGhost; + } + else { + ct->monst = m; + if(ct->monst != moTentacleGhost) + ct->mondir = neighborId(ct, cf); + } + ct->hitpoints = cf->hitpoints; + ct->stuntime = cf->stuntime; + + if(isFriendly(m) || isBug(m) || items[itOrbDiscord]) stabbingAttack(cf, ct, m); + + if(isLeader(m)) { + if(ct->wall == waBigStatue) { + ct->wall = cf->wall; + cf->wall = waBigStatue; + } + + moveBoatIfUsingOne(ct, cf); + } + + if(m == moEarthElemental) + earthMove(cf, neighborId(cf, ct)); + + if(m == moWaterElemental) { + placeWater(ct, cf); + for(int i=0; itype; i++) { + cell *c2 = ct->mov[i]; + if(!c2) continue; + if(c2->wall == waBoat && !(c2 == cwt.c && markOrb(itOrbWater))) { + addMessage(XLAT("%The1 is washed away!", c2->wall, moWaterElemental)); + placeWater(c2, ct); + } + else if(c2->wall == waStrandedBoat) { + addMessage(XLAT("%The1 is washed away!", c2->wall, moWaterElemental)); + c2->wall = waNone; + } + else if(c2->wall == waDeadTroll) { + addMessage(XLAT("%The1 is washed away!", c2->wall, moWaterElemental)); + c2->wall = waNone; + } + else if(isFire(c2) && c2->wall != waEternalFire) { + addMessage(XLAT("%The1 is extinguished!", c2->wall, moWaterElemental)); + c2->wall = waNone; + } + } + } + + if(m == moGreaterShark) for(int i=0; itype; i++) { + cell *c3 = ct->mov[i]; + if(c3 && c3->wall == waBoat) + makeflame(c3, 5, false); + } + + // lancers pierce our friends :( + if(m == moLancer) { + // printf("lancer stab?\n"); + for(int u=2; u<=ct->type-2; u++) { + cell *c3 = ct->mov[(ct->mondir+u)%ct->type]; + if(c3->monst && isKillableSomehow(c3)) { + addMessage(XLAT("%The1 pierces %the2!", m, c3->monst)); + killWithMessage(c3, true); + } + killThePlayerAt(m, c3); + } + } + + if(m == moWitchFire) makeflame(cf, 10, false); + if(m == moFireElemental) makeflame(cf, 20, false); } void moveNormal(cell *c) { bool repeat = true; eMonster m = c->monst; - again: + if(c->stuntime) return; for(int j=0; jtype; j++) if(c->mov[j] && isFriendlyOrBug(c->mov[j]) && repeat && !attackingForbidden(c->mov[j], c)) { // XLATC enemy destroys a friend - addMessage(XLAT("%The1 destroys %the2!", m, c->mov[j]->monst)); - c->mov[j]->monst = moNone; + if(attackJustStuns(c->mov[j])) + addMessage(XLAT("%The1 attacks %the2!", m, c->mov[j]->monst)); + else messageKill(m, c->mov[j]->monst); + killWithMessage(c->mov[j], true); return; } @@ -1968,16 +5235,16 @@ void moveNormal(cell *c) { cell *c2 = c->mov[j]; if(!c2) continue; if(c2->pathdist >= c->pathdist) continue; - if(!passable(c2, c, false, false)) continue; + if(!passable(c2, c, false, false, false)) continue; // crystal sages can't stand out of Cocytus - if(m == moCrystalSage && (c2->land != laCocytus || c2->heat > SAGEMELT)) + if(m == moCrystalSage && (c2->land != laCocytus || HEAT(c2) > SAGEMELT || cwt.c->wall == waBoat)) continue; // lancers don't move next to other monsters if(c->monst == moLancer) { bool lancerok = true; for(int u=2; u<=c2->type-2; u++) { cell *c3 = c2->mov[(c->spn[j]+u)%c2->type]; - if(c3->monst && !isFriendlyOrBug(c3) && isKillableSomehow(c3)) + if(c3->monst && !isFriendlyOrBug(c3) && isKillableSomehow(c3)) lancerok = false; } if(!lancerok) continue; @@ -1993,54 +5260,25 @@ void moveNormal(cell *c) { } } - if(nc == 0 && !passable(c, NULL, true, true)) { + if(nc == 0 && !passable(c, NULL, true, true, false)) { // running dogs run away! // they prefer a straight direction - int sgn = rand() % 2 ? 1 : -1; + int sgn = hrand(2) ? 1 : -1; for(int b=3; b>=0; b--) for(int s=-1; s<=1; s+=2) if(!nc) { int d = (c->mondir + b*s*sgn) % c->type; d += c->type; d %= c->type; cell *c2 = c->mov[d]; - if(passable(c2, c, false, false)) + if(passable(c2, c, false, false, false)) posdir[nc++] = d; } } -/* - // Eagles can fly through chasms/slime if needed - if(m == moEagle && nc == 0) { - printf("no eagle no fly\n"); - for(int j=0; jtype; j++) printf("%d from %d\n", c->mov[j]->cpdist, c->cpdist); - for(int j=0; jtype; j++) - if(c->mov[j] && c->mov[j]->cpdist < c->cpdist && - !c->mov[j]->monst && - (c->mov[j]->land == laMotion || c->mov[j]->land == laAlchemist) && c->wall != waDeadTroll) - if(c->mov[j]->cpdist > 0) - posdest[nc++] = c->mov[j]; - printf("nc=%d\n", nc); - } */ - if(!nc) return; - nc = rand() % nc; - cell *c2 = c->mov[posdir[nc]]; - c2->monst = m, c->monst = moNone; - c2->mondir = c->spn[posdir[nc]]; - if(m == moEagle && repeat && c->pathdist > 1) { repeat = false; c = c2; goto again; } + nc = hrand(nc); + cell *c2 = c->mov[posdir[nc]]; + moveMonster(c2, c); - // lancers pierce our friends :( - if(m == moLancer) { - // printf("lancer stab?\n"); - for(int u=2; u<=c2->type-2; u++) { - cell *c3 = c2->mov[(c->spn[posdir[nc]]+u)%c2->type]; - if(c3->monst && isKillableSomehow(c3)) { - addMessage(XLAT("%The1 pierces %the2!", m, c3->monst)); - killMonster(c3); - } - } - } - - if(m == moWitchFire) firetrail(c); - if(isWitch(m) && c2->item == itOrbLife && passable(c, NULL, true, true)) { + if(isWitch(m) && c2->item == itOrbLife && passable(c, NULL, true, true, false)) { // note that Fire Witches don't pick up Orbs of Life, addMessage(XLAT("%The1 picks up %the2!", moWitch, c2->item)); c->monst = moEvilGolem; c2->item = itNone; @@ -2070,18 +5308,29 @@ void explodeAround(cell *c) { for(int j=0; jtype; j++) { cell* c2 = c->mov[j]; if(c2) { - if(isIcyLand(c2)) c2->heat += 0.5; + if(isIcyLand(c2)) HEAT(c2) += 0.5; if((c2->wall == waDune || c2->wall == waIcewall || c2->wall == waAncientGrave || c2->wall == waFreshGrave || - c2->wall == waColumn || c2->wall == waThumper || c2->wall == waBonfire || + c2->wall == waColumn || c2->wall == waThumperOff || c2->wall == waThumperOn || + (isFire(c2) && !eternalFire(c2)) || c2->wall == waDryTree || c2->wall == waWetTree || c2->wall == waVinePlant || c2->wall == waVineHalfA || c2->wall == waVineHalfB)) { - destroyHalfvine(c2); c2->wall = waNone; + destroyHalfvine(c2); + c2->wall = waNone; } if(c2->wall == waCavewall || c2->wall == waDeadTroll) c2->wall = waCavefloor; if(c2->wall == waDeadfloor2) c2->wall = waDeadfloor; + if(c2->wall == waGargoyleFloor) c2->wall = waChasm; + if(c2->wall == waGargoyleBridge) placeWater(c2, c2); + if(c2->wall == waRubble) c2->wall = waNone; + if(c2->wall == waPlatform) c2->wall = waNone; + if(c2->wall == waStone) c2->wall = waNone; + if(c2->wall == waLadder) c2->wall = waNone; + if(c2->wall == waGargoyle) c2->wall = waNone; if(c2->wall == waDeadwall) c2->wall = waDeadfloor2; if(c2->wall == waBigStatue) c2->wall = waNone; + if(c2->wall == waPalace || c2->wall == waOpenGate || c2->wall == waClosedGate) + c2->wall = waNone; if(c2->wall == waFloorA || c2->wall == waFloorB) if(c->wall == waFloorA || c->wall == waFloorB) c2->wall = c->wall; @@ -2089,6 +5338,26 @@ void explodeAround(cell *c) { } } +void killThePlayer(eMonster m, int id) { + if(markOrb(itOrbShield)) return; + if(shmup::on) { + shmup::cpid = id; + shmup::killThePlayer(m); + } + else if(hardcore) { + addMessage(XLAT("You are killed by %the1!", m)); + canmove = false; + } + else + addMessage(XLAT("%The1 is confused!", m)); + } + +void killThePlayerAt(eMonster m, cell *c) { + for(int i=0; imonst == moWormwait) { c->monst = moWorm; return; } @@ -2107,12 +5376,14 @@ void moveWorm(cell *c) { int id = c->monst - moWorm; for(int j=0; jtype; j++) { - if(c->mov[j] && isFriendlyOrBug(c->mov[j]) && !attackingForbidden(c->mov[j], c)) { + if(c->mov[j] && isFriendlyOrBugS(c->mov[j]) && !attackingForbidden(c->mov[j], c)) { addMessage(XLAT("%The1 eats %the2!", c->monst, c->mov[j]->monst)); + killWithMessage(c->mov[j], false); ncg = 1; gmov[0] = c->mov[j]; break; } - if(c->mov[j] && passable(c->mov[j], c, false, false) && !cellUnstable(c->mov[j]) && c->mov[j] != cwt.c) { + if(isPlayerOn(c->mov[j]) && !attackingForbidden(c->mov[j], c)) killThePlayerAt(c->monst, c->mov[j]); + if(c->mov[j] && passable(c->mov[j], c, false, false, false) && !cellUnstable(c->mov[j]) && (id || !cellEdgeUnstable(c->mov[j])) && c->mov[j] != cwt.c) { if(c->mov[j]->pathdist < c->pathdist) gmov[ncg++] = c->mov[j]; else bmov[ncb++] = c->mov[j]; } } @@ -2126,31 +5397,40 @@ void moveWorm(cell *c) { moveWorm(c); } else { - addMessage(XLAT("The sandworm explodes in a cloud of Spice!")); kills[moWorm]++; spices = 3; } eItem loc = treasureType(c->land); + bool spiceSeen = false; while(c->monst == moWorm || c->monst == moWormtail || c->monst == moTentacle || c->monst == moTentacletail) { // if(!id) explodeAround(c); if(spices > 0 && c->land == laDesert) { - if(notDippingForExtra(itSpice, loc)) + if(notDippingForExtra(itSpice, loc)) { c->item = itSpice; + if(c->cpdist <= 6) spiceSeen = true; + } spices--; } c->monst = moNone; if(c->mondir != NODIR) c = c->mov[c->mondir]; } + if(!id) { + if(spiceSeen) + addMessage(XLAT("The sandworm explodes in a cloud of Spice!")); + else + addMessage(XLAT("The sandworm explodes!")); + } return; } cell* goal; - if(ncg) goal = gmov[rand() % ncg]; - else goal = bmov[rand() % ncb]; + if(ncg) goal = gmov[hrand(ncg)]; + else goal = bmov[hrand(ncb)]; for(int j=0; jtype; j++) if(c->mov[j] == goal) { goal->monst = eMonster(moWormwait + id); + moveEffect(goal, NULL, eMonster(moWormwait + id)); c->monst = eMonster(moWormtail + id); goal->mondir = c->spn[j]; @@ -2216,12 +5496,17 @@ void moveivy() { while(c->monst != moIvyRoot) { for(int j=0; jtype; j++) { - if(c->mov[j] && isFriendly(c->mov[j])) { - addMessage(XLAT("The ivy destroys %the1!", c->mov[j]->monst)); - c->mov[j]->monst = moNone; + if(c->mov[j] && isFriendly(c->mov[j]) && !attackingForbidden(c->mov[j], c)) { + if(isNonliving(c->mov[j]->monst)) + addMessage(XLAT("The ivy destroys %the1!", c->mov[j]->monst)); + else + addMessage(XLAT("The ivy kills %the1!", c->mov[j]->monst)); + killMonster(c->mov[j]); continue; } - if(c->mov[j] && signed(c->mov[j]->pathdist) < pd && passable(c->mov[j], c, false, false)) + if(isPlayerOn(c->mov[j]) && !attackingForbidden(c->mov[j], c)) + killThePlayerAt(c->monst, c->mov[j]); + if(c->mov[j] && signed(c->mov[j]->pathdist) < pd && passable(c->mov[j], c, false, false, false)) mto = c->mov[j], pd = mto->pathdist, sp = c->spn[j]; } c = c->mov[c->mondir]; @@ -2229,6 +5514,7 @@ void moveivy() { if(mto && mto->cpdist) { mto->monst = moIvyWait, mto->mondir = sp; + moveEffect(mto, NULL, moIvyWait); // if this is the only branch, we want to move the head immediately to mto instead if(mto->mov[mto->mondir]->monst == moIvyHead) { mto->monst = moIvyHead; co->monst = moIvyBranch; @@ -2242,251 +5528,320 @@ void moveivy() { } } -// move slimes, and also seeps - -int sval = 1; -vector slimedfs; - -bool isSlimeMover(cell *c) { - return - c->monst == moSlime || c->monst == moSeep || c->monst == moShark || - c->monst == moVineSpirit; - } - -void slimevisit(cell *c, cell *from, int u) { - if(!c) return; - if(eq(c->tmp, sval)) return; - if(c->wall != waCavewall && c->wall != waLake && c->wall != waDeadwall && - c->wall != waFloorA && c->wall != waFloorB && c->wall != waVinePlant && - c->wall != waVineHalfB && c->wall != waVineHalfA - ) return; - bool hv = false; - // cavewalls/deadwalls are the same for seeps - if(c->wall == waCavewall && from->wall == waDeadwall) hv++; - if(c->wall == waDeadwall && from->wall == waCavewall) hv++; - // only travel to halfvines correctly - if(cellHalfvine(c) && from != cwt.c) { - int i=0; - for(int t=0; ttype; t++) if(c->mov[t] && c->mov[t]->wall == c->wall) i=t; - int z = i-u; if(z<0) z=-z; z%=6; - if(z>1) return; - hv=true; - } - // only travel from halfvines correctly - if(cellHalfvine(from) && from != cwt.c) { - int i=0; - for(int t=0; ttype; t++) if(from->mov[t] && from->mov[t]->wall == from->wall) i=t; - int z = i-c->spn[u]; if(z<0) z=-z; z%=6; - if(z>1) return; - hv=true; - } - if(c->wall != from->wall && from != cwt.c && !hv) return; - if(c->item) return; - // if(c->wall == waThumper || c->wall == waBonfire) return; - c->tmp = sval; - if(size(slimedfs) < 1000) slimedfs.push_back(c), reachedfrom.push_back(u); - if(!isWorm(c) && !isIvy(c) && !isMimic(c)) - for(int i=0; itype; i++) if(c->mov[i] == from) - c->mondir = i; - if(isSlimeMover(c)) { - - for(int j=0; jtype; j++) - if(c->mov[j] && isFriendlyOrBug(c->mov[j])) { - // XLATC slime/seep/shark - addMessage(XLAT("%The1 eats %the2!", c->monst, c->mov[j]->monst)); - c->mov[j]->monst = moNone; - return; - } - - if(from->cpdist == 0 || from->monst) return; - - from->monst = c->monst, c->monst = moNone; - } - } - -void moveslimes() { - sval++; - slimedfs.clear(); reachedfrom.clear(); - for(int i=0; itype); - } - for(int i=0; itype; t++) { - int u = (j+t) % c->type; - slimevisit(c->mov[u], c, c->spn[u]); - } - } - } - -// move eagles - -vector eagledfs; - -void eaglevisit(cell *c, cell *from, int id) { - if(!c) return; - if(eq(c->tmp, sval)) return; - if(c->monst == moEagle) { - if(id == 1) for(int j=0; jtype; j++) - if(c->mov[j] && isFriendlyOrBug(c->mov[j]) && !attackingForbidden(c->mov[j], c)) { - // XLATC eagle - addMessage(XLAT("%The1 claws %the2!", c->monst, c->mov[j]->monst)); - c->mov[j]->monst = moNone; - return; - } - - if(from->cpdist == 0 || from->monst) return; - - from->monst = c->monst, c->monst = moNone; - } - if(c->wall == waThumper || isFire(c)) return; - c->tmp = sval; - if(!eaglepassable(c)) return; - if(size(eagledfs) < 1000) eagledfs.push_back(c); - } - -void moveeagles(int id) { - if(invismove) return; - sval++; - eagledfs.clear(); - for(int i=0; itype; t++) - eaglevisit(c->mov[t], c, id); - } - } - -vector earthdfs; - -bool earthpassable(cell *c, cell *from) { - // cannot go through Living Caves... - if(c->wall == waCavefloor) return false; - // but can dig through... - if(c->wall == waDeadwall || c->wall == waDune) - return true; - return passable(c, from, true, false); - } - -void earthMove(cell *from, int dir) { +bool earthMove(cell *from, int dir) { + bool b = false; cell *c2 = from->mov[dir]; int d = from->spn[dir]; - earthWall(from); + b |= earthWall(from); if(c2) for(int u=2; u<=c2->type-2; u++) { cell *c3 = c2->mov[(d + u)% c2->type]; - earthFloor(c3); + b |= earthFloor(c3); } + return b; } -void earthvisit(cell *c, cell *from, int d) { +int sval; vector gendfs; + +void monsterfight(cell *attacker, cell *victim) { + if(isBird(attacker->monst)) + addMessage(XLAT("%The1 claws %the2!", attacker->monst, victim->monst)); + else if(isSlimeMover(attacker)) { + if(attackJustStuns(victim)) + addMessage(XLAT("%The1 attacks %the2!", attacker->monst, victim->monst)); + else + addMessage(XLAT("%The1 eats %the2!", attacker->monst, victim->monst)); + } + else + addMessage(XLAT("%The1 punches %the2!", attacker->monst, victim->monst)); + killWithMessage(victim, true); + } + +void groupmove2(cell *c, cell *from, int d, eMonster movtype, bool noattacks) { if(!c) return; - if(eq(c->tmp, sval)) return; + if(eq(c->aitmp, sval)) return; + if(!passable_for(movtype, from, c, false)) return; - if(!earthpassable(c, from)) return; + if(movegroup(c->monst) == movtype) { + if(movtype == moEagle && noattacks && c->monst != moEagle) return; - if(c->monst == moEarthElemental) { + if(c->stuntime) return; + // note: move from 'c' to 'from'! - for(int j=0; jtype; j++) + if(!noattacks) for(int j=0; jtype; j++) if(c->mov[j] && isFriendlyOrBug(c->mov[j]) && !attackingForbidden(c->mov[j], c)) { + monsterfight(c, c->mov[j]); + c->aitmp = sval; // XLATC eagle - addMessage(XLAT("%The1 punches %the2!", c->monst, c->mov[j]->monst)); - c->mov[j]->monst = moNone; return; } - if(!passable(from, c, false, false)) { + if(movtype == moEarthElemental && !passable(from, c, false, false, false)) { earthFloor(from); return; } - if(from->cpdist == 0 || from->monst) return; - earthMove(c, from->spn[d]); - - from->monst = c->monst, c->monst = moNone; + if(from->cpdist == 0 || from->monst) { c->aitmp = sval; return; } + moveMonster(from, c); } - if(c->wall == waThumper || isFire(c)) return; - c->tmp = sval; - if(size(earthdfs) < 1000) earthdfs.push_back(c); + c->aitmp = sval; + if(size(gendfs) < 1000) gendfs.push_back(c); } -void moveearth() { - if(invismove) return; +#define ONLY_ONE_PLAYER_POSSIBLE 0 + +void groupmove(eMonster movtype, bool noattacks = false) { + if(!noattacks) for(int i=0; itype; i++) { + eMonster m = cwt.c->mov[i]->monst; + if(movegroup(m) == movtype && !attackingForbidden(cwt.c, cwt.c->mov[i])) + killThePlayer(m, ONLY_ONE_PLAYER_POSSIBLE); + } sval++; - earthdfs.clear(); + gendfs.clear(); for(int i=0; itype; t++) - earthvisit(c->mov[t], c, t); + groupmove2(c->mov[t], c, t, movtype, noattacks); } } -vector leaderdfs; +// Hex monsters -bool canPushStatueOn(cell *c) { - return passable(c, NULL, true, false); +vector hexdfs; + +// note: move from 'c' to 'from'! +void moveHexSnake(cell *from, cell *c, int d) { + if(from->wall == waBoat) from->wall = waSea; + moveEffect(from, c, c->monst); + from->monst = c->monst; from->mondir = d; + c->monst = moHexSnakeTail; + + cell *c2 = c, *c3=c2; + for(int a=0;; a++) if(c2->monst == moHexSnakeTail) { + if(a == ROCKSNAKELENGTH) { c2->monst = moNone, c3->mondir = NODIR; break; } + if(c2->mondir == NODIR) break; + c3 = c2, c2 = c3->mov[c2->mondir]; + } + else break; + } + +void snakeAttack(cell *c) { + for(int j=0; jtype; j++) + if(c->mov[j] && isFriendlyOrBug(c->mov[j]) && !attackingForbidden(c->mov[j], c) + /* && + (passable(c->mov[j], c, true, false, false) && !ishept(c->mov[j])) */ + ) { + + if(attackJustStuns(c->mov[j])) + addMessage(XLAT("%The1 attacks %the2!", c->monst, c->mov[j]->monst)); + else + addMessage(XLAT("%The1 kills %the2!", c->monst, c->mov[j]->monst)); + killWithMessage(c->mov[j], true); + } } // note: move from 'c' to 'from'! -void leadervisit(cell *c, cell *from, int d) { +void hexvisit(cell *c, cell *from, int d) { if(!c) return; - if(eq(c->tmp, sval)) return; + if(cellUnstable(c) || cellEdgeUnstable(c)) return; + if(eq(c->aitmp, sval)) return; + + if(cellUnstableOrChasm(c) || cellUnstableOrChasm(from)) return; + + /* if(c->monst == moHexSnake) + printf("%p:%p %s %d\n", from, c, dnameof(from->monst), passable(from, c, true, false, false)); */ - if(c->monst == moCultistLeader) { - // he cannot push big statues into bonfires, just like the player - if(c->wall == waBonfire && from->wall == waBigStatue) - return; - // note: move from 'c' to 'from'! - for(int j=0; jtype; j++) - if(c->mov[j] && isFriendlyOrBug(c->mov[j]) && !attackingForbidden(c->mov[j], c)) { - // XLATC eagle - addMessage(XLAT("%The1 punches %the2!", c->monst, c->mov[j]->monst)); - c->mov[j]->monst = moNone; - return; - } + if(from->cpdist && (!isWatery(from) && !passable(from, c, true, false, false))) return; + + if(c->monst == moHexSnake) { + // printf("got snake\n"); - if(from->wall != waBigStatue && !passable(from, c, false, false)) { - return; + if(ishept(from)) return; + + if(isFriendlyOrBug(from) && !attackingForbidden(from, c)) { + addMessage(XLAT("%The1 eats %the2!", c->monst, from->monst)); + killWithMessage(from, false); } + if(from->cpdist == 0 || from->monst) return; - if(from->wall == waBigStatue) { - from->wall = c->wall; - c->wall = waBigStatue; - } - // earthMove(c, from->spn[d]); - - from->monst = c->monst, c->monst = moNone; + snakeAttack(c); + if(c->monst == moRedTroll) + moveMonster(from, c); + else moveHexSnake(from, c, d); } - else if(c->wall == waBigStatue ? !canPushStatueOn(from) : !passable(c, from, false, false)) - return; + c->aitmp = sval; + if(c->bardir == 0) c->bardir = NOBARRIERS; - if(c->wall == waThumper || isFire(c)) return; - c->tmp = sval; - - if(size(leaderdfs) < 1000) leaderdfs.push_back(c); + if(size(hexdfs) < 2000) hexdfs.push_back(c); } -void moveleader() { - if(invismove) return; +void movehex() { + for(int p=0; ptype; i++) + if(c->mov[i]->monst == moHexSnake && !attackingForbidden(cwt.c, cwt.c->mov[i])) + killThePlayer(moHexSnake, p); + } sval++; - leaderdfs.clear(); - for(int i=0; itype; t++) - leadervisit(c->mov[t], c, t); + hexdfs.clear(); + for(int i=0; iaitmp = sval; + } + //hexdfs.push_back(cwt.c); + + for(int i=0; itype; t++) if(c->mov[t] && !ishept(c->mov[t])) + hexvisit(c->mov[t], c, t); + } + for(int i=0; imonst == moHexSnake) { + int t[2]; + t[0] = (c->mondir+2) % 6; + t[1] = (c->mondir+4) % 6; + if(hrand(2) == 0) swap(t[0], t[1]); + for(int u=0; u<2; u++) { + createMov(c, t[u]); + if(!ishept(c->mov[t[u]])) + hexvisit(c, c->mov[t[u]], c->spn[t[u]]); + } + } + if(c->monst == moHexSnake) { + snakeAttack(c); + kills[moHexSnake]++; + cell *c2 = c; + while(c2->monst == moHexSnakeTail || c2->monst == moHexSnake) { + if(c2->monst != moHexSnake && c2->mondir != NODIR) + snakepile(c2); + snakepile(c2); + c2->monst = moNone; + if(c2->mondir == NODIR) break; + c2 = c2->mov[c2->mondir]; + } + } } } +// next == +1 -> next +// next == -1 -> prev +cell *getWhirlpool(cell *c, int next) { + int i = 0; + if(!euclid && !c->master->alt) return NULL; + int d = celldistAlt(c); + int d2; + while(true) { + if(i == c->type) return NULL; + if(c->mov[i] && (d2 = celldistAlt(c->mov[i])) != d) + break; + i++; + } + if(i == c->type) return NULL; + if(d>d2) next = -next; + for(int j=1; jtype; j++) { + cell *c2 = c->mov[(i+42+next*j) % c->type]; + if(celldistAlt(c2) == d) return c2; + } + return NULL; + } + +void buildWhirlline(vector& whirlline, int d) { + again: + cell *at = whirlline[size(whirlline)-1]; + cell *prev = whirlline[size(whirlline)-2]; + for(int i=0; itype; i++) + if(at->mov[i] && (euclid || at->mov[i]->master->alt) && celldistAlt(at->mov[i]) == d && at->mov[i] != prev) { + whirlline.push_back(at->mov[i]); + goto again; + } + } + +void whirlGenerate(cell *wto) { + if(wto->wall == waBoat || wto->monst) + return; + + if(hrand(35000) < 40 + items[itWhirlpool]) + wto->monst = moCShark; + else if(hrand(5000) < 500) + wto->wall = waBoat; + + if(wto->wall == waBoat && (euclid || wto->master->alt)) { + int d = celldistAlt(wto); + // 250 : hard + if(hrand(5000) < 60 + 3 * items[itWhirlpool]) + wto->monst = moPirate; + if(hrand(5000) < 20 && d < -20) + wto->item = itOrbSafety; + if(hrand(5000) < 20*PRIZEMUL && d < -20) + placePrizeOrb(wto); + if(items[itWhirlpool] >= 10 && hrand(5000) < 20 && d < -15) + wto->item = itOrbWater; + else if(d<-10 && hrand(5000) < 1000-d) + wto->item = itWhirlpool; + } + } + +void whirlMove(cell *wto, cell *wfrom) { + // monsters don't move + if(wfrom && (wfrom == cwt.c || wfrom->monst)) + return; + // disappear + if(!wto) { wfrom->wall = waSea; wfrom->item = itNone; } + + if(wfrom && wto && wfrom->wall == waBoat && wto->wall == waSea && !wto->monst) { + wfrom->wall = waSea; wto->wall = waBoat; + } + + if(wfrom && wto && wfrom->item && !wto->item && wfrom->wall != waBoat) { + moveItem(wfrom, wto, false); + } + + if(wto && !wfrom) + whirlGenerate(wto); + } + +void movewhirlpool() { + sval++; + for(int i=0; iland == laWhirlpool && c->aitmp != sval && (euclid || c->master->alt)) { + cell *c2 = getWhirlpool(c, 1); + if(!c2) continue; + int d = celldistAlt(c); + vector whirlline; + whirlline.push_back(c); + whirlline.push_back(c2); + buildWhirlline(whirlline, d); + reverse(whirlline.begin(), whirlline.end()); + buildWhirlline(whirlline, d); + int z = size(whirlline); + + for(int i=0; iaitmp = sval; + + whirlMove(NULL, whirlline[0]); + + for(int i=0; imonst = moShadow; } -// from-to -bool ghostmove(cell* c1, cell* c2) { - if(c1->monst == moGhost || c1->monst == moWitchGhost) return true; - if(c1->monst == moGreaterShark) return c2->wall == waLake; - if(c1->monst == moWitchWinter) - return c2->wall == waBonfire || passable(c2, c1, false, false); - return false; - } - void moveghosts() { if(invismove) return; @@ -2521,11 +5867,17 @@ void moveghosts() { for(int i=0; istuntime) return; + + if(isGhostMover(c->monst) && c->cpdist == 1) + killThePlayer(c->monst, ONLY_ONE_PLAYER_POSSIBLE); + if(isGhostMover(c->monst) && c->cpdist > 1) { int goodmoves = 0; - for(int k=0; ktype; k++) if(c->mov[k] && !c->mov[k]->monst && c->mov[k]->cpdist < c->cpdist) - if(ghostmove(c, c->mov[k])) + for(int k=0; ktype; k++) if(c->mov[k] && c->mov[k]->cpdist < c->cpdist) + if(ghostmove(c->monst, c->mov[k], c)) goodmoves++; movesofgood[goodmoves].push_back(c); @@ -2534,6 +5886,7 @@ void moveghosts() { for(int d=0; d<8; d++) for(int i=0; istuntime) return; if(isGhostMover(c->monst) && c->cpdist > 1) { @@ -2543,29 +5896,45 @@ void moveghosts() { if(c->mov[j] && isFriendlyOrBug(c->mov[j])) { // XLATC ghost/greater shark addMessage(XLAT("%The1 scares %the2!", c->monst, c->mov[j]->monst)); - c->mov[j]->monst = moNone; + killWithMessage(c->mov[j], true); return; } int qmpos = 0; - for(int k=0; ktype; k++) if(c->mov[k] && !c->mov[k]->monst && c->mov[k]->cpdist < c->cpdist) - if(ghostmove(c, c->mov[k])) + for(int k=0; ktype; k++) if(c->mov[k] && c->mov[k]->cpdist < c->cpdist) + if(ghostmove(c->monst, c->mov[k], c)) mdir[qmpos++] = k; if(!qmpos) continue; - int d = mdir[rand() % qmpos]; + int d = mdir[hrand(qmpos)]; cell *c2 = c->mov[d]; - c2->monst = c->monst; c->monst = moNone; + moveMonster(c2, c); } } } int lastdouble = -3; -void stabbingAttack(cell *mf, cell *mt, eMonster who = moNone) { +void messageKill(eMonster killer, eMonster victim) { + if(isNonliving(victim)) { + if(killer) + addMessage(XLAT("%The1 destroys %the2!", killer, victim)); + else + addMessage(XLAT("You destroy %the1.", victim)); + } + else { + if(killer) + addMessage(XLAT("%The1 kills %the2!", killer, victim)); + else + addMessage(XLAT("You kill %the1.", victim)); + } + } + +void stabbingAttack(cell *mf, cell *mt, eMonster who) { int numsh = 0, numflail = 0, numlance = 0; for(int t=0; ttype; t++) { cell *c = mf->mov[t]; - if(c->monst == moHedge || (!who && items[itOrbThorns] && c->monst && isKillable(c))) { + if(!isUnarmed(who)) + if(c->monst == moHedge || (!who && c->monst && isKillable(c) && markOrb(itOrbThorns))) { for(int u=0; utype; u++) { if(c->mov[u] == mt) { if(who) @@ -2573,27 +5942,46 @@ void stabbingAttack(cell *mf, cell *mt, eMonster who = moNone) { else addMessage(XLAT("You stab %the1.", c->monst)); int k = tkills(); - killMonster(c); + killWithMessage(c, true); if(tkills() > k) numsh++; } } } - if(c->monst == moFlailer) { + if(c->monst == moFlailer || (c->monst == moVizier && !isUnarmed(who))) { bool away = true; + if(c == mt) away = false; for(int u=0; utype; u++) if(c->mov[u] == mt) away = false; if(away) { - if(who) - addMessage(XLAT("%The1 tricks %the2.", who, c->monst)); - else - addMessage(XLAT("You trick %the1.", c->monst)); - int k = tkills(); - killMonster(c); - if(tkills() > k) numflail++; + if(c->monst == moVizier && c->hitpoints > 1) { + if(who) + addMessage(XLAT("%The1 hits %the2.", who, c->monst)); + else + addMessage(XLAT("You hit %the1.", c->monst)); + c->hitpoints--; + // c->stuntime = 1; + } + else { + if(c->monst != moFlailer) { + messageKill(who, c->monst); + } + else { + if(who) + addMessage(XLAT("%The1 tricks %the2.", who, c->monst)); + else + addMessage(XLAT("You trick %the1.", c->monst)); + } + if(c->monst == moFlailer && isPrincess(who) && isUnarmed(who)) + achievement_gain("PRINCESS_PACIFIST"); + + int k = tkills(); + killWithMessage(c); + if(tkills() > k) numflail++; + } } } } - for(int t=0; ttype; t++) { + if(!isUnarmed(who)) for(int t=0; ttype; t++) { cell *c = mt->mov[t]; if(c->monst == moLancer) { if(who) @@ -2601,7 +5989,7 @@ void stabbingAttack(cell *mf, cell *mt, eMonster who = moNone) { else addMessage(XLAT("You trick %the1.", c->monst)); int k = tkills(); - killMonster(c); + killWithMessage(c); if(tkills() > k) numlance++; } } @@ -2623,41 +6011,120 @@ void movegolems() { for(int i=0; imonst; - if(m == moGolem || m == moKnight) { + if(isPrincess(m) && c->stuntime) continue; + if(m == moGolem || m == moKnight || m == moTameBomberbird || m == moPrincess || + m == moPrincessArmed || m == moMouse) { if(m == moGolem) qg++; int bestv = 100, bq = 0, bdirs[7]; for(int k=0; ktype; k++) if(c->mov[k]) { int val; - if(c->mov[k] == cwt.c) val = 0; - else if(isActiveEnemy(c->mov[k], NULL) && isKillable(c->mov[k]) && - !attackingForbidden(c->mov[k], c)) + cell *c2 = c->mov[k]; + if(c2 == cwt.c) val = 0; + else if(m == moPrincess && isStunnable(c2->monst) && c2->stuntime && c2->monst != moSkeleton && + !cellUnstableOrChasm(c) && !attackingForbidden(c2, c) && !isUnarmed(c2->monst)) { + val = 15000; + } + else if(m == moPrincessArmed && isPrincess(c2->monst) && !attackingForbidden(c2, c)) + val = 14000; // jealousy! + else if(isActiveEnemy(c2, NULL, false) && isKillable(c2) && + !attackingForbidden(c2, c) && !isUnarmed(m)) val = 12000; - else if(isInactiveEnemy(c->mov[k]) && isKillable(c->mov[k]) && - !attackingForbidden(c->mov[k], c)) + else if(isInactiveEnemy(c2, false) && isKillable(c2) && + !attackingForbidden(c2, c) && !isUnarmed(m) && c2->monst != moSkeleton) val = 10000; - else if(isIvy(c->mov[k]) && !attackingForbidden(c->mov[k], c)) val = 8000; - else if(monstersnear(c->mov[k], NULL, false)) val = 0; - else if(passable(c->mov[k], c, false, false)) val = 4000; + else if(isIvy(c2) && !attackingForbidden(c2, c) && !isUnarmed(m)) val = 8000; + else if(monstersnear(c2, NULL, m)) val = 50; // linked with mouse suicide! + else if(passable_for(m, c2, c, false)) val = 4000; else val = 0; - if(c->monst == moGolem) - val -= c->mov[k]->cpdist; - if(c->monst == moKnight && c->mov[k]->master->alt) - val -= celldistAlt(c->mov[k]); + if(c->monst == moGolem ) + val -= c2->cpdist; + else if(c->monst == moMouse) { + int d; + if(!euclid && (c2->land != laPalace || !c2->master->alt)) d = 200; + else d = celldistAlt(c2); + // first rule: suicide if the Princess is killed, + // by monstersnear or jumping into a chasm + princess::info *i = princess::getPrisonInfo(c); + if(i && !i->princess) { + if(val == 50 || c2->wall == waChasm) val = 20000; + } + // second rule: move randomly if the Princess is saved + if(i && i->bestdist > 6) + ; + // third rule: do not get too far from the Princess + else if(d > 150) + val -= (700+d); + // fourth rule: do not get too far from the Rogue + // NOTE: since Mouse is not a target, we can use + // the full pathfinding here instead of cpdist! + else if(c2->pathdist > 3 && c2->pathdist <= 19) + val -= (500+c2->pathdist * 10); + else if(c2->pathdist > 19) + val -= (700); + // fifth rule: get close to the Princess, to point the way + else + val -= (250+d); + /* + // avoid stepping on trapdoors and plates + // (REMOVED BECAUSE MICE NO LONGER ACTIVATE TRAPDOORS AND PLATES) + // note that the Mouse will still step on the trapdoor + // if it wants to get close to you and there is no other way + if(c2->wall == waTrapdoor) + val -= 5; + */ + } + if(isPrincess(c->monst)) { + + int d = c2->cpdist; + if(d <= 3) val -= d; + else val -= 10 * d; + + // the Princess also avoids stepping on pressure plates + if(c2->wall == waClosePlate || c2->wall == waOpenPlate || c2->wall == waTrapdoor) + val -= 5; + } + if(c->monst == moTameBomberbird) { + int d = c2->cpdist; + if(d == 1 && c->cpdist > 1) d = 5; + if(d == 2 && c->cpdist > 2) d = 4; + val -= d; + } + if(!euclid && c->monst == moKnight && c2->master->alt) + val -= celldistAlt(c2); if(val > bestv) bestv = val, bq = 0; if(val == bestv) bdirs[bq++] = k; } if(bestv <= 100) continue; - int dir = bdirs[rand() % bq]; + int dir = bdirs[hrand(bq)]; cell *c2 = c->mov[dir]; if(c2->monst) { - addMessage(XLAT("%The1 destroys %the2!", c->monst, c2->monst)); - killMonster(c2); + if(m == moPrincess) { + addMessage(XLAT("%The1 takes %his1 revenge on %the2!", m, c2->monst)); + killWithMessage(c2, false); + c->monst = m = moPrincessArmed; + } + else { + if(attackJustStuns(c2)) + addMessage(XLAT("%The1 attacks %the2!", m, c2->monst)); + else { + messageKill(c->monst, c2->monst); + if(isPrincess(c->monst) && isPrincess(c2->monst)) + addMessage("\"That should teach you to take me seriously!\""); + } + killWithMessage(c2, true); + } } else { - stabbingAttack(c, c2, m); - c2->monst = m == moGolem ? moGolemMoved : moKnightMoved; - c2->mondir = c->spn[dir]; - c->monst = moNone; + moveMonster(c2, c); + if(m != moTameBomberbird) + moveBoatIfUsingOne(c2, c); + + if(m == moGolem) c2->monst = moGolemMoved; + if(m == moMouse) c2->monst = moMouseMoved; + if(m == moPrincess) c2->monst = moPrincessMoved; + if(m == moPrincessArmed) c2->monst = moPrincessArmedMoved; + if(m == moTameBomberbird) c2->monst = moTameBomberbirdMoved; + if(m == moKnight) c2->monst = moKnightMoved; } } } @@ -2667,25 +6134,48 @@ void movegolems() { bool wchance(int a, int of) { of *= 10; a += items[itOrbYendor] * 5 + items[itHolyGrail] + 1; - if(cwt.c->land == laCrossroads) a+= items[itHyperstone] * 10; + if(isCrossroads(cwt.c->land)) + a+= items[itHyperstone] * 10; for(int i=0; icpdist == 7) { + c->monst = moOrangeDog; + return; + } + int q = 0; + cell *ctab[8]; + for(int i=0; itype; i++) { + cell *c3 = c->mov[i]; + if(c3 && c3 != c2 && c3->land == laZebra && c3->wall == waNone) + ctab[q++] = c3; + } + if(!q) break; + c2 = c; c = ctab[hrand(q)]; + } } void wandering() { - int t = turncount - lastexplore; + int t = shmup::on ? (shmup::curtime - lastexplore) / 350 : turncount - lastexplore; int seepcount = 0; - if(t > 40) seepcount = (t-40 + rand() % 20) / 20; + if(t > 40) seepcount = (t-40 + hrand(20)) / 20; int ghostcount = 0; - if(t > 80) ghostcount = (t-80 + rand() % 20) / 20; + if(t > 80) ghostcount = (t-80 + hrand(20)) / 20; + + if(cwt.c->land == laZebra && cwt.c->wall == waNone && wchance(items[itZebra], 20)) + wanderingZebra(cwt.c); while(first7 < size(dcal)) { - int i = first7 + rand() % (size(dcal) - first7); + int i = first7 + hrand(size(dcal) - first7); cell *c = dcal[i]; // wandering seeps & ghosts - if(seepcount && c->wall == waCavewall && !c->monst && eq(c->tmp, sval)) { + if(seepcount && c->wall == waCavewall && !c->monst && eq(c->aitmp, sval)) { c->monst = moSeep; seepcount--; continue; @@ -2697,104 +6187,145 @@ void wandering() { continue; } - if((c->wall == waCavewall || c->wall == waDeadwall) && !c->monst && eq(c->tmp, sval) && + if((c->wall == waCavewall || c->wall == waDeadwall) && !c->monst && eq(c->aitmp, sval) && wchance(items[treasureType(c->land)], 10)) { c->monst = moSeep; continue; } + else if(c->wall == waCTree && !c->monst && eq(c->aitmp, sval) && wchance(items[itPirate], 15)) { + c->monst = moParrot; + continue; + } + + else if(c->wall == waSea && !c->monst && eq(c->aitmp, sval)) { + if(c->land == laCaribbean && wchance(items[itPirate], 15)) { + c->monst = moCShark; + continue; + } + if(c->land == laOcean && cwt.c->landparam < 25 && c->landparam < 25 && wchance(items[itCoast], 25)) { + c->monst = moAlbatross; + continue; + } + if(c->land == laLivefjord && wchance(items[itFjord], 80) && items[itFjord] >= 10) { + c->monst = moWaterElemental; + continue; + } + break; + } + else if(c->monst || c->pathdist == INFD) break; + else if(hrand(50) < statuecount * statuecount) + c->monst = moCultistLeader; + else if(c->land == laIce && wchance(items[itDiamond], 10)) - c->monst = rand() % 2 ? moWolf : moYeti; + c->monst = hrand(2) ? moWolf : moYeti; else if(c->land == laDesert && wchance(items[itSpice], 10)) - c->monst = rand() % 10 ? moDesertman : moWorm; + c->monst = hrand(10) ? moDesertman : moWorm; + + else if(c->land == laRedRock && wchance(items[itRedGem], 10)) + c->monst = hrand(10) ? moRedTroll : moHexSnake; else if(c->land == laCaves && wchance(items[itGold], 5)) - c->monst = rand() % 3 ? moTroll : moGoblin; + c->monst = hrand(3) ? moTroll : moGoblin; + + else if(c->land == laHive && wchance(hivehard(), 25)) + c->monst = randomHyperbug(); else if(c->land == laDeadCaves && wchance(items[itSilver], 5)) - c->monst = rand() % 20 ? (rand() % 3 ? moDarkTroll : moGoblin) : moEarthElemental; + c->monst = hrand(20) ? (hrand(3) ? moDarkTroll : moGoblin) : moEarthElemental; else if(c->land == laJungle && wchance(items[itRuby], 40)) - c->monst = rand() % 10 ? moMonkey : moEagle; + c->monst = hrand(10) ? moMonkey : moEagle; else if(c->land == laMirror && wchance(items[itShard], 15)) - c->monst = rand() % 10 ? moRanger : moEagle; + c->monst = hrand(10) ? moRanger : moEagle; else if(c->land == laHell && wchance(items[itHell], 20)) - c->monst = rand() % 3 ? moLesser : moGreater; + c->monst = hrand(3) ? moLesser : moGreater; + + else if(c->land == laCaribbean && wchance(items[itPirate], 30)) + c->monst = moPirate; else if(c->land == laRlyeh && wchance(items[itStatue], 15)) - c->monst = rand() % 3 ? moPyroCultist : - (rand() % 40 < items[itStatue]-25) ? moCultistLeader : moCultist; + c->monst = hrand(3) ? moPyroCultist : + (hrand(40) < items[itStatue]-25) ? moCultistLeader : moCultist; else if(c->land == laGraveyard && wchance(items[itBone], 15)) - c->monst = rand() % 5 ? moGhost : moNecromancer; + c->monst = hrand(5) ? moGhost : moNecromancer; else if(c->land == laDryForest && wchance(items[itFernFlower], 5)) - c->monst = rand() % 5 ? moHedge : moFireFairy; + c->monst = hrand(5) ? moHedge : moFireFairy; else if(c->land == laCocytus && wchance(items[itSapphire], 45)) c->monst = moCrystalSage; - else if(c->land == laAlchemist && wchance(items[itElixir], 3) && eq(c->tmp, sval) && c->item == itNone) + else if(c->land == laAlchemist && wchance(items[itElixir], 3) && eq(c->aitmp, sval) && c->item == itNone) c->monst = moSlime; - else if(c->land == laFjord && wchance(items[itEmerald], 5)) { + else if(isElemental(c->land) && wchance(items[itElemental], 20)) + c->monst = elementalOf(c->land); + + else if(c->land == laEdge && wchance(items[itEdge], 20)) + c->monst = moGargoyle; + + else if(c->land == laMinefield && wchance(items[itBombEgg]-20, 400)) + c->monst = moBomberbird; + + else if(c->land == laEmerald && wchance(items[itEmerald], 5)) { static eMonster m[4] = {moHedge, moLancer, moMiner, moFlailer}; - c->monst = m[rand() % 4]; + c->monst = m[hrand(4)]; } else if(c->land == laWineyard && wchance(items[itWine], 10)) { c->monst = moVineBeast; } + else if(c->land == laPalace && wchance(items[itPalace], 50)) { + if(princess::dist(c) < OUT_OF_PRISON && !princess::challenge) break; + + if(items[itPalace] >= 15 && hrand(100) < 10) + c->monst = moVizier; + else if(items[itPalace] >= 5 && hrand(100) < 50) + c->monst = hrand(2) ? moFatGuard : moSkeleton; + else c->monst = moPalace; + c->hitpoints = palaceHP(); + } + + else if(c->land == laLivefjord && wchance(items[itFjord], 10)) { + c->monst = moViking; + } + + else if(c->land == laOcean && wchance(items[itCoast], 100)) { + c->monst = moAlbatross; + } + else if(c->land == laPower && wchance(items[itPower], 10)) { - c->monst = eMonster(moWitch + rand() % NUMWITCH); + c->monst = eMonster(moWitch + hrand(NUMWITCH)); } - else if(c->land == laCamelot && rand() % 30 == 0 && celldistAltRelative(c) < 0) { + else if(c->land == laCamelot && hrand(30) == 0 && (euclid || c->master->alt) && celldistAltRelative(c) < 0) { eMonster m[3] = { moHedge, moLancer, moFlailer }; - c->monst = m[rand() % 3]; + c->monst = m[hrand(3)]; } - else if(c->land == laCrossroads && items[itHyperstone] && wchance(items[itHyperstone], 20)) { - // only interesting monsters here! - static eMonster m[12] = { - moWorm, moTroll, moEagle, - moLesser, moGreater, moPyroCultist, moGhost, - moFireFairy, moHedge, - moLancer, moFlailer, moVineBeast - }; - c->monst = m[rand() % 9]; + else if(isCrossroads(c->land) && items[itHyperstone] && wchance(items[itHyperstone], 20)) { + c->monst = wanderingCrossroadsMonster(); } else break; - if(c->monst == moWorm) c->mondir = NODIR; + if(c->monst == moWorm || c->monst == moHexSnake) c->mondir = NODIR; // laMotion -> no respawn! } } void sageheat(cell *c, double v) { - c->heat += v; - if(c->wall == waFrozenLake && c->heat > .6) c->wall = waLake; - } - -bool normalMover(eMonster m) { - return - m == moYeti || m == moRanger || m == moGoblin || m == moTroll || m == moDesertman || - m == moMonkey || m == moZombie || m == moNecromancer || m == moCultist || - m == moLesser || m == moGreater || m == moRunDog || m == moPyroCultist || - m == moFireFairy || m == moCrystalSage || m == moHedge || - m == moVineBeast || m == moLancer || m == moFlailer || - m == moMiner || m == moDarkTroll || - (cwt.c->land == laPower && ( - (isWitch(m) && m != moWitchGhost && m != moWitchWinter) || m == moEvilGolem - )); + HEAT(c) += v; + if(c->wall == waFrozenLake && HEAT(c) > .6) c->wall = waLake; } struct buginfo_t { @@ -2846,9 +6377,7 @@ void bugQueueInsert(int k, int i, int d) { } void bugcell(cell *c) { - if(isActiv(c) || !passable(c, NULL, true, false)) - return; - short& i(c->tmp); + short& i(c->aitmp); if(i >= 0 && i < size(buginfo) && buginfo[i].where == c) return; i = size(buginfo); @@ -2884,8 +6413,8 @@ void bugcell(cell *c) { }*/ // use pheromones! - if(c->land == laHive && c->heat > 1) { - c->heat -= 1; + if(c->land == laHive && c->landparam > 1) { + c->landparam --; for(int dir=0; dirtype; dir++) { cell *c2 = c->mov[dir]; if(c2) { @@ -2910,9 +6439,9 @@ void handleBugQueue(int k, int t) { for(int dir=0; dirtype; dir++) { cell *c2 = c->mov[dir]; if(!c2) continue; - if(c2->tmp < 0 || c2->tmp >= size(buginfo)) continue; - if(!passable(c, c2, true, false)) continue; - int j = c2->tmp; + if(c2->aitmp < 0 || c2->aitmp >= size(buginfo)) continue; + if(!passable(c, c2, true, false, false)) continue; + int j = c2->aitmp; if(buginfo[j].where != c2) continue; if(buginfo[j].dist[k] < d) goodmoves++; bugQueueInsert(k, j, d+1); @@ -2972,6 +6501,7 @@ void movebugs() { buginfo_t& b(buginfo[i]); cell *c = b.where; if(!isBug(c)) continue; + if(c->stuntime) continue; eMonster m = c->monst; int k = (m - moBug0) % BUGCOLORS; int gmoves[8], q=0, bqual = -1; @@ -2984,12 +6514,12 @@ void movebugs() { qual = c2 != cwt.c ? 2 : -5; else { if(c2->monst) continue; - if(!passable(c2, c, false, false)) continue; - if(c2->tmp < 0 || c2->tmp >= size(buginfo)) continue; - if(buginfo[c2->tmp].where != c2) continue; - if(buginfo[c2->tmp].dist[k] < b.dist[k]) + if(!passable(c2, c, false, false, false)) continue; + if(c2->aitmp < 0 || c2->aitmp >= size(buginfo)) continue; + if(buginfo[c2->aitmp].where != c2) continue; + if(buginfo[c2->aitmp].dist[k] < b.dist[k]) qual = 1; - else if(buginfo[c2->tmp].dist[k] == b.dist[k]) + else if(buginfo[c2->aitmp].dist[k] == b.dist[k]) qual = 0; } // printf("%d->#%d %d: %d\n", i, dir, c2->tmp, qual); @@ -2997,14 +6527,14 @@ void movebugs() { if(qual == bqual) gmoves[q++] = dir; } - if(!q) { c->heat += 3; continue; } - int d = gmoves[rand() % q]; + if(!q) { if(c->land == laHive) c->landparam += 3; continue; } + int d = gmoves[hrand(q)]; cell *c2 = c->mov[d]; if(c2->monst) { eMonster killed = c2->monst; if(isBug(killed)) battlecount++; else addMessage(XLAT("%The1 fights with %the2!", c->monst, c2->monst)); - killMonster(c2); + killOrStunMonster(c2); // killMonster(c); if(isBug(killed)) { c2->monst = moDeadBug, deadbug.push_back(c2); @@ -3013,12 +6543,10 @@ void movebugs() { // c->monst = moDeadBug, deadbug.push_back(c); } else { - c2->monst = c->monst; - c2->mondir = c->spn[d]; - c->monst = moNone; + moveMonster(c2, c); // pheromones! - if(c->heat < 90) c->heat += 5; - if(c2->heat < 90) c2->heat += 5; + if(c->land == laHive && c->landparam < 90) c->landparam += 5; + if(c2->land == laHive && c2->landparam < 90) c2->landparam += 5; // if(isHive(c2->land)) c2->land = eLand(laHive0+k); /* if(c2->item == itRoyalJelly && !isQueen(m)) { // advance! @@ -3040,8 +6568,7 @@ void movebugs() { } void bugcitycell(cell *c, int d) { - if(isActiv(c) || !passable(c, NULL, true, false)) return; - short& i = c->tmp; + short& i = c->aitmp; if(i >= 0 && i < size(buginfo) && buginfo[i].where == c) return; i = size(buginfo); @@ -3052,30 +6579,30 @@ void bugcitycell(cell *c, int d) { } void createBugArmy(cell *c) { - int k = rand() % BUGCOLORS; + int k = randomHyperbug() - moBug0; int minbugs = 50, maxbugs = 50; int var = 5 + items[itRoyalJelly]; if(var>25) var=25; // minbugs += 100; maxbugs += 100; minbugs -= var; maxbugs += var; maxbugs += items[itRoyalJelly]; - int numbugs = minbugs + rand() % (maxbugs - minbugs + 1); + int numbugs = minbugs + hrand(maxbugs - minbugs + 1); /* int i = items[itRoyalJelly]; int chance = 20 + 25 * i + 9000; // i=0: 16% // i=10: 73% // i=50: 1270 vs 6000 - eMonster m = eMonster(moBug0 + rand() % BUGCOLORS); + eMonster m = eMonster(moBug0 + hrand(BUGCOLORS)); if(c->wall) return; for(int i=0; itype; i++) { cell *c2 = createMov(c,i); - if(rand() % (100+chance) < chance) { + if(hrand(100+chance) < chance) { if(!c2->wall) c2->monst = m; for(int j=2; j<=c2->type-2; j++) { int jj = (j+c->spn[i]) % c2->type; cell *c3 = createMov(c2, jj); - if(rand() % (6000+chance) < chance && !c3->wall) + if(hrand(6000+chance) < chance && !c3->wall) c3->monst = m; } } @@ -3092,7 +6619,7 @@ void createBugArmy(cell *c) { if(bf.c->type == 6) cwspin(bf, 3); else - cwspin(bf, 3 + rand() % 2); + cwspin(bf, 3 + hrand(2)); cwstep(bf); } cell *citycenter = bf.c; @@ -3107,7 +6634,7 @@ void createBugArmy(cell *c) { // ERRORS! if(c->land != laHive && c->land != laNone) return; if(c->bardir != NODIR) return; - if(c->heat >= 100) return; + if(c->land == laHive && c->landparam >= 100) return; // bfs if(d < 9) for(int t=0; ttype; t++) bugcitycell(createMov(c,t), d+1); @@ -3140,9 +6667,8 @@ void moveFastMonsters() { if(c->monst == moWitchSpeed) { - if(c->pathdist == 1 && c->monst != moGhost) { - if(items[itOrbShield]) continue; - addMessage(XLAT("%The1 is confused!", c->monst)); + if(c->cpdist == 1 && c->monst != moGhost) { + killThePlayer(c->monst, ONLY_ONE_PLAYER_POSSIBLE); break; } @@ -3172,13 +6698,13 @@ bool sagefresh = true; void considerEnemyMove(cell *c) { eMonster m = c->monst; - if(isActiveEnemy(c, NULL)) { + if(isActiveEnemy(c, NULL, true)) { - if(c->pathdist == 1 && c->monst != moGhost) { + if(c->cpdist == 1 && c->monst != moGhost && isNeighbor(c, cwt.c) && !attackingForbidden(cwt.c, c)) { // c->iswall = true; c->ismon = false; - if(items[itOrbShield] || c->monst == moCrystalSage) return; - - addMessage(XLAT("%The1 is confused!", m)); + if(c->monst == moCrystalSage) return; + + killThePlayer(m, ONLY_ONE_PLAYER_POSSIBLE); // playerdead = true; return; } @@ -3193,14 +6719,14 @@ void considerEnemyMove(cell *c) { cell *gtab[8], *ztab[8]; for(int j=0; jtype; j++) if(c->mov[j]) { if(c->mov[j]->wall == waFreshGrave) gtab[gravenum++] = c->mov[j]; - if(passable(c->mov[j], c, false, false) && c->mov[j]->pathdist < c->pathdist) + if(passable(c->mov[j], c, false, false, false) && c->mov[j]->pathdist < c->pathdist) ztab[zombienum++] = c->mov[j]; } if(gravenum && zombienum) { - cell *gr = gtab[rand() % gravenum]; + cell *gr = gtab[hrand(gravenum)]; gr->wall = waAncientGrave; gr->monst = moGhost; - ztab[rand() % zombienum]->monst = moZombie; + ztab[hrand(zombienum)]->monst = moZombie; addMessage(XLAT("%The1 raises some undead!", c->monst)); return; } @@ -3208,31 +6734,35 @@ void considerEnemyMove(cell *c) { if(c->monst == moWolf) { int bhd = NODIR; - ld besth = c->heat; - for(int j=0; jtype; j++) if(c->mov[j]->heat > besth && passable(c->mov[j], c, false, false)) - besth = c->mov[j]->heat, bhd = j; + ld besth = absheat(c); + for(int j=0; jtype; j++) + if(isIcyLand(c->mov[j])) + if(absheat(c->mov[j]) > besth && passable(c->mov[j], c, false, false, false)) + besth = absheat(c->mov[j]), bhd = j; if(bhd != NODIR) { // printf("wolf moved from %Lf (%p) to %Lf (%p)\n", c->heat, c, besth, c->mov[bhd]); - c->mov[bhd]->monst = moWolfMoved, c->monst = moNone; + moveMonster(c->mov[bhd], c); + c->mov[bhd]->monst = moWolfMoved; } } - else if(c->monst == moPyroCultist && c->cpdist <= 4 && cwt.c->wall == waNone && !cellUnstable(cwt.c)) { + else if(c->monst == moPyroCultist && c->cpdist <= 4 && makeflame(cwt.c, 20, true)) { addMessage(XLAT("%The1 throws fire at you!", c->monst)); - if(itemBurns(cwt.c->item)) - addMessage(XLAT("%The1 burns!", cwt.c->item)), cwt.c->item = itNone; - cwt.c->wall = waBonfire; - cwt.c->tmp = 20; + makeflame(cwt.c, 20, false); c->monst = moCultist; } + else if(c->monst == moPyroCultist && c->cpdist <= 3) { + // just wait until the player moves + } + else if(c->monst == moWitchFlash && flashWouldKill(c, true) && !flashWouldKill(c, false)) { addMessage(XLAT("%The1 activates her Flash spell!", c->monst)); c->monst = moWitch; activateFlashFrom(c); } - else if(c->monst == moCrystalSage && c->cpdist <= 4 && isIcyLand(cwt.c)) { + else if(c->monst == moCrystalSage && c->cpdist <= 4 && isIcyLand(cwt.c) && cwt.c->wall != waBoat) { // only one sage attacks if(sagefresh) { sagefresh = false; @@ -3267,6 +6797,110 @@ void considerEnemyMove(cell *c) { } } +void moveworms() { + int wrm = size(worms); + for(int i=0; imonst == moWolfMoved) c->monst = moWolf; + if(c->monst == moIvyNext) { + c->monst = moIvyHead; ivynext(c); + } + if(c->monst == moIvyDead) + removeIvy(c); + if(c->monst == moGolemMoved) c->monst = moGolem; + if(c->monst == moMouseMoved) c->monst = moMouse; + if(c->monst == moPrincessMoved) c->monst = moPrincess; + if(c->monst == moPrincessArmedMoved) c->monst = moPrincessArmed; + if(c->monst == moKnightMoved) c->monst = moKnight; + if(c->monst == moTameBomberbirdMoved) c->monst = moTameBomberbird; + if(c->monst == moSlimeNextTurn) c->monst = moSlime; + if(c->monst == moLesser) c->monst = moLesserM; + else if(c->monst == moLesserM) c->monst = moLesser; + if(c->monst == moGreater) c->monst = moGreaterM; + else if(c->monst == moGreaterM) c->monst = moGreater; + + if(c->stuntime) c->stuntime--; + + if(c->wall == waChasm) { + c->item = itNone; + if(c->monst && !survivesChasm(c->monst)) { + if(c->monst != moRunDog && c->land == laMotion) + achievement_gain("FALLDEATH1"); + addMessage(XLAT("%The1 falls!", c->monst)); + killWithMessage(c, false); + } + } + + if(isFire(c)) { + if(c->monst && !survivesFire(c->monst)) { + addMessage(XLAT("%The1 burns!", c->monst)); + killWithMessage(c, false); + } + } + + if(c->wall == waMineMine && c->monst && !survivesMine(c->monst)) + explodeMine(c); + + if(isWatery(c)) { + if(c->monst == moLesser || c->monst == moLesserM || c->monst == moGreater || c->monst == moGreaterM) + c->monst = moGreaterShark; + if(c->monst && !survivesWater(c->monst)) { + if(isNonliving(c->monst)) + addMessage(XLAT("%The1 sinks!", c->monst)); + else + addMessage(XLAT("%The1 drowns!", c->monst)); + killWithMessage(c, false); + } + } + + if(c->monst && c->wall == waClosedGate && !survivesWall(c->monst)) { + addMessage(XLAT("%The1 is crushed!", c->monst)); + killWithMessage(c, false); + } + + if(c->monst && cellUnstable(c) && !survivesChasm(c->monst) && !ignoresPlates(c->monst) && !shmup::on) { + c->wall = waChasm; + } + } + } + void movemonsters() { sagefresh = true; @@ -3300,73 +6934,31 @@ void movemonsters() { if(sagefresh) sagephase = 0; DEBT("worm"); - int wrm = size(worms); - for(int i=0; imonst == moWolfMoved) c->monst = moWolf; - if(c->monst == moIvyNext) { - c->monst = moIvyHead; ivynext(c); - } - if(c->monst == moIvyDead) - removeIvy(c); - if(c->monst == moGolemMoved) c->monst = moGolem; - if(c->monst == moKnightMoved) c->monst = moKnight; - if(c->monst == moSlimeNextTurn) c->monst = moSlime; - if(c->monst == moLesser) c->monst = moLesserM; - else if(c->monst == moLesserM) c->monst = moLesser; - if(c->monst == moGreater) c->monst = moGreaterM; - else if(c->monst == moGreaterM) c->monst = moGreater; - - if(c->wall == waChasm) { - c->item = itNone; - if(c->monst && c->monst != moGhost && c->monst != moEagle) { - if(c->monst != moRunDog) achievement_gain("FALLDEATH1"); - killMonster(c); - } - } - - if(c->wall == waBonfire) { - if(c->monst && c->monst != moGhost && c->monst != moWitchWinter && c->monst != moWitchGhost) { - addMessage(XLAT("%The1 burns!", c->monst)); - killMonster(c); - } - } - - if(c->wall == waLake) { - c->item = itNone; - if(c->monst == moLesser || c->monst == moLesserM || c->monst == moGreater || c->monst == moGreaterM) - c->monst = moGreaterShark; - if(c->monst && c->monst != moShark && c->monst != moGreaterShark && - c->monst != moGhost && c->monst != moEagle) killMonster(c); - } - - if(c->monst && cellUnstable(c) && c->monst != moGhost && c->monst != moEagle) { - c->wall = waChasm; - } - } + moverefresh(); DEBT("shadow"); moveshadow(); @@ -3379,28 +6971,65 @@ void movemonsters() { vector vinefires; -void heat() { - double rate = items[itOrbSpeed] ? .5 : 1; +void processheat(double rate = 1, bool tick = true) { + if(markOrb(itOrbSpeed)) rate /= 2; int oldmelt = kills[0]; + + vector offscreen2; + + for(int i=0; icpdist > 7) { + bool readd = false; + if(isIcyLand(c)) { + if(HEAT(c) < .01 && HEAT(c) > -.01) + HEAT(c) = 0; + else { + HEAT(c) *= 1 - rate/10; + readd = true; + } + } + if(hasTimeout(c)) { + useup(c); + if(hasTimeout(c)) readd = true; + } + if(readd) offscreen2.push_back(c); + } + } + + offscreen.clear(); swap(offscreen, offscreen2); /* if(cwt.c->heat > .5) cwt.c->heat += .3; if(cwt.c->heat > 1.) cwt.c->heat += .3; if(cwt.c->heat > 1.4) cwt.c->heat += .5; */ - if(isIcyLand(cwt.c)) - cwt.c->heat += (items[itOrbWinter] ? -1.2 : 1.2) * rate; + + for(int i=0; iland == laCocytus && shmup::on) ? rate/3 : rate; + if(isIcyLand(c)) + HEAT(c) += (markOrb(itOrbWinter) ? -1.2 : 1.2) * xrate; + } vinefires.clear(); int dcs = size(dcal); for(int i=0; iland == laCocytus && shmup::on) ? rate/3 : rate; if(c->cpdist > 8) break; - if(isFire(c) && c->tmp > 0) { - if(c->land != laPower) useup(c); - if(c->wall == waBonfire) for(int i=0; itype; i++) { + + if(hasTimeout(c)) { + if(tick) useup(c); + readd = true; + } + + if(isFire(c) && tick) { + if(c->wall != waPartialFire) for(int i=0; itype; i++) { cell *c2 = c->mov[i]; if(c2 && c2->wall == waVinePlant) vinefires.push_back(c2); + if(c2 && c2->wall == waBonfireOff) activateActiv(c2, false); // both halfvines have to be near fire at once if(c2 && cellHalfvine(c2) && c->mov[(i+1)%c->type]->wall == c2->wall) vinefires.push_back(c2); @@ -3416,68 +7045,77 @@ void heat() { } } } - if(!isIcyLand(c)) continue; - if(c->monst == moRanger) c->heat += 3 * rate; - if(c->monst == moDesertman) c->heat += 4 * rate; - if(c->monst == moMonkey) c->heat += rate; - if(c->wall == waDeadTroll) c->heat -= 2 * rate; - if(c->wall == waBigStatue) c->heat -= 3 * rate; - if(c->monst == moLesser || c->monst == moLesserM || c->monst == moGreater || c->monst == moGreaterM) - c->heat += (c->land == laCocytus ? 1.5 : 10) * rate; - if(c->monst == moGreaterShark) - c->heat += 2 * rate; - if(c->monst == moCultist) c->heat += 3 * rate; - if(c->monst == moCultistLeader) c->heat += 4 * rate; - if(c->monst == moPyroCultist) c->heat += 6 * rate; - if(c->monst == moGhost) c->heat -= rate; - if(c->wall == waBonfire && c->tmp > 0) c->heat += 4 * rate; - - ld hmod = 0; - - for(int j=0; jtype; j++) if(c->mov[j]) { - if(!isIcyLand(c->mov[j])) { - // make sure that we can still enter Cocytus, - // it won't heat up right away even without Orb of Winter or Orb of Speed - if(c->mov[j] == cwt.c && (c->land == laIce || items[itOrbWinter])) - hmod += rate * (items[itOrbWinter] ? -1.2 : 1.2) / 4; - continue; + if(isIcyLand(c)) { + if(c->monst == moRanger) HEAT(c) += 3 * xrate; + if(c->monst == moDesertman) HEAT(c) += 4 * xrate; + if(c->monst == moMonkey) HEAT(c) += xrate; + if(c->wall == waDeadTroll) HEAT(c) -= 2 * xrate; + if(c->wall == waBigStatue) HEAT(c) -= .5 * xrate; + if(c->monst == moLesser || c->monst == moLesserM || c->monst == moGreater || c->monst == moGreaterM) + HEAT(c) += (c->land == laCocytus ? 1.5 : 10) * xrate; + if(c->monst == moGreaterShark) + HEAT(c) += 2 * xrate; + if(c->monst == moCultist) HEAT(c) += 3 * xrate; + if(c->monst == moCultistLeader) HEAT(c) += 4 * xrate; + if(c->monst == moPyroCultist) HEAT(c) += 6 * xrate; + if(c->monst == moFireFairy) HEAT(c) += 6 * xrate; + if(c->monst == moFireElemental) HEAT(c) += 8 * xrate; + if(c->monst == moGhost) HEAT(c) -= xrate; + if(c->monst == moWaterElemental) HEAT(c) -= xrate; + if(isFire(c)) HEAT(c) += 4 * xrate; + if(isPrincess(c->monst)) HEAT(c) += 1.2 * xrate; + + ld hmod = 0; + + for(int j=0; jtype; j++) if(c->mov[j]) { + if(!isIcyLand(c->mov[j])) { + // make sure that we can still enter Cocytus, + // it won't heat up right away even without Orb of Winter or Orb of Speed + if(c->mov[j] == cwt.c && (c->land == laIce || markOrb(itOrbWinter))) + hmod += (markOrb(itOrbWinter) ? -1.2 : 1.2) / 4; + continue; + } + ld hdiff = absheat(c->mov[j]) - absheat(c); + hdiff /= 10; + if(shmup::on && (c->land == laCocytus || c->mov[j]->land == laCocytus)) + hdiff /= 3; + if(c->mov[j]->cpdist <= 7) + HEAT(c->mov[j]) -= hdiff * rate; + else + hdiff = -HEAT(c) / 30; + hmod += hdiff; + } + + HEAT(c) += hmod * rate; + if(c->monst == moCrystalSage && HEAT(c) >= SAGEMELT) { + addMessage(XLAT("%The1 melts away!", c->monst)); + killWithMessage(c, false); } - ld hdiff = c->mov[j]->heat - c->heat; - hdiff /= 10; - if(c->mov[j]->cpdist <= 8) - c->mov[j]->heat -= hdiff; - else - hdiff = -c->heat / 250; - hmod += hdiff; } - c->heat += hmod * rate; - if(c->monst == moCrystalSage && c->heat >= SAGEMELT) { - addMessage(XLAT("%The1 melts away!", c->monst)); - killMonster(c); - } + if(readd || HEAT(c)) + offscreen.push_back(c); } for(int i=0; iwall == waIcewall && c->heat > .4) c->wall = waNone, kills[0]++; - if(c->wall == waFrozenLake && c->heat > .6) c->wall = waLake, kills[0]++; - if(c->wall == waLake && c->heat < -.4 && c->monst != moGreaterShark) { + if(c->wall == waIcewall && HEAT(c) > .4) c->wall = waNone, kills[0]++; + if(c->wall == waFrozenLake && HEAT(c) > (c->land == laCocytus ? .6 : .4)) c->wall = waLake, kills[0]++; + + if(c->wall == waLake && HEAT(c) < (c->land == laCocytus ? -.4 : .4) && c->monst != moGreaterShark) { c->wall = waFrozenLake; - if(c->monst == moShark) { + if(c->monst == moShark || c->monst == moCShark) { addMessage(XLAT("%The1 is frozen!", c->monst)); - killMonster(c); + killWithMessage(c, false); } } } - for(int i=0; iwall == waVinePlant) { - if(c->monst == moVineBeast) killMonster(c); - c->wall = waBonfire, c->tmp = 6; - } - else if(cellHalfvine(c)) destroyHalfvine(c, waPartialFire); + if(c->wall == waVinePlant) + makeflame(c, 6, false); + else if(cellHalfvine(c)) destroyHalfvine(c, waPartialFire, 6); } if(kills[0] != oldmelt) bfs(); @@ -3494,52 +7132,110 @@ void livecaves() { cell *c = dcal[i]; if(c->cpdist > 8) break; - if(c->wall != waCavefloor && c->wall != waCavewall) continue; - - // if(c->wall == waThumper || c->wall == waBonfire) continue; - c->tmp = 0; - if(c->monst == moDarkTroll) c->monst = moTroll; - if(c->item || c->monst || c->cpdist == 0) continue; - for(int j=0; jtype; j++) if(c->mov[j]) { - if(c->mov[j]->wall == waDeadfloor) c->tmp++, bringlife.push_back(c->mov[j]); - else if(c->mov[j]->wall == waDeadwall || c->mov[j]->wall == waDeadfloor2) c->tmp--, bringlife.push_back(c->mov[j]); - else if(c->mov[j]->wall == waCavefloor) c->tmp++; - else if(c->mov[j]->wall == waCavewall) c->tmp--; - else if(c->mov[j]->wall == waDeadTroll) c->tmp -= 5; - else if(c->mov[j]->wall == waVinePlant) c->tmp--; - else if(c->mov[j]->wall != waBarrier) c->tmp += 5; - if(c->mov[j]->cpdist == 0 && items[itOrbDigging]) c->tmp+=100; - if(c->mov[j]->wall == waThumper && c->mov[j]->tmp > 0) c->tmp+=100; - if(c->mov[j]->wall == waBonfire) c->tmp+=100; - if(c->mov[j]->wall == waBigStatue) c->tmp-=100; - if(c->mov[j]->item) c->tmp+=2; - if(c->mov[j]->monst == moZombie) c->tmp += 10; - if(c->mov[j]->monst == moGhost) c->tmp += 10; - if(c->mov[j]->monst == moNecromancer) c->tmp += 10; - if(c->mov[j]->monst == moWormtail) c->tmp++; - if(c->mov[j]->monst == moTentacletail) c->tmp-=2; - if(isIvy(c->mov[j])) c->tmp--; - if(isDemon(c->mov[j])) c->tmp-=3; - // if(c->mov[j]->monst) c->tmp++; - // if(c->mov[j]->monst == moTroll) c->tmp -= 3; + if(c->wall == waCavefloor || c->wall == waCavewall) { + c->aitmp = 0; + if(c->monst == moDarkTroll) c->monst = moTroll; + if(c->item || c->monst || c->cpdist == 0) continue; + for(int j=0; jtype; j++) if(c->mov[j]) { + if(c->mov[j]->wall == waDeadfloor) c->aitmp++, bringlife.push_back(c->mov[j]); + else if(c->mov[j]->wall == waDeadwall || c->mov[j]->wall == waDeadfloor2) c->aitmp--, bringlife.push_back(c->mov[j]); + else if(c->mov[j]->wall == waCavefloor) c->aitmp++; + else if(c->mov[j]->wall == waCavewall) c->aitmp--; + else if(c->mov[j]->wall == waRubble) c->aitmp--; + else if(c->mov[j]->wall == waGargoyle) c->aitmp--; + else if(c->mov[j]->wall == waGargoyleFloor) c->aitmp--; + else if(c->mov[j]->wall == waGargoyleBridge) c->aitmp--; + else if(c->mov[j]->wall == waDeadTroll) c->aitmp -= 5; + else if(c->mov[j]->wall == waVinePlant) c->aitmp--; + else if(c->mov[j]->wall != waBarrier) c->aitmp += 5; + if(c->mov[j]->cpdist == 0 && markOrb(itOrbDigging)) c->aitmp+=100; + if(c->mov[j]->wall == waThumperOn) c->aitmp+=100; + if(c->mov[j]->wall == waFire) c->aitmp+=100; + if(c->mov[j]->wall == waBigStatue) c->aitmp-=100; + if(c->mov[j]->item) c->aitmp+=2; + if(c->mov[j]->monst == moZombie) c->aitmp += 10; + if(c->mov[j]->monst == moGhost) c->aitmp += 10; + if(c->mov[j]->monst == moGargoyle) c->aitmp--; + if(c->mov[j]->monst == moNecromancer) c->aitmp += 10; + if(c->mov[j]->monst == moWormtail) c->aitmp++; + if(c->mov[j]->monst == moTentacletail) c->aitmp-=2; + if(isIvy(c->mov[j])) c->aitmp--; + if(isDemon(c->mov[j])) c->aitmp-=3; + // if(c->mov[j]->monst) c->tmp++; + // if(c->mov[j]->monst == moTroll) c->tmp -= 3; + } + } + else if(c->land == laLivefjord) { + c->aitmp = 0; + if(c->monst == moWaterElemental) + c->aitmp += 1000; + if(isPlayerInBoatOn(c) && markOrb(itOrbWater)) + c->aitmp += 1000; + if(c->monst == moEarthElemental) + c->aitmp -= 1000; + if(isPlayerOn(c) && markOrb(itOrbDigging)) + c->aitmp -= 1000; + for(int j=0; jtype; j++) if(c->mov[j]) { + cell *c2 = c->mov[j]; + if(c2->wall == waNone || c2->wall == waStrandedBoat) + c->aitmp -= (c2->land == laLivefjord ? 1 : 100); + if(c2->wall == waTempFloor || c2->wall == waTempBridge) + ; + else if(c2->wall == waDeadTroll || c2->wall == waThumperOn || isFire(c2) || snakelevel(c2)) + c->aitmp -= 10; + if(c2->wall == waBigStatue) + c->aitmp -= 10; + if(c2->wall == waSea || c2->wall == waBoat) + c->aitmp += (c2->land == laLivefjord ? 1 : 100); + if(c2->monst == moWaterElemental) + c->aitmp += 1000; + if(c2 == cwt.c && c2->wall == waBoat && markOrb(itOrbWater)) + c->aitmp += 1000; + if(c2->monst == moEarthElemental) + c->aitmp -= 1000; + if(c2 == cwt.c && markOrb(itOrbDigging)) + c->aitmp -= 1000; + if(c2->wall == waBarrier) { + bool landbar = false; + for(int k=0; ktype; k++) + if(c2->mov[k]) { + cell *c3 = c2->mov[k]; + if(!isSealand(c3->land)) + landbar = true; + } + if(landbar) c->aitmp -= 5; + else c->aitmp += 5; + } + } } } for(int i=0; icpdist > 8) break; - if(c->wall != waCavefloor && c->wall != waCavewall) continue; -// if(c->land != laCaves) continue; -// if(c->wall == waThumper || c->wall == waBonfire) continue; - - if(c->tmp > 0) c->wall = waCavefloor; - if(c->tmp < 0) { - c->wall = waCavewall; - if(c->land != laCaves && c->land != laDeadCaves && c->land != laFjord && !gardener) { - gardener = true; - achievement_gain("GARDENER"); + if(c->wall == waCavefloor || c->wall == waCavewall) { + // if(c->land != laCaves) continue; + // if(c->wall == waThumper || c->wall == waBonfire) continue; + + if(c->aitmp > 0) c->wall = waCavefloor; + if(c->aitmp < 0) { + c->wall = waCavewall; + if(c->land != laCaves && c->land != laDeadCaves && c->land != laEmerald && !gardener) { + gardener = true; + achievement_gain("GARDENER"); + } } } + else if(c->land == laLivefjord) { + if(c->aitmp > 0 && c->wall == waStrandedBoat) c->wall = waBoat; + if(c->aitmp > 0 && c->wall == waNone) { + if(c->item && c->cpdist == 1 && markOrb(itOrbWater)) + collectItem(c); + c->wall = waSea; + } + if(c->aitmp < 0 && c->wall == waBoat) c->wall = waStrandedBoat; + if(c->aitmp < 0 && c->wall == waSea) c->wall = waNone; + } } for(int i=0; iitem == itGreenStone) c->item = itOrbLife; if(c->monst == moEarthElemental) { addMessage(XLAT("%The1 is destroyed by the forces of Life!", c->monst)); - killMonster(c); + killWithMessage(c, false); c->item = itOrbDigging; } } @@ -3568,23 +7264,20 @@ void dryforest() { cell *c = dcal[i]; if(c->cpdist > 8) break; if(c->land != laDryForest) continue; - if(c->wall == waThumper) continue; - if(c->wall == waBonfire) - c->heat = 0; for(int j=0; jtype; j++) if(c->mov[j]) { - if(c->mov[j]->wall == waBonfire) c->heat++; + if(isFire(c->mov[j])) c->landparam++; } + + if(c->landparam >= 10) makeflame(c, 10, false), c->landparam = 0; } for(int i=0; icpdist > 8) break; if(c->land != laDryForest) continue; - if(c->wall == waNone && c->heat >= 10) - burnMonstersAndItems(c, 50); - if((c->wall == waDryTree || c->wall == waWetTree || c->wall == waBonfire) && c->heat >= 1) - c->wall = waBonfire, c->tmp = 50; + if((c->wall == waDryTree || c->wall == waWetTree || isFire(c)) && c->landparam >= 1) + c->wall = waEternalFire; } /* @@ -3619,12 +7312,14 @@ void dryforest() { bool cellMirrorable(cell *c) { return - c->wall == waNone || c->wall == waCavefloor || c->wall == waFloorA || c->wall == waFloorB || - c->wall == waFrozenLake || c->wall == waDeadfloor || c->wall == waDeadfloor2; + c->wall == waNone || c->wall == waCavefloor || c->wall == waFloorA || + c->wall == waFloorB || + c->wall == waFrozenLake || c->wall == waDeadfloor || c->wall == waDeadfloor2 || + c->wall == waGiantRug || c->wall == waCIsland || c->wall == waCIsland2 || + c->wall == waGargoyleFloor || c->wall == waRubble || + c->wall == waGargoyleBridge || c->wall == waTempFloor || c->wall == waTempBridge; } -void castLightningBolt(cellwalker lig); - void createMM(cellwalker& cw, eMonster type) { if(type == moLightningBolt) castLightningBolt(cw); @@ -3717,14 +7412,18 @@ void gomirrors(bool go) { if(m == moMirage) nummirage++; cell *c2 = c->mov[c->mondir]; if(c2 && c2->monst != moNone && !isMimic(c2) && isKillable(c2)) { - addMessage(XLAT("%The1 destroys %the2!", m, c2->monst)); - killMonster(c2); + if(!attackJustStuns(c2)) + messageKill(m, c2->monst); + killOrStunMonster(c2); } + if(c2->wall == waDryTree) + c2->wall = waWetTree; + else if(c2->wall == waWetTree) + c2->wall = waNone; if(!go) continue; c->monst = moNone; if(!c2) continue; - stabbingAttack(c, c2, m); - if(!passable(c2, c, true, true)) continue; + if(!passable(c2, c, true, true, false)) continue; if(isWorm(c2)) continue; if(c2->monst == moGreater) { c2->monst = moLesser; continue; @@ -3745,8 +7444,7 @@ void gomirrors(bool go) { // killIvy(c2); continue; } - c2->monst = m; - c2->mondir = c->spn[c->mondir]; + c->monst = m; moveMonster(c2, c); mirrors2.push_back(c2); } } @@ -3768,22 +7466,57 @@ void gomirrors(bool go) { achievement_count("MIRAGE", nummirage, 0); } +bool reduceOrbPower(eItem it, int cap) { + if(items[it] && (lastorbused[it] || !markOrb(itOrbPreserve) || (it == itOrbShield && items[it]>3))) { + items[it] -= numplayers(); + if(items[it] < 0) items[it] = 0; + if(items[it] > cap) items[it] = cap; + if(items[it] == 0 && it == itOrbLove) + princess::bringBack(); + return true; + } + if(items[it] > cap) items[it] = cap; + return false; + } + +void reduceOrbPowerAlways(eItem it) { + if(items[it]) { + items[it] -= numplayers(); + if(items[it] < 0) items[it] = 0; + } + } + void reduceOrbPowers() { - if(items[itOrbLightning]) items[itOrbLightning]--; - if(items[itOrbSpeed]) items[itOrbSpeed]--; - if(items[itOrbFlash]) items[itOrbFlash]--; - if(items[itOrbShield]) items[itOrbShield]--; - if(items[itOrbWinter]) items[itOrbWinter]--; - if(items[itOrbFire]) items[itOrbFire]--; - if(items[itOrbIllusion]) items[itOrbIllusion]--; - if(items[itOrbDragon]) items[itOrbDragon]--; - if(items[itOrbPsi]) items[itOrbPsi]--; - if(items[itOrbInvis]) items[itOrbInvis]--; - if(items[itOrbGhost]) items[itOrbGhost]--; - if(items[itOrbDigging]) items[itOrbDigging]--; - if(items[itOrbTeleport]) items[itOrbTeleport]--; - if(items[itOrbSafety]) items[itOrbSafety]--; - if(items[itOrbThorns]) items[itOrbThorns]--; + for(int i=0; iland == laCaribbean ? 777 : 150); + if(invismove && !invisfish) markOrb(itOrbInvis); + reduceOrbPower(itOrbLightning, 777); + reduceOrbPower(itOrbSpeed, 67); + reduceOrbPower(itOrbShield, 77); + reduceOrbPower(itOrbFlash, 777); + reduceOrbPower(itOrbWinter, 77); + reduceOrbPower(itOrbFire, 77); + reduceOrbPower(itOrbIllusion, 111); + reduceOrbPower(itOrbDragon, 111); + reduceOrbPower(itOrbPsi, 111); + reduceOrbPower(itOrbInvis, 77); + reduceOrbPower(itOrbGhost, 77); + reduceOrbPower(itOrbDigging, 100); + reduceOrbPower(itOrbTeleport, 200); + reduceOrbPower(itOrbTelekinesis, 150); + reduceOrbPowerAlways(itOrbSafety); + reduceOrbPower(itOrbThorns, 150); + reduceOrbPower(itOrbWater, 150); + reduceOrbPower(itOrbAir, 150); + reduceOrbPower(itOrbFrog, 77); + reduceOrbPower(itOrbDiscord, 67); + reduceOrbPower(itOrbSummon, 333); + reduceOrbPower(itOrbMatter, 333); + reduceOrbPower(itOrbFish, 77); + if(!items[itSavedPrincess]) items[itOrbLove] = 0; + reduceOrbPower(itOrbLove, 777); } void flashAlchemist(cell *c) { @@ -3799,15 +7532,22 @@ void flashCell(cell *c, bool msg) { flashAlchemist(c); if(msg && c->monst && !isWorm(c) && c->monst != moShadow) addMessage(XLAT("%The1 is destroyed by the Flash.", c->monst)); - killMonster(c); + killWithMessage(c, false); if(isIcyLand(c)) - c->heat += 2; + HEAT(c) += 2; if(c->land == laDryForest) - c->heat += 2; + c->landparam += 2; if(c->wall == waCavewall) c->wall = waCavefloor; if(c->wall == waDeadTroll) c->wall = waCavefloor; if(c->wall == waDeadfloor2) c->wall = waDeadfloor; + if(c->wall == waGargoyleFloor) c->wall = waChasm; + if(c->wall == waGargoyleBridge) placeWater(c, c); + if(c->wall == waGargoyle) c->wall = waNone; + if(c->wall == waPlatform) c->wall = waNone; + if(c->wall == waStone) c->wall = waNone; + if(c->wall == waRubble) c->wall = waNone; if(c->wall == waDeadwall) c->wall = waDeadfloor2; + if(c->wall == waGiantRug) c->wall = waNone; if(c->wall == waMirror) c->wall = waNone; if(c->wall == waCloud) c->wall = waNone; if(c->wall == waDune) c->wall = waNone; @@ -3817,11 +7557,22 @@ void flashCell(cell *c, bool msg) { if(c->wall == waGlass) c->wall = waNone; if(c->wall == waDryTree || c->wall == waWetTree) c->wall = waNone; if(c->wall == waBigStatue) c->wall = waNone; - if(isActiv(c)) c->tmp = 77; + if(c->wall == waCTree) c->wall = waCIsland2; + if(c->wall == waPalace) c->wall = waRubble; + if(c->wall == waOpenGate || c->wall == waClosedGate) { + eWall w = c->wall; + c->wall = waNone; + for(int i=0; itype; i++) if(c->mov[i] && c->mov[i]->wall == w) + flashCell(c->mov[i], msg); + } + if(c->wall == waRed1) c->wall = waNone; + else if(c->wall == waRed2) c->wall = waRed1; + else if(c->wall == waRed3) c->wall = waRed2; + if(hasTimeout(c) && c->wparam < 77) c->wparam = 77; + if(isActivable(c)) + activateActiv(c, false); } -extern void drawFlash(cell* c); - void activateFlashFrom(cell *cf) { drawFlash(cf); for(int i=0; itype; if(!c.c->mov[d]) return true; - if(c.c->mov[d]->wall == waBarrier) return true; + // WAS: + // if(c.c->mov[d]->wall == waBarrier) return true; + if(c.c->mov[d]->land == laBarrier || c.c->mov[d]->land == laOceanWall || + c.c->mov[d]->land == laElementalWall) return true; return false; } @@ -3868,15 +7622,18 @@ void castLightningBolt(cellwalker lig) { cell *c = lig.c; flashAlchemist(c); - killMonster(c); - if(isIcyLand(c) || c->land == laDryForest) c->heat += 2; + killWithMessage(c, false); + if(isIcyLand(c)) HEAT(c) += 2; + if(c->land == laDryForest) c->landparam += 2; c->ligon = 1; bool brk = false, spin = false; + if(c->wall == waGargoyle) brk = true; if(c->wall == waCavewall) c->wall = waCavefloor, brk = true; if(c->wall == waDeadTroll) c->wall = waCavefloor, brk = true; if(c->wall == waDeadfloor2)c->wall = waDeadfloor; + if(c->wall == waRubble) c->wall = waNone; if(c->wall == waDeadwall) c->wall = waDeadfloor2, brk = true; if(c->wall == waGlass) c->wall = waNone, spin = true; if(c->wall == waDune) c->wall = waNone, brk = true; @@ -3885,22 +7642,36 @@ void castLightningBolt(cellwalker lig) { if(c->wall == waFreshGrave) c->wall = waNone, spin = true; if(c->wall == waBigStatue) c->wall = waNone, spin = true; if(c->wall == waColumn) c->wall = waNone, spin = true; - if(isActiv(c)) c->tmp = 77; + if(c->wall == waStone) c->wall = waNone, brk = true; + + if(c->wall == waBoat) c->wall = waSea, spin = true; + if(c->wall == waStrandedBoat) c->wall = waNone, spin = true; + + if((c->wall == waNone || c->wall == waSea) && c->land == laLivefjord) + c->wall = eWall(c->wall ^ waSea ^ waNone); + + if(c->wall == waRed1) c->wall = waNone; + if(c->wall == waRed2) c->wall = waRed1; + if(c->wall == waRed3) c->wall = waRed2, brk = true; + + if(isActivable(c)) activateActiv(c, false); if(c->wall == waDryTree || c->wall == waWetTree || c->wall == waVinePlant) { - burnMonstersAndItems(c, 4); + makeflame(c, 4, false); brk = true; } + if(c->wall == waCTree) makeflame(c, 12, false); if(cellHalfvine(c) && c->mov[lig.spin] && c->wall == c->mov[lig.spin]->wall) { destroyHalfvine(c, waPartialFire, 4); brk = true; } if(c == cwt.c) {bnc++; if(bnc > 10) break; } - if(spin) cwspin(lig, rand() % lig.c->type); + if(spin) cwspin(lig, hrand(lig.c->type)); if(brk) break; - if(c->wall == waBarrier || c->wall == waCamelot) { + if(c->wall == waBarrier || c->wall == waCamelot || c->wall == waPalace || c->wall == waPlatform || + c->wall == waTempWall) { int left = -1; int right = 1; while(barrierAt(lig, left)) left--; @@ -3910,7 +7681,7 @@ void castLightningBolt(cellwalker lig) { } else { cwspin(lig, 3); - if(c->type == 7) cwspin(lig, rand() % 2); + if(c->type == 7) cwspin(lig, hrand(2)); } if(c->wall == waCloud) { @@ -3928,7 +7699,6 @@ void castLightningBolt(cellwalker lig) { void activateLightning() { int tk = tkills(); - extern void drawLightning(); drawLightning(); addMessage(XLAT("You activate the Lightning spell!")); items[itOrbLightning] = 0; @@ -3939,31 +7709,53 @@ void activateLightning() { // move the PC in direction d (or stay in place for d == -1) -bool canmove = true; - -bool checkNeedMove(bool checkonly) { - if(items[itOrbGhost] > 1) return false; +bool checkNeedMove(bool checkonly, bool attacking) { if(cwt.c->wall == waRoundTable) { + if(markOrb2(itOrbGhost)) return false; if(checkonly) return true; addMessage(XLAT("It would be impolite to land on the table!")); } else if(cwt.c->wall == waLake) { + if(markOrb2(itOrbGhost)) return false; if(checkonly) return true; addMessage(XLAT("Ice below you is melting! RUN!")); } - else if(isFire(cwt.c) && items[itOrbShield] < 2 && !items[itOrbWinter]) { + else if(!attacking && cellEdgeUnstable(cwt.c)) { + if(markOrb2(itOrbGhost)) return false; + if(checkonly) return true; + addMessage(XLAT("Nothing to stand on here!")); + } + else if(cwt.c->wall == waSea || cwt.c->wall == waCamelotMoat) { + if(markOrb(itOrbFish)) return false; + if(markOrb2(itOrbGhost)) return false; + if(checkonly) return true; + addMessage(XLAT("You have to run away from the water!")); + } + else if(cwt.c->wall == waClosedGate) { + if(markOrb2(itOrbGhost)) return false; + if(checkonly) return true; + addMessage(XLAT("The gate is closing right on you! RUN!")); + } + else if(isFire(cwt.c) && !markOrb(itOrbWinter) && !markOrb2(itOrbShield)) { + if(markOrb2(itOrbGhost)) return false; if(checkonly) return true; addMessage(XLAT("This spot will be burning soon! RUN!")); } else if(items[itOrbGhost] == 1 && !player_passable(cwt.c, NULL, false)) { + if(markOrb2(itOrbGhost)) return false; if(checkonly) return true; addMessage(XLAT("Your Aether power has expired! RUN!")); } else if(cwt.c->wall == waChasm) { + if(markOrb2(itOrbGhost)) return false; if(checkonly) return true; addMessage(XLAT("The floor has collapsed! RUN!")); } else return false; + if(hardcore) { + canmove = false; + return false; + } return true; } @@ -3978,6 +7770,14 @@ vector yi; int yii = 0; +enum eYendorState { ysUntouched, ysLocked, ysUnlocked }; + +eYendorState yendorState(cell *yendor) { + for(int i=0; itype); + cellwalker lig(yendor, hrand(yendor->type)); cell *prev = yendor; + generatingYendor = true; + for(int i=0; itype == 7) cwspin(lig, rand() % 2); + if(lig.c->type == 7) cwspin(lig, hrand(2)); setdist(lig.c, 10, prev); setdist(lig.c, 9, prev); + setdist(lig.c, 8, prev); + setdist(lig.c, 7, prev); } nyi.path[YDIST-1] = lig.c; @@ -4008,17 +7812,27 @@ bool checkYendor(cell *yendor, bool checkonly) { cell *key = lig.c; + generatingYendor = false; + for(int b=10; b>=7; b--) setdist(key, b, prev); for(int i=-1; itype; i++) { cell *c2 = i >= 0 ? key->mov[i] : key; c2->monst = moNone; c2->item = itNone; - if(!passable(c2, NULL, true, true)) { + if(!passable(c2, NULL, true, true, false)) { if(c2->wall == waCavewall) c2->wall = waCavefloor; else if(c2->wall == waDeadwall) c2->wall = waDeadfloor2; else if(c2->wall == waLake) c2->wall = waFrozenLake; + else if(c2->land == laCaribbean) c2->wall = waCIsland; + else if(c2->land == laOcean) c2->wall = waCIsland; + else if(c2->land == laRedRock) c2->wall = waRed3; + else if(c2->land == laWhirlpool) + c2->wall = waBoat, c2->monst = moPirate, c2->item = itOrbWater; else c2->wall = waNone; } + if(c2->land == laEdge && key->land == laEdge && + c2->landparam < key->landparam) + c2->wall = waPlatform; } key->item = itKey; @@ -4030,31 +7844,61 @@ bool checkYendor(cell *yendor, bool checkonly) { return false; } -int countMyGolems() { +void checkOnYendorPath() { + yendorPath = false; + if(yii < size(yi)) { + for(int i=0; icpdist <= 7) { + yendorPath = true; + } + } + } + +int countMyGolems(eMonster m) { int g=0, dcs = size(dcal); for(int i=0; imonst == moGolem) g++; + if(c->monst == m) g++; } return g; } -void restoreGolems(int qty) { +int countMyGolemsHP(eMonster m) { + int g=0, dcs = size(dcal); + for(int i=0; imonst == m) g += c->hitpoints; + } + return g; + } + +void restoreGolems(int qty, eMonster m, int hp = 0) { int dcs = size(dcal); for(int i=1; qty && imonst = moGolem, qty--; + if(m == moTameBomberbird ? + (c->mpdist >= 3 && eaglepassable(c, NULL)) : + passable(c, NULL, false, false, false)) { + c->hitpoints = hp / qty; + c->monst = m, qty--, hp -= c->hitpoints; + if(m == moPrincess || m == moPrincessArmed) + princess::newFakeInfo(c); + } } } void activateSafety(eLand l) { - extern void drawSafety(); - int g = countMyGolems(); + int gg = countMyGolems(moGolem); + int gb = countMyGolems(moTameBomberbird); + int gp1 = countMyGolems(moPrincess); + int gp2 = countMyGolems(moPrincessArmed); + int gph1 = countMyGolemsHP(moPrincess); + int gph2 = countMyGolemsHP(moPrincessArmed); drawSafety(); addMessage(XLAT("You fall into a wormhole!")); + eLand f = firstland; if(l == laTemple) l = laRlyeh; + if(l == laWhirlpool) l = laOcean; if(l == laCamelot) l = laCrossroads; firstland = l; for(int i=0; i<65536; i++) euland[i] = laNone; @@ -4065,8 +7909,10 @@ void activateSafety(eLand l) { initgame(); firstland = f; safety = false; - restoreGolems(g); - extern void restartGraph(); + restoreGolems(gg, moGolem); + restoreGolems(gb, moTameBomberbird); + restoreGolems(gp1, moPrincess, gph1); + restoreGolems(gp2, moPrincessArmed, gph2); restartGraph(); } @@ -4077,29 +7923,50 @@ bool hasSafeOrb(cell *c) { c->item == itOrbYendor; } - -bool movepcto(int d, bool checkonly = false); - void checkmove() { + if(hardcore) return; + bool orbusedbak[ittypes]; + + // do not activate orbs! + for(int i=0; itype; i++) - if(movepcto(1, true)) canmove = true; + if(movepcto(-1, 0, true)) canmove = true; + if(!canmove) + for(int i=0; itype; i++) + if(movepcto(1, -1, true)) canmove = true; + if(!canmove) + for(int i=0; itype; i++) + if(movepcto(1, 1, true)) canmove = true; if(!canmove) achievement_final(true); if(canmove && timerstopped) { timerstart = time(NULL); timerstopped = false; } + + for(int i=0; imonst = m; - else if(on->wall == waBonfire) - addMessage(XLAT("%The1 burns!", m)); + else { + cwt.c->monst = m; + killWithMessage(cwt.c); + if(isFire(on)) + addMessage(XLAT("%The1 burns!", m)); + else if(on->wall == waChasm) + addMessage(XLAT("%The1 falls!", m)); + else if(isWatery(on) && isNonliving(m)) + addMessage(XLAT("%The1 sinks!", m)); + else if(isWatery(on)) + addMessage(XLAT("%The1 drowns!", m)); + else if(on->wall == waClosedGate) + addMessage(XLAT("%The1 is crushed!", m)); + } } void movecost(cell* from, cell *to) { @@ -4113,8 +7980,6 @@ void movecost(cell* from, cell *to) { } } -enum orbAction { roMouse, roKeyboard, roCheck, roMouseForce }; - // roCheck: return orb type if successful, 0 otherwise // roMouse/roKeyboard: // return orb type if successful, eItem(-1) if do nothing, 0 otherwise @@ -4123,11 +7988,13 @@ eItem targetRangedOrb(cell *c, orbAction a); bool haveRangedOrb() { return items[itOrbPsi] || items[itOrbDragon] || items[itOrbTeleport] || - items[itOrbIllusion]; + items[itOrbIllusion] || items[itOrbTelekinesis] || items[itOrbAir] || + items[itOrbFrog] || items[itOrbSummon] || items[itOrbMatter]; } bool isRangedOrb(eItem i) { - return i == itOrbPsi || i == itOrbDragon || i == itOrbTeleport || i == itOrbIllusion; + return i == itOrbPsi || i == itOrbDragon || i == itOrbTeleport || i == itOrbIllusion || + i == itOrbTelekinesis || i == itOrbAir || i == itOrbFrog; } bool haveRangedTarget() { @@ -4135,12 +8002,520 @@ bool haveRangedTarget() { return false; for(int i=0; imaster->alt) return false; + if(c2->item == itGrimoire && items[itGrimoire] > celldistAlt(c2)/-TEMPLE_EACH) { + if(verbose) + addMessage(XLAT("You already have this Grimoire! Seek new tomes in the inner circles.")); + return true; + } + return false; + } + +bool collectItem(cell *c2, bool telekinesis) { + + int pg = gold(); + bool dopickup = true; + + if(itemHidden(c2) && !telekinesis && !(isWatery(c2) && markOrb(itOrbFish))) + return false; + + if(c2->item == itOrbYendor && telekinesis && yendorState(c2) != ysUnlocked) + return false; + + /* if(c2->item == itHolyGrail && telekinesis) + return false; */ + + if(c2->item) { + invismove = false; + if(shmup::on) shmup::visibleFor(2000); + string s0 = ""; + + if(c2->item == itPalace && items[c2->item] == 12) + princess::forceVizier = true; + + if(isElementalShard(c2->item)) { + int tsh = + items[itFireShard] + items[itAirShard] + items[itWaterShard] + items[itEarthShard] + + items[itElemental]; + if(tsh == 0) { + addMessage(XLAT("Collect four different Elemental Shards!")); + addMessage(XLAT("Unbalanced shards in your inventory are dangerous.")); + } + else { + string t = XLAT("You collect %the1.", c2->item); + addMessage(t); + } + } + else if(c2->item == itKey) + addMessage(XLAT("You have found the Key! Now unlock this Orb of Yendor!")); + else if(c2->item == itGreenStone && !items[itGreenStone]) + addMessage(XLAT("This orb is dead...")); + else if(c2->item == itGreenStone) + addMessage(XLAT("Another Dead Orb.")); + else if(itemclass(c2->item) != IC_TREASURE) + addMessage(XLAT("You have found %the1!", c2->item)); + else if(gold() == 0) + addMessage(XLAT("Wow! %1! This trip should be worth it!", c2->item)); + else if(gold() == 1) + addMessage(XLAT("For now, collect as much treasure as possible...")); + else if(gold() == 2) + addMessage(XLAT("Prove yourself here, then find new lands, with new quests...")); + else if(!items[c2->item] && itemclass(c2->item) == IC_TREASURE) + addMessage(XLAT("You collect your first %1!", c2->item)); + else if(items[c2->item] == 4 && maxgold() == 4) { + addMessage(XLAT("You feel that %the2 become%s2 more dangerous.", c2->item, c2->land)); + addMessage(XLAT("With each %1 you collect...", c2->item, c2->land)); + } + else if(items[c2->item] == 9 && maxgold() == 9) + addMessage(XLAT("Are there any magical orbs in %the1?...", c2->land)); + else if(items[c2->item] == 10 && maxgold() == 10) { + addMessage(XLAT("You feel that %the1 slowly become%s1 dangerous...", c2->land)); + addMessage(XLAT("Better find some other place.")); + } + else if(c2->item == itSpice && items[itSpice] == 7) + addMessage(XLAT("You have a vision of the future, fighting demons in Hell...")); + else if(c2->item == itSpice && items[itSpice] == 10) + addMessage(XLAT("You will be fighting red rock snakes, too...")); +// else if(c2->item == itFeather && items[itFeather] == 10) +// addMessage(XLAT("There should be a Palace somewhere nearby...")); + else if(c2->item == itElixir && items[itElixir] == 4) + addMessage(XLAT("With this Elixir, your life should be long and prosperous...")); + else if(c2->item == itBone && items[itBone] == 6) + addMessage(XLAT("The Necromancer's Totem contains hellish incantations...")); + else if(c2->item == itStatue && items[itStatue] == 6) + addMessage(XLAT("The inscriptions on the Statue of Cthulhu point you toward your destiny...")); + else if(c2->item == itStatue && items[itStatue] == 4) + addMessage(XLAT("There must be some temples of Cthulhu in R'Lyeh...")); + else if(c2->item == itDiamond && items[itDiamond] == 8) + addMessage(XLAT("Still, even greater treasures lie ahead...")); + else if(c2->item == itFernFlower && items[itFernFlower] == 4) + addMessage(XLAT("You overheard Hedgehog Warriors talking about emeralds...")); + else if(c2->item == itEmerald && items[itEmerald] == 4) + addMessage(XLAT("You overhear miners talking about a castle...")); + else if(c2->item == itEmerald && items[itEmerald] == 5) + addMessage(XLAT("A castle in the Crossroads...")); + else { + string t = XLAT("You collect %the1.", c2->item); + addMessage(t); + } + } + + if(c2->item == itOrbSpeed) { + items[c2->item] += 31; + } + else if(c2->item == itOrbLife) { + if(shmup::on) { + items[c2->item] ++; + if(items[c2->item] > 5) items[c2->item] = 5; + } + else placeGolem(cwt.c, c2, moGolem); + } + else if(c2->item == itOrbFriend) { + if(shmup::on) { + items[itOrbLife] ++; + if(items[itOrbLife] > 5) items[itOrbLife] = 5; + } + else placeGolem(cwt.c, c2, moTameBomberbird); + } + else if(c2->item == itOrbSafety) { + items[c2->item] += 7; + if(shmup::on) + shmup::safety = true; + else + activateSafety(c2->land); + return true; + } + else if(c2->item == itOrbLightning) { + items[c2->item] += 78; + } + else if(c2->item == itOrbPreserve) { + items[c2->item] += 78; + } + else if(c2->item == itOrbLove) { + items[c2->item] += 31; + } + else if(c2->item == itOrbTelekinesis) { + items[c2->item] += 78; + } + else if(c2->item == itOrbThorns) { + items[c2->item] += 78; + } + else if(c2->item == itOrbFlash) { + items[c2->item] += 78; + } + else if(c2->item == itOrbShield) { + items[c2->item] += 16; + orbused[itOrbShield] = false; + } + else if(c2->item == itOrbWater) { + items[c2->item] += 31; + } + else if(c2->item == itOrbAir) { + items[c2->item] += 67; + } + else if(c2->item == itOrbFrog) { + items[c2->item] += 45; + } + else if(c2->item == itOrbDiscord) { + // make it seem to be 23 + if(!items[c2->item]) items[c2->item]++; + items[c2->item] += 23; + } + else if(c2->item == itOrbSummon) { + items[c2->item] += 121; + } + else if(c2->item == itOrbMatter) { + items[c2->item] += 67; + } + else if(c2->item == itOrbFish) { + items[c2->item] += 31; + } + else if(c2->item == itOrbWinter) { + items[c2->item] += 31; + } + else if(c2->item == itOrbFire) { + items[c2->item] += 31; + } + else if(c2->item == itOrbDragon) { + items[c2->item] += 78; + } + else if(c2->item == itOrbIllusion) { + items[c2->item] += 78; + } + else if(c2->item == itOrbPsi) { + items[c2->item] += 78; + } + else if(c2->item == itOrbInvis) { + items[c2->item] += 31; + } + else if(c2->item == itOrbGhost) { + items[c2->item] += 31; + } + else if(c2->item == itOrbDigging) { + items[c2->item] += 78; + } + else if(c2->item == itOrbTeleport) { + items[c2->item] += 78; + } + else if(c2->item == itOrbYendor) { + items[itOrbShield] += 31; + // Shielding always, so that we know that it protects! + for(int i=0; i<4; i++) switch(hrand(13)) { + case 0: items[itOrbSpeed] += 31; break; + case 1: items[itOrbLightning] += 78; break; + case 2: items[itOrbFlash] += 78; break; + case 3: items[itOrbPreserve] += 78; break; + case 4: items[itOrbWinter] += 151; break; + case 5: items[itOrbDigging] += 151; break; + case 6: items[itOrbTeleport] += 151; break; + case 7: items[itOrbThorns] += 151; break; + case 8: items[itOrbInvis] += 151; break; + case 9: items[itOrbPsi] += 151; break; + case 10: items[itOrbGhost] += 151; break; + case 11: items[itOrbFire] += 151; break; + case 12: items[itOrbTelekinesis] += 78; break; + } + items[itOrbYendor]++; + items[itKey]--; + addMessage(XLAT("CONGRATULATIONS!")); + achievement_collection(itOrbYendor, pg, gold()); + achievement_victory(false); + } + else if(c2->item == itHolyGrail) { + int v = newRoundTableRadius() + 12; + items[itOrbTeleport] += v; + items[itOrbSpeed] += v; + items[itHolyGrail]++; + addMessage(XLAT("Congratulations! You have found the Holy Grail!")); + if(!euclid) c2->master->alt->emeraldval |= GRAIL_FOUND; + achievement_collection(c2->item, pg, gold()); + } + else if(c2->item == itKey) { + for(int i=0; iitem == itCompass) { + dopickup = false; + } + else { + bool lhu = hellUnlocked(); + if(c2->item) gainItem(c2->item); + int g2 = gold(); + + if(items[itFireShard] && items[itAirShard] && items[itWaterShard] && items[itEarthShard]) { + items[itFireShard]--; + items[itAirShard]--; + items[itWaterShard]--; + items[itEarthShard]--; + gainItem(itElemental); + gainItem(itElemental); + gainItem(itElemental); + gainItem(itElemental); + addMessage(XLAT("You construct some Elemental Gems!", c2->item)); + } + + if(c2->item == itHyperstone && items[itHyperstone] == 10) + achievement_victory(true); + + if(pg < 15 && g2 >= 15) + addMessage(XLAT("Collect treasure to access more different lands...")); + if(pg < 30 && g2 >= 30) + addMessage(XLAT("You feel that you have enough treasure to access new lands!")); + if(pg < 45 && g2 >= 45) + addMessage(XLAT("Collect more treasures, there are still more lands waiting...")); + if(pg < 60 && g2 >= 60) + addMessage(XLAT("You feel that the stars are right, and you can access R'Lyeh!")); + if(pg < 75 && g2 >= 75) + addMessage(XLAT("Kill monsters and collect treasures, and you may get access to Hell...")); + if(pg < 90 && g2 >= 90) + addMessage(XLAT("To access Hell, collect 10 treasures each of 9 kinds...")); + if(hellUnlocked() && !lhu) { + addMessage(XLAT("Abandon all hope, the gates of Hell are opened!")); + addMessage(XLAT("And the Orbs of Yendor await!")); + } + } + + if(dopickup) c2->item = itNone; +// if(c2->land == laHive) +// c2->heat = 1; + + int numOrb = 0; + for(int i=0; iitem == itNone) { + items[itGreenStone]--; + if(false) { + c->item = itNone; + spill(c, eWall(c->wall ^ waFloorA ^ waFloorB), 3); + addMessage(XLAT("The slime reacts with %the1!", itGreenStone)); + } + else { + c->item = itGreenStone; + addMessage(XLAT("You drop %the1.", itGreenStone)); + } + } + else { + if(gold() >= 300) + addMessage(XLAT("You feel great, like a true treasure hunter.")); + else if(gold() >= 200) + addMessage(XLAT("Your eyes shine like gems.")); + else if(gold() >= 100) + addMessage(XLAT("Your eyes shine as you glance at your precious treasures.")); + else if(gold() >= 50) + addMessage(XLAT("You glance at your great treasures.")); + else if(gold() >= 10) + addMessage(XLAT("You glance at your precious treasures.")); + else if(gold() > 0) + addMessage(XLAT("You glance at your precious treasure.")); + else + addMessage(XLAT("Your inventory is empty.")); + } + } + +void roundTableMessage(cell *c2) { + if(!euclid && !cwt.c->master->alt) return; + if(!euclid && !c2->master->alt) return; + int dd = celldistAltRelative(c2) - celldistAltRelative(cwt.c); + + bool tooeasy = (roundTableRadius(c2) < newRoundTableRadius()); + + if(dd>0) { + if(grailWasFound(cwt.c)) { + addMessage(XLAT("The Knights congratulate you on your success!")); + knighted = roundTableRadius(cwt.c); + } + else if(!tooeasy) + addMessage(XLAT("The Knights laugh at your failure!")); + } + else { + if(grailWasFound(cwt.c)) + addMessage(XLAT("The Knights stare at you!")); + else if(tooeasy) + addMessage(XLAT("Come on, this is too easy... find a bigger castle!")); + else + addMessage(XLAT("The Knights wish you luck!")); + } + } + +void knightFlavorMessage(cell *c2) { + + long long tab[100], sum[100]; + tab[0] = 1; + tab[1] = 1*7; + tab[2] = 2*7; + tab[3] = 4*7; + tab[4] = 7*7; + for(int i=5; i<100; i++) + tab[i] = tab[i-1] + tab[i-2] + tab[i-3] - tab[i-4]; + sum[0] = 0; + for(int i=1; i<100; i++) + sum[i] = sum[i-1] + tab[i-1]; + + bool grailfound = grailWasFound(c2); + int rad = roundTableRadius(c2); + bool tooeasy = (rad < newRoundTableRadius()); + + static int msgid = 0; + + retry: + if(msgid >= 32) msgid = 0; + + if(msgid == 0 && grailfound) { + addMessage(XLAT("\"I would like to congratulate you again!\"")); + } + else if(msgid == 1 && !tooeasy) { + addMessage(XLAT("\"Find the Holy Grail to become one of us!\"")); + } + else if(msgid == 2 && !tooeasy) { + addMessage(XLAT("\"The Holy Grail is in the center of the Round Table.\"")); + } + else if(msgid == 3) { + addMessage(XLAT("\"I enjoy watching the hyperbug battles.\"")); + } + else if(msgid == 4) { + addMessage(XLAT("\"Have you visited a temple in R'Lyeh?\"")); + } + else if(msgid == 5) { + addMessage(XLAT("\"Nice castle, eh?\"")); + } + else if(msgid == 6 && items[itSpice] < 10) { + addMessage(XLAT("\"The Red Rock Valley is dangerous, but beautiful.\"")); + } + else if(msgid == 7 && items[itSpice] < 10) { + addMessage(XLAT("\"Train in the Desert first!\"")); + } + else if(msgid == 8) { + if(rad <= 76) + addMessage(XLAT("\"Our Table seats %1 Knights!\"", llts(tab[rad]))); + else + addMessage(XLAT("\"By now, you should have your own formula, you know?\"")); + } + else if(msgid == 9 && rad <= 76) { + addMessage(XLAT("\"There are %1 floor tiles inside our Table!\"", llts(sum[rad]))); + } + else if(msgid == 10 && !items[itPirate] && !items[itWhirlpool]) { + addMessage(XLAT("\"Have you tried to take a boat and go into the Ocean? Try it!\"")); + } + else if(msgid == 11 && !princess::saved) { + addMessage(XLAT("\"When I visited the Palace, a mouse wanted me to go somewhere.\"")); + } + else if(msgid == 12 && !princess::saved) { + addMessage(XLAT("\"I wonder what was there...\"")); + } + else { + msgid++; goto retry; + } + + msgid++; + } + +void uncoverMines(cell *c, int lev) { + if(c->wall == waMineUnknown) + c->wall = waMineOpen; + if(!lev) return; + + if(c->wall == waMineOpen) { + bool minesNearby = false; + for(int i=0; itype; i++) + if(c->mov[i] && c->mov[i]->wall == waMineMine) + minesNearby = true; + if(!minesNearby) for(int i=0; itype; i++) + if(c->mov[i] && (c->mov[i]->wall == waMineUnknown || c->mov[i]->wall == waMineOpen)) + uncoverMines(c->mov[i], lev-1); + } + } + +void monstersTurn() { + DEBT("bfs"); + bfs(); + destroyStrayMirrors(); + DEBT("heat"); + processheat(); + DEBT("rop"); + int phase1 = (1 & items[itOrbSpeed]); + reduceOrbPowers(); + DEBT("mmo"); + int phase2 = (1 & items[itOrbSpeed]); + if(!phase2) movemonsters(); + if(cwt.c->land == laPower && !phase1) { bfs(); moveFastMonsters(); } + DEBT("lc"); + if(!phase1) livecaves(); + if(!phase1) dryforest(); + DEBT("check"); + checkmove(); + } + +void pushThumper(cell *th, cell *cto) { + eWall w = th->wall; + cto->wparam = th->wparam; + if(th->land == laAlchemist) + th->wall = (cwt.c->wall == waFloorB || cwt.c->wall == waFloorA) ? cwt.c->wall : cto->wall; + else th->wall = waNone; + if(cto->wall == waOpenPlate || cto->wall == waClosePlate) { + toggleGates(cto, cto->wall, 3); + addMessage(XLAT("%The1 destroys %the2!", waThumperOn, cto->wall)); + } + if(cellUnstable(cto) && cto->land == laMotion) { + addMessage(XLAT("%The1 falls!", waThumperOn)); + } + else if(cellUnstable(cto)) { + addMessage(XLAT("%The1 fills the hole!", waThumperOn)); + cto->wall = waTempFloor; + } + else if(isWatery(cto)) { + addMessage(XLAT("%The1 fills the hole!", waThumperOn)); + cto->wall = waTempBridge; + } + else + cto->wall = w; + } + +bool canPushThumperOn(cell *tgt, cell *thumper, cell *player) { + if(isWatery(tgt) && !tgt->monst) + return true; + if(tgt->wall == waChasm && !tgt->monst) + return true; + return + passable(tgt, thumper, false, true, false) && + passable(tgt, player, false, true, false) && + !tgt->item; + } + +void activateActiv(cell *c, bool msg) { + if(msg) addMessage(XLAT("You activate %the1.", c->wall)); + if(c->wall == waThumperOff) c->wall = waThumperOn; + if(c->wall == waBonfireOff) c->wall = waFire; + c->wparam = 100; + } + +bool movepcto(int d, int subdir, bool checkonly) { + if(hardcore && !canmove) return false; + if(hardcore && checkonly) { printf("hardcore check\n"); return false; } if(checkonly && haveRangedTarget()) return true; if(!checkonly) flipplayer = false; if(!checkonly) DEB("movepc"); @@ -4150,7 +8525,8 @@ bool movepcto(int d, bool checkonly) { d = cwt.spin; } if(d != -1 && !checkonly) playermoved = true; - if(!checkonly) invismove = false; + if(!checkonly) invismove = false; + bool boatmove = false; if(d >= 0) { cell *c2 = cwt.c->mov[d]; @@ -4168,42 +8544,36 @@ bool movepcto(int d, bool checkonly) { return true; } - if(isActiv(c2) && c2->tmp == -1) { + if(isActivable(c2)) { if(checkonly) return true; - addMessage(XLAT("You activate %the1.", c2->wall)); - c2->tmp = 100; + activateActiv(c2, true); checkmove(); return true; } - if((c2->wall == waThumper/* || (c2->wall == waBigStatue && c2->type == 6)*/) && !monstersnear(c2) && !c2->monst) { - eWall w = c2->wall; + if(c2->wall == waThumperOn && !monstersnear(c2) && !c2->monst) { cellwalker push = cwt; cwstep(push); - cwspin(push, 3); + cwspin(push, 3 * -subdir); cwstep(push); /* if(w == waBigStatue && push.c->type == 7) { if(checkonly) return false; addMessage(XLAT("%The1 is too heavy to put it back on the pedestal.", c2->wall)); return false; } */ - if((!passable(push.c, c2, false, true) || !passable(push.c, cwt.c, false, true) || push.c->item) && c2->type == 7) { + if((!canPushThumperOn(push.c, c2, cwt.c) && c2->type == 7)) { cwstep(push); - cwspin(push, 1); + cwspin(push, 1 * -subdir); cwstep(push); } - if(!passable(push.c, c2, false, true) || !passable(push.c, cwt.c, false, true) || push.c->item) { + if(!canPushThumperOn(push.c, c2, cwt.c)) { if(checkonly) return false; addMessage(XLAT("No room to push %the1.", c2->wall)); return false; } if(checkonly) return true; addMessage(XLAT("You push %the1.", c2->wall)); - push.c->tmp = c2->tmp; - if(c2->land == laAlchemist) - c2->wall = (cwt.c->wall == waFloorB || cwt.c->wall == waFloorA) ? cwt.c->wall : push.c->wall; - else c2->wall = waNone; - push.c->wall = w; + pushThumper(c2, push.c); } /* if((c2->wall == waBigStatue) && c2->type == 7 && !monstersnear(c2)) { @@ -4233,10 +8603,37 @@ bool movepcto(int d, bool checkonly) { } } */ + if(isWatery(c2) && !monstersnear(c2) && !c2->monst && cwt.c->wall == waBoat) { + + if(againstWind(c2, cwt.c)) { + if(!checkonly) + addMessage(XLAT("The Air Elemental blows you away!")); + return false; + } + + if(againstCurrent(c2, cwt.c) && !markOrb(itOrbWater)) { + if(markOrb(itOrbFish)) goto escape; + if(!checkonly) + addMessage(XLAT("You cannot go against the current!")); + return false; + } + if(checkonly) return true; + moveBoat(c2, cwt.c); + boatmove = true; + } + + if(!monstersnear(c2) && !c2->monst && cwt.c->wall == waBoat && boatGoesThrough(c2) && markOrb(itOrbWater)) { + if(checkonly) return true; + placeWater(cwt.c, c2); + c2->wall = waBoat; + if(cwt.c->item) moveItem(cwt.c, c2, false), boatmove = true; + } + + escape: if(c2->wall == waBigStatue && !monstersnear(c2) && !c2->monst) { if(!canPushStatueOn(cwt.c)) { if(checkonly) return false; - if(cwt.c->wall == waBonfire) + if(isFire(cwt.c)) addMessage(XLAT("You have to escape first!")); else addMessage(XLAT("There is not enough space!")); @@ -4252,56 +8649,49 @@ bool movepcto(int d, bool checkonly) { cwt.c->wall = waBigStatue; } - if(c2->wall == waDryTree && !monstersnear(cwt.c)) { + if(c2->wall == waDryTree && !markOrb(itOrbGhost) && !monstersnear(cwt.c)) { + if(checkNeedMove(checkonly, true)) return false; if(checkonly) return true; addMessage(XLAT("You start cutting down the tree.")); + gomirrors(0); c2->wall = waWetTree; } - else if(c2->wall == waWetTree && !monstersnear(cwt.c)) { + else if(c2->wall == waWetTree && !markOrb(itOrbGhost) && !monstersnear(cwt.c)) { + if(checkNeedMove(checkonly, true)) return false; if(checkonly) return true; addMessage(XLAT("You cut down the tree.")); + gomirrors(0); c2->wall = waNone; } else if(c2->monst == moKnight) { if(checkonly) return false; - - bool tooeasy = (roundTableRadius(c2) < newRoundTableRadius()); - if(grailWasFound(cwt.c) && rand() % 5 == 0) { - addMessage(XLAT("\"I would like to congratulate you again!\"")); - } - else if(rand() % 5 != 0 && !tooeasy) { - static int i; - i++; - if(i%2) - addMessage(XLAT("\"Find the Holy Grail to become one of us!\"")); - else - addMessage(XLAT("\"The Holy Grail is in the center of the Round Table.\"")); - } - else { - int i = rand() % 3; - if(i == 0) - addMessage(XLAT("\"I enjoy watching the hyperbug battles.\"")); - if(i == 1) - addMessage(XLAT("\"Have you visited a temple in R'Lyeh?\"")); - if(i == 2) - addMessage(XLAT("\"Nice castle, eh?\"")); + if(!euclid && !c2->master->alt) { + addMessage(XLAT("\"I am lost...\"")); + return false; } + knightFlavorMessage(c2); return false; } - else if(c2->monst && !isFriendly(c2)) { + else if(c2->monst && (!isFriendly(c2) || c2->monst == moTameBomberbird)) { if(c2->monst == moWorm || c2->monst == moWormtail || c2->monst == moWormwait) { if(checkonly) return false; addMessage(XLAT("You cannot attack Sandworms directly!")); return false; } + if(c2->monst == moHexSnake || c2->monst == moHexSnakeTail) { + if(checkonly) return false; + addMessage(XLAT("You cannot attack Rock Snakes directly!")); + return false; + } + if(attackingForbidden(c2, cwt.c)) { if(checkonly) return false; addMessage(XLAT("You cannot attack through the Vine!")); return false; } - if(c2->monst == moTentacle || c2->monst == moTentacletail || c2->monst == moTentaclewait) { + if(c2->monst == moTentacle || c2->monst == moTentacletail || c2->monst == moTentaclewait || c2->monst == moTentacleEscaping) { if(checkonly) return false; addMessage(XLAT("You cannot attack Tentacles directly!")); return false; @@ -4313,7 +8703,7 @@ bool movepcto(int d, bool checkonly) { return false; } */ - if(c2->monst == moHedge && !items[itOrbThorns]) { + if(c2->monst == moHedge && !markOrb(itOrbThorns)) { if(checkonly) return false; addMessage(XLAT("You cannot attack %the1 directly!", c2->monst)); addMessage(XLAT("Stab them by walking around them.")); @@ -4327,6 +8717,13 @@ bool movepcto(int d, bool checkonly) { return false; } + if(c2->monst == moVizier && c2->hitpoints > 1) { + if(checkonly) return false; + addMessage(XLAT("You cannot attack %the1 directly!", c2->monst)); + addMessage(XLAT("Hit him by walking away from him.")); + return false; + } + if(c2->monst == moShadow) { if(checkonly) return false; addMessage(XLAT("You cannot defeat the Shadow!")); @@ -4345,32 +8742,32 @@ bool movepcto(int d, bool checkonly) { return false; } - if(checkNeedMove(checkonly)) + if(!(isWatery(cwt.c) && c2->monst == moWaterElemental) && checkNeedMove(checkonly, true)) return false; if(checkonly) return true; - addMessage(XLAT("You kill %the1.", c2->monst)); - - int mt = c2->monst; - int tk = tkills(); - killMonster(c2); - - int ntk = tkills(); - - if(tk == 0 && ntk > 0) - addMessage(XLAT("That was easy, but groups could be dangerous.")); - if(tk < 10 && ntk >= 10) - addMessage(XLAT("Good to know that your fighting skills serve you well in this strange world.")); - - if(tk < 50 && ntk >= 50) - addMessage(XLAT("You wonder where all these monsters go, after their death...")); - - if(tk < 100 && ntk >= 100) - addMessage(XLAT("You feel that the souls of slain enemies pull you to the Graveyard...")); - - if(mt == moIvyRoot && ntk>tk) - achievement_gain("IVYSLAYER"); + if(isStunnable(c2->monst) && c2->hitpoints > 1) { + addMessage(XLAT("You stun %the1.", c2->monst)); + stunMonster(c2); + if(c2->monst != moFatGuard) { + cellwalker push = cwt; + cwstep(push); + cwspin(push, 3 * -subdir); + cwstep(push); + if(c2->type == 7 && !blowable(push.c, c2)) { + cwstep(push); + cwspin(push, 1 * -subdir); + cwstep(push); + } + if(blowable(push.c, c2)) + pushMonster(push.c, c2); + } + } + else { + messageKill(moNone, c2->monst); + killWithMessage(c2); + } gomirrors(0); } @@ -4380,22 +8777,19 @@ bool movepcto(int d, bool checkonly) { addMessage(XLAT("Wrong color!")); else if(c2->wall == waRoundTable) addMessage(XLAT("It would be impolite to land on the table!")); - else + else if(cwt.c->wall == waRed3 && snakelevel(c2) == 0) + addMessage(XLAT("You would get hurt!", c2->wall)); + else if(cellEdgeUnstable(cwt.c) && cellEdgeUnstable(c2)) + addMessage(XLAT("Gravity does not allow this!")); + else if(againstWind(c2, cwt.c)) + addMessage(XLAT("The Air Elemental blows you away!")); + else { addMessage(XLAT("You cannot move through %the1!", c2->wall)); + } return false; } - else if(c2->land == laGameBoard) { - // do not pick up! - if(checkonly) return true; - flipplayer = true; - cwstep(cwt); - setdist(cwt.c, 0, NULL); - bfs(); - checkmove(); - return true; - } else { - if(c2->item == itOrbYendor && !checkYendor(c2, checkonly)) { + if(c2->item == itOrbYendor && !boatmove && !checkYendor(c2, checkonly)) { return false; } if(c2->item == itHolyGrail) { @@ -4432,248 +8826,40 @@ bool movepcto(int d, bool checkonly) { addMessage(XLAT("You jump over the table!")); } - if(cwt.c->wall == waRoundTable) { - int dd = celldistAltRelative(c2) - celldistAltRelative(cwt.c); - - bool tooeasy = (roundTableRadius(c2) < newRoundTableRadius()); - - if(dd>0) { - if(grailWasFound(cwt.c)) { - addMessage(XLAT("The Knights congratulate you on your success!")); - knighted = roundTableRadius(cwt.c); - } - else if(!tooeasy) - addMessage(XLAT("The Knights laugh at your failure!")); - } - else { - if(grailWasFound(cwt.c)) - addMessage(XLAT("The Knights stare at you!")); - else if(tooeasy) - addMessage(XLAT("Come on, this is too easy... find a bigger castle!")); - else - addMessage(XLAT("The Knights wish you luck!")); - } - } + if(cwt.c->wall == waRoundTable) + roundTableMessage(c2); - int pg = gold(); - bool dopickup = true; - invismove = items[itOrbInvis] > 0; if(items[itOrbFire]) { invismove = false; - firetrail(cwt.c); + if(makeflame(cwt.c, 10, false)) markOrb(itOrbFire); } if(items[itOrbDigging]) { invismove = false; - earthMove(cwt.c, d); + if(earthMove(cwt.c, d)) markOrb(itOrbDigging); } - if(c2->item) { + if(!boatmove && collectItem(c2)) return true; + + if(isIcyLand(cwt.c) && cwt.c->wall == waNone && markOrb(itOrbWinter)) { invismove = false; - string s0 = ""; - if(0) ; - if(gold() == 0) - addMessage(XLAT("Wow! %1! This trip should be worth it!", c2->item)); - else if(gold() == 1) - addMessage(XLAT("For now, collect as much treasure as possible...")); - else if(gold() == 2) - addMessage(XLAT("Prove yourself here, then find new lands, with new quests...")); - else if(!items[c2->item] && itemclass(c2->item) == IC_TREASURE) - addMessage(XLAT("You collect your first %1!", c2->item)); - else if(c2->item == itKey) - addMessage(XLAT("You have found the Key! Now unlock this Orb of Yendor!")); - else if(c2->item == itGreenStone && !items[itGreenStone]) - addMessage(XLAT("This orb is dead...")); - else if(c2->item == itGreenStone) - addMessage(XLAT("Another Dead Orb.")); - else if(itemclass(c2->item) != IC_TREASURE) - addMessage(XLAT("You have found %the1!", c2->item)); - else if(items[c2->item] == 4 && maxgold() == 4) { - addMessage(XLAT("You feel that %the2 become%s2 more dangerous.", c2->item, c2->land)); - addMessage(XLAT("With each %1 you collect...", c2->item, c2->land)); - } - else if(items[c2->item] == 9 && maxgold() == 9) - addMessage(XLAT("Are there any magical orbs in %the1?...", c2->land)); - else if(items[c2->item] == 10 && maxgold() == 10) { - addMessage(XLAT("You feel that %the1 slowly become%s1 dangerous...", c2->land)); - addMessage(XLAT("Better find some other place.")); - } - else if(c2->item == itSpice && items[itSpice] == 7) - addMessage(XLAT("You have a vision of the future, fighting demons in Hell...")); - else if(c2->item == itElixir && items[itElixir] == 4) - addMessage(XLAT("With this Elixir, your life should be long and prosperous...")); - else if(c2->item == itBone && items[itBone] == 6) - addMessage(XLAT("The Necromancer's Totem contains hellish incantations...")); - else if(c2->item == itStatue && items[itStatue] == 6) - addMessage(XLAT("The inscriptions on the Statue of Cthulhu point you toward your destiny...")); - else if(c2->item == itStatue && items[itStatue] == 4) - addMessage(XLAT("There must be some temples of Cthulhu in R'Lyeh...")); - else if(c2->item == itDiamond && items[itDiamond] == 8) - addMessage(XLAT("Still, even greater treasures lie ahead...")); - else if(c2->item == itFernFlower && items[itFernFlower] == 4) - addMessage(XLAT("You overheard Hedgehog Warriors talking about emeralds...")); - else if(c2->item == itEmerald && items[itEmerald] == 4) - addMessage(XLAT("You overhear miners talking about a castle...")); - else if(c2->item == itEmerald && items[itEmerald] == 5) - addMessage(XLAT("A castle in the Crossroads...")); - else { - string t = XLAT("You collect %the1.", c2->item); - addMessage(t); - } - } - - if(c2->item == itOrbSpeed) { - items[c2->item] += 31; - if(items[c2->item] > 67) items[c2->item] = 67; - } - else if(c2->item == itOrbLife) { - placeGolem(cwt.c, c2, moGolem); - } - else if(c2->item == itOrbSafety) { - items[c2->item] += 7; - activateSafety(c2->land); - return true; - } - else if(c2->item == itOrbLightning) { - items[c2->item] += 78; - if(items[c2->item] > 777) items[c2->item] = 777; - } - else if(c2->item == itOrbThorns) { - items[c2->item] += 78; - if(items[c2->item] > 151) items[c2->item] = 151; - } - else if(c2->item == itOrbFlash) { - items[c2->item] += 78; - if(items[c2->item] > 777) items[c2->item] = 777; - } - else if(c2->item == itOrbShield) { - items[c2->item] += 16; - if(items[c2->item] > 77) items[c2->item] = 77; - } - else if(c2->item == itOrbWinter) { - items[c2->item] += 31; - if(items[c2->item] > 77) items[c2->item] = 77; - } - else if(c2->item == itOrbFire) { - items[c2->item] += 31; - if(items[c2->item] > 77) items[c2->item] = 77; - } - else if(c2->item == itOrbDragon) { - items[c2->item] += 78; - if(items[c2->item] > 111) items[c2->item] = 111; - } - else if(c2->item == itOrbIllusion) { - items[c2->item] += 78; - if(items[c2->item] > 111) items[c2->item] = 111; - } - else if(c2->item == itOrbPsi) { - items[c2->item] += 78; - if(items[c2->item] > 111) items[c2->item] = 111; - } - else if(c2->item == itOrbInvis) { - items[c2->item] += 31; - if(items[c2->item] > 77) items[c2->item] = 77; - } - else if(c2->item == itOrbGhost) { - items[c2->item] += 31; - if(items[c2->item] > 77) items[c2->item] = 77; - } - else if(c2->item == itOrbDigging) { - items[c2->item] += 78; - if(items[c2->item] > 101) items[c2->item] = 101; - } - else if(c2->item == itOrbTeleport) { - items[c2->item] += 78; - if(items[c2->item] > 201) items[c2->item] = 201; - } - else if(c2->item == itOrbYendor) { - for(int i=0; i<4; i++) switch(rand() % 12) { - case 0: items[itOrbSpeed] += 31; break; - case 1: items[itOrbLightning] += 78; break; - case 2: items[itOrbFlash] += 78; break; - case 3: items[itOrbShield] += 31; break; - case 4: items[itOrbWinter] += 151; break; - case 5: items[itOrbDigging] += 151; break; - case 6: items[itOrbTeleport] += 151; break; - case 7: items[itOrbThorns] += 151; break; - case 8: items[itOrbInvis] += 151; break; - case 9: items[itOrbPsi] += 151; break; - case 10: items[itOrbGhost] += 151; break; - case 11: items[itOrbFire] += 151; break; - } - items[itOrbYendor]++; - items[itKey]--; - addMessage(XLAT("CONGRATULATIONS!")); - achievement_collection(itOrbYendor, pg, gold()); - achievement_victory(false); - } - else if(c2->item == itHolyGrail) { - int v = newRoundTableRadius() + 12; - items[itOrbTeleport] += v; - items[itOrbSpeed] += v; - items[itHolyGrail]++; - addMessage(XLAT("Congratulations! You have found the Holy Grail!")); - if(!euclid) c2->master->alt->fjordval |= GRAIL_FOUND; - achievement_collection(c2->item, pg, gold()); - } - else if(c2->item == itKey) { - for(int i=0; iitem == itGrimoire && items[itGrimoire] > celldistAlt(c2)/-TEMPLE_EACH) { - addMessage(XLAT("You already have this Grimoire! Seek new tomes in the inner circles.")); - dopickup = false; - } - else { - bool lhu = hellUnlocked(); - if(c2->item) items[c2->item]++; - int g2 = gold(); - - if(c2->item == itHyperstone && items[itHyperstone] == 10) - achievement_victory(true); - - achievement_collection(c2->item, pg, g2); - - if(pg < 15 && g2 >= 15) - addMessage(XLAT("Collect treasure to access more different lands...")); - if(pg < 30 && g2 >= 30) - addMessage(XLAT("You feel that you have enough treasure to access new lands!")); - if(pg < 45 && g2 >= 45) - addMessage(XLAT("Collect more treasures, there are still more lands waiting...")); - if(pg < 60 && g2 >= 60) - addMessage(XLAT("You feel that the stars are right, and you can access R'Lyeh!")); - if(pg < 75 && g2 >= 75) - addMessage(XLAT("Kill monsters and collect treasures, and you may get access to Hell...")); - if(pg < 90 && g2 >= 90) - addMessage(XLAT("To access Hell, collect 10 treasures each of 9 kinds...")); - if(hellUnlocked() && !lhu) { - addMessage(XLAT("Abandon all hope, the gates of Hell are opened!")); - addMessage(XLAT("And the Orbs of Yendor await!")); - } - } - - if(dopickup) c2->item = itNone; -// if(c2->land == laHive) -// c2->heat = 1; - - int numOrb = 0; - for(int i=0; iwall == waNone) - cwt.c->wall = waIcewall; + cwt.c->wall = waIcewall; } movecost(cwt.c, c2); - if(c2->monst == moGolem || c2->monst == moIllusion) { - addMessage(XLAT("You switch places with %the1.", c2->monst)); + if(c2->monst == moGolem || c2->monst == moIllusion || isPrincess(c2->monst) || c2->monst == moMouse) { + if(c2->monst == moMouse) + princess::mouseSqueak(c2); + else if(isPrincess(c2->monst)) { + princess::line(c2); + princess::move(cwt.c, c2); + } + else + addMessage(XLAT("You switch places with %the1.", c2->monst)); + cwt.c->hitpoints = c2->hitpoints; + cwt.c->stuntime = c2->stuntime; placeGolem(cwt.c, c2, c2->monst); c2->monst = moNone; } @@ -4687,37 +8873,7 @@ bool movepcto(int d, bool checkonly) { gomirrors(1); - if(c2->wall == waMirror) { - invismove = false; - addMessage(XLAT("The mirror shatters!")); - if(c2->land == laMirror) { - int g = gold(); - items[itShard]++; - achievement_collection(itShard, g+1, g); - } - c2->wall = waNone; - createMirrors(cwt.c, cwt.spin, moMirage); - } - - if(c2->wall == waGlass && items[itOrbGhost] > 2) { - addMessage(XLAT("Your Aether powers are drained by %the1!", c2->wall)); - items[itOrbGhost] = 2; - } - - if(c2->wall == waCloud) { - invismove = false; - addMessage(XLAT("The cloud turns into a bunch of images!")); - if(c2->land == laMirror) { - int g = gold(); - items[itShard]++; - achievement_collection(itShard, g+1, g); - } - c2->wall = waNone; - createMirages(cwt.c, cwt.spin, moMirage); - } - - if(cellUnstable(c2) && !items[itOrbGhost]) - c2->wall = waChasm; + playerMoveEffects(c2); countLocalTreasure(); landvisited[cwt.c->land] = true; @@ -4725,7 +8881,7 @@ bool movepcto(int d, bool checkonly) { } } else { - if(checkNeedMove(checkonly)) + if(checkNeedMove(checkonly, false)) return false; if(monstersnear(cwt.c)) { if(checkonly) return false; @@ -4733,52 +8889,30 @@ bool movepcto(int d, bool checkonly) { return false; } if(checkonly) return true; - if(d == -2 && items[itGreenStone] && cwt.c->item == itNone) { - items[itGreenStone]--; - if(false) { - cwt.c->item = itNone; - spill(cwt.c, eWall(cwt.c->wall ^ waFloorA ^ waFloorB), 3); - addMessage(XLAT("The slime reacts with %the1!", itGreenStone)); - } - else { - cwt.c->item = itGreenStone; - addMessage(XLAT("You drop %the1.", itGreenStone)); - } - } - else if(d == -2) { - if(gold() >= 300) - addMessage(XLAT("You feel great, like a true treasure hunter.")); - else if(gold() >= 200) - addMessage(XLAT("Your eyes shine like gems.")); - else if(gold() >= 100) - addMessage(XLAT("Your eyes shine as you glance at your precious treasures.")); - else if(gold() >= 50) - addMessage(XLAT("You glance at your great treasures.")); - else if(gold() >= 10) - addMessage(XLAT("You glance at your precious treasures.")); - else if(gold() > 0) - addMessage(XLAT("You glance at your precious treasure.")); - else - addMessage(XLAT("Your inventory is empty.")); - } + if(d == -2) + dropGreenStone(cwt.c); } - DEBT("bfs"); - bfs(); - destroyStrayMirrors(); - DEBT("heat"); - heat(); - DEBT("rop"); - int phase1 = (1 & items[itOrbSpeed]); - reduceOrbPowers(); - DEBT("mmo"); - int phase2 = (1 & items[itOrbSpeed]); - if(!phase2) movemonsters(); - if(cwt.c->land == laPower && !phase1) { bfs(); moveFastMonsters(); } - DEBT("lc"); - if(!phase1) livecaves(); - if(!phase1) dryforest(); - DEBT("check"); - checkmove(); + + invisfish = false; + if(items[itOrbFish]) { + invisfish = true; + for(int i=0; iland != laWhirlpool && !escaped) { + escaped = true; + achievement_gain("WHIRL1"); + } + + if(seenSevenMines && cwt.c->land != laMinefield) { + seenSevenMines = false; + achievement_gain("SEVENMINE"); + } + DEBT("done"); return true; } @@ -4794,7 +8928,8 @@ void teleportTo(cell *dest) { cwt.c->monst = dest->monst; dest->monst = moNone; movecost(cwt.c, dest); - cwt.c = dest; cwt.spin = rand() % dest->type; flipplayer = !!(rand() % 2); + playerMoveEffects(dest); + cwt.c = dest; cwt.spin = hrand(dest->type); flipplayer = !!(hrand(2)); items[itOrbTeleport] = 0; addMessage(XLAT("You teleport to a new location!")); @@ -4804,45 +8939,213 @@ void teleportTo(cell *dest) { setdist(cwt.c, i, NULL); bfs(); + + if(shmup::on) + shmup::teleported(); + else + checkmove(); + } + +void jumpTo(cell *dest) { + movecost(cwt.c, dest); + + cwt.c = dest; + + playerMoveEffects(dest); + if(cwt.c->item != itOrbYendor && cwt.c->item != itHolyGrail) + collectItem(cwt.c, true); + + items[itOrbFrog] -= 5; + if(items[itOrbFrog] < 0) items[itOrbFrog] = 0; + + addMessage(XLAT("You jump!")); + destroyMirrors(); + + for(int i=9; i>=0; i--) + setdist(cwt.c, i, NULL); + + if(shmup::on) + shmup::teleported(); + else + monstersTurn(); + } + +void moveItem1(cell *from, cell *to, bool activateYendor) { + if(from->item == itOrbYendor) { + bool xnew = true; + for(int i=0; iitem == itKey) { + for(int i=0; iitem; + to->item = from->item; + from->item = i; + } + +void telekinesis(cell *dest) { + + int cost = dest->cpdist * dest->cpdist; + + if(dest->land == laAlchemist && + (dest->wall == waFloorA || dest->wall == waFloorB) && + (cwt.c->wall == waFloorA || cwt.c->wall == waFloorB)) + dest->wall = cwt.c->wall; + + if(dest->land == laPower && cwt.c->land != laPower && dest->item != itOrbFire && dest->item != itOrbLife) { + items[dest->item] += 2; + dest->item = itNone; + addMessage(XLAT("The Orb loses its power as it leaves the Land of Power!")); + } + + moveItem(dest, cwt.c, true); + collectItem(cwt.c, true); + items[itOrbTelekinesis] -= cost; + + if(!shmup::on) checkmove(); + } + +eMonster summonedAt(cell *dest) { + if(dest->monst) return moNone; + if(dest->wall == waVineHalfA || dest->wall == waVineHalfB || dest->wall == waVinePlant) + return moVineSpirit; + if(dest->wall == waCTree) + return moParrot; + if(dest->wall == waLake) + return moGreaterShark; + if(dest->wall == waAncientGrave || dest->wall == waFreshGrave) + return moGhost; + if(dest->wall == waClosePlate || dest->wall == waOpenPlate) + return moPalace; + if(dest->wall == waFloorA || dest->wall == waFloorB) + return moSlime; + if(dest->wall == waCavefloor) + return moTroll; + if(dest->wall == waDeadfloor) + return moEarthElemental; + if(dest->wall == waDeadfloor2) + return moMiner; + if(dest->wall == waMineOpen || dest->wall == waMineMine || dest->wall == waMineUnknown) + return moBomberbird; + if(dest->wall == waTrapdoor) + return dest->land == laPalace ? moFatGuard : moOrangeDog; + if(dest->wall == waSea) + return + isElemental(dest->land) ? moWaterElemental : + dest->land == laLivefjord ? moViking : + moPirate; + if(dest->wall == waChasm) + return moAirElemental; + if(isFire(dest)) + return moFireElemental; + if(dest->wall == waCavewall || dest->wall == waDeadwall) + return moSeep; + if(dest->wall == waRed1 || dest->wall == waRed2 || dest->wall == waRed3) + return moRedTroll; + if(dest->wall == waFrozenLake) + return moFireElemental; + if(dest->wall == waCIsland || dest->wall == waCIsland2) + return moWaterElemental; + if(dest->wall == waRubble || dest->wall == waGargoyleFloor || dest->wall == waGargoyleBridge || dest->wall == waLadder) + return moGargoyle; + if(dest->wall == waStrandedBoat) + return moWaterElemental; + if(dest->wall == waBoat) + return moAirElemental; + if(dest->wall == waStone) + return moEarthElemental; + if(dest->wall == waGiantRug) + return moVizier; + if(dest->wall == waNone) { + if(dest->land == laIce) return moFireElemental; + if(dest->land == laDesert) return moEarthElemental; + if(dest->land == laJungle) return moWaterElemental; + if(dest->land == laGraveyard) return moZombie; + if(dest->land == laRlyeh || dest->land == laTemple) return moPyroCultist; + if(dest->land == laHell) return moWaterElemental; + if(dest->land == laPower) return moWitchFire; + if(dest->land == laWineyard) return moVineBeast; + if(dest->land == laEmerald) return moMiner; + if(dest->land == laHive) return dest->type == 7 ? moBug1 : moBug0; + if(dest->land == laRedRock) return moRedTroll; + if(dest->land == laOcean) return moEarthElemental; + if(dest->land == laDryForest) return moFireFairy; + if(dest->land == laLivefjord) return moFjordTroll; + if(dest->land == laEdge) return moAirElemental; + if(dest->land == laEAir) return moAirElemental; + if(dest->land == laEWater) return moWaterElemental; + if(dest->land == laEEarth) return moEarthElemental; + if(dest->land == laEFire) return moFireElemental; + if(dest->land == laMotion) return moRunDog; + } + return moNone; + } + +void summonAt(cell *dest) { + dest->monst = summonedAt(dest); + dest->stuntime = 3; + if(dest->monst == moPirate || dest->monst == moViking) + dest->wall = waBoat; + if(dest->wall == waStrandedBoat) + dest->wall = waBoat; + else if(dest->monst == moWaterElemental) + placeWater(dest, dest); + if(dest->wall == waStone) + dest->wall = waNone; + if(dest->monst == moFireElemental && isFire(dest)) + dest->wall = waNone; + addMessage(XLAT("You summon %the1!", dest->monst)); + moveEffect(dest, dest, dest->monst); + + if(hasHitpoints(dest->monst)) + dest->hitpoints = palaceHP(); + + items[itOrbSummon] -= 20; + if(items[itOrbSummon]<0) items[itOrbSummon] = 0; + checkmove(); + } + +bool tempWallPossibleAt(cell *dest) { + if(dest->monst || (dest->item && !itemHidden(dest))) return false; + return dest->wall == waChasm || isWatery(dest) || dest->wall == waNone; + } + +void tempWallAt(cell *dest) { + if(dest->wall == waChasm) + dest->wall = waTempFloor; + else if(dest->wall == waNone) + dest->wall = waTempWall; + else if(isWatery(dest)) + dest->wall = waTempBridge; + dest->wparam = (items[itOrbMatter]+1) / 2; + items[itOrbMatter] /= 2; + dest->item = itNone; // underwater items are destroyed by this checkmove(); } void psi_attack(cell *dest) { - addMessage(XLAT("You kill %the1 with a mental blast!", dest->monst)); - killMonster(dest); + if(isNonliving(dest->monst)) + addMessage(XLAT("You destroy %the1 with a mental blast!", dest->monst)); + else + addMessage(XLAT("You kill %the1 with a mental blast!", dest->monst)); + killWithMessage(dest, false); items[itOrbPsi] -= 30; if(items[itOrbPsi]<0) items[itOrbPsi] = 0; checkmove(); } -bool flammable(cell *c) { - return - c->wall == waNone || c->wall == waFloorA || c->wall == waFloorB || - c->wall == waCavefloor || c->wall == waDeadfloor || - c->wall == waDryTree || c->wall == waWetTree || - c->wall == waVinePlant || c->wall == waVineHalfA || c->wall == waVineHalfB || - c->wall == waIcewall; - } - -void placeDragonfire(cell *c) { - if(cellUnstable(c)) - c->wall = waChasm; - else if(c->wall == waNone && c->land == laCocytus) - c->wall = waLake, c->heat += 20; - else if(cellHalfvine(c)) - flameHalfvine(c, 20); - else { - c->wall = waBonfire; - c->tmp = 20; - } - if(itemBurns(c->item)) - addMessage(XLAT("%The1 burns!", c->item)), c->item = itNone; - addMessage(XLAT("You throw fire!")); - items[itOrbDragon] -= 5; - if(items[itOrbDragon]<0) items[itOrbDragon] = 0; - checkmove(); - } - void placeIllusion(cell *c) { c->monst = moIllusion; items[itOrbIllusion] -= 5; @@ -4851,8 +9154,56 @@ void placeIllusion(cell *c) { checkmove(); } +void blowoff(cell *cf, cell *ct) { + addMessage(XLAT("You blow %the1 away!", cf->monst)); + pushMonster(ct, cf); + items[itOrbAir]--; + checkmove(); + } + +void useOrbOfDragon(cell *c) { + makeflame(c, 20, false); + addMessage(XLAT("You throw fire!")); + items[itOrbDragon] -= 5; + if(items[itOrbDragon]<0) items[itOrbDragon] = 0; + checkmove(); + } + + eItem targetRangedOrb(cell *c, orbAction a) { + + if(false) if(a == roMouse || a == roMouseForce) { + c->item = itShard; + cell *c2 = c; + cell *c3 = c; + cell *c4 = chosenDown(c, 1, 1); + cell *c5 = chosenDown(c, -1, -1); + for(int i=0; i<3; i++) { + printf("i=%d c2=%p c3=%p c4=%p c5=%p\n", i, c2, c3, c4, c5); + c2->item = itDiamond; + c3->item = itRuby; + c4->item = itFjord; + c5->item = itSapphire; + buildEquidistant(c4); buildEquidistant(c5); + c2 = chosenDown(c2, 1, 0); + c3 = chosenDown(c3, -1, 0); + c4 = chosenDown(c4, 1, 0); + c5 = chosenDown(c5, -1, 0); + if(c4->landflags == 3 && c4 == chosenDown(c2, 1, 1)) c->wall = waCIsland; + if(c5->landflags == 3 && c5 == chosenDown(c3, -1, -1)) c->wall = waCIsland; + } + return itOrbDiscord; + } + if(!haveRangedOrb()) return itNone; + + // (-2) shmup variants + eItem shmupEffect = shmup::targetRangedOrb(a); + + if(shmupEffect) return shmupEffect; + + // (-1) distance + if(c == cwt.c || isNeighbor(cwt.c, c)) { if(a == roKeyboard || a == roMouseForce ) addMessage(XLAT("You cannot target that close!")); @@ -4864,6 +9215,57 @@ eItem targetRangedOrb(cell *c, orbAction a) { return itNone; } + // (0) telekinesis + if(c->item && !itemHidden(c) && !cwt.c->item && items[itOrbTelekinesis] >= c->cpdist * c->cpdist && !cantGetGrimoire(c, a != roCheck)) { + if(a != roCheck) telekinesis(c); + return itOrbTelekinesis; + } + + // (0') air blow + bool nowhereToBlow = false; + if(items[itOrbAir] && isBlowableMonster(c->monst)) { + int d = 0; + for(; dtype; d++) if(c->mov[d] && c->mov[d]->cpdist < c->cpdist) break; + if(dtype) for(int e=d; etype; e++) { + nowhereToBlow = true; + cell *c2 = c->mov[e % c->type]; + if(c2 && c2->cpdist > c->cpdist && blowable(c2, c)) { + if(a != roCheck) blowoff(c, c2); + return itOrbAir; + } + } + } + + // (0'') jump + int jumpstate = 0; + cell *jumpthru = NULL; + + if(items[itOrbFrog] && c->cpdist == 2) { + jumpstate = 1; + int i = items[itOrbGhost]; + bool b = markOrb(itOrbGhost); + if(i) items[itOrbGhost] = i-1; + for(int i=0; itype; i++) { + cell *c2 = cwt.c->mov[i]; + if(isNeighbor(c2, c)) { + jumpthru = c2; + if((b || jumpable(c2, c)) && !thruVine(c2,cwt.c)) { + jumpstate = 2; + if(jumpable2(c, c2) && !thruVine(c2,c)) { + jumpstate = 3; + break; + } + } + } + } + items[itOrbGhost] = i; + if(jumpstate == 3 && !monstersnear(c)) { + jumpstate = 4; + if(a != roCheck) jumpTo(c); + return itOrbFrog; + } + } + // (1) switch with an illusion if(items[itOrbTeleport] && c->monst == moIllusion) { if(a != roCheck) teleportTo(c); @@ -4871,19 +9273,20 @@ eItem targetRangedOrb(cell *c, orbAction a) { } // (2) place illusion - if(items[itOrbIllusion] && c->monst == moNone && c->item == itNone && passable(c, NULL, false, true)) { + if(!shmup::on && items[itOrbIllusion] && c->monst == moNone && c->item == itNone && passable(c, NULL, false, true, false)) { if(a != roCheck) placeIllusion(c); return itOrbIllusion; } // (3) teleport - if(items[itOrbTeleport] && c->monst == moNone && c->item == itNone && passable(c, NULL, false, true)) { + if(items[itOrbTeleport] && c->monst == moNone && (c->item == itNone || itemHidden(c)) && + player_passable(c, NULL, false)) { if(a != roCheck) teleportTo(c); return itOrbTeleport; } // (4) remove an illusion - if(items[itOrbIllusion] && c->monst == moIllusion) { + if(!shmup::on && items[itOrbIllusion] && c->monst == moIllusion) { if(a != roCheck) { addMessage(XLAT("You take the Illusion away.")); items[itOrbIllusion] += 4; @@ -4892,39 +9295,88 @@ eItem targetRangedOrb(cell *c, orbAction a) { return itOrbIllusion; } - // (5) psi blast - if(items[itOrbPsi] && c->monst && !isWorm(c) && c->monst != moShadow) { + // (5) psi blast (non-shmup variant) + if(!shmup::on && items[itOrbPsi] && c->monst && !isWorm(c) && c->monst != moShadow) { if(a != roCheck) psi_attack(c); return itOrbPsi; } - // (6) place fire - if(items[itOrbDragon] && flammable(c)) { - if(a != roCheck) placeDragonfire(c); + // (5a) summoning + if(items[itOrbSummon] && summonedAt(c)) { + if(a != roCheck) summonAt(c); + return itOrbSummon; + } + + // (5b) matter + if(items[itOrbMatter] && tempWallPossibleAt(c)) { + if(a != roCheck) tempWallAt(c); + return itOrbMatter; + } + + // (6) place fire (non-shmup variant) + if(!shmup::on && items[itOrbDragon] && makeflame(c, 20, true)) { + if(a != roCheck) useOrbOfDragon(c); return itOrbDragon; } if(a == roCheck) return itNone; - - if(items[itOrbPsi] && c->monst) { + + if(nowhereToBlow) { + addMessage(XLAT("Nowhere to blow %the1!", c->monst)); + } + else if(jumpstate == 1 && jumpthru && jumpthru->monst) { + addMessage(XLAT("Cannot jump through %the1!", jumpthru->monst)); + } + else if(jumpstate == 1 && jumpthru) { + addMessage(XLAT("Cannot jump through %the1!", jumpthru->wall)); + } + else if(jumpstate == 2 && c->monst) { + addMessage(XLAT("Cannot jump on %the1!", c->monst)); + } + else if(jumpstate == 2 && c->wall) { + addMessage(XLAT("Cannot jump on %the1!", c->wall)); + } + else if(jumpstate == 3) { + addMessage(XLAT("%The1 would get you there!", which)); + } + else if(items[itOrbAir] && c->monst) { + addMessage(XLAT("%The1 is immune to wind!", c->monst)); + } + else if(items[itOrbPsi] && c->monst) { addMessage(XLAT("%The1 is immune to mental blasts!", c->monst)); } else if(items[itOrbTeleport] && c->monst) { addMessage(XLAT("Cannot teleport on a monster!")); } + else if(c->item && items[itOrbTelekinesis]) { + addMessage(XLAT("Not enough power for telekinesis!")); + } else if(items[itOrbIllusion] && c->item) addMessage(XLAT("Cannot cast illusion on an item!")); else if(items[itOrbIllusion] && c->monst) addMessage(XLAT("Cannot cast illusion on a monster!")); - else if(items[itOrbIllusion] && !passable(c, NULL, false, true)) + else if(items[itOrbIllusion] && !passable(c, NULL, false, true, false)) addMessage(XLAT("Cannot cast illusion here!")); + else if(items[itOrbTeleport] && !player_passable(c, NULL, false)) { + addMessage(XLAT("Cannot teleport here!")); + } + else if(items[itOrbMatter] && !tempWallPossibleAt(c)) { + if(c->monst) + addMessage(XLAT("Cannot create temporary matter on a monster!")); + else if(c->item) + addMessage(XLAT("Cannot create temporary matter on an item!")); + else addMessage(XLAT("Cannot create temporary matter here!")); + } + else if(items[itOrbSummon] && !summonedAt(c)) { + if(c->monst) + addMessage(XLAT("Cannot summon on a monster!")); + else + addMessage(XLAT("No summoning possible here!")); + } else if(items[itOrbTeleport] && c->item) { addMessage(XLAT("Cannot teleport on an item!")); } - else if(items[itOrbTeleport] && !passable(c, NULL, false, true)) { - addMessage(XLAT("Cannot teleport here!")); - } - else if(items[itOrbDragon] && !flammable(c)) { + else if(items[itOrbDragon] && !makeflame(c, 20, true)) { addMessage(XLAT("Cannot throw fire there!")); } else return eItem(0); @@ -4932,8 +9384,8 @@ eItem targetRangedOrb(cell *c, orbAction a) { return eItem(-1); } -#define MAXBOX 120 -#define POSSCORE 107 // update this when new boxes are added! +#define MAXBOX 180 +#define POSSCORE 161 // update this when new boxes are added! struct score { string ver; @@ -4941,14 +9393,15 @@ struct score { }; int savebox[MAXBOX], boxid; -bool saving; +bool saving, loading, loadingHi; string boxname[MAXBOX]; bool fakebox[MAXBOX]; void applyBox(int& t) { if(saving) savebox[boxid++] = t; - else t = savebox[boxid++]; + else if(loading) t = savebox[boxid++]; + else boxid++; } void applyBoxNum(int& i, string name = "") { @@ -4957,6 +9410,12 @@ void applyBoxNum(int& i, string name = "") { applyBox(i); } +void applyBoxBool(bool& b, string name = "") { + int i = b; + applyBoxNum(i, name); + b = i; + } + // just skips the value when loading void applyBoxSave(int i, string name = "") { fakebox[boxid] = (name == ""); @@ -4974,7 +9433,10 @@ int applyBoxLoad(string name = "") { void applyBoxI(eItem it, bool f = false) { boxname[boxid] = iinf[it].name; fakebox[boxid] = f; - applyBox(items[it]); + if(loadingHi) { + updateHi(it, savebox[boxid++]); + } + else applyBox(items[it]); } void applyBoxM(eMonster m, bool f = false) { @@ -4983,11 +9445,6 @@ void applyBoxM(eMonster m, bool f = false) { applyBox(kills[m]); } -void killbox(eMonster m, int& val) { - if(saving) kills[m] = val; - else { val = kills[m]; kills[m] = 0; } - } - void applyBoxes() { applyBoxSave(timerstart, "time elapsed"); @@ -5005,7 +9462,7 @@ void applyBoxes() { else applyBoxI(eItem(i)); for(int i=0; i<43; i++) { - kills[i] = 0; + if(loading) kills[i] = 0; bool fake = i == moLesserM || i == moNone || i == moWolfMoved || i == moTentacletail; if(i == moWormtail) applyBoxM(moCrystalSage); @@ -5021,13 +9478,15 @@ void applyBoxes() { if(saving) { applyBoxSave(savetime + timer - timerstart); } - else savetime = applyBoxLoad(); + else if(loading) savetime = applyBoxLoad(); + else boxid++; savecount++; applyBoxNum(savecount, "number of saves"); savecount--; applyBoxNum(cheater); if(saving) applyBoxSave(cwt.c->land); - else firstland = eLand(applyBoxLoad()); + else if(loading) firstland = eLand(applyBoxLoad()); + else boxid++; for(int i=itOrbLightning; i<25; i++) applyBoxI(eItem(i), true); @@ -5060,15 +9519,86 @@ void applyBoxes() { applyBoxI(itGrimoire); applyBoxM(moKnight); applyBoxM(moCultistLeader); + + applyBoxM(moPirate); + applyBoxM(moCShark); + applyBoxM(moParrot); + applyBoxI(itPirate); + applyBoxI(itOrbPreserve, true); + + applyBoxM(moHexSnake); + applyBoxM(moRedTroll); + applyBoxI(itRedGem); + applyBoxI(itOrbTelekinesis, true); + + applyBoxBool(euclid); + applyBoxBool(hardcore); + applyBoxNum(hardcoreAt); + applyBoxBool(shmup::on); + if(saving) applyBoxSave(euclidland); + else if(loading) euclidland = eLand(applyBoxLoad()); + else boxid++; + + applyBoxI(itCoast); + applyBoxI(itWhirlpool); + applyBoxI(itBombEgg); + applyBoxM(moBomberbird); + applyBoxM(moTameBomberbird); + applyBoxM(moAlbatross); + applyBoxI(itOrbFriend, true); + applyBoxI(itOrbAir, true); + applyBoxI(itOrbWater, true); + + applyBoxI(itPalace); + applyBoxI(itFjord); + applyBoxI(itOrbFrog); + applyBoxI(itOrbDiscord); + applyBoxM(moPalace); + applyBoxM(moFatGuard); + applyBoxM(moSkeleton); + applyBoxM(moVizier); + applyBoxM(moViking); + applyBoxM(moFjordTroll); + applyBoxM(moWaterElemental); + + applyBoxI(itSavedPrincess); + applyBoxI(itOrbLove); + applyBoxM(moPrincess); + applyBoxM(moPrincessMoved); // live Princess for Safety + applyBoxM(moPrincessArmedMoved); // live Princess for Safety + applyBoxM(moMouse); + applyBoxNum(princess::saveArmedHP); + applyBoxNum(princess::saveHP); + + applyBoxI(itEdge); + applyBoxI(itElemental); + applyBoxI(itZebra); + applyBoxI(itFireShard); + applyBoxI(itWaterShard); + applyBoxI(itAirShard); + applyBoxI(itEarthShard); + + applyBoxM(moAirElemental); + applyBoxM(moFireElemental); + applyBoxM(moEdgeMonkey); + applyBoxM(moGargoyle); + applyBoxM(moOrangeDog); + applyBoxI(itOrbSummon); + applyBoxI(itOrbMatter); } void saveBox() { - boxid = 0; saving = true; applyBoxes(); + boxid = 0; saving = true; applyBoxes(); saving = false; } void loadBox() { // have boxid - boxid = 0; saving = false; applyBoxes(); + boxid = 0; loading = true; applyBoxes(); loading = false; + } + +void loadBoxHigh() { + // have boxid + boxid = 0; loadingHi = true; applyBoxes(); loadingHi = false; } // certify that saves and achievements were received @@ -5086,9 +9616,10 @@ int achievement_certify(const char *s, int a, int b, int c) { return 0; } #endif void saveStats() { - if(euclid) return; #ifndef ANDROID + if(randomPatternsMode) return; + FILE *f = fopen(scorefile, "at"); if(!f) { printf("Could not open the score file '%s'!\n", scorefile); @@ -5109,6 +9640,12 @@ void saveStats() { if(true) { fprintf(f, VER); + if(!shmup::on) items[itOrbLife] = countMyGolems(moGolem); + if(!shmup::on) items[itOrbFriend] = countMyGolems(moTameBomberbird); + if(!shmup::on) kills[moPrincessMoved] = countMyGolems(moPrincess); + if(!shmup::on) kills[moPrincessArmedMoved] = countMyGolems(moPrincessArmed); + if(!shmup::on) princess::saveHP = countMyGolemsHP(moPrincess); + if(!shmup::on) princess::saveArmedHP = countMyGolemsHP(moPrincessArmed); saveBox(); for(int i=0; iitem]++; - c->item = itNone; - } - if(u == ' ') - c->item = itNone; - - extern void movepckeydir(int); - if(sym == 'd' || sym == SDLK_KP6) movepckeydir(0); - if( sym == SDLK_KP3) movepckeydir(1); - if(sym == 'x' || sym == SDLK_KP2) movepckeydir(2); - if( sym == SDLK_KP1) movepckeydir(3); - if(sym == 'a' || sym == SDLK_KP4) movepckeydir(4); - if( sym == SDLK_KP7) movepckeydir(5); - if(sym == 'w' || sym == SDLK_KP8) movepckeydir(6); - if( sym == SDLK_KP9) movepckeydir(7); - - if(u == 'g') - c->item = itGreenStone; - if(u == 'r') - c->item = itOrbSpeed; - if(u == 't') - c->item = itOrbFlash; - if(u == 'o') - c->item = itOrbShield; - if(u == 'i') - c->item = itOrbTeleport; - if(u == 'p') - c->item = itOrbLightning; - if(u == 'h') - c->item = itDiamond; - if(u == 'j') - c->item = itHell; - if(u == 'k') - c->item = itFernFlower; - if(u == 'l') - c->item = itSapphire; - - if(boardmode == 'f') { - int fv = fjordval(c); - if(u == '0' || u == '1' || u == '2' || u == '3' || u == '4') fjordwalled[fv] = !fjordwalled[fv]; - if(u == '1' || u == '4') fjordwalled[fv^1] = !fjordwalled[fv^1]; - if(u == '2' || u == '4') fjordwalled[fv^2] = !fjordwalled[fv^2]; - if(u == '3' || u == '4') fjordwalled[fv^3] = !fjordwalled[fv^3]; - return; - } - - if(u == '0') - c->wall = waNone; - if(u == '1') - c->wall = waFloorA; - if(u == '2') - c->wall = waFloorB; - if(u == '3') - c->wall = waFrozenLake; - if(u == '4') - c->wall = waCavefloor; - if(u == '5') - c->wall = waLake; - if(u == '6') - c->wall = waCavewall; - if(u == '7') - c->wall = waIcewall; - if(u == '8') - c->wall = waDryTree; - if(u == '9') - c->wall = waColumn; - } -#endif +bool emeraldwalled[64]; static int orbid = 0; @@ -5345,7 +9822,7 @@ eItem nextOrb() { } eItem randomTreasure() { - eItem i = eItem(rand() % ittypes); + eItem i = eItem(hrand(ittypes)); if(itemclass(i) == IC_TREASURE) return i; else return randomTreasure(); } @@ -5361,35 +9838,39 @@ eItem randomTreasure2(int cv) { if(a == lt) q -= (2*cv-1); if(a == itEmerald && cwt.c->land == laCrossroads) q -= 5; if(q < bq) bq = q, cq = 0; - if(q == bq) { cq++; if(rand() % cq == 0) best = i; } + if(q == bq) { cq++; if(hrand(cq) == 0) best = i; } } return best; } -extern int webdisplay; - -void applyCheat(char u, cell *c = NULL) { +bool applyCheat(char u, cell *c = NULL) { if(u == 'M' && cwt.c->type == 6) { addMessage(XLAT("You summon some Mirages!")); cheater++; createMirrors(cwt.c, cwt.spin, moMirage), createMirages(cwt.c, cwt.spin, moMirage); + return true; } if(u == 'G') { addMessage(XLAT("You summon a golem!")); cheater++; int i = cwt.spin; - if(passable(cwt.c->mov[i], NULL, false, false)) - cwt.c->mov[i]->monst = moGolem; + if(passable(cwt.c->mov[i], NULL, false, false, false)) + cwt.c->mov[i]->monst = hrand(2) ? moGolem : moTameBomberbird; + return true; } if(u == 'L') { do { - firstland = eLand(firstland+1); - if(firstland == landtypes) firstland = eLand(2); + if(firstland == eLand(landtypes-1)) + firstland = eLand(2); + else + firstland = eLand(firstland+1); } - while(firstland == laGameBoard || firstland == laCamelot || firstland == laTemple); + while(firstland == laCanvas || firstland == laCamelot || firstland == laTemple || + firstland == laWhirlpool || firstland == laOceanWall); euclidland = firstland; cheater++; addMessage(XLAT("You will now start your games in %1", firstland)); + return true; } if(u == 'C') { cheater++; @@ -5406,20 +9887,23 @@ void applyCheat(char u, cell *c = NULL) { kills[moMonkey] = 20; kills[moCultist] = 20; kills[moTroll] = 20; + return true; } if(u == 'P') { for(int i=0; itype; i++) - if(passable(cwt.c->mov[i], NULL, false, false)) { + if(passable(cwt.c->mov[i], NULL, false, false, false)) { eItem it = nextOrb(); cwt.c->mov[i]->item = it; } + return true; } if(u == 'F') { items[itOrbFlash] += 1; @@ -5428,30 +9912,58 @@ void applyCheat(char u, cell *c = NULL) { items[itOrbSpeed] += 1; items[itOrbShield] += 1; cheater++; addMessage(XLAT("Orb power gained!")); + return true; } if(u == 'D') { items[itGreenStone] += 10; cheater++; addMessage(XLAT("Dead orbs gained!")); + return true; + } + if(u == 'D'-64) { + mapeditor::drawplayer = !mapeditor::drawplayer; + return true; + } + if(u == 'A') { + cmode = emMapEditor; + return true; + } + if(u == 'A'-64) { + cmode = emDraw; + return true; } if(u == 'Y') { items[itOrbYendor] ++; cheater++; addMessage(XLAT("Orb of Yendor gained!")); + return true; } if(u == 'T') { items[randomTreasure2(10)] += 10; cheater++; addMessage(XLAT("Treasure gained!")); + return true; } if(u == 'T'-64) { items[randomTreasure2(100)] += 100; cheater++; addMessage(XLAT("Lots of treasure gained!")); + return true; + } + if(u == 'I'-64) { + items[randomTreasure2(10)] += 25; + cheater++; addMessage(XLAT("Treasure gained!")); + return true; + } + if(u == 'U'-64) { + items[randomTreasure2(10)] += 50; + cheater++; addMessage(XLAT("Treasure gained!")); + return true; } if(u == 'W') { addMessage(XLAT("You summon a sandworm!")); cheater++; int i = cwt.spin; - if(passable(cwt.c->mov[i], NULL, false, false)) + if(passable(cwt.c->mov[i], NULL, false, false, false)) cwt.c->mov[i]->monst = moWorm, cwt.c->mov[i]->mondir = NODIR; + return true; } if(u == 'I') { addMessage(XLAT("You summon an Ivy!")); @@ -5459,7 +9971,8 @@ void applyCheat(char u, cell *c = NULL) { int i = cwt.spin; int j = cwt.c->spn[i]; cell* c = cwt.c->mov[i]->mov[(j+3)%cwt.c->mov[i]->type]; - if(passable(c, NULL, false, false)) buildIvy(c, 0, 1); + if(passable(c, NULL, false, false, false)) buildIvy(c, 0, 1); + return true; } if(u == 'E') { addMessage(XLAT("You summon a monster!")); @@ -5467,28 +9980,49 @@ void applyCheat(char u, cell *c = NULL) { int i = cwt.spin; if(cwt.c->mov[i]->wall == waChasm) cwt.c->mov[i]->wall = waNone; - if(passable(cwt.c->mov[i], NULL, true, false)) { - eMonster mo[7] = { moEagle, moPyroCultist, moGhost, moTroll, moKnight, moMiner, moVineBeast }; - cwt.c->mov[i]->monst = mo[rand() % 7]; + if(passable(cwt.c->mov[i], NULL, true, false, false)) { + eMonster mo[9] = { moEagle, moPyroCultist, moGhost, moTroll, moMiner, moVineBeast, moBug0, + moBomberbird, moSkeleton }; + cwt.c->mov[i]->monst = mo[hrand(9)]; + cwt.c->mov[i]->stuntime = 3; + cwt.c->mov[i]->hitpoints = 3; } + return true; + } + if(u == 'E'-64) { + addMessage(XLAT("You summon many monsters!")); + cheater++; + for(int i=0; itype; i++) { + cell *c2 = cwt.c->mov[i]; + if(passable(c2, NULL, true, false, false)) { + eMonster mo[2] = { moRedTroll, moDarkTroll }; + c2->monst = mo[hrand(2)]; + } + } + return true; } if(u == 'H') { addMessage(XLAT("You summon some Thumpers!")); cheater++; for(int i=0; itype; i++) - if(passable(cwt.c->mov[i], NULL, false, false)) - cwt.c->mov[i]->wall = rand() % 2 ? waThumper : waBigStatue, cwt.c->mov[i]->tmp = -1; + if(passable(cwt.c->mov[i], NULL, false, false, false)) { + eWall ws[3] = { waThumperOff, waBigStatue, waBoat }; + cwt.c->mov[i]->wall = ws[hrand(3)]; + } + return true; } if(u == 'B') { addMessage(XLAT("You summon a bonfire!")); cheater++; int i = cwt.spin; - if(passable(cwt.c->mov[i], NULL, false, false)) - cwt.c->mov[i]->wall = waBonfire, cwt.c->mov[i]->tmp = -1; + if(passable(cwt.c->mov[i], NULL, false, false, false)) + cwt.c->mov[i]->wall = waBonfireOff; + return true; } if(u == 'Z') { cwt.spin++; flipplayer = false; cwt.spin %= cwt.c->type; + return true; } if(u == 'J') { if(items[localTreasureType()] > 0) @@ -5497,24 +10031,39 @@ void applyCheat(char u, cell *c = NULL) { if(itemclass(eItem(i)) == IC_TREASURE) items[i] = 0; cheater++; addMessage(XLAT("Treasure lost!")); + return true; } if(u == 'K') { for(int i=0; iland); items[itOrbSafety] += 3; cheater++; addMessage(XLAT("Activated Orb of Safety!")); + return true; } if(u == 'U') { activateSafety(firstland); cheater++; addMessage(XLAT("Teleported to %1!", firstland)); + return true; } if(u == 'W'-64) { webdisplay++; cheater++; addMessage(XLAT("Cheat-changed the display.", firstland)); + return true; } + if(u == 'F'-64) { + items[itOrbShield] += 30; + return true; + } + if(u == 'Y'-64) { + int i = cwt.spin; + cwt.c->mov[i]->item = itOrbYendor; + return true; + } + return false; } void generateAlts(heptagon *h) { @@ -5559,20 +10108,19 @@ void generateAlts(heptagon *h) { } } -heptagon *createAlternateMap(cell *c, int rad, hstate firststate) { +heptagon *createAlternateMap(cell *c, int rad, hstate firststate, int special) { // check for direction int gdir = -1; for(int i=0; itype; i++) { if(c->mov[i] && c->mov[i]->mpdist < c->mpdist) gdir = i; } - if(!gdir) return NULL; + if(gdir < 0) return NULL; // check for non-crossing int bd = 2; cellwalker bb(c, bd); - cellwalker bb2 = bb; - if(!(checkBarriersFront(bb) && checkBarriersBack(bb2))) { + if(!(checkBarriersFront(bb) && checkBarriersBack(bb))) { return NULL; } @@ -5584,17 +10132,27 @@ heptagon *createAlternateMap(cell *c, int rad, hstate firststate) { if(bf.c->type == 6) cwspin(bf, 3); else - cwspin(bf, 3 + rand() % 2); + cwspin(bf, 3 + hrand(2)); cwstep(bf); } cx[rad] = bf.c; heptagon *h = bf.c->master; + if(special == waPalace) { + + // type 7 is ensured + cell *c = bf.c; + + if(cdist50(c) != 0) return NULL; + if(polarb50(c) != 1) return NULL; + } + heptagon *alt = new heptagon; allAlts.push_back(alt); //printf("new alt {%p}\n", alt); alt->s = firststate; - alt->fjordval = 0; + alt->emeraldval = 0; + alt->zebraval = 0; for(int i=0; i<7; i++) alt->move[i] = NULL; alt->distance = 0; alt->c7 = NULL; @@ -5606,6 +10164,23 @@ heptagon *createAlternateMap(cell *c, int rad, hstate firststate) { cx[d]->bardir = NOBARRIERS; } + if(special == waPalace) { + + cell *c = bf.c; + + princess::generating = true; + c->land = laPalace; + for(int j=BARLEV; j>=0; j--) + setdist(c, j, NULL); + princess::generating = false; + + princess::newInfo(c); + princess::forceMouse = false; + + // static bool debug=true; if(debug) debug=false, cwt.c = c; + } + return alt; //for(int d=rad; d>=0; d--) printf("%3d. %p {%d}\n", d, cx[d]->master, cx[d]->master->alt->distance); } + diff --git a/graph.cpp b/graph.cpp index 08894349..93ca323e 100644 --- a/graph.cpp +++ b/graph.cpp @@ -1,6 +1,8 @@ -#define GL #define GL_GLEXT_PROTOTYPES +#define BTOFF 0x404040 +#define BTON 0xC0C000 + // #define PANDORA // Hyperbolic Rogue @@ -8,27 +10,6 @@ // basic graphics: -// disable this if you have no access to SDL_gfx -#ifndef STEAM -#define GFX -#endif - -#ifdef NOGFX -#undef GFX -#endif - -// scale the Euclidean -#define EUCSCALE 2.3 - -// disable this if you have no access to SDL_mixer -#ifndef MOBILE -#define AUDIO -#endif - -#define BTOFF 0x404040 -#define BTON 0xC0C000 - - #ifndef MOBILE #include @@ -43,40 +24,7 @@ int audiovolume = 60; #endif #include - -#ifdef GFX -#include #endif -#endif - -#ifndef MOBILE -#ifdef GL -#ifdef MAC -#include -#include -#else -#include -#include -#endif - -#ifdef MAC -#include -#else -#include -#endif -#endif -#endif - -#ifdef ANDROID -#ifndef FAKE -#ifdef GL -#include -#include -#include -#endif -#endif -#endif - #ifndef MOBILE @@ -86,7 +34,8 @@ int audiovolume = 60; SDL_Surface *s; TTF_Font *font[256]; -SDL_Joystick *stick, *panstick; +SDL_Joystick* sticks[8]; +int numsticks; #endif @@ -94,49 +43,10 @@ int webdisplay = 0; // R:239, G:208, B:207 -struct videopar { - ld scale, eye, alpha, aspeed; - bool full; - bool goteyes; - bool quick; - bool darkhepta; - bool shifttarget; - - int xres, yres, framelimit; - - int xscr, yscr; - - // paramaters calculated from the above - int xcenter, ycenter; - int radius; - ld alphax, beta; - - int fsize; - int flashtime; - - int wallmode, monmode, axes; - - // for OpenGL - float scrdist; - - bool usingGL; - bool usingAA; - - int joyvalue, joyvalue2, joypanthreshold; - float joypanspeed; - - bool female; - int language; - int boardmode; - - int skincolor, haircolor, dresscolor, swordcolor; - int killreduction; - }; - -int skincolors[] = { 7, 0xD0D0D0FF, 0xEFD0C9FF, 0xC77A58FF, 0xA58869FF, 0x602010FF, 0xFFDCB1FF, 0xEDE4C8FF }; -int haircolors[] = { 8, 0x686868FF, 0x8C684AFF, 0xF2E1AEFF, 0xB55239FF, 0xFFFFFFFF, 0x804000FF, 0x502810FF, 0x301800FF }; -int dresscolors[] = { 6, 0xC00000FF, 0x00C000FF, 0x0000C0FF, 0xC0C000FF, 0xC0C0C0FF, 0x202020FF }; -int swordcolors[] = { 6, 0xC0C0C0FF, 0xFFFFFFFF, 0xFFC0C0FF, 0xC0C0FFFF, 0x808080FF, 0x202020FF }; +unsigned int skincolors[] = { 7, 0xD0D0D0FF, 0xEFD0C9FF, 0xC77A58FF, 0xA58869FF, 0x602010FF, 0xFFDCB1FF, 0xEDE4C8FF }; +unsigned int haircolors[] = { 8, 0x686868FF, 0x8C684AFF, 0xF2E1AEFF, 0xB55239FF, 0xFFFFFFFF, 0x804000FF, 0x502810FF, 0x301800FF }; +unsigned int dresscolors[] = { 6, 0xC00000FF, 0x00C000FF, 0x0000C0FF, 0xC0C000FF, 0xC0C0C0FF, 0x202020FF }; +unsigned int swordcolors[] = { 6, 0xC0C0C0FF, 0xFFFFFFFF, 0xFFC0C0FF, 0xC0C0FFFF, 0x808080FF, 0x202020FF }; // is the player using mouse? (used for auto-cross) bool mousing = true; @@ -144,17 +54,21 @@ bool mousing = true; // is the mouse button pressed? bool mousepressed = false; +emtype cmode = emNormal, lastmode = emNormal; // last mode in Help + // int axestate; int ticks; -hyperpoint ccenter; ld crad; - videopar vid; int default_language; int playergender() { return vid.female ? GEN_F : GEN_M; } +int princessgender() { + return vid.samegender ? playergender() : vid.female ? GEN_M : GEN_F; + } + int lang() { if(vid.language >= 0) return vid.language; @@ -162,36 +76,35 @@ int lang() { } int sightrange = 7; - -cell *mouseover, *lmouseover, *centerover, *lcenterover; ld modist, centdist; + +cell *mouseover, *mouseover2, *lmouseover, *centerover, *lcenterover; +ld modist, modist2, centdist; string mouseovers; -int mousex, mousey, mousedist, mousedest, joyx, joyy, joydir, panjoyx, panjoyy; +movedir mousedest, joydir; + +int mousex, mousey, joyx, joyy, panjoyx, panjoyy; bool autojoy = true; hyperpoint mouseh; -bool leftclick, rightclick, targetclick, hiliteclick; +bool leftclick, rightclick, targetclick, hiliteclick, anyshiftclick; bool gtouched; bool revcontrol; -bool doHighlight() { - return hiliteclick ? vid.monmode == 2 : vid.monmode == 3; - } - int getcstat; ld getcshift; int ZZ; string help; -enum emtype {emNormal, emHelp, emVisual1, emVisual2, - emChangeMode, emCustomizeChar, - emQuit, emDraw, emScores, emPickEuclidean, emPickScores} cmode; - int andmode = 0; int darken = 0; +bool doHighlight() { + return (hiliteclick && darken < 2) ? vid.monmode == 2 : vid.monmode == 3; + } + #ifndef MOBILE int& qpixel(SDL_Surface *surf, int x, int y) { if(x<0 || y<0 || x >= surf->w || y >= surf->h) return ZZ; @@ -213,15 +126,15 @@ int qpixel3(SDL_Surface *surf, int x, int y) { void loadfont(int siz) { if(!font[siz]) { font[siz] = TTF_OpenFont("DejaVuSans-Bold.ttf", siz); + // Destination set by ./configure + #ifdef FONTDESTDIR if (font[siz] == NULL) { - // Destination set by ./configure - #ifdef FONTDESTDIR font[siz] = TTF_OpenFont(FONTDESTDIR, siz); - #endif - if (font[siz] == NULL) { - printf("error: Font file not found\n"); - exit(1); - } + } + #endif + if (font[siz] == NULL) { + printf("error: Font file not found\n"); + exit(1); } } } @@ -297,8 +210,8 @@ void selectEyeGL(int ed) { glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - float sc = vid.radius / (vid.yres/2.); - GLfloat mat[16] = {sc,0,0,0, 0,-sc,0,0, 0,0,-1,0, 0,0,-vid.alpha,1}; + GLfloat sc = vid.radius / (vid.yres/2.); + GLfloat mat[16] = {sc,0,0,0, 0,-sc,0,0, 0,0,-1,0, 0,0, GLfloat(-vid.alpha),1}; glMultMatrixf(mat); if(ve) glTranslatef(ve, 0, vid.eye); @@ -587,7 +500,7 @@ bool displaystr(int x, int y, int shift, int size, const char *str, int color, i loadfont(size); - SDL_Surface *txt = (vid.usingAA?TTF_RenderText_Blended:TTF_RenderText_Solid)(font[size], str, col); + SDL_Surface *txt = (vid.usingAA?TTF_RenderUTF8_Blended:TTF_RenderUTF8_Solid)(font[size], str, col); if(txt == NULL) return false; @@ -806,6 +719,7 @@ void getcoord(const hyperpoint& H, int& x, int& y, int &shift) { if(tz < 1e-3 && tz > -1e-3) tz = 1000; x = vid.xcenter + int(vid.radius * H[0] / tz); y = vid.ycenter + int(vid.radius * H[1] / tz); + #ifndef MOBILE shift = vid.goteyes ? int(vid.eye * vid.radius * (1 - vid.beta / tz)) : 0; #endif @@ -813,16 +727,6 @@ void getcoord(const hyperpoint& H, int& x, int& y, int &shift) { int dlit; -int polyi; - -#define POLYMAX 60000 - -#ifdef MOBILE -short polyx[POLYMAX], polyy[POLYMAX]; -#else -Sint16 polyx[POLYMAX], polyxr[POLYMAX], polyy[POLYMAX]; -#endif - void drawline(const hyperpoint& H1, int x1, int y1, int s1, const hyperpoint& H2, int x2, int y2, int col) { dlit++; if(dlit>500) return; @@ -955,8 +859,6 @@ transmatrix cwtV; // player-relative view heptspin viewctr; // heptagon and rotation where the view is centered at bool playerfound; // has player been found in the last drawing? -#include "geometry.cpp" - ld spina(cell *c, int dir) { return 2 * M_PI * dir / c->type; } @@ -991,10 +893,27 @@ int firecolor(int phase) { return gradient(0xFFFF00, 0xFF0000, -1, sin((phase + ticks)/100.0), 1); } -int fc(int ph, int col) { +int watercolor(int phase) { + return 0x0080C0FF + 256 * int(63 * sin((ticks + phase) / 50.)); + } + +int aircolor(int phase) { + return 0x8080FF00 | int(32 + 32 * sin(ticks/200.0 + 2 * phase * M_PI / 21.)); + } + +int weakfirecolor(int phase) { + return gradient(0xFF8000, 0xFF0000, -1, sin((phase + ticks)/500.0), 1); + } + +int fc(int ph, int col, int z) { if(items[itOrbFire]) col = darkena(firecolor(ph), 0, 0xFF); if(items[itOrbGhost]) col = (col &~0XFF) | (col&0xFF) / 2; - if(invismove) col = (col &~0XFF) | (int((col&0xFF) * (100+100*sin(ticks / 500.)))/200); + if(items[itOrbFish] && isWatery(cwt.c) && z != 3) return watercolor(ph); + if(invismove) + col = + shmup::on ? + (col &~0XFF) | (int((col&0xFF) * .25)) + : (col &~0XFF) | (int((col&0xFF) * (100+100*sin(ticks / 500.)))/200); return col; } @@ -1005,12 +924,6 @@ void drawFlash(cell *c) { flashat = ticks; flashcell = c; } void drawLightning() { lightat = ticks; } void drawSafety() { safetyat = ticks; } -#include "polygons.cpp" - -bool drawplayer = true; - -transmatrix playertrans; - double eurad = 0.52; bool outofmap(hyperpoint h) { @@ -1023,12 +936,14 @@ bool outofmap(hyperpoint h) { void drawShield(const transmatrix& V) { float ds = ticks / 300.; int col = darkened(iinf[itOrbShield].color); + if(items[itOrbPreserve] && !orbused[itOrbShield]) + col = (col & 0xFEFEFE) / 2; for(int a=0; a<84*5; a++) drawline(V*ddi(a, hexf + sin(ds + M_PI*2*a/20)*.1)*C0, V*ddi((a+1), hexf + sin(ds + M_PI*2*(a+1)/20)*.1)*C0, col); } void drawSpeed(const transmatrix& V) { - ld ds = ticks / 10.; + ld ds = ticks / 10.; int col = darkened(iinf[itOrbSpeed].color); for(int b=0; b<84; b+=14) for(int a=0; a<84; a++) @@ -1053,6 +968,22 @@ void drawFlash(const transmatrix& V) { } } +void drawLove(const transmatrix& V, int hdir) { + float ds = ticks / 300.; + int col = darkened(iinf[itOrbLove].color); + col &= ~1; + for(int u=0; u<5; u++) { + for(int a=0; a<84; a++) { + double d = (1 + cos(a * M_PI/42)) / 2; + int z = a; if(z>42) z = 84-z; + if(z <= 10) d += (10-z) * (10-z) * (10-z) / 3000.; + + ld rad = hexf * (2.5 + .5 * sin(ds+u*.3)) * d; + drawline(V*ddi(hdir+a-1, rad)*C0, V*ddi(hdir+a+1, rad)*C0, col); + } + } + } + void drawWinter(const transmatrix& V, int hdir) { float ds = ticks / 300.; int col = darkened(iinf[itOrbWinter].color); @@ -1078,84 +1009,475 @@ int displaydir(cell *c, int d) { return 42 - d * 84 / c->type; } +#include "shmup.cpp" + +void drawPlayerEffects(const transmatrix& V, cell *c) { + if(items[itOrbShield] > (shmup::on ? 0 : 1)) drawShield(V); + + if(items[itOrbSpeed]) drawSpeed(V); + + int ct = c->type; + + if(items[itOrbSafety]) drawSafety(V, ct); + + if(items[itOrbFlash]) drawFlash(V); + if(items[itOrbLove]) drawLove(V, displaydir(c, cwt.spin)); + + if(items[itOrbWinter]) + drawWinter(V, displaydir(c, cwt.spin)); + + if(items[itOrbLightning] > 1) drawLightning(V); + + if(safetyat > 0) { + int tim = ticks - safetyat; + if(tim > 2500) safetyat = 0; + for(int u=tim; u<=2500; u++) { + if((u-tim)%250) continue; + ld rad = hexf * u / 250; + int col = iinf[itOrbSafety].color; + for(int a=0; a<84; a++) + drawline(V*ddi(a, rad)*C0, V*ddi(a+1, rad)*C0, col); + } + } + } + +void drawStunStars(const transmatrix& V, int t) { + for(int i=0; i<3*t; i++) { + transmatrix V2 = V * spin(M_PI * 2 * i / (3*t) + M_PI * ticks/600.); + queuepoly(V2, shFlailBall, 0xFFFFFFFF); + } + } + +bool drawUserShape(transmatrix V, int group, int id, int color) { +#ifdef MOBILE + return false; +#else + usershape *us = usershapes[group][id]; + if(!us) return false; + + for(int i=0; id[i]); + hpcshape& sh(ds.sh); + if(sh.s != sh.e) + queuepoly(V, sh, ds.color ? darkena(ds.color, 0, 0xFF) : color); + } + + if(cmode == emDraw && mapeditor::editingShape(group, id)) { + + usershapelayer &ds(usershapes[group][id]->d[mapeditor::dslayer]); + + hyperpoint mh = inverse(mapeditor::drawtrans) * mouseh; + + for(int a=0; a 0 && c->cpdist <= 3) { + lalpha = 0x80; + transmatrix movtocc = V2 * inverse(cwtV) * rgpushxto0(ccenter); + for(int d=0; d<84; d++) + drawline(movtocc * ddi(d+1, crad) * C0, movtocc * ddi(d, crad) * C0, 0xC00000); + lalpha = 0xFF; + } */ + } + } + + return true; +#endif + } + +bool drawMonsterType(eMonster m, cell *where, const transmatrix& V, int col) { + + char xch = minf[m].glyph; + +#ifndef MOBILE + if(where == mapeditor::drawcell) + mapeditor::drawtrans = V; +#endif + + if(m != moPlayer) + drawStunStars(V, where->stuntime); + + if(m == moPlayer) { + + bool havus = drawUserShape(V, 0, vid.female ? 1 : 0, vid.skincolor); + + if(mapeditor::drawplayer && !havus) { + + queuepoly(V, vid.female ? shFemaleBody : shPBody, fc(0, vid.skincolor, 0)); + + if(items[itOrbThorns]) + queuepoly(V, shHedgehogBladePlayer, items[itOrbDiscord] ? watercolor(0) : 0x00FF00FF); + else if(!shmup::on && items[itOrbDiscord]) + queuepoly(V, shPSword, watercolor(0)); + else if(!shmup::on) + queuepoly(V, shPSword, fc(314, vid.swordcolor, 3)); // 3 not colored + else if(shmup::curtime >= shmup::getPlayer()->nextshot) + queuepoly(V, shPKnife, fc(314, vid.swordcolor, 3)); // 3 not colored + + if(cheater) { + queuepoly(V, vid.female ? shGoatHead : shDemon, darkena(0xFFFF00, 0, 0xFF)); + // queuepoly(V, shHood, darkena(0xFF00, 1, 0xFF)); + } + else { + queuepoly(V, shPFace, fc(500, vid.skincolor, 1)); + queuepoly(V, vid.female ? shFemaleHair : shPHead, fc(150, vid.haircolor, 2)); + } + if(vid.female) + queuepoly(V, shFemaleDress, fc(500, vid.dresscolor, 4)); + + if(knighted) + queuepoly(V, shKnightCloak, darkena(cloakcolor(knighted), 1, 0xFF)); + + if(items[itOrbFish]) + queuepoly(V, shFishTail, watercolor(100)); + + } + } + + else if(drawUserShape(V, 1, m, darkena(col, 0, 0xFF))) return false; + + else if(isMimic(m)) { + if(drawUserShape(V, 0, vid.female?1:0, darkena(col, 0, 0x80))) return false; + queuepoly(V, vid.female ? shFemaleBody : shPBody, darkena(col, 0, 0X80)); + + if(!shmup::on) + queuepoly(V, shPSword, darkena(col, 0, 0XC0)); + else if(shmup::curtime >= shmup::getPlayer()->nextshot) + queuepoly(V, shPKnife, darkena(col, 0, 0XC0)); + + queuepoly(V, vid.female ? shFemaleHair : shPHead, darkena(col, 1, 0XC0)); + queuepoly(V, shPFace, darkena(col, 0, 0XC0)); + if(vid.female) + queuepoly(V, shFemaleDress, darkena(col, 1, 0XC0)); + } + + else if(m == moIllusion) { + if(drawUserShape(V, 0, vid.female?1:0, darkena(col, 0, 0x80))) return false; + queuepoly(V, vid.female ? shFemaleBody : shPBody, darkena(col, 0, 0X80)); + queuepoly(V, shPSword, darkena(col, 0, 0XC0)); + queuepoly(V, vid.female ? shFemaleHair : shPHead, darkena(col, 1, 0XC0)); + queuepoly(V, shPFace, darkena(col, 0, 0XC0)); + if(vid.female) + queuepoly(V, shFemaleDress, darkena(col, 1, 0XC0)); + } + + else if(m == moBullet) { + queuepoly(V * spin(-M_PI/4), shKnife, vid.swordcolor); + } + + else if(m == moKnight) { + queuepoly(V, shPBody, darkena(0xC0C0A0, 0, 0xC0)); + queuepoly(V, shPSword, darkena(0xFFFF00, 0, 0xFF)); + queuepoly(V, shKnightArmor, darkena(0xD0D0D0, 1, 0xFF)); + int col; + if(!euclid && where->master->alt) + col = cloakcolor(roundTableRadius(where)); + else + col = cloakcolor(newRoundTableRadius()); + queuepoly(V, shKnightCloak, darkena(col, 1, 0xFF)); + queuepoly(V, shPHead, darkena(0x703800, 1, 0XFF)); + queuepoly(V, shPFace, darkena(0xC0C0A0, 0, 0XFF)); + return false; + } + + else if(m == moGolem) { + queuepoly(V, shPBody, darkena(col, 0, 0XC0)); + queuepoly(V, shGolemhead, darkena(col, 1, 0XFF)); + } + + else if(isPrincess(m)) { + + bool girl = princessgender(); + + queuepoly(V, girl ? shFemaleBody : shPBody, 0xD0C080FF); + + if(m == moPrincessArmed) + queuepoly(V, shSabre, 0xFFFFFFFF); + + queuepoly(V, girl ? shFemaleHair : shPHead, 0x332A22FF); + queuepoly(V, shPFace, 0xD0C080FF); + if(girl) { + queuepoly(V, shFemaleDress, 0x00C000FF); + queuepoly(V, shPrincessDress, 0x8080FFC0); + } + else { + queuepoly(V, shPrinceDress, 0x404040FF); + } + } + + else if(m == moWolf) { + queuepoly(V, shWolfLegs, darkena(col, 0, 0xFF)); + queuepoly(V, shWolfBody, darkena(col, 0, 0xFF)); + queuepoly(V, shWolfHead, darkena(col, 0, 0xFF)); + queuepoly(V, shWolfEyes, darkena(col, 3, 0xFF)); + } + else if(m == moVineBeast) { + queuepoly(V, shWolfLegs, 0x00FF00FF); + queuepoly(V, shWolfBody, darkena(col, 1, 0xFF)); + queuepoly(V, shWolfHead, darkena(col, 0, 0xFF)); + queuepoly(V, shWolfEyes, 0xFF0000FF); + } + else if(m == moMouse) { + queuepoly(V, shMouse, darkena(col, 0, 0xFF)); + queuepoly(V, shMouseLegs, darkena(col, 1, 0xFF)); + queuepoly(V, shMouseEyes, 0xFF); + } + else if(isBug(m)) { + queuepoly(V, shBugBody, darkena(col, 0, 0xFF)); + queuepoly(V, shBugArmor, darkena(col, 1, 0xFF)); + } + else if(m == moRunDog) { + queuepoly(V, shWolf, darkena(col, 0, 0xFF)); + queuepoly(V, shWolf1, darkena(0x202020, 0, 0xFF)); + queuepoly(V, shWolf2, darkena(0x202020, 0, 0xFF)); + queuepoly(V, shWolf3, darkena(0x202020, 0, 0xFF)); + } + else if(m == moOrangeDog) { + queuepoly(V, shWolf, darkena(0xFFFFFF, 0, 0xFF)); + queuepoly(V, shWolf1, darkena(0x202020, 0, 0xFF)); + queuepoly(V, shWolf2, darkena(0x202020, 0, 0xFF)); + queuepoly(V, shWolf3, darkena(0x202020, 0, 0xFF)); + queuepoly(V, shDogStripes, darkena(0x303030, 0, 0xFF)); + } + else if(m == moShark || m == moGreaterShark || m == moCShark) + queuepoly(V, shShark, darkena(col, 0, 0xFF)); + else if(m == moEagle || m == moParrot || m == moBomberbird || m == moAlbatross || + m == moTameBomberbird) + queuepoly(V, shEagle, darkena(col, 0, 0xFF)); + else if(m == moGargoyle) { + queuepoly(V, shGargoyleWings, darkena(col, 0, 0xD0)); + queuepoly(V, shGargoyleBody, darkena(col, 0, 0xFF)); + } + else if(m == moZombie) + queuepoly(V, shPBody, darkena(col, 0, 0xFF)); + else if(m == moDesertman) { + queuepoly(V, shPBody, darkena(col, 0, 0xC0)); + queuepoly(V, shPSword, 0xFFFF00FF); + queuepoly(V, shHood, 0xD0D000C0); + } + else if(m == moPalace || m == moFatGuard || m == moVizier || m == moSkeleton) { + queuepoly(V, shSabre, 0xFFFFFFFF); + if(m == moSkeleton) { + queuepoly(V, shSkeletonBody, darkena(0xFFFFFF, 0, 0xFF)); + queuepoly(V, shSkull, darkena(0xFFFFFF, 0, 0xFF)); + queuepoly(V, shSkullEyes, darkena(0, 0, 0xFF)); + } + else { + if(m == moFatGuard) { + queuepoly(V, shFatBody, darkena(0xC06000, 0, 0xFF)); + col = 0xFFFFFF; + if(where->hitpoints >= 3) + queuepoly(V, shKnightCloak, darkena(0xFFC0C0, 1, 0xFF)); + } + else { + queuepoly(V, shPBody, darkena(0xFFD500, 0, 0xFF)); + queuepoly(V, shKnightArmor, m == moVizier ? 0xC000C0FF : + darkena(0x00C000, 1, 0xFF)); + if(where->hitpoints >= 3) + queuepoly(V, shKnightCloak, m == moVizier ? 0x800080Ff : + darkena(0x00FF00, 1, 0xFF)); + } + queuepoly(V, shTurban1, darkena(col, 1, 0xFF)); + if(where->hitpoints >= 2) + queuepoly(V, shTurban2, darkena(col, 0, 0xFF)); + } + + drawStunStars(V, where->stuntime); + } + else if(m == moCrystalSage) { + queuepoly(V, shPBody, 0xFFFFFFFF); + queuepoly(V, shPHead, 0xFFFFFFFF); + queuepoly(V, shPFace, 0xFFFFFFFF); + } + else if(m == moHedge) { + queuepoly(V, shPBody, darkena(col, 0, 0xFF)); + queuepoly(V, shHedgehogBlade, 0xC0C0C0FF); + queuepoly(V, shPHead, 0x804000FF); + queuepoly(V, shPFace, 0xF09000FF); + } + else if(m == moYeti || m == moMonkey) { + queuepoly(V, shYeti, darkena(col, 0, 0xC0)); + queuepoly(V, shPHead, darkena(col, 0, 0xFF)); + } + else if(m == moEdgeMonkey) { + queuepoly(V, shYeti, darkena(0xC04040, 0, 0xC0)); + queuepoly(V, shPHead, darkena(col, 0, 0xFF)); + } + else if(m == moShadow) { + queuepoly(V, vid.female ? shFemaleBody : shPBody, darkena(col, 0, 0X80)); + queuepoly(V, shPSword, darkena(col, 0, 0XC0)); + queuepoly(V, vid.female ? shFemaleHair : shPHead, darkena(col, 1, 0XC0)); + queuepoly(V, shPFace, darkena(col, 0, 0XC0)); + + if(vid.female) + queuepoly(V, shFemaleDress, darkena(col, 1, 0xC0)); + } + else if(m == moRanger) { + queuepoly(V, shPBody, darkena(col, 0, 0xC0)); + queuepoly(V, shPSword, darkena(col, 0, 0xFF)); + queuepoly(V, shArmor, darkena(col, 1, 0xFF)); + } + else if(m == moGhost || m == moSeep) { + queuepoly(V, shGhost, darkena(col, 0, 0x80)); + queuepoly(V, shEyes, 0xFF); + } + else if(m == moVineSpirit) { + queuepoly(V, shGhost, 0xD0D0D0C0); + queuepoly(V, shEyes, 0xFF0000FF); + } + else if(m == moFireFairy) { + col = firecolor(0); + queuepoly(V, shFemaleBody, darkena(col, 0, 0XC0)); + queuepoly(V, shFemaleHair, darkena(col, 1, 0xFF)); + queuepoly(V, shPFace, darkena(col, 0, 0XFF)); + } + else if(m == moSlime) { + queuepoly(V, shSlime, darkena(col, 0, 0x80)); + queuepoly(V, shEyes, 0xFF); + } + else if(m == moCultist || m == moPyroCultist || m == moCultistLeader) { + queuepoly(V, shPBody, darkena(col, 0, 0xC0)); + queuepoly(V, shPSword, darkena(col, 2, 0xFF)); + queuepoly(V, shHood, darkena(col, 1, 0xFF)); + } + else if(m == moPirate) { + queuepoly(V, shPBody, darkena(0x404040, 0, 0xFF)); + queuepoly(V, shPirateHook, darkena(0xD0D0D0, 0, 0xFF)); + queuepoly(V, shPFace, darkena(0xFFFF80, 0, 0xFF)); + queuepoly(V, shEyepatch, darkena(0, 0, 0xC0)); + queuepoly(V, shPirateHood, darkena(col, 0, 0xFF)); + } + else if(m == moViking) { + queuepoly(V, shPBody, darkena(0xE00000, 0, 0xFF)); + queuepoly(V, shPSword, darkena(0xD0D0D0, 0, 0xFF)); + queuepoly(V, shKnightCloak, darkena(0x404040, 0, 0xFF)); + queuepoly(V, shVikingHelmet, darkena(0xC0C0C0, 0, 0XFF)); + queuepoly(V, shPFace, darkena(0xFFFF80, 0, 0xFF)); + } + else if(m == moNecromancer) { + queuepoly(V, shPBody, 0xC00000C0); + queuepoly(V, shHood, darkena(col, 1, 0xFF)); + } + else if(m == moGoblin) { + queuepoly(V, shYeti, darkena(col, 0, 0xC0)); + queuepoly(V, shArmor, darkena(col, 1, 0XFF)); + } + else if(m == moLancer || m == moFlailer || m == moMiner) { + transmatrix V2 = V; + if(m == moLancer) + V2 = V * spin(where->type == 6 ? -M_PI/3 : -M_PI/2 ); + queuepoly(V2, shPBody, darkena(col, 0, 0xC0)); + queuepoly(V2, m == moFlailer ? shArmor : shHood, darkena(col, 1, 0XFF)); + if(m == moMiner) + queuepoly(V2, shPickAxe, darkena(0xC0C0C0, 0, 0XFF)); + if(m == moLancer) + queuepoly(V2, shPike, darkena(col, 0, 0XFF)); + if(m == moFlailer) { + queuepoly(V2, shFlailBall, darkena(col, 0, 0XFF)); + queuepoly(V2, shFlailChain, darkena(col, 1, 0XFF)); + queuepoly(V2, shFlailTrunk, darkena(col, 0, 0XFF)); + } + } + else if(m == moTroll) { + queuepoly(V, shYeti, darkena(col, 0, 0xC0)); + queuepoly(V, shPHead, darkena(col, 1, 0XFF)); + queuepoly(V, shPFace, darkena(col, 2, 0XFF)); + } + else if(m == moFjordTroll) { + queuepoly(V, shYeti, darkena(col, 0, 0xC0)); + queuepoly(V, shPHead, darkena(col, 1, 0XFF)); + queuepoly(V, shPFace, darkena(col, 2, 0XFF)); + } + else if(m == moDarkTroll) { + queuepoly(V, shYeti, darkena(col, 0, 0xC0)); + queuepoly(V, shPHead, darkena(col, 1, 0XFF)); + queuepoly(V, shPFace, 0xFFFFFF80); + } + else if(m == moRedTroll) { + queuepoly(V, shYeti, darkena(col, 0, 0xC0)); + queuepoly(V, shPHead, darkena(0xFF8000, 0, 0XFF)); + queuepoly(V, shPFace, 0xFFFFFF80); + } + else if(m == moEarthElemental) { + queuepoly(V, shYeti, darkena(col, 0, 0xC0)); + queuepoly(V, shPHead, darkena(col, 0, 0XFF)); + queuepoly(V, shPFace, 0xF0000080); + } + else if(m == moWaterElemental) { + queuepoly(V, shWaterElemental, watercolor(0)); + queuepoly(V, shFemaleHair, watercolor(100)); + queuepoly(V, shPFace, watercolor(200)); + } + else if(m == moFireElemental) { + queuepoly(V, shWaterElemental, darkena(firecolor(0), 0, 0xFF)); + queuepoly(V, shFemaleHair, darkena(firecolor(100), 0, 0xFF)); + queuepoly(V, shPFace, darkena(firecolor(200), 0, 0xFF)); + } + else if(m == moAirElemental) { + queuepoly(V, shWaterElemental, darkena(col, 0, 0x80)); + queuepoly(V, shFemaleHair, darkena(col, 0, 0x80)); + queuepoly(V, shPFace, darkena(col, 0, 0x80)); + } + else if(xch == 'd' || xch == 'D') { + queuepoly(V, shPBody, darkena(col, 1, 0xC0)); + int acol = col; + if(xch == 'D') acol = 0xD0D0D0; + queuepoly(V, shDemon, darkena(acol, 0, 0xFF)); + } + else if(m == moEvilGolem) { + queuepoly(V, shPBody, darkena(col, 0, 0XC0)); + queuepoly(V, shGolemhead, darkena(col, 1, 0XFF)); + } + else if(isWitch(m)) { + int c = 0xFF; + if(m == moWitchGhost) c = 0x85 + 120 * sin(ticks / 160.0); + if(m == moWitchWinter) drawWinter(V, 42); + if(m == moWitchFlash) drawFlash(V); + if(m == moWitchSpeed) drawSpeed(V); + if(m == moWitchFire) col = firecolor(0); + queuepoly(V, shFemaleBody, darkena(col, 0, c)); +// queuepoly(cV2, ct, shPSword, darkena(col, 0, 0XFF)); +// queuepoly(V, shHood, darkena(col, 0, 0XC0)); + if(m == moWitchFire) col = firecolor(100); + queuepoly(V, shFemaleHair, darkena(col, 1, c)); + if(m == moWitchFire) col = firecolor(200); + queuepoly(V, shPFace, darkena(col, 0, c)); + if(m == moWitchFire) col = firecolor(300); + queuepoly(V, shWitchDress, darkena(col, 1, 0XC0)); + } + + else return true; + + return false; + } + bool drawMonster(const transmatrix& V, int ct, cell *c, int col) { + if(shmup::on) shmup::drawMonster(V, c); + if(doHighlight()) poly_outline = (c->cpdist == 0 || isFriendly(c)) ? 0x00FF00FF : 0xFF0000FF; eMonster m = c->monst; - if(c->cpdist == 0) { - - if(items[itOrbShield] > 1) drawShield(V); - - if(items[itOrbSpeed]) drawSpeed(V); - - int ct = c->type; - - if(items[itOrbSafety]) drawSafety(V, ct); - - if(items[itOrbFlash]) drawFlash(V); - - if(items[itOrbWinter]) - drawWinter(V, displaydir(c, cwt.spin)); - - if(items[itOrbLightning] > 1) drawLightning(V); - - if(safetyat > 0) { - int tim = ticks - safetyat; - if(tim > 2500) safetyat = 0; - for(int u=tim; u<=2500; u++) { - if((u-tim)%250) continue; - ld rad = hexf * u / 250; - int col = iinf[itOrbSafety].color; - for(int a=0; a<84; a++) - drawline(V*ddi(a, rad)*C0, V*ddi(a+1, rad)*C0, col); - } - } - - transmatrix cV2 = c == cwt.c ? cwtV : V; + if(c->cpdist == 0 && !shmup::on && mapeditor::drawplayer) { + transmatrix cV2 = cwtV; // if(flipplayer) cV2 = cV2 * spin(M_PI); if(flipplayer) cV2 = cV2 * spin(M_PI); - if(vid.monmode < 2) return true; - - bool havus = shUser[0][2].s; - playertrans = cV2; - - for(int i=0; i<8; i++) if(shUser[i][2].s) - queuepoly(cV2, ct, shUser[i][2], 0xFFFFFFFF); - - if(drawplayer && !havus) { - - if(c->monst == moGolem) { - queuepoly(cV2, ct, shPBody, darkena(col, 0, 0XC0)); - queuepoly(cV2, ct, shGolemhead, darkena(col, 1, 0XFF)); - } - else { - queuepoly(cV2, ct, vid.female ? shFemaleBody : shPBody, fc(0, vid.skincolor)); - - if(items[itOrbThorns]) - queuepoly(cV2, ct, shHedgehogBladePlayer, 0x00FF00FF); - else - queuepoly(cV2, ct, shPSword, fc(314, vid.swordcolor)); - - if(cheater) { - queuepoly(cV2, ct, shDemon, darkena(0xFFFF00, 0, 0xFF)); - // queuepoly(cV2, ct, shHood, darkena(0xFF00, 1, 0xFF)); - } - else { - queuepoly(cV2, ct, shPFace, fc(500, vid.skincolor)); - queuepoly(cV2, ct, vid.female ? shFemaleHair : shPHead, fc(150, vid.haircolor)); - } - if(vid.female) - queuepoly(cV2, ct, shFemaleDress, fc(500, vid.dresscolor)); - - if(knighted) - queuepoly(cV2, ct, shKnightCloak, darkena(cloakcolor(knighted), 1, 0xFF)); - } - } + drawPlayerEffects(V, c); + if(vid.monmode > 1) + drawMonsterType(moPlayer, c, cV2, col); + else return true; } if(isIvy(c) || isWorm(c)) { @@ -1167,15 +1489,29 @@ bool drawMonster(const transmatrix& V, int ct, cell *c, int col) { if(vid.monmode > 1) { V2 = V2 * spin(hdir * M_PI / 42); + +#ifndef MOBILE + if(c == mapeditor::drawcell) mapeditor::drawtrans = V2; +#endif + + if(drawUserShape(V2, 1, c->monst, (col << 8) + 0xFF)) return false; + if(isIvy(c)) - queuepoly(V2, ct, shIBranch, (col << 8) + 0xFF); + queuepoly(V2, shIBranch, (col << 8) + 0xFF); else if(c->monst < moTentacle) { - queuepoly(V2, ct, shTentacleX, 0xFF); - queuepoly(V2, ct, shTentacle, (col << 8) + 0xFF); + queuepoly(V2, shTentacleX, 0xFF); + queuepoly(V2, shTentacle, (col << 8) + 0xFF); } else { - queuepoly(V2, ct, shTentacleX, 0xFFFFFFFF); - queuepoly(V2, ct, shTentacle, (col << 8) + 0xFF); + if(c->monst == moTentacleGhost) { + hyperpoint V0 = inverse(cwtV) * V * C0; + hyperpoint V1 = spintox(V0) * V0; + transmatrix VL = cwtV * rspintox(V0) * rpushxto0(V1) * spin(M_PI); + drawMonsterType(moGhost, c, VL, darkena(col, 0, 0xFF)); + col = minf[moTentacletail].color; + } + queuepoly(V2, shTentacleX, 0xFFFFFFFF); + queuepoly(V2, shTentacle, (col << 8) + 0xFF); } } @@ -1185,15 +1521,15 @@ bool drawMonster(const transmatrix& V, int ct, cell *c, int col) { if(vid.monmode > 1) { if(isIvy(c)) - queuepoly(V, ct, shILeaf[ct-6], darkena(col, 0, 0xFF)); - else if(m == moWorm || m == moWormwait) { - queuepoly(V2 * spin(M_PI), ct, shWormHead, darkena(col, 0, 0xFF)); - queuepoly(V2 * spin(M_PI), ct, shEyes, 0xFF); + queuepoly(V, shILeaf[ct-6], darkena(col, 0, 0xFF)); + else if(m == moWorm || m == moWormwait || m == moHexSnake) { + queuepoly(V2 * spin(M_PI), shWormHead, darkena(col, 0, 0xFF)); + queuepoly(V2 * spin(M_PI), shEyes, 0xFF); } else if(m == moTentacle || m == moTentaclewait || m == moTentacleEscaping) - queuepoly(V2 * spin(M_PI), ct, shTentHead, darkena(col, 0, 0xFF)); + queuepoly(V2 * spin(M_PI), shTentHead, darkena(col, 0, 0xFF)); else - queuepoly(V2, ct, shJoint, darkena(col, 0, 0xFF)); + queuepoly(V2, shJoint, darkena(col, 0, 0xFF)); } return vid.monmode < 2; @@ -1203,23 +1539,19 @@ bool drawMonster(const transmatrix& V, int ct, cell *c, int col) { int hdir = displaydir(c, c->mondir); - transmatrix mirrortrans = Id; - if(c->monst == moMirror) mirrortrans[1][1] = -1; - transmatrix V2 = V * spin(M_PI*hdir/42) * mirrortrans; - - if(vid.monmode > 1) { - if(flipplayer) V2 = V2 * spin(M_PI); - queuepoly(V2, ct, vid.female ? shFemaleBody : shPBody, darkena(col, 0, 0X80)); - queuepoly(V2, ct, shPSword, darkena(col, 0, 0XC0)); - queuepoly(V2, ct, vid.female ? shFemaleHair : shPHead, darkena(col, 1, 0XC0)); - queuepoly(V2, ct, shPFace, darkena(col, 0, 0XC0)); - if(vid.female) - queuepoly(V2, ct, shFemaleDress, darkena(col, 1, 0XC0)); - if(flipplayer) V2 = V2 * spin(M_PI); - } + transmatrix V2 = V * spin(M_PI*hdir/42); + if(c->monst == moMirror) V2 = V2 * Mirror; + if(flipplayer) V2 = V2 * spin(M_PI); + + if(vid.monmode > 1) drawMonsterType(c->monst, c, V2, col); + + if(flipplayer) V2 = V2 * spin(M_PI); + if(!outofmap(mouseh)) { - hyperpoint P2 = V2 * inverse(cwtV) * mouseh; + // transmatrix invxy = Id; invxy[0][0] = invxy[1][1] = -1; + + hyperpoint P2 = V2 * inverse(cwtV) * mouseh; int xc, yc, sc; getcoord(P2, xc, yc, sc); displaychr(xc, yc, sc, 10, 'x', 0xFF00); @@ -1228,46 +1560,38 @@ bool drawMonster(const transmatrix& V, int ct, cell *c, int col) { return vid.monmode < 2; } - else if(c->monst == moIllusion) { - if(vid.monmode > 1) { - queuepoly(V, ct, vid.female ? shFemaleBody : shPBody, darkena(col, 0, 0X80)); - queuepoly(V, ct, shPSword, darkena(col, 0, 0XC0)); - queuepoly(V, ct, vid.female ? shFemaleHair : shPHead, darkena(col, 1, 0XC0)); - queuepoly(V, ct, shPFace, darkena(col, 0, 0XC0)); - if(vid.female) - queuepoly(V, ct, shFemaleDress, darkena(col, 1, 0XC0)); - } - return vid.monmode < 2; - } - else if(c->monst && vid.monmode < 2) return true; - else if(isFriendly(c)) { - // golems and knights don't face player - int hdir = displaydir(c, c->mondir) + 42; - transmatrix V2 = V * spin(hdir * M_PI / 42) ; - if(m == moKnight) { - queuepoly(V2, ct, shPBody, darkena(0xC0C0A0, 0, 0xC0)); - queuepoly(V2, ct, shPSword, darkena(0xFFFF00, 0, 0xFF)); - queuepoly(V2, ct, shKnightArmor, darkena(0xD0D0D0, 1, 0xFF)); - int col; - if(c->master->alt) - col = cloakcolor(roundTableRadius(c)); - else - col = cloakcolor(newRoundTableRadius()); - queuepoly(V2, ct, shKnightCloak, darkena(col, 1, 0xFF)); - queuepoly(V2, ct, shPHead, darkena(0x703800, 1, 0XFF)); - queuepoly(V2, ct, shPFace, darkena(0xC0C0A0, 0, 0XFF)); - } - else { - queuepoly(V2, ct, shPBody, darkena(col, 0, 0XC0)); - queuepoly(V2, ct, shGolemhead, darkena(col, 1, 0XFF)); - } + // illusions face randomly + + else if(c->monst == moIllusion) { + drawMonsterType(c->monst, c, V, col); } - else if(c->monst) { + // golems, knights, and hyperbugs don't face the player (mondir-controlled) + + else if(isFriendly(c) || isBug(c)) { + int hdir = displaydir(c, c->mondir) + 42; + transmatrix V2 = V * spin(hdir * M_PI / 42) ; + return drawMonsterType(m, c, V2, col); + } + + // wolves face the heat - // face the player + else if(c->monst == moWolf && c->cpdist > 1) { + int d = 0; + double bheat = -999; + for(int i=0; itype; i++) if(c->mov[i] && HEAT(c->mov[i]) > bheat) { + bheat = HEAT(c->mov[i]); + d = i; + } + int hdir = displaydir(c, d); + transmatrix V2 = V * spin(hdir * M_PI / 42); + return drawMonsterType(m, c, V2, col); + } + + else if(c->monst) { + // other monsters face the player transmatrix VL; if(false) { @@ -1281,166 +1605,19 @@ bool drawMonster(const transmatrix& V, int ct, cell *c, int col) { VL = cwtV * rspintox(V0) * rpushxto0(V1) * spin(M_PI); } - char xch = minf[m].glyph; - - if(m == moWolf) { - queuepoly(VL, ct, shWolfLegs, darkena(col, 0, 0xFF)); - queuepoly(VL, ct, shWolfBody, darkena(col, 0, 0xFF)); - queuepoly(VL, ct, shWolfHead, darkena(col, 0, 0xFF)); - queuepoly(VL, ct, shWolfEyes, darkena(col, 3, 0xFF)); - } - else if(m == moVineBeast) { - queuepoly(VL, ct, shWolfLegs, 0x00FF00FF); - queuepoly(VL, ct, shWolfBody, darkena(col, 1, 0xFF)); - queuepoly(VL, ct, shWolfHead, darkena(col, 0, 0xFF)); - queuepoly(VL, ct, shWolfEyes, 0xFF0000FF); - } - else if(isBug(m)) { - - int hdir = displaydir(c, c->mondir) + 42; - - transmatrix V2 = V * spin(hdir * M_PI / 42) ; - - queuepoly(V2, ct, shBugBody, darkena(col, 0, 0xFF)); - queuepoly(V2, ct, shBugArmor, darkena(col, 1, 0xFF)); - } - else if(m == moRunDog) { - queuepoly(VL, ct, shWolf, darkena(col, 0, 0xFF)); - } - else if(m == moShark || m == moGreaterShark) - queuepoly(VL, ct, shShark, darkena(col, 0, 0xFF)); - else if(m == moEagle) - queuepoly(VL, ct, shEagle, darkena(col, 0, 0xFF)); - else if(m == moZombie) - queuepoly(VL, ct, shPBody, darkena(col, 0, 0xFF)); - else if(m == moDesertman) { - queuepoly(VL, ct, shPBody, darkena(col, 0, 0xC0)); - queuepoly(VL, ct, shPSword, 0xFFFF00FF); - queuepoly(VL, ct, shHood, 0xD0D000C0); - } - else if(m == moCrystalSage) { - queuepoly(VL, ct, shPBody, 0xFFFFFFFF); - queuepoly(VL, ct, shPHead, 0xFFFFFFFF); - queuepoly(VL, ct, shPFace, 0xFFFFFFFF); - } - else if(m == moHedge) { - queuepoly(VL, ct, shPBody, darkena(col, 0, 0xFF)); - queuepoly(VL, ct, shHedgehogBlade, 0xC0C0C0FF); - queuepoly(VL, ct, shPHead, 0x804000FF); - queuepoly(VL, ct, shPFace, 0xF09000FF); - } - else if(m == moYeti || m == moMonkey) { - queuepoly(VL, ct, shYeti, darkena(col, 0, 0xC0)); - queuepoly(VL, ct, shPHead, darkena(col, 0, 0xFF)); - } - else if(m == moShadow) { - queuepoly(VL, ct, shPBody, darkena(col, 0, 0X80)); - queuepoly(VL, ct, shPSword, darkena(col, 0, 0XC0)); - queuepoly(VL, ct, shPHead, darkena(col, 1, 0XC0)); - queuepoly(VL, ct, shPFace, darkena(col, 0, 0XC0)); - } - else if(m == moRanger) { - queuepoly(VL, ct, shPBody, darkena(col, 0, 0xC0)); - queuepoly(VL, ct, shPSword, darkena(col, 0, 0xFF)); - queuepoly(VL, ct, shArmor, darkena(col, 1, 0xFF)); - } - else if(m == moGhost || m == moSeep) { - queuepoly(VL, ct, shGhost, darkena(col, 0, 0x80)); - queuepoly(VL, ct, shEyes, 0xFF); - } - else if(m == moVineSpirit) { - queuepoly(VL, ct, shGhost, 0xD0D0D0C0); - queuepoly(VL, ct, shEyes, 0xFF0000FF); - } - else if(m == moFireFairy) { - col = firecolor(0); - queuepoly(VL, ct, shFemaleBody, darkena(col, 0, 0XC0)); -// queuepoly(cV2, ct, shPSword, darkena(col, 0, 0XFF)); - queuepoly(VL, ct, shFemaleHair, darkena(col, 1, 0xFF)); - queuepoly(VL, ct, shPFace, darkena(col, 0, 0XFF)); -// queuepoly(cV2, ct, shFemaleDress, 0xC00000FF); - } - else if(m == moSlime) { - queuepoly(VL, ct, shSlime, darkena(col, 0, 0x80)); - queuepoly(VL, ct, shEyes, 0xFF); - } - else if(m == moCultist || m == moPyroCultist || m == moCultistLeader) { - queuepoly(VL, ct, shPBody, darkena(col, 0, 0xC0)); - queuepoly(VL, ct, shPSword, darkena(col, 2, 0xFF)); - queuepoly(VL, ct, shHood, darkena(col, 1, 0xFF)); - } - else if(m == moNecromancer) { - queuepoly(VL, ct, shPBody, 0xC00000C0); - queuepoly(VL, ct, shHood, darkena(col, 1, 0xFF)); - } - else if(m == moGoblin) { - queuepoly(VL, ct, shYeti, darkena(col, 0, 0xC0)); - queuepoly(VL, ct, shArmor, darkena(col, 1, 0XFF)); - } - else if(m == moLancer || m == moFlailer || m == moMiner) { - if(m == moLancer) - VL = VL * spin(c->type == 6 ? -M_PI/3 : -M_PI/2 ); - queuepoly(VL, ct, shPBody, darkena(col, 0, 0xC0)); - queuepoly(VL, ct, m == moFlailer ? shArmor : shHood, darkena(col, 1, 0XFF)); - if(m == moMiner) - queuepoly(VL, ct, shPickAxe, darkena(0xC0C0C0, 0, 0XFF)); - if(m == moLancer) - queuepoly(VL, ct, shPike, darkena(col, 0, 0XFF)); - if(m == moFlailer) { - queuepoly(VL, ct, shFlailBall, darkena(col, 0, 0XFF)); - queuepoly(VL, ct, shFlailChain, darkena(col, 1, 0XFF)); - queuepoly(VL, ct, shFlailTrunk, darkena(col, 0, 0XFF)); - } - } - else if(m == moTroll) { - queuepoly(VL, ct, shYeti, darkena(col, 0, 0xC0)); - queuepoly(VL, ct, shPHead, darkena(col, 1, 0XFF)); - queuepoly(VL, ct, shPFace, darkena(col, 2, 0XFF)); - } - else if(m == moDarkTroll) { - queuepoly(VL, ct, shYeti, darkena(col, 0, 0xC0)); - queuepoly(VL, ct, shPHead, darkena(col, 0, 0XFF)); - queuepoly(VL, ct, shPFace, 0xFFFFFF80); - } - else if(m == moEarthElemental) { - queuepoly(VL, ct, shYeti, darkena(col, 0, 0xC0)); - queuepoly(VL, ct, shPHead, darkena(col, 0, 0XFF)); - queuepoly(VL, ct, shPFace, 0xF0000080); - } - else if(xch == 'd' || xch == 'D') { - queuepoly(VL, ct, shPBody, darkena(col, 1, 0xC0)); - int acol = col; - if(xch == 'D') acol = 0xD0D0D0; - queuepoly(VL, ct, shDemon, darkena(acol, 0, 0xFF)); - } - else if(m == moEvilGolem) { - queuepoly(VL, ct, shPBody, darkena(col, 0, 0XC0)); - queuepoly(VL, ct, shGolemhead, darkena(col, 1, 0XFF)); - } - else if(isWitch(m)) { - int c = 0xFF; - if(m == moWitchGhost) c = 0x85 + 120 * sin(ticks / 160.0); - if(m == moWitchWinter) drawWinter(VL, 42); - if(m == moWitchFlash) drawFlash(VL); - if(m == moWitchSpeed) drawSpeed(VL); - if(m == moWitchFire) col = firecolor(0); - queuepoly(VL, ct, shFemaleBody, darkena(col, 0, c)); -// queuepoly(cV2, ct, shPSword, darkena(col, 0, 0XFF)); -// queuepoly(VL, ct, shHood, darkena(col, 0, 0XC0)); - if(m == moWitchFire) col = firecolor(100); - queuepoly(VL, ct, shFemaleHair, darkena(col, 1, c)); - if(m == moWitchFire) col = firecolor(200); - queuepoly(VL, ct, shPFace, darkena(col, 0, c)); - if(m == moWitchFire) col = firecolor(300); - queuepoly(VL, ct, shWitchDress, darkena(col, 1, 0XC0)); - } - else return true; + return drawMonsterType(m, c, VL, col); } return false; } -cell *keycell; +bool showPirateX; +cell *keycell, *pirateTreasureSeek, *pirateTreasureFound; +transmatrix pirateCoords; + +double downspin; +cell *straightDownSeek; + int keycelldist; void drawCircle(int x, int y, int size, int color) { @@ -1480,6 +1657,8 @@ void drawCircle(int x, int y, int size, int color) { #endif } +int fnt[100][7]; + bool bugsNearby(cell *c, int dist = 2) { if(!havebugs) return false; if(isBug(c)) return true; @@ -1487,16 +1666,62 @@ bool bugsNearby(cell *c, int dist = 2) { return false; } +int minecolors[8] = { + 0xFFFFFF, 0xF0, 0xF000, 0xF00000, + 0x60, 0x600000, 0x00C0C0, 0 + }; + +const char* minetexts[8] = { + "No mines next to you.", + "A mine is next to you!", + "Two mines next to you!", + "Three mines next to you!", + "Four mines next to you!", + "Five mines next to you!", + "Six mines next to you!", + "Seven mines next to you!" + }; + +int countMinesAround(cell *c) { + int mines = 0; + for(int i=0; itype; i++) + if(c->mov[i] && c->mov[i]->wall == waMineMine) + mines++; + return mines; + } + +transmatrix movecell[7], curcell; + +transmatrix applyPatterndir(cell *c, char patt = mapeditor::whichPattern) { + int hdir = displaydir(c, mapeditor::patterndir(c, patt)); + transmatrix V = spin((42+hdir) * M_PI / 42); + + if(mapeditor::reflectPatternAt(c)) + return V * Mirror; + + return V; + } + void drawcell(cell *c, transmatrix V, int spinv) { +#ifdef BUILDZEBRA + if(c->type == 6 && c->tmp > 0) { + int i = c->tmp; + zebra(cellwalker(c, i&15), 1, i>>4, "", 0); + } + + c->item = eItem(c->heat / 4); + buildAutomatonRule(c); +#endif + // todo: fix when scrolling - if(c->land != laGameBoard && sightrange < 10) { + if(!buggyGeneration && c->land != laCanvas && sightrange < 10) { // not yet created - if(c->mpdist > 7) return; + if(c->mpdist > 7 && !cheater) return; // (incorrect comment) too far, no bugs nearby if(playermoved && c->cpdist > sightrange) return; } - + if(!euclid) { // draw a web-like map if(webdisplay & 1) { @@ -1514,7 +1739,7 @@ void drawcell(cell *c, transmatrix V, int spinv) { drawline(V*C0, V*xpush(tessf)*C0, 0xd0d0 >> darken); } - if(webdisplay & 4) if(c->type == 7 && c->master->alt) { + if(webdisplay & 4) if(c->type == 7 && !euclid && c->master->alt) { for(int i=0; i<7; i++) if(c->master->move[i]->alt == c->master->alt->move[0]) drawline(V*C0, V*spin(-2*M_PI*i/7)*xpush(tessf)*C0, 0xd000d0 >> darken); @@ -1522,7 +1747,7 @@ void drawcell(cell *c, transmatrix V, int spinv) { } // save the player's view center - if(c == cwt.c) { + if(c == cwt.c && !shmup::on) { playerfound = true; /* if(euclid) @@ -1533,15 +1758,27 @@ void drawcell(cell *c, transmatrix V, int spinv) { cwtV = V * spin(displaydir(c, cwt.spin) * M_PI/42); } + + /* if(cwt.c->land == laEdge) { + if(c == chosenDown(cwt.c, 1, 0)) + playerfoundL = c, cwtVL = V; + if(c == chosenDown(cwt.c, -1, 0)) + playerfoundR = c, cwtVR = V; + } */ if(1) { hyperpoint VC0 = V*C0; if(intval(mouseh, VC0) < modist) { + modist2 = modist; mouseover2 = mouseover; modist = intval(mouseh, VC0); mouseover = c; } + else if(intval(mouseh, VC0) < modist2) { + modist2 = intval(mouseh, VC0); + mouseover2 = c; + } double dfc = euclid ? intval(VC0, C0) : VC0[2]; @@ -1555,30 +1792,59 @@ void drawcell(cell *c, transmatrix V, int spinv) { getcoord(V*xpush(.5)*C0, xs, ys, ss); // int col = 0xFFFFFF - 0x20 * c->maxdist - 0x2000 * c->cpdist; - if(c->mpdist > 8) return; // not yet generated - + if(!buggyGeneration && c->mpdist > 8 && !cheater) return; // not yet generated + + if(c->land == laNone && cmode == emMapEditor) { + queuepoly(V, shTriangle, 0xFF0000FF); + } + char ch = winf[c->wall].glyph; int col = winf[c->wall].color; if(c->land == laAlchemist && c->wall == waNone) col = 0x202020; if(c->land == laCrossroads && c->wall == waNone) col = (vid.goteyes ? 0xFF3030 : 0xFF0000); + if(c->land == laCrossroads2 && c->wall == waNone) + col = linf[laCrossroads2].color; + + if(c->land == laCrossroads3 && c->wall == waNone) + col = linf[laCrossroads3].color; + + if(isElemental(c->land) && c->wall == waNone) + col = linf[c->land].color; + + if(c->land == laElementalWall && c->wall == waNone) + col = (linf[c->barleft].color>>1) + (linf[c->barright].color>>1); + + if(c->land == laZebra && c->wall == waNone) { + col = 0xE0E0E0; + } + + if(c->land == laZebra && c->wall == waTrapdoor) + col = 0x808080; + if(c->land == laDesert && c->wall == waNone) col = 0xEDC9AF; if(c->land == laCaves && c->wall == waNone) col = 0x202020; - if(c->land == laFjord && c->wall == waNone) col = 0x202020; + if(c->land == laEmerald && c->wall == waNone) col = 0x202020; if(c->land == laDeadCaves && c->wall == waNone) col = 0x202020; - if(isHive(c->land)) { + + if(c->land == laNone && c->wall == waNone) { + col = 0x101010; + queuepoly(V, shTriangle, 0xFFFF0000); + } + + if(isHive(c->land) && !isWateryOrBoat(c) && c->wall != waCloud && c->wall != waMirror && c->wall != waMineMine) { col = linf[c->land].color; if(c->wall == waWaxWall) - col = int(c->heat) & 0xFFFFFF; + col = c->landparam; } if(c->land == laJungle && c->wall == waNone) col = (vid.goteyes ? 0x408040 : 0x008000); if(c->land == laPower && c->wall == waNone) col = linf[c->land].color; -/* if(c->land == laFjord && c->wall == waNone) { +/* if(c->land == laEmerald && c->wall == waNone) { col = 0x50A020; } - if(c->land == laFjord && c->wall == waLake) { + if(c->land == laEmerald && c->wall == waLake) { col = 0x202080; int i = 0; for(int k=0; ktype; k++) if(c->mov[k] && c->mov[k]->wall != waLake) @@ -1596,19 +1862,19 @@ void drawcell(cell *c, transmatrix V, int spinv) { else if(c->wall == waWetTree) col = (vid.goteyes ? 0x60C060 : 0x00C000); else if(c->wall == waNone) { - col = gradient(0x008000, 0x800000, 0, c->heat, 10); + col = gradient(0x008000, 0x800000, 0, c->landparam, 10); } } if(c->land == laMirror && c->wall == waNone) col = 0x808080; if(c->land == laMotion && c->wall == waNone) col = 0xF0F000; if(c->land == laGraveyard && c->wall == waNone) col = 0x107010; if(c->land == laCamelot && c->wall == waNone) { - int d = showoff ? 0 : celldistAltRelative(c); + int d = showoff ? 0 : ((euclid||c->master->alt) ? celldistAltRelative(c) : 0); if(d < 0) col = 0xA0A0A0; else { // a nice floor pattern - int v = fjordval(c); + int v = emeraldval(c); int v0 = (v&~3); bool sw = (v&1); if(v0 == 8 || v0 == 12 || v0 == 20 || v0 == 40 || v0 == 36 || v0 == 24) @@ -1621,7 +1887,7 @@ void drawcell(cell *c, transmatrix V, int spinv) { } if(c->land == laRlyeh && c->wall == waNone) col = (vid.goteyes ? 0x4080C0 : 0x004080); if(c->land == laTemple) { - int d = showoff ? 0 : celldistAlt(c); + int d = showoff ? 0 : (euclid||c->master->alt) ? celldistAlt(c) : 99; if(d % TEMPLE_EACH == 0) col = c->wall == waColumn ? winf[waColumn].color : gradient(0x304080, winf[waColumn].color, 0, 0.5, 1); @@ -1633,30 +1899,28 @@ void drawcell(cell *c, transmatrix V, int spinv) { col = 0x405090; } if(c->land == laHell && c->wall == waNone) col = (vid.goteyes ? 0xC03030 : 0xC00000); - if(c->land == laGameBoard) { - col = linf[c->land].color; - if(c->wall != waNone) - col = winf[c->wall].color; - if(c->wall == waLake) col = 0x202020; - if(c->wall == waFrozenLake) col = 0xC0C0C0; - - if(c->type == 7 && vid.boardmode == '3') col = 0; - if(c->type == 6 && vid.boardmode == '7') col = 0; - } + if(c->land == laPalace && (c->wall == waNone || c->wall == waClosePlate || c->wall == waOpenPlate || + c->wall == waTrapdoor) && (c->wall == waNone || vid.wallmode != 0)) + col = 0x806020; + + if(c->land == laPalace && c->wall == waCamelot) + col = 0xFFD500; + if(isIcyLand(c) && isIcyWall(c)) { - if(c->heat < -0.4) - col = gradient(0x4040FF, 0x0000FF, -0.4, c->heat, -1); - else if(c->heat < 0) - col = gradient(0x8080FF, 0x4040FF, 0, c->heat, -0.4); - else if(c->heat < 0.2) - col = gradient(0x8080FF, 0xFFFFFF, 0, c->heat, 0.2); - // else if(c->heat < 0.4) - // col = gradient(0xFFFFFF, 0xFFFF00, 0.2, c->heat, 0.4); - else if(c->heat < 0.6) - col = gradient(0xFFFFFF, 0xFF0000, 0.2, c->heat, 0.6); - else if(c->heat < 0.8) - col = gradient(0xFF0000, 0xFFFF00, 0.6, c->heat, 0.8); + float h = HEAT(c); + if(h < -0.4) + col = gradient(0x4040FF, 0x0000FF, -0.4, h, -1); + else if(h < 0) + col = gradient(0x8080FF, 0x4040FF, 0, h, -0.4); + else if(h < 0.2) + col = gradient(0x8080FF, 0xFFFFFF, 0, h, 0.2); + // else if(h < 0.4) + // col = gradient(0xFFFFFF, 0xFFFF00, 0.2, h, 0.4); + else if(h < 0.6) + col = gradient(0xFFFFFF, 0xFF0000, 0.2, h, 0.6); + else if(h < 0.8) + col = gradient(0xFF0000, 0xFFFF00, 0.6, h, 0.8); else col = 0xFFFF00; if(c->wall == waNone) @@ -1665,16 +1929,16 @@ void drawcell(cell *c, transmatrix V, int spinv) { col = (col & 0xFCFCFC) >> 2; } - if(c->wall == waBonfire && c->tmp == 0) - col = 0x404040; + /* if(c->wall == waBonfireOff) + col = 0x404040; */ - if(isFire(c) && c->tmp > 0) - col = firecolor(100); + if(isFire(c)) + col = c->wall == waEternalFire ? weakfirecolor(1500) : firecolor(100); - if(c->wall == waThumper && c->tmp == 0) - col = 0xEDC9AF; + /* if(c->wall == waThumperOff) + col = 0xEDC9AF; */ - if(c->wall == waThumper && c->tmp > 0) { + if(c->wall == waThumperOn) { int ds = ticks; for(int u=0; u<5; u++) { ld rad = hexf * (.3 * u + (ds%1000) * .0003); @@ -1684,21 +1948,54 @@ void drawcell(cell *c, transmatrix V, int spinv) { } } - if(c->land == laFjord && c->wall == waCavefloor) { + if(c->land == laEmerald && c->wall == waCavefloor) { col = gradient(col, 0xFF00, 0, 0.5, 1); // col |= 0xFF00; // col += 0x300060; // col += 0x2F18; col -= 0x100000; } + + if(c->land == laOcean && (c->wall == waNone || c->wall == waStrandedBoat)) { + col = 0xD0D020; + } + + if(c->land == laLivefjord && (c->wall == waNone || c->wall == waStrandedBoat)) + col = 0x306030; - if(c->land == laFjord && c->wall == waCavewall) { + if(c->land == laEmerald && c->wall == waCavewall) { col = 0xC0FFC0; // col |= 0xFF00; // col += 0x300060; // col += 0x2F18; col -= 0x100000; } - if(c->land == laHive && items[itOrbInvis] && c->wall == waNone && c->heat) - col = gradient(col, 0xFF0000, 0, c->heat, 100); + if(c->land == laHive && items[itOrbInvis] && c->wall == waNone && c->landparam) + col = gradient(col, 0xFF0000, 0, c->landparam, 100); - if(vid.darkhepta && ishept(c)) - col = gradient(0, col, 0, 0.75, 1); + if(c->land == laCaribbean && (c->wall == waCIsland || c->wall == waCIsland2)) + col = winf[c->wall].color; + + if(c->wall == waBoat && !vid.wallmode) { + col = 0xC06000; + } + + if(c->land == laMinefield && c->wall == waMineMine && (cmode == emMapEditor || !canmove)) + col = 0xFF4040; + + if(c->land == laMinefield && c->wall == waNone) + col = 0x80A080; + + if(c->land == laCaribbean && c->wall == waNone) + col = 0x006000; + + if(c->land == laRedRock && (c->wall == waNone || snakelevel(c))) { + col = linf[c->land].color; + } + + if(c->land == laCanvas && c->wall == waNone) { + col = c->landparam; + } + + if(ishept(c)) { + if(vid.darkhepta) + col = gradient(0, col, 0, 0.75, 1); + } int ycol = col; @@ -1708,18 +2005,26 @@ void drawcell(cell *c, transmatrix V, int spinv) { int xcol = col; - if(c->item) - ch = iinf[c->item].glyph, col = iinf[c->item].color; + eItem it = c->item; + + bool hidden = itemHidden(c); + bool hiddens = itemHiddenFromSight(c); + + if(hiddens && cmode != emMapEditor) + it = itNone; + + if(it) + ch = iinf[it].glyph, col = iinf[it].color; int icol = col; - if(c->item && c->land == laAlchemist) + if(it && c->land == laAlchemist) xcol = col; if(c->monst) ch = minf[c->monst].glyph, col = minf[c->monst].color; - if(c->cpdist == 0 && drawplayer) { ch = '@'; col = cheater ? 0xFF3030 : 0xD0D0D0; } + if(c->cpdist == 0 && mapeditor::drawplayer) { ch = '@'; col = cheater ? 0xFF3030 : 0xD0D0D0; } if(c->monst == moSlime) { col = winf[c->wall].color; @@ -1740,6 +2045,24 @@ void drawcell(cell *c, transmatrix V, int spinv) { bool error = false; + if(c->land == laEdge && (c->wall == waNone || c->wall == waLadder)) + // xcol = (c->landparam&1) ? 0xD00000 : 0x00D000; + xcol = 0x10101 * (32 + (c->landparam&1) * 32) - 0x000010; + + if(c->wall == waSea || c->wall == waBoat) { + if(c->land == laOcean) + xcol = c->landparam > 25 ? 0x000090 : + 0x1010C0 + int(32 * sin(ticks / 500. + c->landparam*1.5)); + else if(c->land == laOceanWall) + xcol = 0x2020FF; + else if(c->land == laAlchemist) + xcol = 0x900090; + else if(c->land == laWhirlpool) + xcol = 0x0000C0 + int(32 * sin(ticks / 200. + ((euclid||c->master->alt) ? celldistAlt(c) : 0)*1.5)); + else if(c->land == laLivefjord) + xcol = 0x000080; + } + if(vid.wallmode) { poly_outline = 0x000000FF; @@ -1747,16 +2070,42 @@ void drawcell(cell *c, transmatrix V, int spinv) { // floor int fd = + c->land == laRedRock ? 0 : (c->land == laOcean || c->land == laLivefjord) ? 1 : c->land == laAlchemist || c->land == laIce || c->land == laGraveyard || - c->land == laRlyeh || c->land == laTemple ? 1 : 2; + c->land == laRlyeh || c->land == laTemple || c->land == laWineyard || + c->land == laDeadCaves || c->land == laPalace ? 1 : + c->land == laCanvas ? 0 : + c->land == laEdge ? 1 : + 2; - if(shUser[0][ct-6].s) { - for(int i=0; i<8; i++) if(shUser[i][ct-6].s) - queuepoly(V, ct, shUser[i][ct-6], darkena(xcol, 2, 0xC0)); + transmatrix Vpdir = V * applyPatterndir(c); +#ifndef MOBILE + if(c == mapeditor::drawcell && c != cwt.c && !c->monst && !c->item) { + mapeditor::drawtrans = Vpdir; + } +#endif + + if(c->wall == waChasm) ; + +#ifndef MOBILE + else if(drawUserShape(Vpdir, mapeditor::cellShapeGroup(), mapeditor::realpattern(c), + darkena(xcol, fd, cmode == emDraw ? 0xC0 : 0xFF))) ; + + else if(mapeditor::whichShape == '7') { + if(ishept(c)) + queuepoly(V, vid.wallmode == 1 ? shBFloor[ct-6] : + euclid ? shBigHex : + shBigHepta, darkena(xcol, fd, 0xFF)); } - else if(c->wall == waChasm) - ; + else if(mapeditor::whichShape == '6') { + if(!ishept(c)) + queuepoly(V, + vid.wallmode == 1 ? shBFloor[ct-6] : + euclid ? (ishex1(c) ? shBigHexTriangle : shBigHexTriangleRev) : + shBigTriangle, darkena(xcol, fd, 0xFF)); + } +#endif else if(c->land == laWineyard && (c->wall == waVineHalfA || c-> wall == waVineHalfB)) { @@ -1773,139 +2122,280 @@ void drawcell(cell *c, transmatrix V, int spinv) { if(vid.wallmode == 1) shar = shSemiBFloor; if(vid.wallmode == 2) shar = shSemiFloor; - int dk = vid.wallmode == 1 ? 0 : vid.wallmode == 2 ? 2 : 1; + int dk = vid.wallmode == 1 ? 0 : vid.wallmode == 2 ? 1 : 1; - queuepoly(V2, ct, shar[0], darkena(winf[waVinePlant].color, dk, 0xFF)); - queuepoly(V2, ct, shar[1], darkena(xcol, dk, 0xFF)); + queuepoly(V2, shar[0], darkena(winf[waVinePlant].color, dk, 0xFF)); + queuepoly(V2, shar[1], darkena(xcol, dk, 0xFF)); } else if(vid.wallmode == 1 && c->land == laAlchemist) - queuepoly(V, ct, shFloor[ct-6], darkena(xcol, 1, 0xFF)); + queuepoly(V, shFloor[ct-6], darkena(xcol, 1, 0xFF)); - else if(vid.wallmode == 1 && c->land != laGameBoard) - queuepoly(V, ct, shBFloor[ct-6], darkena(xcol, 0, 0xFF)); + else if(vid.wallmode == 1 && c->wall == waMineOpen) + ; - else if(vid.wallmode == 2 && c->land != laGameBoard) { - queuepoly(V, ct, shFloor[ct-6], darkena(xcol, fd, 0xFF)); + else if(vid.wallmode == 1) + queuepoly(V, shBFloor[ct-6], darkena(xcol, 0, 0xFF)); + + else if(vid.wallmode == 2) { + queuepoly(V, shFloor[ct-6], darkena(xcol, fd, 0xFF)); } else if(c->land == laWineyard) { - queuepoly(V, ct, (euclid ? shStarFloor : shFeatherFloor)[ct-6], darkena(xcol, 1, 0xFF)); + queuepoly(V, (euclid ? shStarFloor : shFeatherFloor)[ct-6], darkena(xcol, 1, 0xFF)); + } + + else if(c->land == laZebra && !euclid) { + int i = zebra40(c); + i &= ~3; + + int j; + + if(i >=4 && i < 16) j = 2; + else if(i >= 16 && i < 28) j = 1; + else if(i >= 28 && i < 40) j = 3; + else j = 0; + + queuepoly(V * applyPatterndir(c, 'z'), shZebra[j], darkena(xcol, fd, 0xFF)); + } + + else if(c->land == laEdge && !euclid) { + int j = -1; + + if(c->landparam > 1) { + int i = towerval(c); + if(i == 4) j = 0; + if(i == 5) j = 1; + if(i == 6) j = 2; + if(i == 8) j = 3; + if(i == 9) j = 4; + if(i == 10) j = 5; + if(i == 13) j = 6; + } + + if(j >= 0) + queuepoly(V * applyPatterndir(c, 'H'), shTower[j], darkena(xcol, fd, 0xFF)); + else if(c->wall != waLadder) + queuepoly(V * applyPatterndir(c, 'H'), shMFloor[c->type-6], darkena(xcol, fd, 0xFF)); + } + + else if(c->land == laEmerald) { + int j = -1; + + if(!euclid) { + int i = emeraldval(c) & ~3; + if(i == 8) j = 0; + else if(i == 12) j = 1; + else if(i == 16) j = 2; + else if(i == 20) j = 3; + else if(i == 28) j = 4; + else if(i == 36) j = 5; + } + + if(j >= 0) + queuepoly(V * applyPatterndir(c, 'f'), shEmeraldFloor[j], darkena(xcol, fd, 0xFF)); + else + queuepoly(V, (euclid ? shFloor : shCaveFloor)[ct-6], darkena(xcol, 2, 0xFF)); } else if(c->land == laRlyeh) - queuepoly(V, ct, (euclid ? shFloor: shTriFloor)[ct-6], darkena(xcol, 1, 0xFF)); + queuepoly(V, (euclid ? shFloor: shTriFloor)[ct-6], darkena(xcol, 1, 0xFF)); else if(c->land == laTemple) - queuepoly(V, ct, (euclid ? shFloor: shTriFloor)[ct-6], darkena(xcol, 1, 0xFF)); + queuepoly(V, (euclid ? shFloor: shTriFloor)[ct-6], darkena(xcol, 1, 0xFF)); else if(c->land == laAlchemist) - queuepoly(V, ct, shCloudFloor[ct-6], darkena(xcol, 1, 0xFF)); + queuepoly(V, shCloudFloor[ct-6], darkena(xcol, 1, 0xFF)); + + else if((isElemental(c->land) || c->land == laElementalWall) && !euclid) + queuepoly(V, shNewFloor[ct-6], darkena(xcol, fd, 0xFF)); else if(c->land == laJungle) - queuepoly(V, ct, (euclid ? shStarFloor : shFeatherFloor)[ct-6], darkena(xcol, 2, 0xFF)); + queuepoly(V, (euclid ? shStarFloor : shFeatherFloor)[ct-6], darkena(xcol, 2, 0xFF)); else if(c->land == laGraveyard) - queuepoly(V, ct, (euclid ? shFloor : shCrossFloor)[ct-6], darkena(xcol, 1, 0xFF)); - - else if(c->land == laFjord) { - queuepoly(V, ct, (euclid ? shFloor : shCaveFloor)[ct-6], darkena(xcol, 2, 0xFF)); - } + queuepoly(V, (euclid ? shFloor : shCrossFloor)[ct-6], darkena(xcol, 1, 0xFF)); else if(c->land == laDeadCaves) { - queuepoly(V, ct, (euclid ? shFloor : shCaveFloor)[ct-6], darkena(xcol, 1, 0xFF)); + queuepoly(V, (euclid ? shFloor : shCaveFloor)[ct-6], darkena(xcol, 1, 0xFF)); } else if(c->land == laMotion) - queuepoly(V, ct, shMFloor[ct-6], darkena(xcol, 2, 0xFF)); + queuepoly(V, shMFloor[ct-6], darkena(xcol, 2, 0xFF)); else if(c->land == laHell) - queuepoly(V, ct, (euclid ? shStarFloor : shDemonFloor)[ct-6], darkena(xcol, 2, 0xFF)); + queuepoly(V, (euclid ? shStarFloor : shDemonFloor)[ct-6], darkena(xcol, 2, 0xFF)); else if(c->land == laIce) -// queuepoly(V, ct, shFloor[ct-6], darkena(xcol, 2, 0xFF)); - queuepoly(V, ct, shStarFloor[ct-6], darkena(xcol, 1, 0xFF)); +// queuepoly(V, shFloor[ct-6], darkena(xcol, 2, 0xFF)); + queuepoly(V, shStarFloor[ct-6], darkena(xcol, 1, 0xFF)); else if(c->land == laCocytus) - queuepoly(V, ct, (euclid ? shCloudFloor : shDesertFloor)[ct-6], darkena(xcol, 1, 0xFF)); + queuepoly(V, (euclid ? shCloudFloor : shDesertFloor)[ct-6], darkena(xcol, 1, 0xFF)); else if(c->land == laPower) - queuepoly(V, ct, (euclid ? shCloudFloor : shPowerFloor)[ct-6], darkena(xcol, 1, 0xFF)); + queuepoly(V, (euclid ? shCloudFloor : shPowerFloor)[ct-6], darkena(xcol, 1, 0xFF)); - else if(c->land == laHive) { - queuepoly(V, ct, shFloor[ct-6], darkena(xcol, 1, 0xFF)); - queuepoly(V, ct, shMFloor[ct-6], darkena(xcol, 2, 0xFF)); - if(c->wall != waWaxWall && c->wall != waDeadTroll && c->wall != waVinePlant) - queuepoly(V, ct, shMFloor2[ct-6], darkena(xcol, xcol==ycol ? 1 : 2, 0xFF)); + else if(c->land == laHive && !isWateryOrBoat(c) && c->wall != waFloorB && c->wall != waFloorA && + c->wall != waMirror && c->wall != waCloud) { + queuepoly(V, shFloor[ct-6], darkena(xcol, 1, 0xFF)); + if(!snakelevel(c) && c->wall != waMirror && c->wall != waCloud) + queuepoly(V, shMFloor[ct-6], darkena(xcol, 2, 0xFF)); + if(c->wall != waWaxWall && c->wall != waDeadTroll && c->wall != waVinePlant && + !snakelevel(c) && c->wall != waMirror && c->wall != waCloud) + queuepoly(V, shMFloor2[ct-6], darkena(xcol, xcol==ycol ? 1 : 2, 0xFF)); } else if(c->land == laCaves) - queuepoly(V, ct, (euclid ? shCloudFloor : shCaveFloor)[ct-6], darkena(xcol, 2, 0xFF)); + queuepoly(V, (euclid ? shCloudFloor : shCaveFloor)[ct-6], darkena(xcol, 2, 0xFF)); - else if(c->land == laGameBoard) { - if(c->type == 7 && vid.boardmode == '7') - queuepoly(V, ct, vid.wallmode == 1 ? shBFloor[ct-6] : shBigHepta, darkena(xcol, 2, 0xFF)); + else if(c->land == laDesert) + queuepoly(V, (euclid ? shCloudFloor : shDesertFloor)[ct-6], darkena(xcol, 2, 0xFF)); - if(c->type == 6 && vid.boardmode == '3') - queuepoly(V, ct, vid.wallmode == 1 ? shBFloor[ct-6] : shBigTriangle, darkena(xcol, 2, 0xFF)); + else if(c->land == laDryForest) + queuepoly(V, (euclid ? shStarFloor : shDesertFloor)[ct-6], darkena(xcol, 2, 0xFF)); - if(vid.boardmode == 'h') - queuepoly(V, ct, vid.wallmode == 1 ? shBFloor[ct-6] : shFloor[c->type - 6], darkena(xcol, 2, 0xFF)); - - if(vid.boardmode == 'f') { - static int fcol[4] = { 0x404040FF, 0xFF000080, 0x008000FF, 0x000080FF }; - int fv = fjordval(c); - col = fcol[fv&3]; - queuepoly(V, ct, vid.wallmode == 1 ? shBFloor[ct-6] : shFloor[c->type - 6], col); - if(fjordwalled[fv]) - queuepoly(V, ct, shWall[ct-6], col | 0xFF3F3F); - int siz = int(sqrt(squar(xc-xs)+squar(yc-ys))) / 5; - displaystr(xc, yc, sc, siz, its(fv), 0xFFFFFFFF, 8); + else if(c->land == laCaribbean || c->land == laOcean || c->land == laOceanWall || c->land == laWhirlpool) + queuepoly(V, shCloudFloor[ct-6], darkena(xcol, 1, 0xFF)); + + else if(c->land == laLivefjord) + queuepoly(V, (euclid ? shCloudFloor : shCaveFloor)[ct-6], darkena(xcol, 1, 0xFF)); + + else if(c->land == laRedRock) + queuepoly(V, euclid ? shFloor[ct-6] : shDesertFloor[ct-6], darkena(xcol, 0, 0xFF)); + + else if(c->land == laPalace) + queuepoly(V, (euclid?shFloor:shPalaceFloor)[ct-6], darkena(xcol, 1, 0xFF)); + + else { + queuepoly(V, shFloor[ct-6], darkena(xcol, fd, 0xFF)); + } + // walls + +#ifndef MOBILE + if(cmode == emMapEditor && mapeditor::displaycodes) { + + int labeli = mapeditor::displaycodes == 1 ? mapeditor::realpattern(c) : mapeditor::subpattern(c); + + string label = its(labeli); + int siz = int(sqrt(squar(xc-xs)+squar(yc-ys))) / 5; + displaystr(xc, yc, sc, siz, label, 0xFFFFFFFF, 8); + + /* transmatrix V2 = V * applyPatterndir(c); + queuepoly(V2, shNecro, 0x80808080); + queuepoly(V2, shStatue, 0x80808080); */ + } +#endif + + if(realred(c->wall)) { + int s = snakelevel(c); + if(s >= 1) + queuepoly(V, shRedRockFloor[0][ct-6], darkena(winf[waRed1].color, 0, 0xFF)); + if(s >= 2) + queuepoly(V, shRedRockFloor[1][ct-6], darkena(winf[waRed2].color, 0, 0xFF)); + if(s >= 3) + queuepoly(V, shRedRockFloor[2][ct-6], darkena(winf[waRed3].color, 0, 0xFF)); + } + + if(c->land == laRedRock && ishept(c)) { + queuepoly(V, shHeptaMarker, 0x00000080); +// queuepoly(V * spin((c-(cell*)NULL)), shScratch, 0xFF); +// queuepoly(V * spin((c->mov[0]-(cell*)NULL)), shScratch, 0xFF); +// queuepoly(V * spin((c->mov[1]-(cell*)NULL)), shScratch, 0xFF); + } + + /* if(c->land == laBarrier || c->land == laCrossroads2) { + int siz = int(sqrt(squar(xc-xs)+squar(yc-ys))) / 5; + displaystr(xc, yc, sc, siz, its(int(c->heat + .5)), 0xFFFFFFFF, 8); + } */ + + char xch = winf[c->wall].glyph; + + if(c->wall == waLadder) { + if(euclid) { + queuepoly(V, shMFloor[ct-6], 0x804000FF); + queuepoly(V, shMFloor2[ct-6], 0x000000FF); + } + else { + queuepoly(V, shFloor[ct-6], 0x804000FF); + queuepoly(V, shMFloor[ct-6], 0x000000FF); } } - else if(c->land == laDesert) - queuepoly(V, ct, (euclid ? shCloudFloor : shDesertFloor)[ct-6], darkena(xcol, 2, 0xFF)); + if(c->wall == waBoat || c->wall == waStrandedBoat) { + int hdir = displaydir(c, c->mondir); + transmatrix V2 = V * spin((42+hdir) * M_PI / 42); + if(c == cwt.c && items[itOrbWater]) { + queuepoly(V2, shBoatOuter, watercolor(0)); + queuepoly(V2, shBoatInner, 0x0060C0FF); + } + else { + queuepoly(V2, shBoatOuter, 0xC06000FF); + queuepoly(V2, shBoatInner, 0x804000FF); + } + } - else if(c->land == laDryForest) - queuepoly(V, ct, (euclid ? shStarFloor : shDesertFloor)[ct-6], darkena(xcol, 2, 0xFF)); - - else - queuepoly(V, ct, shFloor[ct-6], darkena(xcol, 2, 0xFF)); - // walls - - char xch = winf[c->wall].glyph; - - if(c->wall == waBigStatue) - queuepoly(V, ct, shStatue, + else if(c->wall == waBigStatue) + queuepoly(V, shStatue, darkena(winf[c->wall].color, 0, 0xFF) ); - else if(c->wall == waSulphurC) - queuepoly(V, ct, shGiantStar[ct-6], darkena(xcol, 0, 0xFF)); - + else if(c->wall == waSulphurC) { + bool drawStar = true; + for(int t=0; ttype; t++) + if(c->mov[t] && c->mov[t]->wall != waSulphur && c->mov[t]->wall != waSulphurC && + c->mov[t]->wall != waBarrier) + drawStar = false; + if(drawStar) queuepoly(V, shGiantStar[ct-6], darkena(xcol, 0, 0xFF)); + } + + else if(c->wall == waClosePlate || c->wall == waOpenPlate || (c->wall == waTrapdoor && c->land != laZebra)) { + transmatrix V2 = V; + if(ct == 7 && vid.wallmode == 3) V2 = V * spin(M_PI); + queuepoly(V2, shMFloor[ct-6], darkena(winf[c->wall].color, 0, 0xFF)); + queuepoly(V2, shMFloor2[ct-6], vid.wallmode >= 2 ? darkena(xcol, 1, 0xFF) : darkena(0,1,0xFF)); + } + else if(c->wall == waFrozenLake || c->wall == waLake || c->wall == waCamelotMoat || - c->wall == waRoundTable) + c->wall == waRoundTable || c->wall == waSea || c->wall == waClosePlate || c->wall == waOpenPlate || + c->wall == waOpenGate || c->wall == waTrapdoor) ; else if(xch == '#') { if(c->wall == waVinePlant) xcol = 0x60C000; - queuepoly(V, ct, shWall[ct-6], darkena(xcol, 0, 0xFF)); + if(c->wall != waPlatform) + queuepoly(V, shWall[ct-6], darkena(xcol, 0, 0xFF)); } else if(xch == '%') - queuepoly(V, ct, shMirror, darkena(xcol, 0, 0xC0)); + queuepoly(V, shMirror, darkena(xcol, 0, 0xC0)); - else if(isActiv(c)) { - ld sp = c->tmp > 0 ? ticks / 500. : 0; - queuepoly(V * spin(sp), ct, shStar, darkena(col, 0, 0xF0)); + else if(isFire(c) || isThumper(c) || c->wall == waBonfireOff) { + ld sp = 0; + if(hasTimeout(c)) sp = ticks / (c->land == laPower ? 5000. : 500.); + queuepoly(V * spin(sp), shStar, darkena(col, 0, 0xF0)); } else if(xch == '+' && c->land == laGraveyard && c->wall != waFloorB && c->wall != waFloorA) - queuepoly(V, ct, shCross, darkena(xcol, 0, 0xFF)); + queuepoly(V, shCross, darkena(xcol, 0, 0xFF)); - else if(xch != '.' && xch != '+' && xch != '>' && xch != ':' && xch != ';' && c->wall != waSulphur) + else if(xch == '+' && c->wall == waClosedGate) { + int hdir = 0; + for(int i=0; itype; i++) if(c->mov[i]->wall == waClosedGate) + hdir = i; + hdir = displaydir(c, hdir); + transmatrix V2 = V * spin((42+hdir) * M_PI / 42); + queuepoly(V2, shPalaceGate, darkena(xcol, 0, 0xFF)); + } + + else if(xch == '+' && c->wall == waGiantRug) { + queuepoly(V, shBigCarpet1, darkena(0xC09F00, 0, 0xFF)); + queuepoly(V, shBigCarpet2, darkena(0x600000, 0, 0xFF)); + queuepoly(V, shBigCarpet3, darkena(0xC09F00, 0, 0xFF)); + } + + else if(xch != '.' && xch != '+' && xch != '>' && xch != ':' && xch != ';' && c->wall != waSulphur && xch != ',') error = true; /* if(c->master->alt) { @@ -1915,20 +2405,37 @@ void drawcell(cell *c, transmatrix V, int spinv) { displaystr(xc, yc, sc, siz, its(d), 0xFFFFFFFF, 8); } */ } - else if(!(c->item || c->monst || c->cpdist == 0)) error = true; + else if(!(it || c->monst || c->cpdist == 0)) error = true; + + if(c->wall == waMineOpen) { + int mines = countMinesAround(c); + + if(vid.wallmode == 0) { + if(ch == '.') { + if(mines == 0) ch = ' '; + else ch = '0' + mines, col = minecolors[mines]; + } + else if(ch == '@') col = minecolors[mines]; + } + else if(mines > 0) + queuepoly(V, shMineMark[c->type-6], (minecolors[mines] << 8) | 0xFF); + } // treasure - - char xch = iinf[c->item].glyph; + + char xch = iinf[it].glyph; hpcshape *xsh = - c->item == itHolyGrail ? &shGrail : + it == itPirate ? &shPirateX : + it == itHolyGrail ? &shGrail : + isElementalShard(it) ? &shElementalShard : xch == '*' ? &shGem[ct-6] : xch == '%' ? &shDaisy : xch == '$' ? &shStar : xch == ';' ? &shTriangle : - xch == '!' ? &shTriangle : c->item == itBone ? &shNecro : c->item == itStatue ? &shStatue : + xch == '!' ? &shTriangle : it == itBone ? &shNecro : it == itStatue ? &shStatue : + it == itEdge ? &shFigurine : xch == '?' ? &shBookCover : - c->item == itKey ? &shKey : NULL; + it == itKey ? &shKey : NULL; if(doHighlight()) { - int k = itemclass(c->item); + int k = itemclass(it); if(k == IC_TREASURE) poly_outline = 0xFFFF00FF; else if(k == IC_ORB) @@ -1937,23 +2444,61 @@ void drawcell(cell *c, transmatrix V, int spinv) { poly_outline = 0xFFFFFFFF; } - if(vid.monmode == 0 && c->item) +#ifndef MOBILE + if(c == mapeditor::drawcell && mapeditor::drawcellShapeGroup() == 2) + mapeditor::drawtrans = V; +#endif + + if(vid.monmode == 0 && it) error = true; - else if(xsh) - queuepoly(V * spin(ticks / 1500.), ct, *xsh, darkena(icol, 0, 0xF0)); - - else if(xch == 'o') { - if(c->item == itOrbFire) icol = firecolor(100); - queuepoly(V, ct, shDisk, darkena(icol, 0, 0xC0)); - if(c->item == itOrbFire) icol = firecolor(200); - queuepoly(V, ct, shRing, darkena(icol, 0, int(0x80 + 0x70 * sin(ticks / 300.)))); + else if(it == itCompass) { + transmatrix V2 = V; + if(euclid) V2 = V2 * spin(M_PI/2); + else V2 = V2 * rspintox(inverse(V) * pirateCoords * C0); + V2 = V2 * spin(M_PI * sin(ticks/100.) / 30); + queuepoly(V2, shCompass1, 0xFF8080FF); + queuepoly(V2, shCompass2, 0xFFFFFFFF); + queuepoly(V2, shCompass3, 0xFF0000FF); + queuepoly(V2 * spin(M_PI), shCompass3, 0x000000FF); + xsh = NULL; } - else if(c->item) error = true; + else if(it == itPalace) { + transmatrix V2 = V * spin(ticks / 1500.); + queuepoly(V2, shMFloor3[ct-6], 0xFFD500FF); + queuepoly(V2, shMFloor4[ct-6], darkena(icol, 0, 0xFF)); + queuepoly(V2, shGem[ct-6], 0xFFD500FF); + xsh = NULL; + } + + else if(drawUserShape(V, 2, it, darkena(icol, 0, 0xFF))) ; + + else if(xsh) { + if(it == itFireShard) icol = firecolor(100); + if(it == itWaterShard) icol = watercolor(100) >> 8; + + if(it == itZebra) icol = 0x202020; + + queuepoly(V * spin(ticks / 1500.), *xsh, darkena(icol, 0, hidden ? 0x40 : 0xF0)); + if(xsh == &shBookCover && vid.monmode) + queuepoly(V * spin(ticks / 1500.), shBook, 0x805020FF); + if(it == itZebra) + queuepoly(V * spin(ticks / 1500. + M_PI/c->type), *xsh, darkena(0xFFFFFF, 0, hidden ? 0x40 : 0xF0)); + } + + else if(xch == 'o') { + if(it == itOrbFire) icol = firecolor(100); + queuepoly(V, shDisk, darkena(icol, 0, hidden ? 0x20 : 0xC0)); + if(it == itOrbFire) icol = firecolor(200); + if(it == itOrbFriend || it == itOrbDiscord) icol = 0xC0C0C0; + if(it == itOrbFrog) icol = 0xFF0000; + queuepoly(V, shRing, darkena(icol, 0, int(0x80 + 0x70 * sin(ticks / 300.)))); + } + + else if(it) error = true; + - if(xsh == &shBookCover) - queuepoly(V * spin(ticks / 1500.), ct, shBook, 0x805020FF); // monsters @@ -1974,6 +2519,29 @@ void drawcell(cell *c, transmatrix V, int spinv) { } error |= drawMonster(V, ct, c, col); + + int ad = airdist(c); + if(ad == 1 || ad == 2) { + + for(int i=0; itype; i++) { + cell *c2 = c->mov[i]; + if(airdist(c2) < airdist(c)) { + int hdir = displaydir(c, i); + transmatrix V0 = spin((42+hdir) * M_PI / 42); + + double ph = ticks / 75.0 + airdir * M_PI / 21.; + + int aircol = 0x8080FF00 | int(32 + 32 * -cos(ph)); + + double ph0 = ph/2; + ph0 -= floor(ph0/M_PI)*M_PI; + + queuepoly(V*V0*ddi(0, hexf*-cos(ph0)), shDisk, aircol); + } + } + +// queuepoly(V*ddi(rand() % 84, hexf*(rand()%100)/100), shDisk, aircolor(airdir)); + } /* if(ch == '.') { col = darkened(col); @@ -1992,6 +2560,9 @@ void drawcell(cell *c, transmatrix V, int spinv) { if(error) { int siz = int(sqrt(squar(xc-xs)+squar(yc-ys))); + + if(c->wall == waSea) col = xcol; + if(vid.wallmode >= 2) { displaychr(xc-2, yc, sc, siz, ch, 0); displaychr(xc+2, yc, sc, siz, ch, 0); @@ -2006,54 +2577,60 @@ void drawcell(cell *c, transmatrix V, int spinv) { displaystr(xc, yc, sc, vid.fsize, its(keycelldist), 0x10101 * int(128 - 100 * sin(ticks / 150.)), 8); } + if(c == pirateTreasureFound) { + pirateCoords = V; + if(showPirateX) { + displaychr(xc, yc, sc, 2*vid.fsize, 'X', 0x10100 * int(128 + 100 * sin(ticks / 150.))); + if(cwt.c->master->alt) + displaystr(xc, yc, sc, vid.fsize, its(-celldistAlt(cwt.c)), 0x10101 * int(128 - 100 * sin(ticks / 150.)), 8); + } + } + + if(!euclid && c->master->alt && (!pirateTreasureSeek || celldistAlt(c) < celldistAlt(pirateTreasureSeek))) + pirateTreasureSeek = c; + + if(!euclid && (!straightDownSeek || edgeDepth(c) < edgeDepth(straightDownSeek))) { + straightDownSeek = c; + if(cwt.c->land == laEdge) { + downspin = atan2(VC0[1], VC0[0]) - M_PI/2; + if(downspin < -M_PI) downspin += 2*M_PI; + if(downspin > +M_PI) downspin -= 2*M_PI; + if(cwt.c->landparam < 10) + downspin = downspin * cwt.c->landparam / 10; + } + } + + #if defined(ANDROID) || defined(PANDORA) || defined(IOS) if(c == lmouseover && (mousepressed || ISANDROID || ISMOBILE)) { drawCircle(xc, yc, int(sqrt(squar(xc-xs)+squar(yc-ys)) * .8), c->cpdist > 1 ? 0x00FFFF : 0xFF0000); } #endif - if(c == lmouseover && c->land == laGameBoard) { +#ifndef MOBILE + if(cmode == emMapEditor && !mapeditor::subscreen && lmouseover && + (mapeditor::whichPattern ? mapeditor::subpattern(c) == mapeditor::subpattern(lmouseover) : c == lmouseover)) { drawCircle(xc, yc, int(sqrt(squar(xc-xs)+squar(yc-ys)) * .8), 0x00FFFF); } +#endif - if(joydir >= 0 && c == cwt.c->mov[(joydir+cwt.spin) % cwt.c->type]) + if(joydir.d >= 0 && c == cwt.c->mov[(joydir.d+cwt.spin) % cwt.c->type]) drawCircle(xc, yc, int(sqrt(squar(xc-xs)+squar(yc-ys)) * (.78 - .02 * sin(ticks/199.0))), 0x00FF00); #ifndef MOBILE if(c == lcenterover && !playermoved) drawCircle(xc, yc, int(sqrt(squar(xc-xs)+squar(yc-ys)) * (.70 - .06 * sin(ticks/200.0))), int(175 + 25 * sin(ticks / 200.0))); #endif + +#ifndef MOBILE + mapeditor::drawGhosts(c, V, ct); +#endif - if(cmode == emDraw && cwt.c->type == 6 && ct == 6) for(int a=0; arots; a++) { - - transmatrix V2 = V * spin(M_PI + 2*M_PI*a/dsCur->rots); - - if(outofmap(mouseh)) break; - - hyperpoint P2 = V2 * inverse(cwtV) * mouseh; - - int xc, yc, sc; - getcoord(P2, xc, yc, sc); - displaychr(xc, yc, sc, 10, 'x', 0xFF); - - if(crad > 0 && c->cpdist <= 3) { - lalpha = 0x80; - transmatrix movtocc = V2 * inverse(cwtV) * rgpushxto0(ccenter); - for(int d=0; d<84; d++) - drawline(movtocc * ddi(d+1, crad) * C0, movtocc * ddi(d, crad) * C0, 0xC00000); - lalpha = 0xFF; - } - } - // process mouse - for(int i=-1; itype; i++) if(i == -1 ? cwt.c == c : cwt.c->mov[i % cwt.c->type] == c) { - int mx = mousex, my = mousey; - if(revcontrol) mx = vid.xcenter*2-mx, my = vid.ycenter*2-my; - - int ndist = (xc-mx) * (xc-mx) + (yc-my) * (yc-my); - if(ndist < mousedist) mousedist = ndist, mousedest = i; - } + if(c == cwt.c) curcell = V; + for(int i=0; itype; i++) + if(c == cwt.c->mov[i]) movecell[i] = V; // drawline(V*C0, V*Crad[0], 0xC00000); if(c->bardir != NODIR && c->bardir != NOBARRIERS) { @@ -2078,30 +2655,30 @@ string buildHelpText() { h += XLAT("! (version %1)\n\n", VER); h += XLAT( -MC "You have been trapped in a strange, non-Euclidean world. Collect as much treasure as possible " -MC "before being caught by monsters. The more treasure you collect, the more " -MC "monsters come to hunt you, as long as you are in the same land type. The " -M "Orbs of Yendor are the ultimate treasure; get at least one of them to win the game!" + "You have been trapped in a strange, non-Euclidean world. Collect as much treasure as possible " + "before being caught by monsters. The more treasure you collect, the more " + "monsters come to hunt you, as long as you are in the same land type. The " + "Orbs of Yendor are the ultimate treasure; get at least one of them to win the game!" ); h += XLAT(" (press ESC for some hints about it)."); h += "\n\n"; h += XLAT( -MC "You can fight most monsters by moving into their location. " -MC "The monster could also kill you by moving into your location, but the game " -M "automatically cancels all moves which result in that.\n\n" + "You can fight most monsters by moving into their location. " + "The monster could also kill you by moving into your location, but the game " + "automatically cancels all moves which result in that.\n\n" ); #ifdef MOBILE h += XLAT( -MC "Usually, you move by touching somewhere on the map; you can also touch one " -MC "of the four buttons on the map corners to change this (to scroll the map " -MC "or get information about map objects). You can also touch the " -M "numbers displayed to get their meanings.\n" + "Usually, you move by touching somewhere on the map; you can also touch one " + "of the four buttons on the map corners to change this (to scroll the map " + "or get information about map objects). You can also touch the " + "numbers displayed to get their meanings.\n" ); #else h += XLAT( -MC "Move with mouse, num pad, qweadzxc, or hjklyubn. Wait by pressing 's' or '.'. Spin the world with arrows, PageUp/Down, and Home/Space. " -MC "To save the game you need an Orb of Safety. Press 'v' for config, ESC for the quest status and menu.\n\n" + "Move with mouse, num pad, qweadzxc, or hjklyubn. Wait by pressing 's' or '.'. Spin the world with arrows, PageUp/Down, and Home/Space. " + "To save the game you need an Orb of Safety. Press 'v' for config, ESC for the quest status and menu.\n\n" ); h += XLAT( "You can right click any element to get more information about it.\n\n" @@ -2109,6 +2686,9 @@ MC "To save the game you need an Orb of Safety. Press 'v' for config, ESC for t #endif h += XLAT("See more on the website: ") + "http//roguetemple.com/z/hyper.php\n\n"; + + + h += XLAT("Still confused? Read the FAQ on the HyperRogue website!\n\n"); #ifdef MOBILE h += buildCredits(); @@ -2127,13 +2707,14 @@ string buildCredits() { h += XLAT("add credits for your translation here"); #ifndef NOLICENSE h += XLAT( -MC "released under GNU General Public License version 2 and thus " -M "comes with absolutely no warranty; see COPYING for details\n\n" + "released under GNU General Public License version 2 and thus " + "comes with absolutely no warranty; see COPYING for details\n\n" ); #endif h += XLAT( -M "special thanks to the following people for their bug reports, feature requests, porting, and other help:\n\n%1\n\n", - "Konstantin Stupnik, ortoslon, chrysn, Adam Borowski, Damyan Ivanov, Ryan Farnsley, mcobit, Darren Grey, tricosahedron, Maciej Chojecki, Marek Čtrnáct" + "special thanks to the following people for their bug reports, feature requests, porting, and other help:\n\n%1\n\n", + "Konstantin Stupnik, ortoslon, chrysn, Adam Borowski, Damyan Ivanov, Ryan Farnsley, mcobit, Darren Grey, tricosahedron, Maciej Chojecki, Marek Čtrnáct, " + "wonderfullizardofoz, Piotr Migdał, tehora, Michael Heerdegen, Sprite Guard, zelda0x181e, Vipul" ); #ifdef EXTRALICENSE h += EXTRALICENSE; @@ -2142,6 +2723,23 @@ M "special thanks to the following people for their bug reports, feature reque return h; } +string pushtext(stringpar p) { + string s = XLAT( + "\n\nNote: when pushing %the1 off a heptagonal cell, you can control the pushing direction " + "by clicking left or right half of the heptagon.", p); +#ifndef MOBILE + s += XLAT(" With the keyboard, you can rotate the view for a similar effect (Page Up/Down)."); +#endif + return s; + } + +string princedesc() { + if(vid.female) + return XLAT("Apparently a prince is kept locked somewhere, but you won't ever find him in this hyperbolic palace. "); + else + return XLAT("Apparently a princess is kept locked somewhere, but you won't ever find her in this hyperbolic palace. "); + } + string generateHelpForItem(eItem it) { string help = XLAT(iinf[it].help); #ifdef ANDROID @@ -2160,18 +2758,133 @@ string generateHelpForItem(eItem it) { return help; } +string generateHelpForWall(eWall w) { + string s = XLAT(winf[w].help); + if(isThumper(w)) s += pushtext(w); + return s; + } + +string generateHelpForMonster(eMonster m) { + string s = XLAT(minf[m].help); + if(m == moPalace || m == moSkeleton) + s += pushtext(m); + if(m == moTroll) s += XLAT(trollhelp2); + return s; + } + +string generateHelpForLand(eLand l) { + string s = XLAT(linf[l].help); + + if(l == laPalace) s = princedesc() + s; + + s += "\n\n"; + if(l == laIce || l == laCaves || l == laDesert || l == laMotion || l == laJungle || + l == laCrossroads) + s += XLAT("Always available.\n"); + + if(l == laMirror || l == laMinefield || l == laAlchemist || l == laPalace || + l == laOcean || l == laLivefjord || l == laZebra) + s += XLAT("Treasure required: %1 $$$.\n", "30"); + + if(l == laCaribbean || l == laWhirlpool) + s += XLAT("Accessible only from %the1.\n", laOcean); + + if(l == laRlyeh) + s += XLAT("Accessible only from %the1 (until finished).\n", laOcean); + + if(l == laTemple) + s += XLAT("Accessible only from %the1.\n", laRlyeh); + + if(l == laPrincessQuest) + s += XLAT("Accessible only from %the1.\n", laPalace); + + if(l == laCamelot) + s += XLAT("Accessible only from %the1 or %the2.\n", laCrossroads, laCrossroads3); + + if(l == laDryForest || l == laWineyard || l == laDeadCaves || l == laHive || l == laRedRock || + l == laEdge) + s += XLAT("Treasure required: %1 $$$.\n", "60"); + + if(l == laGraveyard || l == laHive) + s += XLAT("Kills required: %1.\n", "100"); + + if(l == laHell || l == laCrossroads3) + s += XLAT("Finished lands required: %1 (collect 10 treasure)\n", "9"); + + if(l == laCocytus || l == laPower) + s += XLAT("Treasure required: %1 x %2.\n", "10", itHell); + + if(l == laRedRock) + s += XLAT("Treasure required: %1 x %2.\n", "10", itSpice); + + if(l == laDeadCaves) + s += XLAT("Treasure required: %1 x %2.\n", "10", itGold); + + if(l == laCamelot) + s += XLAT("Treasure required: %1 x %2.\n", "5", itEmerald); + + if(l == laEmerald) { + s += XLAT("Treasure required: %1 x %2.\n", "5", itFernFlower); + s += XLAT("Treasure required: %1 x %2.\n", "5", itGold); + s += XLAT("Alternatively: kill a %1 in %the2.\n", moVizier, laPalace); + } + + if(l == laPrincessQuest) + s += XLAT("Kills required: %1.\n", moVizier); + + if(l == laElementalWall) + s += XLAT("Kills required: any Elemental (Living Fjord/Dead Caves).\n"); + + if(l == laZebra) + s += XLAT("Treasure required: %1 x %2.\n", "10", itFeather); + + int rl = isRandland(l); + if(rl == 2) + s += XLAT("Variants of %the1 are always available in the Random Pattern Mode.", l); + else if(rl == 1) + s += XLAT( + "Variants of %the1 are available in the Random Pattern Mode after " + "getting a highscore of at least 10 %2.", l, treasureType(l)); + + return s; + } + void describeMouseover() { + cell *c = mousing ? mouseover : playermoved ? NULL : centerover; string out = mouseovers; if(!c) { } - else if(cmode == emNormal) { + else if(cmode == emNormal || cmode == emQuit || cmode == emMapEditor) { out = XLAT1(linf[c->land].name); - help = XLAT(linf[c->land].help); + help = generateHelpForLand(c->land); + + // Celsius // if(c->land == laIce) out = "Icy Lands (" + fts(60 * (c->heat - .4)) + " C)"; - if(c->land == laIce) out += " (" + fts(60 * (c->heat-.4)) + " °C)"; - if(c->land == laCocytus) out += " (" + fts(60 * (c->heat-.8)) + " °C)"; - if(c->land == laDryForest && c->heat > .5) out += " (" + its(int(c->heat+.1))+"/10)"; + if(c->land == laIce || c->land == laCocytus) + out += " (" + fts(celsius(c)) + " °C)"; + if(c->land == laDryForest && c->landparam) + out += " (" + its(c->landparam)+"/10)"; + if(c->land == laOcean && c->landparam <= 25) + out += " (" + its(c->landparam)+")"; + + if(buggyGeneration) { + char buf[20]; sprintf(buf, " H=%d M=%d", c->landparam, c->mpdist); out += buf; + } + +// if(c->land == laBarrier) +// out += "(" + string(linf[c->barleft].name) + " / " + string(linf[c->barright].name) + ")"; + + // out += " MD"+its(c->mpdist); + // char zz[64]; sprintf(zz, " P%p", c); out += zz; + + // char zz[64]; sprintf(zz, " P%p", c); out += zz; + + // char zz[64]; sprintf(zz, " P%d", princess::dist(c)); out += zz; + // out += " MD"+its(c->mpdist); + // out += " H "+its(c->heat); + // if(c->type == 7) out += " Z"+its(c->master->zebraval); + // out += " H"+its(c->heat); /* // Hive debug if(c->land == laHive) { @@ -2187,28 +2900,45 @@ void describeMouseover() { out += "]"; } */ - if(c->wall && !((c->wall == waFloorA || c->wall == waFloorB) && c->item)) { + if(c->wall && + !((c->wall == waFloorA || c->wall == waFloorB) && c->item)) { out += ", "; out += XLAT1(winf[c->wall].name); - if(!((c->wall == waCavefloor || c->wall == waCavewall) && c->land == laFjord)) - help = XLAT(winf[c->wall].help); + if(c->wall != waSea && c->wall != waPalace) + if(!((c->wall == waCavefloor || c->wall == waCavewall) && c->land == laEmerald)) + help = generateHelpForWall(c->wall); } - if(isActiv(c)) { - if(c->tmp < 0) out += XLAT(" (touch to activate)"); - if(c->tmp == 0) out += XLAT(" (expired)"); - if(c->tmp > 0 && !(c->land == laPower && c->wall == waBonfire)) - out += XLAT(" [%1 turns]", its(c->tmp)); + if(isActivable(c)) out += XLAT(" (touch to activate)"); + + if(hasTimeout(c)) out += XLAT(" [%1 turns]", its(c->wparam)); + + if(c->monst) { + out += ", "; out += XLAT1(minf[c->monst].name); + if(hasHitpoints(c->monst)) + out += " (" + its(c->hitpoints)+" HP)"; + if(c->stuntime) + out += " (" + its(c->stuntime) + "*)"; + + help = generateHelpForMonster(c->monst); } - if(c->monst) {out += ", "; out += XLAT1(minf[c->monst].name); help = XLAT(minf[c->monst].help);} - - if(c->item) { + if(c->item && !itemHiddenFromSight(c)) { out += ", "; out += XLAT1(iinf[c->item].name); if(!c->monst) help = generateHelpForItem(c->item); } - if(!c->cpdist) out += XLAT(", you"); + if(!c->cpdist && !shmup::on) out += XLAT(", you"); + + if(shmup::mousetarget && intval(mouseh, shmup::mousetarget->pat*C0) < .1) { + out += ", "; out += XLAT1(minf[shmup::mousetarget->type].name); + help = XLAT(minf[shmup::mousetarget->type].help); +/* char buf[64]; + sprintf(buf, "%Lf", intval(mouseh, shmup::mousetarget->pat*C0)); + mouseovers = mouseovers + " D: " + buf; + printf("ms = %s\n", mouseovers.c_str());*/ + } + } else if(cmode == emVisual1) { if(getcstat == 'p') { @@ -2241,7 +2971,7 @@ void describeMouseover() { else out = ""; } else if(cmode == emVisual2) { - if(getcstat == 'p') { // stick) { + if(getcstat == 'p') { if(autojoy) out = XLAT("joystick mode: automatic (release the joystick to move)"); if(!autojoy) @@ -2252,12 +2982,26 @@ void describeMouseover() { else if(getcstat == 'f') out = XLAT("Reduce the framerate limit to conserve CPU energy"); } - + else if(cmode == emChangeMode) { + if(getcstat == 'h') + out = XLAT("One wrong move and it is game over!"); + } + mouseovers = out; #ifndef MOBILE + + int col = linf[cwt.c->land].color; + if(cwt.c->land == laRedRock) col = 0xC00000; if(cmode != emPickScores) - displayfr(vid.xres/2, vid.fsize, 2, vid.fsize, out, linf[cwt.c->land].color, 8); + displayfr(vid.xres/2, vid.fsize, 2, vid.fsize, out, col, 8); if(mousey < vid.fsize * 3/2) getcstat = SDLK_F1; + + if(false && shmup::mousetarget) { + char buf[64]; + sprintf(buf, "%Lf", intval(mouseh, shmup::mousetarget->pat*C0)); + mouseovers = mouseovers + " D: " + buf; + return; + } #endif } @@ -2293,8 +3037,8 @@ int mindx=-7, mindy=-7, maxdx=7, maxdy=7; void drawEuclidean() { eucoord px, py; if(!lcenterover) lcenterover = cwt.c; - printf("centerover = %p player = %p [%d,%d]-[%d,%d]\n", lcenterover, cwt.c, - mindx, mindy, maxdx, maxdy); + // printf("centerover = %p player = %p [%d,%d]-[%d,%d]\n", lcenterover, cwt.c, + // mindx, mindy, maxdx, maxdy); decodeMaster(lcenterover->master, px, py); int minsx = mindx-1, maxsx=maxdx+1, minsy=mindy-1, maxsy=maxdy+1; @@ -2339,8 +3083,18 @@ void drawEuclidean() { void drawthemap() { + for(int m=0; mitem == itCompass; + if(yii < size(yi)) { if(!yi[yii].found) for(int i=0; icpdist <= sightrange) { keycell = yi[yii].path[i]; @@ -2351,9 +3105,9 @@ void drawthemap() { #ifndef MOBILE lmouseover = mouseover; #endif - mousedist = 1000000; - mousedest = -1; - modist = 1e20; mouseover = NULL; mouseovers = XLAT("Press F1 or right click for help"); + modist = 1e20; mouseover = NULL; + modist2 = 1e20; mouseover2 = NULL; + mouseovers = XLAT("Press F1 or right click for help"); centdist = 1e20; lcenterover = centerover; centerover = NULL; #ifdef MOBILE mouseovers = XLAT("No info about this..."); @@ -2361,6 +3115,8 @@ void drawthemap() { if(outofmap(mouseh)) modist = -5; playerfound = false; + // playerfoundL = false; + // playerfoundR = false; if(euclid) drawEuclidean(); @@ -2368,12 +3124,35 @@ void drawthemap() { drawrec(viewctr, (!playermoved) ? sightrange+1 : sightrange + 4, hsOrigin, View); + + if(shmup::on) { + if(shmup::players == 1) + cwtV = shmup::pc[0]->pat; + else if(shmup::centerplayer == -1) { + hyperpoint h0 = shmup::pc[0]->pat * C0; + hyperpoint h1 = shmup::pc[1]->pat * C0; + hyperpoint h2 = mid(h0, h1); + cwtV = rgpushxto0(h2); + } + else + cwtV = shmup::pc[shmup::centerplayer]->pat; + } + } + +void spinEdge(ld aspd) { + if(downspin > aspd) downspin = aspd; + if(downspin < -aspd) downspin = -aspd; + View = spin(downspin) * View; } void centerpc(ld aspd) { hyperpoint H = cwtV * C0; ld R = sqrt(H[0] * H[0] + H[1] * H[1]); if(R < 1e-9) { + /* if(playerfoundL && playerfoundR) { + + } */ + spinEdge(aspd); return; } @@ -2387,13 +3166,16 @@ void centerpc(ld aspd) { } else { - aspd *= (1+R); + aspd *= (1+R+(shmup::on?1:0)); if(R < aspd) { View = gpushxto0(H) * View; } else View = rspintox(H) * xpush(-aspd) * spintox(H) * View; + + fixmatrix(View); + spinEdge(aspd); } } @@ -2401,6 +3183,8 @@ void drawmovestar() { if(!playerfound) return; + if(shmup::on) return; + if(vid.axes == 0 || (vid.axes == 1 && mousing)) return; hyperpoint H = cwtV * C0; @@ -2414,7 +3198,7 @@ void drawmovestar() { int starcol = (vid.goteyes? 0xE08060 : 0xC00000); if(vid.axes == 3 || (vid.wallmode == 2 && vid.axes == 1)) - queuepoly(Centered, 7, shMovestar, darkena(starcol, 0, 0xFF)); + queuepoly(Centered, shMovestar, darkena(starcol, 0, 0xFF)); else for(int d=0; d<8; d++) { int col = starcol; @@ -2454,7 +3238,7 @@ void optimizeview() { } } -int vectodir(const hyperpoint& P) { +movedir vectodir(const hyperpoint& P) { hyperpoint H = cwtV * C0; ld R = sqrt(H[0] * H[0] + H[1] * H[1]); transmatrix Centered = cwtV; @@ -2462,14 +3246,24 @@ int vectodir(const hyperpoint& P) { Centered = gpushxto0(H) * Centered; else if(R > 1e-9) Centered = eupush(-H[0], -H[1]) * Centered; - int bdir = -1; ld binv = 99; + + ld dirdist[7]; + for(int i=0; itype; i++) + dirdist[i] = intval(Centered * spin(-i * 2 * M_PI /cwt.c->type) * xpush(1) * C0, P); + + movedir res; + res.d = -1; + for(int i=0; itype; i++) { - ld inv = intval(Centered * spin(-i * 2 * M_PI /cwt.c->type) * xpush(1) * C0, P); - if(inv < binv) binv = inv, bdir = i; + if(dirdist[i] < binv) { + binv = dirdist[i]; + res.d = i; + res.subdir = dirdist[(i+1)%cwt.c->type] < dirdist[(i+cwt.c->type-1)%cwt.c->type] ? 1 : -1; + } } // if(euclid) bdir = (bdir + 3) % 6; - return bdir; + return res; } void movepckeydir(int d) { @@ -2480,28 +3274,64 @@ void movepckeydir(int d) { movepcto(vectodir(spin(-d * M_PI/4) * xpush(1) * C0)); } +void calcMousedest() { + if(outofmap(mouseh)) return; + ld mousedist = intval(mouseh, curcell * C0); + mousedest.d = -1; + + ld dists[7]; + + for(int i=0; itype; i++) + dists[i] = intval(mouseh, movecell[i] * C0); + + /* printf("curcell = %Lf\n", mousedist); + for(int i=0; itype; i++) + printf("d%d = %Lf\n", i, dists[i]); */ + + for(int i=0; itype; i++) if(dists[i] < mousedist) { + mousedist = dists[i]; + mousedest.d = fixdir(i - cwt.spin, cwt.c); + + mousedest.subdir = + dists[(i+1)%cwt.c->type] < dists[(i+cwt.c->type-1)%cwt.c->type] ? 1 : -1; + } + + } + +void mousemovement() { + calcMousedest(); + movepcto(mousedest); + } + +long double sqr(long double x) { return x*x; } + void checkjoy() { - ld joyvalue1 = vid.joyvalue * vid.joyvalue; - ld joyvalue2 = vid.joyvalue2 * vid.joyvalue2; + if(shmup::on) return; + ld joyvalue1 = sqr(vid.joyvalue); + ld joyvalue2 = sqr(vid.joyvalue2); ld jx = joyx; ld jy = joyy; ld sq = jx*jx+jy*jy; if(autojoy) { - if(sq < joyvalue1) { if(joydir >= 0) movepcto(joydir); joydir = -1; return; } - if(sq < joyvalue2 && joydir == -1) return; + if(sq < joyvalue1) { if(joydir.d >= 0) movepcto(joydir); joydir.d = -1; return; } + if(sq < joyvalue2 && joydir.d == -1) return; } else { - if(sq < joyvalue1) { joydir = -1; return; } + if(sq < joyvalue1) { joydir.d = -1; return; } } joydir = vectodir(hpxy(jx, jy)); } void checkpanjoy(double t) { - - if(panjoyx * panjoyx + panjoyy * panjoyy < vid.joypanthreshold * vid.joypanthreshold) + + if(shmup::on) return; + + if(vid.joypanspeed < 1e-7) return; + + if(sqr(panjoyx) + sqr(panjoyy) < sqr(vid.joypanthreshold)) return; ld jx = panjoyx * t * vid.joypanspeed; @@ -2567,13 +3397,20 @@ void displayStatHelp(int y, string name) { displaystr(dx+100, dy, 0, vid.fsize, name, 0xC0C0C0, 0); } -void displayButton(int x, int y, const string& name, int key, int align, int rad = 0) { +void displayButton(int x, int y, const string& name, int key, int align, int rad) { if(displayfr(x, y, rad, vid.fsize, name, 0x808080, align)) { displayfr(x, y, rad, vid.fsize, name, 0xFFFF00, align); getcstat = key; } } +void displayColorButton(int x, int y, const string& name, int key, int align, int rad, int color, int color2) { + if(displayfr(x, y, rad, vid.fsize, name, color, align)) { + if(color2) displayfr(x, y, rad, vid.fsize, name, color2, align); + getcstat = key; + } + } + void quitOrAgain() { int y = vid.yres * (618) / 1000; displayButton(vid.xres/2, y + vid.fsize*1/2, @@ -2583,8 +3420,10 @@ void quitOrAgain() { SDLK_RETURN, 8, 2); displayButton(vid.xres/2, y + vid.fsize*2, XLAT("or 'r' or F5 to restart"), 'r', 8, 2); displayButton(vid.xres/2, y + vid.fsize*7/2, XLAT("or 't' to see the top scores"), 't', 8, 2); - if(canmove) displayButton(vid.xres/2, y + vid.fsize*10/2, XLAT("or another key to continue"), ' ', 8, 2); - else displayButton(vid.xres/2, y + vid.fsize*10/2, XLAT("or ESC to see how it ended"), ' ', 8, 2); + displayButton(vid.xres/2, y + vid.fsize*10/2, XLAT("or 'v' to see the main menu"), 't', 8, 2); + displayButton(vid.xres/2, y + vid.fsize*13/2, XLAT("or 'o' to see the world overview"), 'o', 8, 2); + if(canmove) displayButton(vid.xres/2, y + vid.fsize*16/2, XLAT("or another key to continue"), ' ', 8, 2); + else displayButton(vid.xres/2, y + vid.fsize*16/2, XLAT("or ESC to see how it ended"), SDLK_ESCAPE, 8, 2); } #endif @@ -2605,7 +3444,110 @@ string timeline() { int timespent = savetime + (timerstopped ? 0 : (time(NULL) - timerstart)); char buf[20]; sprintf(buf, "%d:%02d", timespent/60, timespent % 60); - return XLAT("%1 turns (%2)", its(turncount), buf); + return + shmup::on ? + XLAT("%1 knives (%2)", its(turncount), buf) + : + XLAT("%1 turns (%2)", its(turncount), buf); + } + +#define NUMSEQ 29 +#define NUMLIST 33 + +eLand lseq[NUMLIST] = { + laIce, laCaves, laDesert, laMotion, laJungle, + laCrossroads, + laMirror, laMinefield, laAlchemist, laZebra, laPalace, laPrincessQuest, + laOcean, laLivefjord, laCaribbean, laWhirlpool, laRlyeh, laTemple, + laCrossroads2, laElementalWall, + laDryForest, laWineyard, laDeadCaves, laGraveyard, laHive, laRedRock, laEdge, + laEmerald, laCamelot, + laHell, laCrossroads3, laCocytus, laPower + }; + +eLand seq[NUMSEQ] = { + laHell, laCocytus, laGraveyard, + laWineyard, laDryForest, laCaves, + laPalace, laEmerald, laHive, laDeadCaves, laPower, + laOcean, laLivefjord, laRlyeh, laTemple, laIce, + laDesert, laRedRock, + laWhirlpool, + laCaribbean, laJungle, laAlchemist, laMotion, laMirror, laMinefield, + laCrossroads, laZebra, laElementalWall, laEdge + }; + +void showOverview() { + mouseovers = XLAT("world overview"); + mouseovers += " "; + mouseovers += XLAT(" kills: %1", its(tkills())); + mouseovers += XLAT(" $$$: %1", its(gold())); + if(hellUnlocked()) { + int i1, i2; countHyperstoneQuest(i1, i2); + mouseovers += XLAT(" Hyperstone: %1/%2", its(i1), its(i2)); + } + else + mouseovers += XLAT(" Hell: %1/9", its(orbsUnlocked())); + + int nl = NUMLIST; eLand *landtab = lseq; + if(randomPatternsMode) { nl = RANDLANDS; landtab = randlands; } + + int vf = min((vid.yres-64) / nl, vid.xres/40); + + eLand curland = cwt.c->land; + if(curland == laPalace && princess::dist(cwt.c) < OUT_OF_PRISON) + curland = laPrincessQuest; + if(isElemental(curland)) curland = laElementalWall; + + for(int i=0; i= 25) col = 0xFFD500; + else if(lv >= 10) col = 0x00D500; + else if(items[it]) col = 0xC0C0C0; + else col = 0x202020; + if(displayfr(xr*24-48, i0, 1, vf-4, its(items[it]), col, 16)) + getcstat = 2000+it; + if(displayfr(xr*24, i0, 1, vf-4, its(hiitems[it]), col, 16)) + getcstat = 2000+it; + if(items[it]) col = iinf[it].color; else col = 0x202020; + if(displayfr(xr*24+32, i0, 1, vf-4, s0 + iinf[it].glyph, col, 16)) + getcstat = 2000+it; + if(displayfr(xr*24+40, i0, 1, vf-4, XLAT1(iinf[it].name), col, 0)) + getcstat = 2000+it; + eItem io = orbType(l); + if(io == itShard) { + if(items[it] >= 10) col = winf[waMirror].color; else col = 0x202020; + if(displayfr(xr*46, i0, 1, vf-4, XLAT1(winf[waMirror].name), col, 0)) + getcstat = 3000+waMirror; + if(getcstat == 3000+waMirror) + mouseovers = XLAT( + olrDescriptions[getOLR(io, cwt.c->land)], cwt.c->land, it, treasureType(cwt.c->land)); + } + else if(io) { + if(lv >= 25) col = 0xFFD500; + else if(lv >= 10) col = 0xC0C0C0; + else col = 0x202020; + if(displayfr(xr*46-32, i0, 1, vf-4, its(items[io]), col, 16)) + getcstat = 2000+io; + if(items[it] >= 10) col = iinf[io].color; else col = 0x202020; + if(displayfr(xr*46-8, i0, 1, vf-4, s0 + iinf[io].glyph, col, 16)) + getcstat = 2000+io; + if(displayfr(xr*46, i0, 1, vf-4, XLAT1(iinf[io].name), col, 0)) + getcstat = 2000+io; + if(getcstat == 2000+io) + mouseovers = XLAT( + olrDescriptions[getOLR(io, curland)], curland, it, treasureType(curland)); + } + } } void showGameover() { @@ -2613,6 +3555,7 @@ void showGameover() { displayfr(vid.xres/2, y, 4, vid.fsize*2, cheater ? XLAT("It is a shame to cheat!") : showoff ? XLAT("Showoff mode") : + canmove && princess::challenge ? XLAT("%1 Challenge", moPrincess) : canmove ? XLAT("Quest status") : XLAT("GAME OVER"), 0xC00000, 8 ); @@ -2631,7 +3574,8 @@ void showGameover() { displayfr(vid.xres/2, y + vid.fsize*5, 2, vid.fsize, XLAT("CONGRATULATIONS!"), 0xFFFF00, 8); } else { - if(gold() < 30) + if(princess::challenge) ; + else if(gold() < 30) displayfr(vid.xres/2, y+vid.fsize*5, 2, vid.fsize, XLAT("Collect 30 $$$ to access more worlds"), 0xC0C0C0, 8); else if(gold() < 60) displayfr(vid.xres/2, y+vid.fsize*5, 2, vid.fsize, XLAT("Collect 60 $$$ to access even more lands"), 0xC0C0C0, 8); @@ -2644,16 +3588,16 @@ void showGameover() { else displayfr(vid.xres/2, y+vid.fsize*5, 2, vid.fsize, XLAT("Unlock the Orb of Yendor!"), 0xC0C0C0, 8); } - if(tkills() < 100) + if(princess::challenge) + displayfr(vid.xres/2, y+vid.fsize*6, 2, vid.fsize, XLAT("Follow the Mouse and escape with %the1!", moPrincess), 0xC0C0C0, 8); + else if(tkills() < 100) displayfr(vid.xres/2, y+vid.fsize*6, 2, vid.fsize, XLAT("Defeat 100 enemies to access the Graveyard"), 0xC0C0C0, 8); + else if(kills[moVizier] == 0 && (items[itFernFlower] < 5 || items[itGold] < 5)) { + displayfr(vid.xres/2, y+vid.fsize*6, 2, vid.fsize, XLAT("Kill a Vizier in the Palace to access Emerald Mine"), 0xC0C0C0, 8); + } + else if(items[itEmerald] < 5) + displayfr(vid.xres/2, y+vid.fsize*6, 2, vid.fsize, XLAT("Collect 5 Emeralds to access Camelot"), 0xC0C0C0, 8); else if(hellUnlocked()) { - #define NUMSEQ 19 - eLand seq[NUMSEQ] = { - laHell, laCocytus, laGraveyard, - laWineyard, laFjord, laHive, laDeadCaves, laPower, - laRlyeh, laTemple, laDryForest, laIce, laCaves, - laJungle, laDesert, laAlchemist, laMotion, laMirror, laCrossroads - }; bool b = true; for(int i=0; i 0) q = "continue game"; + else q = "play the game!"; + + displayButton(vid.xres/2, y + vid.fsize*25, ifMousing(XLAT("other"), q), ' ', 8, 2); + } +#endif + void displayabutton(int px, int py, string s, int col) { // TMP int siz = vid.yres > vid.xres ? vid.fsize*2 : vid.fsize * 3/2; @@ -2714,6 +3702,7 @@ vector scores; int scoresort = 2; int scoredisplay = 1; int scorefrom = 0; +int scoremode = 0; bool scorerev = false; bool scorecompare(const score& s1, const score &s2) { @@ -2782,7 +3771,11 @@ void loadScores() { fclose(f); addMessage(its(size(scores))+" games have been recorded in "+scorefile); cmode = emScores; + boxid = 0; applyBoxes(); scoresort = 2; reverse(scores.begin(), scores.end()); + scoremode = 0; + if(shmup::on) scoremode = 1; + else if(hardcore) scoremode = 2; scorefrom = 0; stable_sort(scores.begin(), scores.end(), scorecompare); } @@ -2820,8 +3813,17 @@ void showPickScores() { void showScores() { int y = vid.fsize * 7/2; int bx = vid.fsize; + + string modes = + scoremode == 0 ? XLAT(", m - mode: normal") : + scoremode == 1 ? XLAT(", m - mode: shoot'em up") : + scoremode == 2 ? XLAT(", m - mode: hardcore only") : + "?"; - mouseovers = XLAT("t/left/right - change display, up/down - scroll, s - sort by"); + if(euclid) modes += XLAT(" (E:%1)", euclidland); + + + mouseovers = XLAT("t/left/right - change display, up/down - scroll, s - sort by") + modes; displaystr(bx*4, vid.fsize*2, 0, vid.fsize, "#", 0xFFFFFF, 16); displaystr(bx*8, vid.fsize*2, 0, vid.fsize, "$$$", 0xFFFFFF, 16); @@ -2831,9 +3833,22 @@ void showScores() { displaystr(bx*23, vid.fsize*2, 0, vid.fsize, displayfor(NULL), 0xFFFFFF, 0); if(scorefrom < 0) scorefrom = 0; int id = scorefrom; - while(y < (ISIOS ? vid.yres - 3*vid.fsize : vid.yres)) { + while(y < (ISIOS ? vid.yres - 3*vid.fsize : vid.yres)) { if(id >= size(scores)) break; + score& S(scores[id]); + + bool wrongtype = false; + + wrongtype |= (euclid && (!S.box[116] || S.box[120] != euclidland)); + wrongtype |= (!euclid && S.box[116]); + + wrongtype |= (scoremode == 1 && !S.box[119]); + wrongtype |= (scoremode != 1 && S.box[119]); + wrongtype |= (scoremode == 2 && (!S.box[117] || S.box[118] >= PUREHARDCORE_LEVEL)); + + if(wrongtype) { id++; continue; } + char buf[16]; sprintf(buf, "%d", id+1); @@ -2888,6 +3903,7 @@ void handleScoreKeys(int sym, SDL_Event& ev) { else if(sym == SDLK_DOWN || sym == 'j' || sym == 'x') scorefrom += 5; else if(sym == 's') sortScores(); + else if(sym == 'm') { scoremode++; scoremode %= 3; } else if(sym != 0 || ev.type == SDL_MOUSEBUTTONDOWN) cmode = emNormal; } @@ -2902,10 +3918,6 @@ void handlePickScoreKeys(int uni, SDL_Event& ev) { #endif -string ONOFF(bool b) { - return XLAT(b ? "ON" : "OFF"); - } - void drawStats() { DEB("stats"); @@ -2940,11 +3952,11 @@ void drawStats() { if(displaynum(vx, vy, 0, vid.fsize, 0xFFFFFF, gold(), "$$$")) { mouseovers = XLAT("Your total wealth"), help = XLAT( -MC "The total value of the treasure you have collected.\n\n" -MC "Every world type contains a specific type of treasure, worth 1 $$$; " -MC "your goal is to collect as much treasure as possible, but every treasure you find " -MC "causes more enemies to hunt you in its native land.\n\n" -M "Orbs of Yendor are worth 50 $$$ each.\n\n" + "The total value of the treasure you have collected.\n\n" + "Every world type contains a specific type of treasure, worth 1 $$$; " + "your goal is to collect as much treasure as possible, but every treasure you find " + "causes more enemies to hunt you in its native land.\n\n" + "Orbs of Yendor are worth 50 $$$ each.\n\n" ); } @@ -2990,24 +4002,24 @@ M "Orbs of Yendor are worth 50 $$$ each.\n\n" mouseovers = XLAT("frames per second"), help = XLAT( -MC "The higher the number, the smoother the animations in the game. " -MC "If you find that animations are not smooth enough, you can try " -M "to change the options " + "The higher the number, the smoother the animations in the game. " + "If you find that animations are not smooth enough, you can try " + "to change the options " ) + #ifdef ANDROID XLAT( -MC "(Menu button) and select the ASCII mode, which runs much faster. " -MC "Depending on your device, turning the OpenGL mode on or off might " -M "make it faster, slower, or cause glitches."); + "(Menu button) and select the ASCII mode, which runs much faster. " + "Depending on your device, turning the OpenGL mode on or off might " + "make it faster, slower, or cause glitches."); #else #ifdef IOS XLAT( -MC "(in the MENU). You can reduce the sight range, this should make " -M "the animations smoother."); + "(in the MENU). You can reduce the sight range, this should make " + "the animations smoother."); #else XLAT( -MC "(press v) and change the wall/monster mode to ASCII, or change " -M "the resolution."); + "(press v) and change the wall/monster mode to ASCII, or change " + "the resolution."); #endif // todo: iOS #endif @@ -3049,7 +4061,134 @@ M "the resolution."); DEB("stats OK"); achievement_display(); } + +#ifndef MOBILE + +void saveHighQualityShot() { + +#ifndef GFX + addMessage(XLAT("High quality shots not available on this platform")); + return; +#endif + + int dcs = size(dcal); + for(int i=0; icpdist <= 4) setdist(c, 1, NULL); + } + + time_t timer; + timer = time(NULL); + + SDL_Surface *sav = s; + s = SDL_CreateRGBSurface(SDL_SWSURFACE,2000,2000,32,0,0,0,0); + int ssr = sightrange; sightrange = 10; int sch = cheater; cheater = 0; + + bool b = vid.usingGL; + vid.usingGL = false; + videopar vid2 = vid; + vid.xres = vid.yres = 2000; vid.scale = 0.99; + calcparam(); + + darken = 0; + ptds.clear(); + drawthemap(); + + for(int i=0; i<2; i++) { + SDL_FillRect(s, NULL, i ? 0xFFFFFF : 0); + + #ifdef GFX + aacircleColor(s, vid.xcenter, vid.ycenter, vid.radius, 0x0000FF80); + #endif + + if(vid.wallmode < 2) { + int ls = size(lines); + for(int t=0; t> darken); + } + + drawqueue(); + ptds.clear(); + drawthemap(); + + char buf[128]; strftime(buf, 128, "bigshota-%y%m%d-%H%M%S.bmp", localtime(&timer)); + buf[7] += i; + SDL_SaveBMP(s, buf); + + if(i == 0) addMessage(XLAT("Saved the high quality shot to %1", buf)); + } + + + SDL_FreeSurface(s); s = sav; vid = vid2; sightrange = ssr; cheater = sch; + vid.usingGL = b; + } + +void showVisual1() { + displayStat(2, XLAT("video resolution"), its(vid.xres) + "x"+its(vid.yres), 'r'); + displayStat(3, XLAT("fullscreen mode"), ONOFF(vid.full), 'f'); + displayStat(4, XLAT("animation speed"), fts(vid.aspeed), 'a'); + displayStat(5, XLAT("dist from hyperboloid ctr"), fts(vid.alpha), 'p'); + displayStat(6, XLAT("scale factor"), fts(vid.scale), 'z'); + + const char *wdmodes[4] = {"ASCII", "black", "plain", "Escher"}; + const char *mdmodes[4] = {"ASCII", "items only", "items and monsters", "high contrast"}; + const char *axmodes[4] = {"no axes", "auto", "light", "heavy"}; + + displayStat(7, XLAT("draw the heptagons darker"), ONOFF(vid.darkhepta), '7'); + + displayStat(8, XLAT("wall display mode"), + XLAT(wdmodes[vid.wallmode]), 'w'); + displayStat(9, XLAT("monster display mode"), + XLAT(mdmodes[vid.monmode]), 'm'); + displayStat(10, XLAT("cross display mode"), + XLAT(axmodes[vid.axes]), 'c'); + displayStat(11, XLAT("background music volume"), + its(audiovolume), 'b'); + if(lang() != 0) { + string s = XLAT("TRANSLATIONWARNING"); + if(s != "" && s != "TRANSLATIONWARNING") { + int dy = vid.fsize * 12 + vid.yres/4; + int dx = vid.xres/2; + displaystr(dx, dy, 0, vid.fsize, s, 0xFF0000, 8); + } + } + displayStat(13, XLAT("language"), XLAT("EN"), 'l'); + displayStat(14, XLAT("player character"), + XLAT(vid.female ? "female" : "male"), 'g'); + } + +void showVisual2() { + #ifdef GL + displayStat(2, XLAT("openGL & antialiasing mode"), vid.usingGL ? "OpenGL" : vid.usingAA ? "AA" : "OFF", 'o'); + #endif + displayStat(3, XLAT("distance between eyes"), fts(vid.eye * 10), 'e'); + displayStat(4, XLAT("framerate limit"), its(vid.framelimit), 'f'); + + displayStat(6, XLAT("joystick mode"), XLAT(autojoy ? "automatic" : "manual"), 'p'); + + displayStat(7, XLAT("first joystick: movement threshold"), its(vid.joyvalue), 'a'); + displayStat(8, XLAT("first joystick: execute movement threshold"), its(vid.joyvalue2), 'b'); + displayStat(9, XLAT("second joystick: pan threshold"), its(vid.joypanthreshold), 'c'); + displayStat(10, XLAT("second joystick: panning speed"), fts(vid.joypanspeed * 1000), 'd'); + displayStat(12, XLAT("message flash time"), its(vid.flashtime), 't'); + displayStat(13, XLAT("targetting ranged Orbs Shift+click only"), ONOFF(vid.shifttarget), 'i'); + } + + +void showConfig() { + displayStatHelp(0, XLAT("Configuration:")); + + if(cmode == emVisual1) showVisual1(); + else showVisual2(); + + displayStatHelp(16, XLAT("use Shift to decrease and Ctrl to fine tune ")); + displayStatHelp(17, XLAT("(e.g. Shift+Ctrl+Z)")); + + displayStat(19, XLAT("exit configuration"), "", 'v'); + displayStat(21, XLAT("save the current config"), "", 's'); + } +#endif + void drawscreen() { #ifdef GL @@ -3071,11 +4210,17 @@ void drawscreen() { if(!canmove) darken = 1; if(cmode != emNormal && cmode != emDraw && cmode != emCustomizeChar) darken = 2; if(cmode == emQuit && !canmove) darken = 0; +#ifndef MOBILE + if(cmode == emMapEditor && !mapeditor::subscreen && !mapeditor::choosefile) darken = 0; + if(cmode == emDraw && mapeditor::choosefile) darken = 2; + if(cmode == emOverview) darken = 4; +#endif + if(hiliteclick && darken == 0 && vid.monmode == 2) darken = 1; if(!vid.goteyes && !euclid) - drawCircle(vid.xcenter, vid.ycenter, vid.radius, 0xFF); + drawCircle(vid.xcenter, vid.ycenter, vid.radius, 0xFF >> darken); - if(vid.wallmode < 2 && !euclid && !(vid.boardmode != 'h' && cwt.c->land == laGameBoard)) { + if(vid.wallmode < 2 && !euclid && !mapeditor::whichShape) { int ls = size(lines); if(ISMOBILE) ls /= 10; for(int t=0; t> darken); @@ -3092,23 +4237,10 @@ void drawscreen() { #ifndef MOBILE if(cmode == emNormal) drawmovestar(); #endif - - if(cmode == emDraw) { - lalpha = 0x20; - for(int d=0; d<84; d++) - drawline(C0, spin(M_PI*d/42)* xpush(crossf) * C0, 0xC0C0C0); - for(int d=0; d<84; d++) for(int u=2; u<=20; u++) - drawline(spin(M_PI*d/42)* xpush(crossf*u/20) * C0, spin(M_PI*(d+1)/42)* xpush(crossf*u/20) * C0, 0xC0C0C0); - lalpha = 0x80; - if(crad > 0) { - transmatrix movtocc = rgpushxto0(ccenter); - for(int d=0; d<84; d++) - drawline(movtocc * ddi(d+1, crad) * C0, movtocc * ddi(d, crad) * C0, 0x00C000); - } - // spin(M_PI*(d+1)/42) * xpush(crad) * spin(-M_PI*(d+1)/42) * ccenter, spin(M_PI*d/42) * xpush(crad) * spin(-M_PI*d/42) * ccenter, 0xC0C0C0); - lalpha = 0xFF; - } +#ifndef MOBILE + mapeditor::drawGrid(); +#endif getcstat = 0; @@ -3128,15 +4260,8 @@ void drawscreen() { displayabutton(-1, +1, XLAT("NEW"), BTON); displayabutton(+1, +1, XLAT(canmove ? "PLAY" : ISIOS ? " " : "SHARE"), BTON); } - #endif - if(cmode == emDraw) { - mouseovers = - floordraw ? (cwt.c->type == 6 ? "hex floor" : "hepta floor") : "character"; - - mouseovers = - XLAT("Drawing %1 (layer %2), F1 for help", XLAT(mouseovers), its(dslayer)); - } + #endif // displaynum(vx,100, 0, 24, 0xc0c0c0, celldist(cwt.c), ":"); @@ -3166,15 +4291,18 @@ void drawscreen() { #ifndef MOBILE if(cmode == emChangeMode) { displayStat(2, XLAT("vector graphics editor"), "", 'g'); - displayStat(3, XLAT("Euclidean mode"), "", 'e'); - displayStat(4, XLAT("cheat mode"), "", 'c'); - displayStat(6, XLAT("heptagonal game board"), "", '7'); - displayStat(7, XLAT("triangular game board"), "", '3'); - displayStat(8, XLAT("HyperRogue game board"), "", 'h'); - displayStat(9, XLAT("Periodic Editor"), "", 'f'); + displayStat(3, XLAT("map editor"), ONOFF(false), 'm'); + displayStat(4, XLAT("cheat mode"), ONOFF(cheater), 'c'); - displayStat(18, XLAT("first page [Space]"), "", ' '); - displayStat(19, XLAT("exit configuration"), "", 'v'); + displayStat(6, XLAT("Euclidean mode"), ONOFF(euclid), 'e'); + displayStat(7, XLAT("shoot'em up mode"), ONOFF(shmup::on), 's'); + if(!shmup::on) displayStat(8, XLAT("hardcore mode"), + hardcore && !pureHardcore() ? XLAT("PARTIAL") : ONOFF(hardcore), 'h'); + + displayStat(9, XLAT("%1 Challenge", moPrincess), ONOFF(princess::challenge), 'p'); + displayStat(10, XLAT("random pattern mode"), ONOFF(randomPatternsMode), 'r'); + + displayStat(19, XLAT("return to the game"), "", 'v'); } if(cmode == emCustomizeChar) { @@ -3186,106 +4314,101 @@ void drawscreen() { displayStat(5, XLAT("hair color"), "?", 'h'); if(vid.female) displayStat(6, XLAT("dress color"), "?", 'd'); + displayStat(8, XLAT("save whom"), XLAT1(minf[moPrincess].name), 'p'); displayStatHelp(16, XLAT("Shift=random, Ctrl=mix")); - displayStat(19, XLAT("exit configuration"), "", 'v'); + displayStat(19, XLAT("return to the game"), "", 'v'); } + if(cmode == emShmupConfig) + shmup::showShmupConfig(); + +#ifndef MOBILE + if(cmode == emMapEditor) + mapeditor::showMapEditor(); + + if(cmode == emOverview) + showOverview(); + + if(cmode == emDraw) + mapeditor::showDrawEditor(); +#endif + if(cmode == emPickEuclidean) { int s = vid.fsize; vid.fsize = vid.fsize * 4/5; - displayStatHelp(0, XLAT("Euclidean mode")); - int lt = landtypes; + displayStatHelp(-8, XLAT("Euclidean mode")); + if(cheater) for(int i=0; i= 25) landvisited[i] = true; landvisited[laCrossroads] = true; landvisited[laIce] = true; landvisited[laMirror] = true; + landvisited[laPrincessQuest] = princess::everSaved; // for(int i=2; itype; i++) if(cwt.c->mov[i]) { + if(cwt.c->mov[i]->land == laMinefield) + minefieldNearby = true; + if(cwt.c->mov[i]->wall == waMineMine) + mines++; + } + + if((minefieldNearby || mines) && canmove && !items[itOrbGhost] && darken == 0) { + string s; + int col = minecolors[mines]; + + if(mines == 7) seenSevenMines = true; + + displayfr(vid.xres/2, vid.ycenter - vid.radius * 3/4, 2, + vid.fsize, + XLAT(minetexts[mines]), col, 8); + + if(minefieldNearby && cwt.c->land != laMinefield && cwt.c->mov[cwt.spin]->land != laMinefield) { + displayfr(vid.xres/2, vid.ycenter - vid.radius * 3/4 - vid.fsize*3/2, 2, + vid.fsize, + XLAT("WARNING: you are entering a minefield!"), + col, 8); + } + } #ifndef MOBILE - if(cmode == emNormal || cmode == emVisual1 || cmode == emVisual2 || cmode == emChangeMode) - displayButton(vid.xres-8, vid.yres-vid.fsize, XLAT("(v) config"), 'v', 16); + if(cmode == emNormal || cmode == emVisual1 || cmode == emVisual2 || cmode == emChangeMode ) + displayButton(vid.xres-8, vid.yres-vid.fsize, XLAT("(v) menu"), 'v', 16); #endif if(cmode == emQuit) { @@ -3329,9 +4452,15 @@ void drawscreen() { #endif #ifndef MOBILE + // DEB if(mouseover && targetclick) { + shmup::cpid = 0; eItem i = targetRangedOrb(mouseover, roCheck); - if(i) + if(i == itOrbSummon) { + eMonster m = summonedAt(mouseover); + displaychr(mousex, mousey, 0, vid.fsize, minf[m].glyph, minf[m].color); + } + else if(i) displaychr(mousex, mousey, 0, vid.fsize, '@', iinf[i].color); } #endif @@ -3340,14 +4469,18 @@ void drawscreen() { DEB("msgs3"); // SDL_UnlockSurface(s); +//profile("swapbuffers"); #ifdef GL if(vid.usingGL) SDL_GL_SwapBuffers(); else #endif SDL_UpdateRect(s, 0, 0, vid.xres, vid.yres); + +//printf("\ec"); #endif - if(playermoved && vid.aspeed > 4.99) { +//profile("centerpc"); + if(playermoved && vid.aspeed > 4.99 && !shmup::on) { centerpc(1000); playermoved = false; return; @@ -3425,10 +4558,19 @@ void saveConfig() { fprintf(f, "%f %f %f %f\n", float(vid.scale), float(vid.eye), float(vid.alpha), float(vid.aspeed)); fprintf(f, "%d %d %d %d %d %d %d\n", vid.wallmode, vid.monmode, vid.axes, audiovolume, vid.framelimit, vid.usingGL, vid.usingAA); fprintf(f, "%d %d %d %f %d %d\n", vid.joyvalue, vid.joyvalue2, vid.joypanthreshold, vid.joypanspeed, autojoy, vid.flashtime); + + int gflags = 0; + if(vid.female) gflags |= 1; + if(vid.samegender) gflags |= 16; + fprintf(f, "%d %d %08x %08x %08x %08x\n", - vid.female?1:0, vid.language, vid.skincolor, vid.haircolor, vid.swordcolor, vid.dresscolor); + gflags, vid.language, vid.skincolor, vid.haircolor, vid.swordcolor, vid.dresscolor); fprintf(f, "%d %d\n", vid.darkhepta, vid.shifttarget); + + fprintf(f, "%d %d %d %d\n", euclid, euclidland, shmup::on, hardcore); + + shmup::saveConfig(f); fprintf(f, "\n\nThis is a configuration file for HyperRogue (version "VER")\n"); fprintf(f, "\n\nThe numbers are:\n"); @@ -3436,8 +4578,10 @@ void saveConfig() { fprintf(f, "scale, eye distance, parameter, animation speed\n"); fprintf(f, "wallmode, monster mode, cross mode, audiovolume, framerate limit, usingGL, usingAA\n"); fprintf(f, "calibrate first joystick (threshold A, threshold B), calibrate second joystick (pan threshold, pan speed), joy mode\n"); - fprintf(f, "gender (1=female), language, skin color, hair color, sword color, dress color\n"); + fprintf(f, "gender (1=female, 16=same gender prince), language, skin color, hair color, sword color, dress color\n"); fprintf(f, "darken hepta, shift target\n"); + fprintf(f, "euclid, euclid land, shmup, hardcore\n"); + fprintf(f, "version number, shmup players, shmup keyboard/joystick config\n"); fclose(f); addMessage(s0 + "Configuration saved to: " + conffile); @@ -3447,7 +4591,7 @@ void loadConfig() { vid.xres = 9999; vid.yres = 9999; vid.framelimit = 300; FILE *f = fopen(conffile, "rt"); if(f) { - int fs, gl=1, aa=1, bb=1; + int fs, gl=1, aa=1, bb=1, cc, dd; int err; err=fscanf(f, "%d%d%d%d", &vid.xres, &vid.yres, &fs, &vid.fsize); vid.full = fs; @@ -3460,12 +4604,21 @@ void loadConfig() { vid.usingGL = gl; vid.usingAA = aa; err=fscanf(f, "%d%d%d%f%d%d", &vid.joyvalue, &vid.joyvalue2, &vid.joypanthreshold, &vid.joypanspeed, &aa, &vid.flashtime); autojoy = aa; aa = 0; - err=fscanf(f, "%d%d%x%x%x%x", &aa, &vid.language, &vid.skincolor, &vid.haircolor, &vid.swordcolor, &vid.dresscolor); - vid.female = aa; + int gflags; + err=fscanf(f, "%d%d%x%x%x%x", &gflags, &vid.language, &vid.skincolor, &vid.haircolor, &vid.swordcolor, &vid.dresscolor); + + vid.female = (gflags & 1) ? true : false; + vid.samegender = (gflags & 16) ? true : false; aa=0; bb=0; err=fscanf(f, "%d%d", &aa, &bb); vid.darkhepta = aa; vid.shifttarget = bb; + aa = euclid; bb = euclidland; cc = shmup::on; dd = hardcore; + err=fscanf(f, "%d%d%d%d", &aa, &bb, &cc, &dd); + euclid = aa; euclidland = eLand(bb); shmup::on = cc; hardcore = dd; + + shmup::loadConfig(f); + fclose(f); printf("Loaded configuration: %s\n", conffile); } @@ -3482,6 +4635,10 @@ void loadConfig() { case 'p': vid.wallmode = 2; vid.monmode = 2; break; case 'a': vid.wallmode = 0; vid.monmode = 0; break; case 'o': vid.usingGL = !vid.usingGL; break; + case 'E': euclid = !euclid; if(euclid) euclidland = firstland; break; + case 'S': shmup::on = !shmup::on; break; + case 'P': vid.scfg.players = 3-vid.scfg.players; break; + case 'H': hardcore = !hardcore; break; } #endif } @@ -3528,6 +4685,29 @@ bool loadMusicInfo(string dir) { } #endif +#ifndef MOBILE +void initJoysticks() { + numsticks = SDL_NumJoysticks(); + if(numsticks > 8) numsticks = 8; + for(int i=0; i= 2) panstick = SDL_JoystickOpen(1); + initJoysticks(); #ifdef AUDIO @@ -3712,10 +4890,10 @@ void panning(hyperpoint hf, hyperpoint ht) { #include "showoff.cpp" #endif -void switchcolor(int& c, int* cs, int mod) { +void switchcolor(int& c, unsigned int* cs, int mod) { int id = 0; int q = cs[0]; cs++; - for(int i=0; imaster; + else centerover = cwt.c; + // SDL_LockSurface(s); + drawthemap(); + // SDL_UnlockSurface(s); + centerpc(INF); + } + playermoved = true; + } + #ifndef MOBILE // Warning: a very long function! todo: refactor -void loadShape(hpcshape& sh, int d, int layer) { - dsCur = &(dsUser[layer][2]); - dsCur->list.clear(); - dsCur->sym = d==2; - for(int i=sh.s; i < sh.s + (sh.e-sh.s)/d; i++) - dsCur->list.push_back(hpc[i]); - } - void mainloop() { int lastt = 0; + cmode = emNormal; while(true) { #ifndef GFX @@ -3761,31 +4937,39 @@ void mainloop() { optimizeview(); ticks = SDL_GetTicks(); - dslayer %= 8; - dsCur = &(dsUser[dslayer][floordraw ? cwt.c->type-6 : 2]); - int cframelimit = vid.framelimit; - if((cmode == emVisual1 || cmode == emVisual2 || cmode == emHelp || cmode == emQuit) && cframelimit > 15) + if((cmode == emVisual1 || cmode == emVisual2 || cmode == emHelp || cmode == emQuit || + cmode == emCustomizeChar || cmode == emMenu || cmode == emPickEuclidean || + cmode == emScores || cmode == emPickScores) && cframelimit > 15) cframelimit = 15; if(outoffocus && cframelimit > 10) cframelimit = 10; int timetowait = lastt + 1000 / cframelimit - ticks; + + if(shmup::on && cmode == emNormal) + timetowait = 0, shmup::turn(ticks - lastt); + if(timetowait > 0) SDL_Delay(timetowait); else { if(playermoved && vid.aspeed > -4.99 && !outoffocus) centerpc((ticks - lastt) / 1000.0 * exp(vid.aspeed)); - if(panstick || panjoyx || panjoyy) + if(panjoyx || panjoyy) checkpanjoy((ticks - lastt) / 1000.0); lastt = ticks; frames++; - if(!outoffocus) drawscreen(); + if(!outoffocus) { + drawscreen(); + } } Uint8 *keystate = SDL_GetKeyState(NULL); rightclick = keystate[SDLK_RCTRL]; leftclick = keystate[SDLK_RSHIFT]; hiliteclick = keystate[SDLK_LALT] | keystate[SDLK_RALT]; + anyshiftclick = keystate[SDLK_LSHIFT] | keystate[SDLK_RSHIFT]; + + bool didsomething = false; if(vid.shifttarget) { leftclick = false; @@ -3795,7 +4979,7 @@ void mainloop() { leftclick = keystate[SDLK_RSHIFT]; targetclick = true; } - + #ifdef AUDIO if(audio) handlemusic(); #endif @@ -3805,7 +4989,14 @@ void mainloop() { while(SDL_PollEvent(&ev)) { int sym = 0; int uni = 0; - ld shift = 1; + ld shiftmul = 1; + + /* if(ev.type == SDL_JOYDEVICEADDED || ev.type == SDL_JOYDEVICEREMOVED) { + joyx = joyy = 0; + panjoyx = panjoyy = 0; + closeJoysticks(); + initJoysticks(); + } */ if(ev.type == SDL_ACTIVEEVENT) { if(ev.active.state & SDL_APPINPUTFOCUS) { @@ -3834,12 +5025,13 @@ void mainloop() { } if(ev.type == SDL_JOYAXISMOTION) { - if(ev.jaxis.value != 0 && + flashMessages(); + /* if(ev.jaxis.value != 0 && ev.jaxis.axis >= 2) printf("which = %d axis = %d value = %d\n", ev.jaxis.which, ev.jaxis.axis, - ev.jaxis.value); + ev.jaxis.value); */ if(ev.jaxis.which == 0) { if(ev.jaxis.axis == 0) joyx = ev.jaxis.value; @@ -3850,7 +5042,7 @@ void mainloop() { else if(ev.jaxis.axis == 4) panjoyy = ev.jaxis.value; checkjoy(); - printf("panjoy = %d,%d\n", panjoyx, panjoyy); + // printf("panjoy = %d,%d\n", panjoyx, panjoyy); } else { if(ev.jaxis.axis == 0) @@ -3860,7 +5052,30 @@ void mainloop() { } } - if(ev.type == SDL_JOYBUTTONDOWN) { + if(ev.type == SDL_JOYBUTTONDOWN && cmode == emShmupConfig && vid.scfg.setwhat) { + int joyid = ev.jbutton.which; + int button = ev.jbutton.button; + if(joyid < 8 && button < 32) + vid.scfg.joyaction[joyid][button] = vid.scfg.setwhat; + vid.scfg.setwhat = 0; + } + + else if(ev.type == SDL_JOYHATMOTION && cmode == emShmupConfig && vid.scfg.setwhat) { + int joyid = ev.jhat.which; + int hat = ev.jhat.hat; + int dir = 4; + if(ev.jhat.value == SDL_HAT_UP) dir = 0; + if(ev.jhat.value == SDL_HAT_RIGHT) dir = 1; + if(ev.jhat.value == SDL_HAT_DOWN) dir = 2; + if(ev.jhat.value == SDL_HAT_LEFT) dir = 3; + if(joyid < 8 && hat < 4 && dir < 4) { + vid.scfg.hataction[joyid][hat][dir] = vid.scfg.setwhat; + vid.scfg.setwhat = 0; + } + } + + else if(ev.type == SDL_JOYBUTTONDOWN && !shmup::on) { + flashMessages(); movepcto(joydir); checkjoy(); } @@ -3870,8 +5085,8 @@ void mainloop() { mousing = false; sym = ev.key.keysym.sym; uni = ev.key.keysym.unicode; - if(ev.key.keysym.mod & (KMOD_LSHIFT | KMOD_RSHIFT)) shift = -1; - if(ev.key.keysym.mod & (KMOD_LCTRL | KMOD_RCTRL)) shift /= 10; + if(ev.key.keysym.mod & (KMOD_LSHIFT | KMOD_RSHIFT)) shiftmul = -1; + if(ev.key.keysym.mod & (KMOD_LCTRL | KMOD_RCTRL)) shiftmul /= 10; } if(ev.type == SDL_MOUSEBUTTONDOWN) { @@ -3881,7 +5096,13 @@ void mainloop() { if(ev.button.button==SDL_BUTTON_RIGHT || leftclick) sym = SDLK_F1; else if(ev.button.button==SDL_BUTTON_MIDDLE || rightclick) - sym = 1; + sym = 1, didsomething = true; + else if(ev.button.button==SDL_BUTTON_WHEELUP && ((cmode == emQuit) ^ !canmove)) { + sym = 1; msgscroll++; didsomething = true; + } + else if(ev.button.button==SDL_BUTTON_WHEELDOWN && ((cmode == emQuit) ^ !canmove)) { + sym = 1; msgscroll--; didsomething = true; + } else if(ev.button.button==SDL_BUTTON_WHEELUP) { ld jx = (mousex - vid.xcenter - .0) / vid.radius / 10; ld jy = (mousey - vid.ycenter - .0) / vid.radius / 10; @@ -3890,22 +5111,31 @@ void mainloop() { sym = 1; } else { - sym = getcstat, uni = getcstat, shift = getcshift; + sym = getcstat, uni = getcstat, shiftmul = getcshift; } } if(ev.type == SDL_MOUSEBUTTONUP) mousepressed = false; - if(cmode != emScores) { + if(((cmode == emNormal && canmove) || (cmode == emQuit && !canmove) || cmode == emDraw || cmode == emMapEditor) && !shmup::on) { #ifndef PANDORA - if(sym == SDLK_RIGHT) View = xpush(-0.2*shift) * View, playermoved = false; - if(sym == SDLK_LEFT) View = xpush(+0.2*shift) * View, playermoved = false; - if(sym == SDLK_UP) View = ypush(+0.2*shift) * View, playermoved = false; - if(sym == SDLK_DOWN) View = ypush(-0.2*shift) * View, playermoved = false; + if(sym == SDLK_RIGHT) + View = xpush(-0.2*shiftmul) * View, playermoved = false, didsomething = true; + if(sym == SDLK_LEFT) + View = xpush(+0.2*shiftmul) * View, playermoved = false, didsomething = true; + if(sym == SDLK_UP) + View = ypush(+0.2*shiftmul) * View, playermoved = false, didsomething = true; + if(sym == SDLK_DOWN) + View = ypush(-0.2*shiftmul) * View, playermoved = false, didsomething = true; #endif - if(sym == SDLK_PAGEUP) View = spin(M_PI/21*shift) * View; - if(sym == SDLK_PAGEDOWN) View = spin(-M_PI/21*shift) * View; + if(sym == SDLK_PAGEUP) + View = spin(M_PI/21*shiftmul) * View, didsomething = true; + if(sym == SDLK_PAGEDOWN) + View = spin(-M_PI/21*shiftmul) * View, didsomething = true; + + if(sym == SDLK_PAGEUP || sym == SDLK_PAGEDOWN) + if(cwt.c->land == laEdge) playermoved = false; } if(ev.type == SDL_MOUSEMOTION) { @@ -3932,7 +5162,7 @@ void mainloop() { } DEB("r1"); - if(sym == SDLK_F7) { + if(sym == SDLK_F7 && !vid.usingGL) { time_t timer; timer = time(NULL); @@ -3944,139 +5174,14 @@ void mainloop() { DEB("r2"); - if(cmode == emDraw) { - - hyperpoint mh = inverse(playertrans) * mouseh; - // inverse(playertrans) * - // mouseh; - - // spin(-M_PI/2) * mouseh; - - if(uni == 'n') { - dsCur->list.clear(); - dsCur->list.push_back(mh); -#ifdef GL - GL_initialized = false; -#endif - } - - if(uni == 'a') { - dsCur->list.push_back(mh); -#ifdef GL - GL_initialized = false; -#endif - } - - if(uni == 'u') { - if(!vid.female) loadShape(shPBody, 2, 0); - else loadShape(shFemaleBody, 2, 0); - - loadShape(shPSword, 1, 1); - - if(vid.female) - loadShape(shFemaleDress, 2, 2); - - if(vid.female) - loadShape(shFemaleHair, 2, 3); - else - loadShape(shPHead, 2, 3); - - loadShape(shPFace, 2, 4); - -#ifdef GL - GL_initialized = false; -#endif - } - - if(uni == 'm' || uni == 'd' || uni == 'c' || uni == 'b') { - int i = 0; - if(size(dsCur->list) < 2) continue; - for(int j=1; jlist); j++) - if(intval(mh, dsCur->list[j]) < intval(mh, dsCur->list[i])) - i = j; - if(uni == 'm') - dsCur->list[i] = mh; - if(uni == 'd') - dsCur->list.erase(dsCur->list.begin() + i); - if(uni == 'c') - dsCur->list.push_back(dsCur->list[i]); - if(uni == 'b') { - while(i) { - dsCur->list.push_back(dsCur->list[0]); - dsCur->list.erase(dsCur->list.begin()); - i--; - } - } -#ifdef GL - GL_initialized = false; -#endif - } - - if(uni == 'f') { - if(floordraw) dslayer++; else floordraw = true; - } - if(uni == 'p') { - if(!floordraw) dslayer++; else floordraw = false; - } - if(uni == 'g') ccenter = mouseh, crad += shift / 20; - - if(uni == '1') dsCur->rots = 1; - if(uni == '2') dsCur->rots = 2; - if(uni == '3') dsCur->rots = 3; - if(uni == '4') dsCur->rots = 4; - if(uni == '5') dsCur->rots = 5; - if(uni == '6') dsCur->rots = 6; - if(uni == '7') dsCur->rots = 7; - if(uni == '8') dsCur->rots = 8; - if(uni == '9') dsCur->rots = 21; - if(uni == '0') dsCur->sym = !dsCur->sym; - - if(uni == 't') dsCur->shift = mh; - if(uni == 'y') dsCur->spin = mh; - -#ifdef GL - if(uni == 't' || uni == 'y') GL_initialized = false; -#endif - - - if(uni == 's') { - for(int i=prehpc; i < qhpc; i++) { - for(int k=0; k<8; k++) - for(int j=0; j<3; j++) if(i == shUser[k][j].s) - printf("\n // group %d layer %d\n\n", j, k); - printf(" hpcpush(hpxyz(%f,%f,%f));\n", double(hpc[i][0]), double(hpc[i][1]), double(hpc[i][2])); - } - } - - if(uni == 'z') vid.alpha = -.5; - if(uni == 'o') vid.alpha = 1; - - saveImages(); - - if(sym == SDLK_F6) { - cmode = emNormal; - sym = 0; - } - - if(sym == SDLK_ESCAPE) cmode = emNormal; - - if(sym == SDLK_F1) { - cmode = emHelp; - sym = 0; - help = XLAT(drawhelp); - } - - if(sym == SDLK_F2) { - cmode = emVisual1; - sym = 0; - } - - if(sym == SDLK_F10) cmode = emNormal; - } - if(cmode == emNormal) { + + if(cheater) { + if(applyCheat(uni, mouseover)) + sym = 0; + } - if(!(uni >= 'A' && uni <= 'Z') && cwt.c->land != laGameBoard) { + if(!(uni >= 'A' && uni <= 'Z') && !shmup::on) { if(sym == 'l' || sym == 'd' || sym == SDLK_KP6) movepckeydir(0); if(sym == 'n' || sym == 'c' || sym == SDLK_KP3) movepckeydir(1); if(sym == 'j' || sym == 'x' || sym == SDLK_KP2) movepckeydir(2); @@ -4088,27 +5193,24 @@ void mainloop() { } #ifdef PANDORA - if(sym == SDLK_RIGHT) movepckeydir(0); - if(sym == SDLK_LEFT) movepckeydir(4); - if(sym == SDLK_DOWN) movepckeydir(2 + (leftclick?1:0) - (rightclick?1:0)); - if(sym == SDLK_UP) movepckeydir(6 - (leftclick?1:0) + (rightclick?1:0)); + if(!shmup::on) { + if(sym == SDLK_RIGHT) movepckeydir(0); + if(sym == SDLK_LEFT) movepckeydir(4); + if(sym == SDLK_DOWN) movepckeydir(2 + (leftclick?1:0) - (rightclick?1:0)); + if(sym == SDLK_UP) movepckeydir(6 - (leftclick?1:0) + (rightclick?1:0)); + } #endif - if(cheater) - applyCheat(uni, mouseover); - - if(cwt.c->land == laGameBoard) - applyGameBoard(uni, sym, mouseover, vid.boardmode); - else { - if(sym == '.' || sym == 's') movepcto(-1); + if(!shmup::on) { + if(sym == '.' || sym == 's') movepcto(-1, 1); if((sym == SDLK_DELETE || sym == SDLK_KP_PERIOD || sym == 'g') && uni != 'G' && uni != 'G'-64) - movepcto(-2); + movepcto(-2, 1); if(sym == 't' && uni != 'T' && uni != 'T'-64) { targetRangedOrb(centerover, roKeyboard); } } - if(sym == SDLK_KP5) movepcto(-1); + if(sym == SDLK_KP5 && !shmup::on) movepcto(-1, 1); // if(sym == SDLK_F4) restartGameSwitchEuclid(); @@ -4131,70 +5233,99 @@ void mainloop() { restartGame(); loadScores(); } + else if(sym == SDLK_UP || sym == SDLK_KP8) msgscroll++; + else if(sym == SDLK_DOWN || sym == SDLK_KP2) msgscroll--; + else if(sym == SDLK_PAGEUP || sym == SDLK_KP9) msgscroll+=5; + else if(sym == SDLK_PAGEDOWN || sym == SDLK_KP3) msgscroll-=5; } - if(sym == SDLK_HOME || sym == SDLK_F3 || sym == ' ') { - if(playerfound) centerpc(INF); - else { - View = Id; - // EUCLIDEAN - if(!euclid) viewctr.h = cwt.c->master; - else centerover = cwt.c; - // SDL_LockSurface(s); - drawthemap(); - // SDL_UnlockSurface(s); - centerpc(INF); - } - playermoved = true; + if(uni == 'o') { + cmode = emOverview; } + + if(sym == SDLK_HOME || sym == SDLK_F3 || (sym == ' ' && !shmup::on)) + fullcenter(); - if(sym == SDLK_F6) { +/* if(sym == SDLK_F6) { View = spin(M_PI/2) * inverse(cwtV) * View; if(flipplayer) View = spin(M_PI) * View; cmode = emDraw; + } */ + + if(sym == 'v') { + cmode = emMenu; } - if(sym == 'v' || sym == SDLK_F2) { + if(sym == SDLK_F2) { cmode = emVisual1; } #ifdef PANDORA - if(ev.type == SDL_MOUSEBUTTONUP && sym == 0 && !rightclick) { + if(ev.type == SDL_MOUSEBUTTONUP && sym == 0 && !rightclick) #else - if(ev.type == SDL_MOUSEBUTTONDOWN && sym == 0 && !rightclick) { + if(ev.type == SDL_MOUSEBUTTONDOWN && sym == 0 && !rightclick) #endif - + { bool forcetarget = (keystate[SDLK_RSHIFT] | keystate[SDLK_LSHIFT]); - if(mouseover && targetclick && targetRangedOrb(mouseover, forcetarget ? roMouseForce : roMouse)) + shmup::cpid = 0; + if(mouseover && targetclick && (numplayers() == 1) && targetRangedOrb(mouseover, forcetarget ? roMouseForce : roMouse)) ; else if(forcetarget) ; - else if(mousedest == -1) - movepcto(mousedest); - else - movepcto((mousedest + 42 - cwt.spin)%42); + else if(shmup::on) + ; + else mousemovement(); } if(sym == SDLK_F1) { + lastmode = cmode; cmode = emHelp; } } + else if(cmode == emMenu) { + + if(sym == SDLK_F1 || sym == 'h') { + lastmode = cmode; + cmode = emHelp; + } + else if(sym == 'b') + cmode = emVisual1; + else if(sym == 'a') + cmode = emVisual2; + else if(sym == 'm') + cmode = emChangeMode; + else if(sym == 't') + loadScores(); + else if(sym == 'r' || sym == SDLK_F5) { + restartGame(); + cmode = emNormal; + } + else if(sym == 'q' || sym == SDLK_F10) + return; + else if(sym == 'o') + cmode = emOverview; + else if(sym == SDLK_ESCAPE) + cmode = emQuit; + else if((sym != 0 && sym != SDLK_F12) || ev.type == SDL_MOUSEBUTTONDOWN) { + cmode = emNormal; + msgs.clear(); + } + } + else if(cmode == emVisual1) { char xuni = uni | 96; if(uni >= 32 && uni < 64) xuni = uni; - if(uni == ' ') cmode = emVisual2; - - if(xuni == 'p') vid.alpha += shift * 0.1; - if(xuni == 'z') vid.scale += shift * 0.1; - if(xuni == 'a') vid.aspeed += shift; + if(xuni == 'p') vid.alpha += shiftmul * 0.1; + if(xuni == 'z') vid.scale += shiftmul * 0.1; + if(xuni == 'a') vid.aspeed += shiftmul; if(xuni == 'f') { vid.full = !vid.full; - if(shift > 0) { + if(shiftmul > 0) { vid.xres = vid.full ? vid.xscr : 9999; vid.yres = vid.full ? vid.yscr : 9999; setfsize = true; @@ -4206,11 +5337,11 @@ void mainloop() { if(xuni == 's') saveConfig(); if(xuni == '7') { vid.darkhepta = !vid.darkhepta; } - if(xuni == 'w') { vid.wallmode += 60 + (shift > 0 ? 1 : -1); vid.wallmode %= 4; } - if(xuni == 'm') { vid.monmode += 60 + (shift > 0 ? 1 : -1); vid.monmode %= 4; } - if(xuni == 'c') { vid.axes += 60 + (shift > 0 ? 1 : -1); vid.axes %= 4; } + if(xuni == 'w') { vid.wallmode += 60 + (shiftmul > 0 ? 1 : -1); vid.wallmode %= 4; } + if(xuni == 'm') { vid.monmode += 60 + (shiftmul > 0 ? 1 : -1); vid.monmode %= 4; } + if(xuni == 'c') { vid.axes += 60 + (shiftmul > 0 ? 1 : -1); vid.axes %= 4; } if(xuni == 'b') { - audiovolume += int(10.5 * shift); + audiovolume += int(10.5 * shiftmul); if(audiovolume < 0) audiovolume = 0; if(audiovolume > MIX_MAX_VOLUME) audiovolume = MIX_MAX_VOLUME; Mix_VolumeMusic(audiovolume); @@ -4222,22 +5353,18 @@ void mainloop() { process_showoff(sym); #endif - if(sym == SDLK_F1 || sym == 'h') { - cmode = emHelp; - } - if(xuni == 'l') { - vid.language++; + vid.language += (shiftmul>0?1:-1); vid.language %= NUMLAN; - printf("lan = %d\n", vid.language); + if(vid.language < 0) vid.language += NUMLAN; } if(xuni == 'g') { - vid.female = !vid.female; - switchcolor(vid.skincolor, skincolors, 0); - switchcolor(vid.haircolor, haircolors, 0); - switchcolor(vid.dresscolor, dresscolors, 0); - switchcolor(vid.swordcolor, swordcolors, 0); + // vid.female = !vid.female; + // switchcolor(vid.skincolor, skincolors, 0); + // switchcolor(vid.haircolor, haircolors, 0); + // switchcolor(vid.dresscolor, dresscolors, 0); + // switchcolor(vid.swordcolor, swordcolors, 0); cmode = emCustomizeChar; } @@ -4246,12 +5373,13 @@ void mainloop() { else if(cmode == emCustomizeChar) { char xuni = uni | 96; int mod = ev.key.keysym.mod; - if(shift < -.5) + if(shiftmul < -.5) mod = 1; - else if(shift > -.2 && shift < .2) + else if(shiftmul > -.2 && shiftmul < .2) mod = 2; else mod = 0; if(xuni == 'g') vid.female = !vid.female; + if(xuni == 'p') vid.samegender = !vid.samegender; if(xuni == 's') switchcolor(vid.skincolor, skincolors, mod); if(xuni == 'h') switchcolor(vid.haircolor, haircolors, mod); if(xuni == 'w') switchcolor(vid.swordcolor, swordcolors, mod); @@ -4262,17 +5390,21 @@ void mainloop() { else if(cmode == emVisual2) { char xuni = uni | 96; -#ifdef GL if(xuni == 'v' || sym == SDLK_F2 || sym == SDLK_ESCAPE) cmode = emNormal; + if(xuni == 's') saveConfig(); + + if(sym == SDLK_F1 || sym == 'h') + lastmode = cmode, cmode = emHelp; +#ifdef GL - if(xuni == 'o' && shift > 0) { + if(xuni == 'o' && shiftmul > 0) { vid.usingGL = !vid.usingGL; if(vid.usingGL) addMessage(XLAT("openGL mode enabled")); if(!vid.usingGL) addMessage(XLAT("openGL mode disabled")); setvideomode(); } - if(xuni == 'o' && shift < 0 && !vid.usingGL) { + if(xuni == 'o' && shiftmul < 0 && !vid.usingGL) { vid.usingAA = !vid.usingAA; if(vid.usingAA) addMessage(XLAT("anti-aliasing enabled")); if(!vid.usingAA) addMessage(XLAT("anti-aliasing disabled")); @@ -4280,68 +5412,153 @@ void mainloop() { #endif if(xuni == 'f') { - vid.framelimit += int(10.5 * shift); + vid.framelimit += int(10.5 * shiftmul); if(vid.framelimit < 5) vid.framelimit = 5; } - if(xuni == 'a') vid.joyvalue += int(shift * 100); - if(xuni == 'b') vid.joyvalue2 += int(shift * 100); - if(xuni == 'c') vid.joypanthreshold += int(shift * 100); - if(xuni == 'd') vid.joypanspeed += shift / 50000; - if(xuni == 'e') vid.eye += shift * 0.01; - if(xuni == 't') vid.flashtime += shift>0?1:-1; + if(xuni == 'a') vid.joyvalue += int(shiftmul * 100); + if(xuni == 'b') vid.joyvalue2 += int(shiftmul * 100); + if(xuni == 'c') vid.joypanthreshold += int(shiftmul * 100); + if(xuni == 'd') vid.joypanspeed += shiftmul / 50000; + if(xuni == 'e') vid.eye += shiftmul * 0.01; + if(xuni == 't') vid.flashtime += shiftmul>0?1:-1; if(xuni == 'p') autojoy = !autojoy; - if(xuni == 's') { vid.shifttarget = !vid.shifttarget; } - - if(uni == ' ') cmode = emChangeMode; + if(xuni == 'i') { vid.shifttarget = !vid.shifttarget; } } else if(cmode == emChangeMode) { - char xuni = uni | 96; + char xuni = uni; + + if((uni >= 'A' && uni <= 'Z') || (uni >= 1 && uni <= 26)) + xuni |= 96; + if(xuni == 'v' || sym == SDLK_F2 || sym == SDLK_ESCAPE) cmode = emNormal; - if(uni == ' ') cmode = emVisual1; if(sym == 'c') { - cheater++; - addMessage(XLAT("You activate your demonic powers!")); - addMessage(XLAT("Shift+F, Shift+O, Shift+T, Shift+L, Shift+U, etc.")); - cmode = emNormal; + if(!cheater) { + cheater++; + addMessage(XLAT("You activate your demonic powers!")); + addMessage(XLAT("Shift+F, Shift+O, Shift+T, Shift+L, Shift+U, etc.")); + cmode = emNormal; + } + else { + cmode = emNormal; + firstland = princess::challenge ? laPalace : laIce; + restartGame(); + } } - if(xuni == 'g') cmode = emDraw; - if(xuni == 'e') cmode = emPickEuclidean; - - if(uni == 'h' || uni == '3' || uni == '7' || uni == 'f') { - vid.boardmode = uni; - cheater = 1; - showid = 0; firstland = laGameBoard; - for(int i=0; i0?1:-1); + if(items[umod] < 0) items[umod] = 0; + if(hardcore) canmove = true; + else checkmove(); + } + else { + lastmode = cmode; + cmode = emHelp; help = generateHelpForItem(eItem(umod)); + if(hardcore) canmove = true; + else checkmove(); + } + } + else if(udiv == 3 && umod < walltypes) { + lastmode = cmode; + cmode = emHelp; help = generateHelpForWall(eWall(umod)); + } + else if(uni) cmode = emNormal; + } + + else if(cmode == emDraw) + mapeditor::drawHandleKey(uni, sym, shiftmul); + else if(cmode == emPickEuclidean) { - char xuni = uni | 96; - if(xuni == 'z') { - if(euclid) restartGameSwitchEuclid(); + int lid; + if(uni >= 'a' && uni <= 'z') + lid = uni - 'a'; + else if(uni >= 'A' && uni <= 'Z') + lid = 26 + uni - 'A'; + else + lid = -1; + + if(uni == '0') { + if(euclid) restartGame('e'); cmode = emNormal; } - else if(xuni >= 'a' && xuni < 'a' + landtypes) { - euclidland = eLand(2 + (xuni - 'a')); - if(landvisited[euclidland]) { + else if(lid >= 0 && lid < NUMLIST) { + euclidland = lseq[lid]; + if(landvisited[euclidland] && euclidland != laOceanWall) { if(euclid) restartGame(); - else restartGameSwitchEuclid(); + else restartGame('e'); cmode = emNormal; } else euclidland = laIce; @@ -4354,7 +5571,7 @@ void mainloop() { else if(uni == 'c') help = buildCredits(); else if((sym != 0 && sym != SDLK_F12) || ev.type == SDL_MOUSEBUTTONDOWN) - cmode = (help == XLAT(drawhelp) ? emDraw : emNormal); + cmode = lastmode; } else if(cmode == emQuit) { @@ -4363,18 +5580,23 @@ void mainloop() { restartGame(), cmode = emNormal; msgs.clear(); } + else if(uni == 'v') cmode = emMenu; else if(sym == SDLK_UP || sym == SDLK_KP8) msgscroll++; else if(sym == SDLK_DOWN || sym == SDLK_KP2) msgscroll--; else if(sym == SDLK_PAGEUP || sym == SDLK_KP9) msgscroll+=5; else if(sym == SDLK_PAGEDOWN || sym == SDLK_KP3) msgscroll-=5; + else if(sym == SDLK_HOME || sym == SDLK_F3 || (sym == ' ' && !shmup::on)) + fullcenter(); + else if(uni == 'o') cmode = emOverview; else if(uni == 't') { if(!canmove) restartGame(); loadScores(); msgs.clear(); } - else if((sym != 0 && sym != SDLK_F12) || ev.type == SDL_MOUSEBUTTONDOWN) { + else if(((sym != 0 && sym != SDLK_F12) || ev.type == SDL_MOUSEBUTTONDOWN) && !didsomething) { cmode = emNormal; + msgscroll = 0; msgs.clear(); } } @@ -4402,8 +5624,7 @@ void cleargraph() { for(int i=0; i<256; i++) if(font[i]) TTF_CloseFont(font[i]); for(int i=0; i<128; i++) if(glfont[i]) delete glfont[i]; #ifndef SIMULATE_JOYSTICK - if(stick) SDL_JoystickClose(stick); - if(panstick) SDL_JoystickClose(panstick); + closeJoysticks(); #endif SDL_Quit(); } @@ -4411,5 +5632,17 @@ void cleargraph() { void cleargraphmemory() { mouseover = centerover = lmouseover = NULL; +#ifndef MOBILE + if(mapeditor::painttype == 4) + mapeditor::painttype = 0, mapeditor::paintwhat = 0, + mapeditor::paintwhat_str = "clear monster"; + mapeditor::copywhat = NULL; + mapeditor::undo.clear(); + if(!cheater) mapeditor::displaycodes = 0; + if(!cheater) mapeditor::whichShape = 0; +#endif } +void showMissionScreen() { + cmode = emQuit; + } diff --git a/heptagon.cpp b/heptagon.cpp index 22f805b5..26be9c25 100644 --- a/heptagon.cpp +++ b/heptagon.cpp @@ -25,13 +25,19 @@ struct heptagon { heptagon* move[7]; // distance from the origin short distance; - // fjord/wineyard generator - short fjordval; - heptagon*& modmove(int i) { return move[fixrot(i)]; } - unsigned char& gspin(int i) { return spin[fixrot(i)]; } + // emerald/wineyard generator + short emeraldval; + // fifty generator + short fiftyval; + // zebra generator (1B actually) + short zebraval; + // central cell cell *c7; // associated generator of alternate structure, for Camelot and horocycles heptagon *alt; + // functions + heptagon*& modmove(int i) { return move[fixrot(i)]; } + unsigned char& gspin(int i) { return spin[fixrot(i)]; } }; // the automaton is used to generate each heptagon in an unique way @@ -65,14 +71,20 @@ heptagon *buildHeptagon(heptagon *parent, int d, hstate s, int pard = 0) { parent->move[d] = h; parent->spin[d] = pard; if(parent->c7) { h->c7 = newCell(7, h); - h->fjordval = fjord_heptagon(parent->fjordval, d); + h->emeraldval = emerald_heptagon(parent->emeraldval, d); + h->zebraval = zebra_heptagon(parent->zebraval, d); + if(parent == &origin) + h->fiftyval = fiftytable[0][d]; + else + h->fiftyval = nextfiftyval(parent->fiftyval, parent->move[0]->fiftyval, d); } else { h->c7 = NULL; - h->fjordval = 0; + h->emeraldval = 0; + h->fiftyval = 0; } -//generateFjordval(parent); -//generateFjordval(h); +//generateEmeraldval(parent); +//generateEmeraldval(h); if(pard == 0) { if(parent->s == hsOrigin) h->distance = 2; else if(h->spin[0] == 5) @@ -92,7 +104,7 @@ void addSpin(heptagon *h, int d, heptagon *from, int rot, int spin) { h->spin[d] = fixrot(from->spin[rot] + spin); h->move[d]->move[fixrot(from->spin[rot] + spin)] = h; h->move[d]->spin[fixrot(from->spin[rot] + spin)] = d; -//generateFjordval(h->move[d]); generateFjordval(h); +//generateEmeraldval(h->move[d]); generateEmeraldval(h); } heptagon *createStep(heptagon *h, int d) { diff --git a/hyper.cpp b/hyper.cpp index baec6040..575daec0 100644 --- a/hyper.cpp +++ b/hyper.cpp @@ -19,9 +19,9 @@ #define ISANDROID 0 #define ISMOBILE 0 #define ISIOS 0 -#define VER "6.6" -#define VERNUM 6600 -#define VERNUM_HEX 0x6600 +#define VER "7.4h" +#define VERNUM 7480 +#define VERNUM_HEX 0x7480 #include @@ -40,13 +40,27 @@ using namespace std; const char *scorefile = "hyperrogue.log"; const char *conffile = "hyperrogue.ini"; + +string levelfile = "hyperrogue.lev"; +string picfile = "hyperrogue.pic"; + +const char *loadlevel = NULL; const char *musicfile = ""; typedef long double ld; template int size(T& x) {return x.size(); } string its(int i) { char buf[64]; sprintf(buf, "%d", i); return buf; } +string cts(char c) { char buf[8]; buf[0] = c; buf[1] = 0; return buf; } +string llts(long long i) { + // sprintf does not work on Windows IIRC + if(i < 0) return "-" + llts(-i); + if(i < 10) return its(i); + return llts(i/10) + its(i%10); + } string fts(float x) { char buf[64]; sprintf(buf, "%4.2f", x); return buf; } +string fts4(float x) { char buf[64]; sprintf(buf, "%6.4f", x); return buf; } +string itsh(int i) {static char buf[16]; sprintf(buf, "%03X", i); return buf; } #undef DEBT void DEBT(const char *buf) { @@ -60,7 +74,7 @@ int clWidth, clHeight, clFont; string commandline; #include "hyperpoint.cpp" -#include "fjordgen.cpp" +#include "patterns.cpp" #include "heptagon.cpp" #include "classes.cpp" #include "language.cpp" @@ -69,22 +83,31 @@ string commandline; #define NOLICENSE #endif -#include "achievement.h" +#include "hyper.h" #include "cell.cpp" #include "game.cpp" + +// #include "patterngen.cpp" + +#include "geometry.cpp" + +#include "polygons.cpp" + +#ifndef MOBILE +#include "mapeditor.cpp" +#endif + #include "graph.cpp" #include "achievement.cpp" #include - -bool switchEuclid = false; - int main(int argc, char **argv) { printf("HyperRogue by Zeno Rogue , version "VER"\n"); + #ifndef NOLICENSE printf("released under GNU General Public License version 2 and thus\n"); printf("comes with absolutely no warranty; see COPYING for details\n"); @@ -94,6 +117,7 @@ int main(int argc, char **argv) { // printf("cell size = %d\n", int(sizeof(cell))); srand(time(NULL)); + shrand(time(NULL)); #ifdef FHS char sbuf[640], cbuf[640]; @@ -102,18 +126,51 @@ int main(int argc, char **argv) { snprintf(cbuf, 640, "%s/.%s", getenv("HOME"), conffile); conffile = cbuf; } #endif - + for(int i=1; i= 0; uu--) { printf("uu=%d\n", uu); @@ -167,34 +238,45 @@ int main(int argc, char **argv) { restartGame(); } */ - eLand f = firstland; - - loadsave(); + #ifdef BUILDZEBRA + firstland = laCanvas; + shmup::on = false; + #endif initgame(); + #ifdef BUILDZEBRA + zebraPattern(); + #endif - restoreGolems(items[itOrbLife]); items[itOrbLife] = 0; + if(!shmup::on) { + restoreGolems(items[itOrbLife], moGolem); items[itOrbLife] = 0; + restoreGolems(items[itOrbFriend], moTameBomberbird); items[itOrbFriend] = 0; + restoreGolems(kills[moPrincessMoved], moPrincess, princess::saveHP); kills[moPrincessMoved] = 0; + restoreGolems(kills[moPrincessArmedMoved], moPrincessArmed, princess::saveArmedHP); kills[moPrincessArmedMoved] = 0; + } firstland = f; + + // verifyHell(); // exit(1); - initgraph(); - int t1 = SDL_GetTicks(); - if(switchEuclid) restartGameSwitchEuclid(); - + // if(switchEuclid) restartGame('e'); + + if(loadlevel) mapstream::loadMap(loadlevel); + mainloop(); achievement_final(!items[itOrbSafety]); - SDL_Quit(); saveStats(); int msec = SDL_GetTicks() - t1; printf("frame : %f ms (%f fps)\n", 1.*msec/frames, 1000.*frames/msec); + offscreen.clear(); clearMemory(); cleargraph(); achievement_close(); - + return 0; } diff --git a/hyper.h b/hyper.h new file mode 100644 index 00000000..552f6afe --- /dev/null +++ b/hyper.h @@ -0,0 +1,260 @@ +// definitions + +// disable this if you have no access to SDL_gfx +#ifndef STEAM +#define GFX +#endif + +#define GL + +#ifdef NOGFX +#undef GFX +#endif + +// scale the Euclidean +#define EUCSCALE 2.3 + +// disable this if you have no access to SDL_mixer +#ifndef MOBILE +#define AUDIO +#endif + +#define NUMWITCH 7 + +// achievements + +// initialize the achievement system. +void achievement_init(); + +// close the achievement system. +void achievement_close(); + +// gain the achievement with the given name. +// Only awarded if euclid equals euclideanAchievement. +void achievement_gain(const char*, bool euclideanAchievement = false, bool shmupAchievement = false); + +// gain the achievement for collecting a number of 'it'. +void achievement_collection(eItem it, int prevgold, int newgold); + +// this is used for 'counting' achievements, such as kill 10 +// monsters at the same time. +void achievement_count(const string& s, int current, int prev); + +// scores for special challenges +void achievement_score(int cat, int score); + +// gain the victory achievements. Set 'hyper' to true for +// the Hyperstone victory, and false for the Orb of Yendor victory. +void achievement_victory(bool hyper); + +// gain the final achievements. Called with really=false whenever the user +// looks at their score, and really=true when the game really ends. +void achievement_final(bool really); + +// display the last achievement gained. +void achievement_display(); + +// achievements received this game +vector achievementsReceived; + +// game forward declarations + +bool isCrossroads(eLand l); +enum orbAction { roMouse, roKeyboard, roCheck, roMouseForce }; +void moveItem (cell *from, cell *to, bool activateYendor); +void uncoverMines(cell *c, int lev); +bool survivesMine(eMonster m); +void killMonster(cell *c); +void toggleGates(cell *ct, eWall type, int rad); +bool destroyHalfvine(cell *c, eWall newwall = waNone, int tval = 6); +void buildCrossroads2(cell *c); +void createBugArmy(cell *c); +heptagon *createAlternateMap(cell *c, int rad, hstate firststate, int special=0); +void generateAlts(heptagon *h); +void whirlGenerate(cell *wto); +void setdist(cell *c, int d, cell *from); +void checkOnYendorPath(); +void killThePlayerAt(eMonster m, cell *c); +bool collectItem(cell *c2, bool telekinesis = false); +void castLightningBolt(struct cellwalker lig); +bool movepcto(int d, int subdir = 1, bool checkonly = false); +void stabbingAttack(cell *mf, cell *mt, eMonster who = moNone); +bool earthMove(cell *from, int dir); +void messageKill(eMonster killer, eMonster victim); +void moveMonster(cell *ct, cell *cf); +int palaceHP(); + +void createMirrors(cell *c, int dir, eMonster type); +void createMirages(cell *c, int dir, eMonster type); + +int neighborId(cell *c1, cell *c2); + +struct movedir { int d; int subdir; }; +inline bool movepcto(const movedir& md) { return movepcto(md.d, md.subdir); } + +void activateActiv(cell *c, bool msg); + +// shmup + +namespace shmup { + extern bool on; + extern bool safety; + extern int curtime; + extern int players, cpid; + void clearMemory(); + void init(); + void teleported(); + extern struct monster* mousetarget; + extern eItem targetRangedOrb(orbAction a); + void degradeDemons(); + void killThePlayer(eMonster m); + void killThePlayer(eMonster m, int i); + void visibleFor(int t); + + void shmupDrownPlayers(cell *c); + + cell *playerpos(int i); + + bool playerInBoat(int i); + +#define MAXBUTTON 64 +#define MAXAXE 16 +#define MAXHAT 4 + + struct config { + int players; + int subconfig; + int setwhat; + char keyaction[512]; + char joyaction[8][MAXBUTTON]; + char axeaction[8][MAXAXE]; + char hataction[8][MAXHAT][4]; + }; + } + +// graph + +void showMissionScreen(); + +void restartGraph(); +void resetmusic(); + +void cleargraphmemory(); + +void drawFlash(cell* c); + +void drawLightning(); +void drawSafety(); +void restartGraph(); +void movepckeydir(int); + +void centerpc(ld aspd); + +void displayStat(int y, const string& name, const string& val, char mkey); +void displayButton(int x, int y, const string& name, int key, int align, int rad = 0); +void displayColorButton(int x, int y, const string& name, int key, int align, int rad, int color, int color2 = 0); +inline string ONOFF(bool b) { return XLAT(b ? "ON" : "OFF"); } +int darkened(int c); +extern int getcstat; +bool displaychr(int x, int y, int shift, int size, char chr, int col); +bool displayfr(int x, int y, int b, int size, const string &s, int color, int align); +void saveHighQualityShot(); + +bool outofmap(hyperpoint h); +void getcoord(const hyperpoint& H, int& x, int& y, int &shift); +void drawline(const hyperpoint& H1, int x1, int y1, int s1, const hyperpoint& H2, int x2, int y2, int col); +void drawline(const hyperpoint& H1, const hyperpoint& H2, int col); + +string ifMousing(string key, string s); + +void saveConfig(); + +extern hyperpoint mouseh; + +extern int webdisplay; + +extern bool GL_initialized; +extern hyperpoint ccenter; +extern ld crad; + +extern bool mousepressed, anyshiftclick; +extern string help; + +extern int lalpha; + +struct videopar { + ld scale, eye, alpha, aspeed; + bool full; + bool goteyes; + bool quick; + bool darkhepta; + bool shifttarget; + + int xres, yres, framelimit; + + int xscr, yscr; + + // paramaters calculated from the above + int xcenter, ycenter; + int radius; + ld alphax, beta; + + int fsize; + int flashtime; + + int wallmode, monmode, axes; + + // for OpenGL + float scrdist; + + bool usingGL; + bool usingAA; + + int joyvalue, joyvalue2, joypanthreshold; + float joypanspeed; + + bool female; + bool samegender; // same gender for the Princess? + int language; + + int skincolor, haircolor, dresscolor, swordcolor; + int killreduction; + + shmup::config scfg; + }; + +extern videopar vid; + +enum emtype {emNormal, emHelp, + emMenu, + emVisual1, emVisual2, + emChangeMode, emCustomizeChar, + emQuit, emDraw, emScores, emPickEuclidean, + emPickScores, + emShmupConfig, + emMapEditor, + emPatternPicker, + emOverview + }; + +extern emtype cmode, lastmode; + +extern transmatrix View; // current rotation, relative to viewctr +extern transmatrix cwtV; // player-relative view + +extern cell *mouseover, *mouseover2; + +extern struct SDL_Surface *s; + +namespace mapeditor { + extern bool drawplayer; + extern char whichPattern; + int generateCanvas(cell *c); + void clearModelCells(); + void applyModelcell(cell *c); + int realpattern(cell *c); + int patterndir(cell *c, char w = whichPattern); + } + +void selectEyeGL(int ed); +void selectEyeMask(int ed); diff --git a/hyperpoint.cpp b/hyperpoint.cpp index 8c65c76f..faf9b91a 100644 --- a/hyperpoint.cpp +++ b/hyperpoint.cpp @@ -99,6 +99,8 @@ struct transmatrix { // identity matrix transmatrix Id = {{{1,0,0}, {0,1,0}, {0,0,1}}}; +transmatrix Mirror = {{{1,0,0}, {0,-1,0}, {0,0,1}}}; + hyperpoint operator * (const transmatrix& T, const hyperpoint& H) { hyperpoint z; for(int i=0; i<3; i++) { @@ -141,6 +143,10 @@ transmatrix xpush(ld alpha) { return T; } +double inverse_sinh(ld z) { + return log(z+sqrt(1+z*z)); + } + // push alpha units vertically transmatrix ypush(ld alpha) { if(euclid) return eupush(0, alpha); @@ -205,8 +211,22 @@ transmatrix rgpushxto0(hyperpoint H) { // fix the matrix T so that it is indeed an isometry // (without using this, imprecision could accumulate) +void display(const transmatrix& T); + void fixmatrix(transmatrix& T) { - for(int x=0; x<3; x++) for(int y=0; y<=x; y++) { + if(euclid) { + for(int x=0; x<2; x++) for(int y=0; y<=x; y++) { + ld dp = 0; + for(int z=0; z<2; z++) dp += T[z][x] * T[z][y]; + + if(y == x) dp = 1 - sqrt(1/dp); + + for(int z=0; z<2; z++) T[z][x] -= dp * T[z][y]; + } + for(int x=0; x<2; x++) T[2][x] = 0; + T[2][2] = 1; + } + else for(int x=0; x<3; x++) for(int y=0; y<=x; y++) { ld dp = 0; for(int z=0; z<3; z++) dp += T[z][x] * T[z][y] * sig(z); diff --git a/langen.cpp b/langen.cpp index 49c1cae2..2e1d3e56 100644 --- a/langen.cpp +++ b/langen.cpp @@ -12,7 +12,7 @@ using namespace std; template int size(T x) { return x.size(); } -#define NUMLAN 5 +#define NUMLAN 6 // language generator @@ -40,7 +40,7 @@ void addutftoset(set& s, string& w) { //printf("%s\n", w.c_str()); while(i < size(w)) { - if(w[i] < 0) { + if(((signed char)(w[i])) < 0) { string z = w.substr(i, 2); // printf("Insert: %s [%02x%02x]\n", z.c_str(), w[i], w[i+1]); s.insert(w.substr(i, 2)); @@ -126,6 +126,9 @@ int main() { nothe.insert("R'Lyeh"); plural.insert("Crossroads"); + plural.insert("Crossroads II"); + plural.insert("Crossroads III"); + plural.insert("Elemental Planes"); #define S(a,b) d[1].add(a,b); #define N(a,b,c,d,e,f) \ @@ -155,6 +158,13 @@ int main() { {noun n; n.genus = b; n.nom = c; n.nomp = d; n.acc = e; n.abl = f; nouns[4].add(a,n);} #include "language-ru.cpp" #undef N +#undef S + +#define S(a,b) d[5].add(a,b); +#define N(a,b,c,d,e) \ + {noun n; n.genus = b; n.nom = c; n.nomp = d; n.acc = e; n.abl = e; nouns[5].add(a,n);} +#include "language-de.cpp" +#undef N #undef S // verify @@ -167,7 +177,7 @@ int main() { string mis = ""; for(int i=1; i::iterator it = d[i].m.begin(); it != d[i].m.end(); it++) + s.insert(it->first); + + printf("\n//statistics\n"); + for(map::iterator it = d[1].m.begin(); it != d[1].m.end(); it++) + d[0][it->first] = it->first; + for(map::iterator it = nouns[1].m.begin(); it != nouns[1].m.end(); it++) { + noun n = it->second; + n.nom = n.nomp = n.acc = n.abl = it->first; + nouns[0][it->first] = n; + } + + printf("// total: %5d nouns, %5d sentences\n", int(nouns[1].m.size()), int(d[1].m.size())); + + for(int i=0; i::iterator it = d[i].m.begin(); it != d[i].m.end(); it++) + dict += it->second.size(); + for(map::iterator it = nouns[i].m.begin(); it != nouns[i].m.end(); it++) { + noun& n = it->second; + bnouns += n.nom.size(); + bnouns += n.nomp.size(); + bnouns += n.acc.size(); + bnouns += n.abl.size(); + } + + printf("// %s: %5dB nouns, %5dB sentences\n", + d[i]["EN"].c_str(), bnouns, dict); + } set allsent; for(map::iterator it = d[1].m.begin(); it != d[1].m.end(); it++) diff --git a/language-cz.cpp b/language-cz.cpp index c49662b9..cc673ad9 100644 --- a/language-cz.cpp +++ b/language-cz.cpp @@ -117,7 +117,7 @@ N("red slime", GEN_O, "červený sliz", "červené slizy", "červený sliz", "č N("blue slime", GEN_O, "modrý sliz", "modré slizy", "modrý sliz", "modrým slizem") N("living wall", GEN_F, "živoucí zeď", "živoucí zdi", "živoucí zeď", "živoucí zdí") N("living floor", GEN_F, "živoucí podlaha", "živoucí podlahy", "živoucí podlahu", "živoucí podlahou") -N("dead troll", GEN_M, "mrtvý šutroll" ,"mrtví šutrollové", "mrtvého šutrolla", "mrtvým šutrollem") +N("dead troll", GEN_M, "mrtvý troll" ,"mrtví trollové", "mrtvého trolla", "mrtvým trollem") N("sand dune", GEN_F, "písečná duna", "písečné duny", "písečnou dunu", "písečnou dunou") N("Magic Mirror", GEN_N, "Kouzelné zrcadlo", "Kouzelná zrcadla", "Kouzelné zrcadlo", "Kouzelným zrcadlem") N("Cloud of Mirage", GEN_O, "Oblak přeludů", "Oblaky přeludů", "Oblak přeludů", "Oblakem přeludů") @@ -1216,7 +1216,7 @@ S( "The Land of Power is filled with everburning fire, magical Orbs, and guarde "Witches are allowed to use all the powers of the " "basic orbs against intruders. These powers never expire, but a Witch " "can use only one power at a time (not counting Orbs of Life).\n\n" - "Witches and Golems don't pursue you into other Lands. Also, most Orb powers" + "Witches and Golems don't pursue you into other Lands. Also, most Orb powers " "are drained when you leave the Land of Power.", "Kraj Moci je plný věčně planoucích ohňů a magických Sfér a střeží ho " "čarodějnice a golemové. Základní Sféry se válejí všude kolem a ty cennější " @@ -1307,6 +1307,7 @@ S("You can right click any element to get more information about it.\n\n", ) S("TRANSLATIONWARNING", "") +// S("TRANSLATIONWARNING", "Warning: new features from 7.2 are not yet translated to Czech") S("The Hyperbugs are fighting!", "Hyperhmyzáci bojují mezi sebou!") @@ -1490,8 +1491,6 @@ S("Illusions are targetted " S("You create an Illusion!", "Vytvořil jsi iluzi!") S("You take the Illusion away.", "Zrušil jsi iluzi.") -#undef Orb - S("Cannot teleport on a monster!", "Nemůžeš se teleportovat na netvora!") S("Cannot teleport on an item!", "Nemůžeš se teleportovat na předmět!") S("Cannot teleport here!", "Sem se teleportovat nemůžeš!") @@ -1516,3 +1515,1273 @@ S("Shift+F, Shift+O, Shift+T, Shift+L, Shift+U, etc.", "Shift+F, Shift+O, Shift+T, Shift+L, Shift+U, atd.") S("also hold Alt during the game to toggle high contrast", "Podržením klávesy Alt během hry lze přepnout vysoký kontrast") + +// Crossroads II + +N("Crossroads II", GEN_N, "Křižovatka II", "Křižovatky II", "Křižovatku II", "na Křižovatce II") + +S( + "An alternate layout of the Crossroads. It is more dense and more regular, " + "although you won't find the castle of Camelot here.", + + "Alternativní plán Křižovatky. Je hustší a pravidelnější, ale hrad Camelot tady nenajdete.") + +// Caribbean + +// 'Karaiby' is plural in Polish, should probably fix the grammar for this + +N("Caribbean", GEN_M, "Karibik", "Karibiky", "Karibuku", "v Karibiku") + +N("Pirate", GEN_M, "Pirát", "Piráti", "Piráta", "Pirátem") +N("Shark", GEN_M, "Žralok", "Žraloci", "Žraloka", "Žralokem") +N("Parrot", GEN_M, "Papoušek", "Papoušci", "Papouška", "Papouškem") +N("Pirate Treasure", GEN_M, "Pirátský poklad", "Pirátské poklady", "Pirátský poklad", "Pirátským pokladem") +N("Compass", GEN_M, "Kompas", "Kompasy", "Kompas", "Kompasem") + +N("sea", GEN_N, "moře", "moře", "moře", "mořem") +N("boat", GEN_O, "člun", "čluny", "člun", "člunem") +N("island", GEN_O, "ostrov", "ostrovy", "ostrov", "ostrovem") +N("tree", GEN_O, "strom", "stromy", "strom", "stromem") + +Orb("Time", "Času") + +S("This dangerous sea contains nasty sharks and pirates. ", + "V tomto nebezpečném moři se vyskytují nebezpeční žraloci a piráti.") + +S("The islands of Caribbean are infinite and circular, and " + "the pirates probably have hidden their treasures somewhere far from the coast.", + "Karibské ostrovy jsou nekonečné a kulaté a piráti pravděpodobně ukryli své poklady kdesi daleko od pobřeží.") + +S( + "Hyperbolic pirates do not need huge ships, since so many lands to conquest " + "are so close. These small boats are enough for them.\n\n" + "Boats allow you to go through water. If you are in a boat, you can move into " + "a water cell (and the boat will come with you).", + + "Hyperboličtí piráti nepotřebují velké lodě, protože tolik zemí, které mohou dobývat, " + "je tak blízko. Tyto malé čluny jim stačí.\n\n" + "Čluny ti umožňují pohybovat se po vodě. Pokud jsi ve člunu, můžeš vstoupit na " + "vodní políčko (člun se přesune spolu s tebou).") + +S( + "The forests of Caribbean are too dense to be traversed by humans, " + "and they are hard to burn. Many colorful parrots can be found there.", + "Karibské lesy jsou příliš husté na to, aby jimi mohl projít člověk, " + "a špatně hoří. Lze v nich najít mnoho barevných papoušků.") + +S("Ye wonder where did th' Pirates find all these riches...", + "Říkáš si, kde asi ti piráti našli všechno tohle bohatství...") + +S( + "The hyperbolic pirates have no use for treasure maps. However, they have found " + "out that a compass points to the center of the island. So they just go as " + "far towards the center as they can, and hide their treasure there.", + + "Mapy jsou hyperbolickým pirátům k ničemu. Zjistili ale, že kompas vždy ukazuje do středu ostrova. " + "A tak se prostě vydávají tak daleko do středu, jak to jen jde, a tam ukrývají své poklady.") + +S("Just a nasty shark.", "Obyčejný, nebezpečný žralok.") + +S("Parrots feel safe in the forests of Caribbean, so they " + "never leave them. But they will help the Pirates by attacking the intruders.", + + "Papoušci se v karibských lesích cítí bezpečně, a tak je nikdy neopouštějí. " + "Pomáhají ale pirátům tím, že útočí na vetřelce.") + +S("Just a typical hyperbolic pirate.", "Typický hyperbolický pirát.") + +S( + "Normally, the power of most Orbs slowly fades away, even when " + "you are not actively using them. This Orb prevents this.\n\n" + + "When you have the Orb of Time, Orbs which are not active won't lose their power. " + "Orbs are considered active if they have a continuous power which has actually " + "affected something in the last turn.\n\n" + + "Orbs of Shielding remain active after being activated (even if you are no longer " + "attacked), and Orbs of Time have a bigger cap inside their native Caribbean than " + "outside.", + + "Síla většiny Sfér se většinou pomalu vytrácí, a to i tehdy, když je aktivně nepoužíváte. " + "Tato sféra tomu brání.\n\n" + + "Když máš Sféru Času, nebudou neaktivní Sféry ztrácet sílu. 'Aktivní Sféra' je taková Sféra, " + "která má stálý efekt a která v minulém kole něco skutečně ovlivnila.\n\n" + + "Sféry Štítu zůstávají trvale aktivní, jakmile jednou zablokují útok (i když na tebe právě nikdo " + "neútočí a Sféry Času mohou ve svém domovském Karibiku dosahovat vyšších hodnot síly než mimo něj.") + +// Achievements: + +// Parrot : Find and collect Pirate Treasure. +// Caribbean Shark : Collect 10 Pirate Treasures. +// Pirate : Collect 25 Pirate Treasures. +// Master of Caribbean : Collect 50 Pirate Treasures. + +// Papoušek : Najdi a získej Pirátský poklad. +// Karibský žralok : Získej 10 Pirátských pokladů. +// Pirát : Získej 25 Pirátských pokladů. +// Pán Karibiku : Získej 50 Pirátských pokladů. + +// Red Rock Valley + +N("Red Rock Valley", GEN_N, "Údolí červených skal", "Údolí červených skal", "Údolí červených skal", "v Údolí červených skal") + +N("Rock Snake", GEN_M, "Kamenný had", "Kamenní hadi", "Kamenného hada", "Kamenným hadem") +N("Rock Snake Tail", GEN_O, "Ocas Kamenného hada", "Ocasy Kamenných hadů", "Ocas Kamenného hada", "Ocasem Kamenného hada") +N("Red Troll", GEN_M, "Červený troll", "Červení trollové", "Červeného trolla", "Červeným trollem") +N("Red Gem", GEN_O, "Červený drahokam", "Červené drahokamy", "Červený drahokam", "Červeným drahokamem") + +N("rock I", GEN_F, "skála I", "skály I", "skálu I", "skálou I") +N("rock II", GEN_F, "skála II", "skály II", "skálu II", "skálou II") +N("rock III", GEN_F, "skála III", "skály III", "skálu III", "skálou III") + +Orb("Space", "Prostoru") + +S("Not enough power for telekinesis!", "Nemáš dost síly na telekinezi!") + +S("This land contains high rock formations. Most of the valley is at level 0, " + "while items are found at level 3. It is impossible to gain two or more levels, " + "or to lose three levels, in a single move, (attacks are possible at any " + "difference, though). Kill Red Trolls and Rock Snakes to make a cell higher.", + + "V tomto kraji se nacházejí vysoké skalní útvary. Většina údolí je na úrovni 0, " + "ale předměty se nacházejí pouze na úrovni 3. Jedním pohybem se můžete dostat " + "maximálně o jednu úroveň výš nebo o dvě úrovně níž, ale útočit je možné bez " + "ohledu na výškový rozdíl. Zabíjením Červených trollů a Skalních hadů můžete " + "pole posouvat nahoru.") + +S("A kind of Troll native to the Red Rock Valley.", + "Typ trolla, který se vyskytuje v Údolí červených skal.") + +S( + "Rock snakes are similar to Sandworms, but they move each turn. However, they " + "only move on the hexagonal cells. They are also somewhat longer than the Sandworms.", + + "Kamenní hadi jsou podobní Písečným červům, ale pohybují se v každém kole. Mohou se " + "však pohybovat pouze po šestiúhelníkových polích. Kromě toho jsou oproti Písečným " + "červům o něco delší.") + +S("A gem from the Red Rock Valley.", "Drahokam z Údolí červených skal.") + +S( + "This Orb is able to bring faraway items to your location, even if there are " + "monsters or barriers on the way. The cost of " + "bringing an item (in charges) equals the square of its distance to you. Contrary " + "to some other Orbs, usage is not allowed if you have not enough power left.", + + "Tato Sféra vám dokáže přinášet vzdálené předměty, a to i skrz netvory nebo bariéry. " + "Přinesení předmětu stojí tolik síly, kolik je druhá mocnina vzdálenosti předmětu. " + "Na rozdíl od některých jiných Sfér, Sféru Prostoru není možné použít, pokud vám už " + "nezbývá dostatečné množství síly.") + +// Climber : Find and collect a Red Gem. +// Red Troll : Collect 10 Red Gems. +// Rock Snake : Collect 25 Red Gems. +// Master of Red Rock : Collect 50 Red Gems. + +// Horolezec : Najdi a získej Červený drahokam. +// Červený troll : Získej 10 Červených drahokamů. +// Kamenný had : Získej 25 Červených drahokamů. +// Pán Červených skal: Získej 50 Červených drahokamů. + +// missing sentences + +S("%The1 drowns!", "%1 se utopi%l1!"); +S("%The1 falls!", "%1 spad%l1!"); + +// these were missing from the translation for some reason + +S("Hell has these lakes everywhere... They are shaped like evil stars, and filled with burning sulphur.", + "Tato jezera se nacházejí po celém Pekle... Mají tvar zlých hvězd a jsou naplněna hořící sírou.") + +// Hardcore Mode + +S("hardcore mode", "hardcore mód"); + +S("One wrong move and it is game over!", "Jediný špatný tah a hra končí!"); +S("Not so hardcore?", "Že bys nebyl zas až tak hardcore?"); + +// Shoot'em up Mode + +S("shoot'em up mode", "mód střílečky"); +S("Welcome to the Shoot'em Up mode!", "Vítej v módu střílečky!"); +S("F/;/Space/Enter/KP5 = fire, WASD/IJKL/Numpad = move", "F/;/Space/Enter/KP5 = střelba, WASD/IJKL/Numpad = pohyb"); + +N("Rogue", GEN_M, "Chytrák", "Chytráci", "Chytráka", "Chytrákem") +N("Knife", GEN_O, "Nůž", "Nože", "Nůž", "Nožem") +N("Flail", GEN_O, "Řemdih", "Řemdihy", "Řemdih", "Řemdihem") +N("Fireball", GEN_F, "Ohnivá koule", "Ohnivé koule", "Ohnivou kouli", "Ohnivou koulí") +N("Tongue", GEN_O, "Jazyk", "Jazyky", "Jazyk", "Jazykem") + +S("In the Shoot'em Up mode, you are armed with thrown Knives.", + "V módu střílečky jsi vyzbrojený vrhacími noži.") +S("A simple, but effective, missile, used by rogues.", + "Prostá, ale efektivní vrhací zbraň, kterou používají lovci pokladů.") +S("This attack is likely to hit the attacker.", + "Tento útok může velmi snadno zasáhnout i samotného útočníka.") +S("This magical missile burns whatever it hits.", "Tato magická střela spálí všechno, co zasáhne.") +S("Some monsters have long tongues, which allow them to attack enemies in nearby cells.", + "Někteří netvoři mají dlouhé jazyky, které jim umožňují útočit na sousední pole.") + +// modes for the local highscores + +S(", m - mode: normal", ", m - normální mód") +S(", m - mode: hardcore only", ", m - pouze hardcore mód") +S(", m - mode: shoot'em up", "m - mód střílečky") + +// update description for Steam: + +// (Mód střílečky a dva nové kraje oproti neplacené verzi. Další kraje jsou v plánu!) + +S("You would get hurt!", "To by bolelo!") +S("PARTIAL", "CZĘŚCIOWO") + +S("Cannot drop %the1 here!", "Tady nelze položit Mrtvou Sféru!"); + +// Euclidean scores +S(" (E:%1)", " (E:%1)"); + +S("You cannot attack Rock Snakes directly!", "Na Kamenné hady nemůžeš útočit přímo!"); + +S("\"I am lost...\"", "\"I am lost...\""); + +S("You are killed by %the1!", "Zabi%l1 tě %1!") + +// achievements from Version 7.0 which have not yet been translated + +// Hardcore : Získej Yendorskou sféru v hardcore módu +// Mistr nožů : Získej Yendorskou sféru v módu střílečky + +// new menu for Version 7.1 + +S("(v) menu", "(v) menu") +S("return to the game", "vrať se do hry") +S("or 'v' to see the main menu", "nebo stiskni 'v' pro hlavní menu") + +S("HyperRogue %1", "HyperRogue %1") +S("basic configuration", "základní konfigurace") +S("advanced configuration", "pokročilá konfigurace") +S("local highscores", "lokální hi-score") +S("help", "nápověda") +S("restart game", "restartovat hru") +S("special game modes", "speciální herní módy") +S("save the game", "uložit a ukončit hru") +S("quit the game", "ukončit hru") +S("review your quest", "přehled úkolů") +S("review the scene", "přehled scény") +S("game over screen", "obrazovka konce hry") +S("continue game", "pokračuj ve hře") +S("play the game!", "hraj!") + +// fixed descriptions for Shmup achievements + +S("You have used less knives than ever before. Congratulations!", + "Použil jsi méně nožů než kdykoli předtím. Gratulujeme!") + +S("You have improved both your real time and knife count. Congratulations!", + "Zlepšil jsi jak svůj čas, tak počet nožů. Gratulujeme!") + +S("%1 knives (%2)", "nožů: %1 (%2)") + +// temporary +S("No description yet." ,"Zatím bez popisu.") + +// special case when no Spice is visible +S("The sandworm explodes!", "Písečný červ vybuchl!") + +// Ocean + +// achievements: +// Došel jsi k Oceánu: Najdi a získej Jantar. +// Albatros: Získej 10 Jantarů. +// Jantarový albatros: Získej 25 Jantarů. +// Pán přílivu: Získej 50 Jantarů. + +N("Ocean", GEN_O, "Oceán", "Oceány", "Oceán", "na Oceánu") + +S( + "You can collect some valuable Ambers on the coast, but beware the tides!\n\n" + "You can also take one of the boats and venture into the Ocean, " + "to find other coasts, dangerous whirlpools, and islands inhabited by Pirates.", + + "Na pobřeží můžeš sbírat cenný Jantar, ale pozor na příliv a odliv!\n\n" + "Také si můžeš vzít člun a vyplout na Oceán, " + "kde najdeš další pobřeží, nebezpečné víry a ostrovy obývané piráty.") + +N("Albatross", GEN_O, "Albatros", "Albatrosové", "Albatrosa", "Albatrosem") + +S( + "Those large seabirds attack you for some reason. At least they are not " + "as fast as Eagles...", + "Tito velcí mořští ptáci na tebe z nějakého důvodu útočí. Aspoň že nejsou tak rychlí jako Orli...") + +N("stranded boat", GEN_O, "člun na mělčině", "čluny na mělčině", "člun na mělčině", "ve člunu na mělčině") + +S( + "This boat cannot go through the sand. But if you sit inside and " + "wait for the tide, you will be able to use it to travel through the Ocean.", + + "Tento člun nemůže plout po písku. Ale pokud si do něj sedneš a počkáš na příliv, " + "můžeš na něm cestovat přes Oceán." + ) + +N("Ocean", GEN_O, "Oceán", "Oceány", "Oceán", "na Oceánu") + +N("Amber", GEN_O, "Jantar", "Jantary", "Jantar", "Jantarem") + +S( + "When the tide is away, beautiful ambers can be found on the hyperbolic beaches. " + "Perhaps there used to be a forest here?", + "Za odlivu můžeš na hyperbolické pláži najít krásné kusy jantaru." + "Možná tu kdysi býval les?") + +Orb("Air", "Vzduchu") + +S("This Orb allows you to blow your enemies away.\n\n" + "Click a monster to blow it one cell away. It cannot be used against mimics, ghosts, sharks and other monsters restricted to a specific terrain, and multi-tile monsters." +, + "Tato sféra ti umožňuje odfouknout nepřátele daleko od tebe.\n\n" + "Kliknutím na netvora ho můžeš odfouknout o jedno pole od sebe. Tuto schopnost nelze použít na mimiky, duchy, žraloky a jiné netvory, kteří jsou omezení pouze na specifický terén nebo zabírají více než jedno pole." + ) + +N("Sea Border", GEN_O, "Mořská hranice", "Mořské hranice", "Mořskou hranici", "na Mořské hranici") + +S("Border between seas.", "Hranice mezi moři.") + +// Whirlpool + +// achievements: +// Útěk z Víru: Získej Perlu a unikni z Víru. +// Vírový žralok: Získej 10 Perel. +// Vírový pirát: Získej 25 Perel. +// Pán Víru: Získej 50 Perel. + +N("Whirlpool", GEN_O, "Vír", "Víry", "Vír", "ve Víru") + +S( + "Many lost boats are spinning in this whirlpool. Some of them contain treasures " + "and Pirates.\n\n" + "Unmanned boats will go one cell clockwise in each turn. Sharks and manned boats " + "are only allowed to go with the current, that is, towards the center, or clockwise.", + + "V tomto víru se točí mnoho ztracených člunů. Na některých z nich se nachází poklad nebo piráti.\n\n" + "Čluny bez posádky se v každém kole posunou o jedno pole po směru hodinových ručiček. Žraloci a čluny s posádkou " + "se smějí pohybovat pouze po proudu, tedy do středu nebo po směru hodinových ručiček " + ) + +N("Pearl", GEN_F, "Perla", "Perly", "Perlu", "Perlou") + +S( + "You do not know exactly why, but there are valuable pearls on many boats " + "in the whirlpool.", + "Nevíš tak úplně jistě proč, ale na mnoha člunech ve Víru jsou cenné perly." + ) + +Orb("Water", "vody") + +S( "This Orb allows your boat to go against the current, " + "and also to go into the land, creating water on the way.", + "Tato Sféra tvému člunu umožňuje plout proti proudu. " + "Také můžeš vyplout na souš a přitom vytvářet vodu, kamkoli se vydáš.") + +S("You cannot go against the current!", "Nemůžeš plout proti proudu!") + +// Minefield + +// achievements: +// Došel jsi na Minové pole: Získej Vejce Bombarďáka. +// Minolovka: Získej 10 Vajec Bombarďáka. +// Bombarďák: Získej 25 Vajec Bombarďáka. +// Pán Minového pole: Získej 50 Vajec Bombarďáka. + +N("Minefield", GEN_N, "Minové pole", "Minová pole", "Minové pole", "v Minovém poli") +N("minefield", GEN_N, "minové pole", "minová pole", "minové pole", "minovým polem") +N("cell without mine", GEN_N, "pole bez miny", "pole bez min", "pole bez miny", "polem bez min") + +S( + "This minefield has been created by the Bomberbirds to protect their valuable eggs. " + "Mines explode when they are stepped on, creating fire all around them " + "(this fire never expires in the Minefield). If you don't step on a mine, you " + "know the number of mines in cells around you. These numbers are marked with " + "color codes on the cells you have visited.", + "Toto minové pole vytvořili ptáci Bombarďáci, aby ochránili svá cenná vejce. " + "Mina exploduje, když na ni někdo nebo něco šlápne, čímž zapálí oheň na svém poli a na všech sousedních polích " + "(v Minovém poli tento oheň nikdy neuhasne). A samozřejmě ji také odpálí jakýkoli oheň! Pokud " + "nešlápneš na minu, budeš vždy vědět, kolik min se nachází na polích okolo tebe. " + "Tento počet bude označený barevnými kódy na polích, která jsi už navštívil." + ) + +N("Bomberbird", GEN_M, "Bombarďák", "Bombarďáci", "Bombarďáka", "Bombarďákem") + +S( + "Dark red birds who have created the minefield.\n\n" + "They create a mine on the spot where they are killed, provided " + "that the terrain is suitable. Also note that mines are triggered " + "by dead birds falling on them.", + + "Tmavočervení ptáci, kteří vytvořili minové pole.\n\n" + "Když zemřou, vytvoří na poli, kam spadnou, minu, pokud to terén dovoluje. " + "Měj na paměti, že i pád mrtvého ptáka na minu stačí k tomu, aby ji odpálil!") + +N("Tame Bomberbird", GEN_M, "Ochočený Bombarďák", "Ochočení Bombarďáci", "Ochočeného Bombarďáka", "Ochočeným Bombarďákem") + +S( + "This bomberbird will follow you at some distance, and attack your enemies. " + "You can kill it to place a mine.", + + "Tento Bombarďák tě bude sledovat v určité vzdálenosti a útočit na tvé nepřátele. " + "Kromě toho ho můžeš zabít, a tím položit minu.") + +N("Bomberbird Egg", GEN_N, "Vejce Bombarďáka", "Vejce Bombarďáka", "Vejce Bombarďáka", "Vejcem Bombarďáka") + +S( + "Bomberbird eggs are big and tasty, and thus valuable. " + "They can hatch when left alone for some time (but this will never happen " + "if you are watching).", + + "Vejce Bombarďáků jsou velká a chutná -- a tudíž i cenná. Mohou se vylíhnout, " + "když je necháš nějaký čas na pokoji (ale to se nikdy nestane, když se na ně díváš)." + ) + +Orb("Friendship", "Přátelství") + +S("This Orb summons a friendly Bomberbird.", + "Tato sféra vyvolá přátelského Bombarďáka.") + +S("Nowhere to blow %the1!", "%a1 není kam odfouknout!") +S("%The1 is immune to wind!", "%1 je imunní proti větru!") +S("You blow %the1 away!", "Odfoukl jsi %a1!") + +S("WARNING: you are entering a minefield!", "VAROVÁNÍ: vstupuješ do minového pole!") +S("No mines next to you.", "Ve tvé blízkosti se nenacházejí žádné miny.") +S("A mine is next to you!", "Ve tvé blízkosti se nachází jedna mina!") +S("Two mines next to you!", "Ve tvé blízkosti se nacházejí dvě miny!") +S("Three mines next to you!", "Ve tvé blízkosti se nacházejí tři miny!") +S("Four mines next to you!", "Ve tvé blízkosti se nacházejí čtyři miny!") +S("Five mines next to you!", "Ve tvé blízkosti se nachází pět min!") +S("Six mines next to you!", "Ve tvé blízkosti se nachází šest min!") +S("Seven mines next to you!", "Ve tvé blízkosti se nachází sedm min!") + +S("Still confused? Read the FAQ on the HyperRogue website!\n\n", + "Stále zmatení? Přečtěte si FAQ na webové stránce HyperRogue (prozatím pouze v angličtině)\n\n") + +S("You have to run away from the water!", "Musíš utéct před vodou!") + +// 7.2 + +N("Palace", GEN_O, "Palác", "Paláce", "Palác", "v Paláci") +N("palace wall", GEN_F, "zeď paláce", "zdi paláce", "zeď paláce", "zeď paláce") + +S("Apparently a princess is kept locked somewhere, but you won't ever find her in this hyperbolic palace. ", + "Někde je tu prý uvězněná princezna, ale tu v tomhle hyperbolickém paláci nikdy nenajdeš. ") + +S("Apparently a prince is kept locked somewhere, but you won't ever find him in this hyperbolic palace. ", + "Někde je tu prý uvězněný princ, ale toho v tomhle hyperbolickém paláci nikdy nenajdeš. ") + +S("So better just to concentrate on collecting treasure. " + "Beware the traps, and the guards, who are hard to kill!", + + "Takže se raději soustřeď jen na sbírání pokladů. " + "Pozor na pasti a na stráže -- je těžké je zabít!" + ) + +N("trapdoor", GEN_N, "propadlo", "propadla", "propadlo", "propadlem") +S("This floor will fall after someone goes there. Go quickly!", + "Tato podlaha se propadne poté, co přes ni někdo projde. Běž rychle!") + +N("closed gate", GEN_F, "zavřená brána", "zavřené brány", "zavřenou bránu", "zavřenou bránou") +N("open gate", GEN_F, "otevřená brána", "otevřené brány", "otevřenou bránu", "otevřenou bránou") +N("closing plate", GEN_F, "zavírací deska", "zavírací desky", "zavírací desku", "zavírací deskou") +N("opening plate", GEN_F, "otvírací deska", "otvírací desky", "otvírací desku", "otvírací deskou") + +S("Green pressure plates open all gates in radius 3 around them. " + "Similarly, red pressure plates close all gates in this radius.", + + "Zelené desky otevřou všechny brány v okruhu 3 polí, když na ně někdo šlápne. " + "Červené desky naopak všechny brány v tomto okruhu zavřou.") + +N("Hypersian Rug", GEN_O, "Hyperský koberec", "Hyperské koberce", "Hyperský koberec", "Hyperským kobercem") +S("Nice, a hyperbolic rug! It will not fit very well on your flat Euclidean floor, but who cares?", + "Prima, hyperbolický koberec! Na tvoji placatou eukleidovskou podlahu moc dobře pasovat nebude, ale co?") + +Orb("the Frog", "Žáby") +S("This Orb lets you jump to a place which is two cell away from you, in a single turn. " + "You can jump over water, chasms and fire, but not over walls.", + "Tato Sféra ti umožňuje skočit v jednom kole dvě pole daleko. " + "Můžeš skákat přes vodu, propasti a oheň, ale ne přes zdi.") +S("Cannot jump through %the1!", "Nemůžeš skočit přes %a1!") +S("You jump!", "Skočil jsi!") + +S("\n\nNote: when pushing %the1 off a heptagonal cell, you can control the pushing direction " + "by clicking left or right half of the heptagon.", + "\n\nPoznámka: Když tlačíš %a1 ze sedmiúhelníku, můžeš ovládat směr tlačení " + "tím, že klikneš na levou či pravou polovinu tohoto sedmiúhelníku." + ) + +S(" With the keyboard, you can rotate the view for a similar effect (Page Up/Down).", + " Na klávesnici můžeš podobného efektu dosáhnout otočením hrací plochy (Page Up/Down).") + +N("Palace Guard", GEN_M, "Strážce Paláce", "Strážci Paláce", "Strážce Paláce", "Strážcem Paláce") + +S("You have to hit Palace Guards several times to kill them. After each hit, they " + "are pushed away and stunned for some time.", + "Na zabití Strážce Paláce potřebuješ několik útoků. Každý zásah Strážce " + "odstrčí dozadu a na chvíli ho omráčí.") + +N("Fat Guard", GEN_M, "Tlustý strážce", "Tlustí strážci", "Tlustého strážce", "Tlustým strážcem") + +S("Fat guards are too heavy to be pushed away by your hits.", + "Tlustí strážci jsou příliš těžcí na to, aby je tvé zásahy dokázaly odstrčit.") + +N("Skeleton", GEN_M, "Kostlivec", "Kostlivci", "Kostlivce", "Kostlivcem") +S("Skeletons work similar to Palace Guards, but they won't die no matter how many " + "times you hit them. Well, you have to be more creative...\n\n" + "Skeletons attacked outside of their native land, Palace, are stunned for a longer time.", + "Kostlivci fungují podobně jako Strážci Paláce, ale ať na ně zaútočíš, " + "kolikrát chceš, nikdy je nezabiješ. No, musíš být vynalézavější...\n\n" + "Mimo Palác, jejich rodný kraj, budou Kostlivci útokem omráčení na delší dobu." + ) + +N("Vizier", GEN_M, "Vezír", "Vezírové", "Vezíra", "Vezírem") +S("Viziers are neither pushed away nor stunned. However, you attack them automatically when " + "escaping from them.", + "Vezíry nemůžeš odstrčit ani omráčit, ale automaticky na ně útočíš, když od nich utíkáš.") + +S("You stun %the1.", "Omráčil jsi %a1.") +S("The gate is closing right on you! RUN!", "Brána se zavírá! UTÍKEJ!") +S("%The1 is crushed!", "Brána rozdrtila %a1!") +S("You hit %the1.", "Zasáhl jsi %a1.") +S("Hit him by walking away from him.", "Zasáhni ho tak, že se pohneš směrem od něj.") +S("Hmm, he has been training in the Emerald Mine. Interesting...", "Hmm, tak on trénoval ve Smaragdovém dole. Zajímavé...") + +// Reached the Palace: Find and collect a Hypersian Rug. +// Palace Guard: Collect 10 Hypersian Rugs. +// Vizier: Colect 25 Hypersian Rugs. +// Prince: Colect 50 Hypersian Rugs. + +// Došel jsi do Paláce: Najdi a získej Hyperský koberec. +// Strážce Paláce: Získej 10 Hyperských koberců. +// Vezír: Získej 25 Hyperských koberců. +// Princ: Získej 50 Hyperských koberců. + +// Living Fjord + +N("Living Fjord", GEN_O, "Živoucí fjord", "Živoucí fjordy", "Živoucí Fjord", "v Živoucím Fjordu") + +S("A coastal area, from where you can get both to the inland worlds and to the Ocean. " + "Each turn, each cell will become water or earth, based on the majority of cells around it. " + "Contrary to the Living Caves, this process is not affected by most items and monsters, " + "but elementals, dead Trolls, and cells outside of the Living Fjord have " + "a very powerful effect.", + "Pobřežní oblast, odkud se můžeš dostat jak do vnitrozemských světů, tak do Oceánu. " + "V každém kole se každé pole změní na vodu nebo na souš podle toho, kterého typu je většina polí kolem něj. " + "Na rozdíl od Živoucí jeskyně nemá většina předmětů a netvorů na tento proces žádný vliv, " + "ale elementálové, mrtví trollové a pole mimo Živoucí fjord mají " + "velmi silný efekt." + ) + +N("Fjord Troll", GEN_M, "Fjordtroll", "Fjordtrollové", "Fjordtrolla", "Fjordtrollem") +S("Fjord Trolls leave a wall when they die, causing the living fjord to rise around it. " + "Contrary to Rock Trolls, items around are not destroyed.", + "Fjordtrollové se po smrti promění v zeď, kolem které se zvedají vody Živoucího fjordu. " + "Fjordtrollové na rozdíl od Šutrollů neničí předměty kolem sebe." + ) + +N("Viking", GEN_M, "Viking", "Vikingové", "Vikinga", "Vikingem") +S("Mighty warriors from the Fjord, who can use boats.", + "Mocní válečníci z Fjordu, kteří se dokážou plavit na člunech.") + +N("Water Elemental", GEN_M, "Elementál Vody", "Elementálové Vody", "Elementála Vody", "Elementálem Vody") +S("Wherever this powerful being goes, the living fjord " + "sinks below water, non-magical boats are destroyed, and fires are extinguished.\n\n" + "As a special case, you can attack the Water Elemental from the water, without drowning immediately.", + "Kamkoli se vydá tato mocná bytost, tam se Živoucí fjord potápí pod vodu, všechny čluny kromě magických " + "jsou zničeny a veškerý oheň je uhašen.\n\n" + "Na Elementála Vody můžeš zaútočit z vody, aniž by ses okamžitě utopil; to je speciální případ.") + + +N("Garnet", GEN_O, "Granát", "Granáty", "Granát", "Granátem") +S("Vikings believe that garnets improve their strength.", + "Vikingové věří, že granáty zvyšují jejich sílu.") + +Orb("the Fish", "Ryby") +S("This Orb lets you dive into the water. While diving, you are able to see and collect underwater treasures, " + "while being invisible to monsters yourself. You are afraid of jumping into the water straight from a boat, so usually you won't do it.", + "Tato Sféra ti umožňuje potopit se pod vodu. Když jsi potopený, můžeš vidět a získávat podvodní poklady, " + "zatímco netvoři tě nevidí. Obvykle ale nebudeš skákat do vody přímo ze člunu -- to tě trochu děsí.") + +S("%The1 is washed away!", "Elementál Vody spláchl %a1!") +S("%The1 is extinguished!", "Elementál Vody uhasil %a1!") + +// Reached the Living Fjord: Find and collect a Garnet. +// Viking: Collect 10 Garnets. +// Water Elemental: Colect 25 Garnets. +// Master of the Fjord: Colect 50 Garnets. + +// Došel jsi do Živoucího fjordu: Najdi a získej Granát. +// Viking: Získej 10 Granátů. +// Elementál Vody: Získej 25 Granátů. +// Pán Fjordu: Získej 50 Granátů. + +// implemented, not appears in the game yet + +Orb("Discord", "Nesváru") + +S("Causes most monsters to attack other monsters, not only you and your friends.", + "Díky této Sféře bude většina netvorů útočit nejen na tebe a na tvé kamarády, ale i na jiné netvory.") + +// Shmup Configuration + +S("forward", "dopředu") +S("backward", "dozadu") +S("turn left", "otočení vlevo") +S("turn right", "otočení vpravo") +S("move up", "nahoru") +S("move right", "doprava") +S("move down", "dolů") +S("move left", "doleva") +S("throw a knife", "házení nože") +S("face the pointer", "otočení ke kurzoru") +S("throw at the pointer", "házení na kurzor") +S("drop Dead Orb", "položení Mrtvé sféry") +S("center the map on me", "vycentrování mapy na postavě") +S("activate Orb power", "aktivace schopnosti Sféry") + +S("pan up", "scrollování nahoru") +S("pan right", "scrollování doprava") +S("pan down", "scrollování dolů") +S("pan left", "scrollování doleva") +S("rotate left", "otočení vlevo") +S("rotate right", "otočení vpravo") +S("home", "vycentrování") + +S("do nothing", "nic") +S("rotate view", "otočení hrací plochy") +S("panning X", "scrollování ve směru X") +S("panning Y", "scrollování ve směru Y") +S("player 1 X", "hráč 1 X") +S("player 1 Y", "hráč 1 Y") +S("player 1 go", "hráč 1 pohyb") +S("player 1 spin", "hráč 1 otáčení") +S("player 2 X", "hráč 2 X") +S("player 2 Y", "hráč 2 Y") +S("player 2 go", "hráč 2 pohyb") +S("player 2 spin", "hráč 2 otáčení") + +S("Joystick %1, axis %2", "Joystick %1, osa %2") +S("one player", "jeden hráč") +S("two players", "dva hráči") +S("configure player 1", "konfigurace hráče 1") +S("configure player 2", "konfigurace hráče 2") +S("configure panning", "konfigurace scrollování") +S("configure joystick axes", "konfigurace os joysticku") +S("continue playing", "pokračuj ve hře") +S("start playing in the shmup mode", "začni hrát v módu střílečky") +S("return to the turn-based mode", "vrať se do módu na kola") +S("save the configuration", "ulož konfiguraci") +S("press a key to unassign", "stiskni klávesu, kterou chceš zrušit") +S("press a key for '%1'", "stiskni klávesu pro '%1'") +S("unassign a key", "zruš klávesu") + +// extra pattern modes + +S("explore the Emerald Pattern", "Zkoumání Smaragdového vzoru") +S("explore the Palace Pattern (4 colors)", "Zkoumání Palácového vzoru (4 barvy)") +S("explore the Palace Pattern (8 colors)", "Zkoumání Palácového vzoru (8 barev)") + +// extra flavor/Knight lines + +S("Kill a Vizier in the Palace to access Emerald Mine", "Zabij Vezíra v Paláci a dostaneš se do Smaragdového dolu") +S("Collect 5 Emeralds to access Camelot", "Získej 5 Smaragdů a dostaneš se do Camelotu") +S("Some lands unlock at specific treasures or kills", "Některé kraje se otevřou získáním určitých pokladů nebo zabitím určitých netvorů.") + +S("You will be fighting red rock snakes, too...", "Budeš bojovat i s kamennými hady...") + +S("\"The Red Rock Valley is dangerous, but beautiful.\"", + "\"Údolí červených skal je nebezpečné, ale krásné.\"") +S("\"Train in the Desert first!\"", "\"Nejdřív se natrénuj v Poušti!\"") +S("\"I like collecting ambers at the beach.\"", "\"Rád sbírám Jantar na pláži.\"") +S("\"Our Table seats %1 Knights!\"", "\"U našeho stolu sedí %1 rytířů!\"") +S("\"There are %1 floor tiles inside our Table!\"", "\"Uvnitř našeho stolu je %1 dlaždic!\"") +S("\"By now, you should have your own formula, you know?\"", "\"Teď už bys mě%l0 mít svůj vlastní vzorec, ne?\"") +S("\"Have you tried to take a boat and go into the Ocean? Try it!\"", "\"Už jsi zkouše%l0 vzít člun a vyplout na Oceán?\"") + +//====================// +// NEW IN VERSION 7.3 // +//====================// + +// new name for 'Ivy D' + +N("Dead Ivy", GEN_M, "Mrtvý břečťan", "Mrtvé břečťany", "Mrtvý břečťan", "Mrtvým břečťanem") + +// new messages for living/nonliving monsters + +S("%The1 bites %the2!", "%1 kous%l1 %2!") +S("%The1 attacks %the2!", "%1 útočí na %a2!") +S("You destroy %the1 with a mental blast!", "Zniči%l0 jsi %a1 mentálním úderem!") +S("The ivy kills %the1!", "Břečťan zabil %a1!") +S("You destroy %the1.", "Zniči%l0 jsi %a1.") +S("%The1 kills %the2!", "%1 zabi%l1 %a2!") +S("%The1 sinks!", "%1 zmize%l1 pod vodou!"); + +S("Cannot jump on %the1!", "Nemůžeš skočit na %1!") + +// Map Editor +//============ + +S("map editor", "mapový editor") +S("You activate your terraforming powers!", "Aktivova%l0 jsi své terramorfické schopnosti!") +S("Press F5 to clear the board.", "F5 vymaže desku.") +S("Press F5 to restart the game normally.", "Stisknutím F5 restartuješ hru v normálním módu.") +S("High quality shots not available on this platform", "HQ snímky nejsou na této platformě k dispozici") +S("Saved the high quality shot to %1", "HQ snímek uložen do %1") +S("Map saved to %1", "Mapa uložena do %1") +S("Map loaded from %1", "Mapa načtena z %1") +S("copying", "kopíruje") +S("boundary", "hranice") +S("clear monster", "vymazat netvore") +S("use at your own risk!", "použití na vlastní nebezpečí!") + +// Note: in English, these have been arranged from longest to shortest. +// This gives a somewhat nice effect on the top left corner of the screen. +// You may want to aim for the same effect when translating + +S("0-9 = radius (%1)", "0-9 = poloměr (%1)") +S("b = boundary", "c = kopírování") +S("m = monsters", "i = předměty") +S("w = walls", "b = hranice") +S("i = items", "m = netvoři") +S("l = lands", "l = kraje") +S("c = copy", "w = zdi") + +// And this is from shortest to longest (bottom left corner) +S("F1 = help", "F1 = nápověda") +S("F2 = save", "F2 = uložení") +S("F3 = load", "F3 = nahrání") +S("F5 = restart", "F5 = restart") +S("F6 = HQ shot", "F6 = HQ snímek") +S("F7 = player on/off", "F7 = zapnout/vypnout hráče") +S("ESC = return to the game", "ESC = návrat do hry") + +S( + "This mode allows you to edit the map.\n\n" + "NOTE: Use at your own risk. Combinations which never " + "appear in the real game may work in an undefined way " + "(do not work, look strangely, give strange messages, or crash the game).\n\n" + "To get the most of this editor, " + "some knowledge of inner workings of HyperRogue is required. " + "Each cell has four main fields: land type, wall type, monster type, item type. " + "The same wall type (especially \"none\", \"sea\", or \"bonfire\") may look or " + "work a bit differently, based on the land it is in. Sometimes an object may " + "appear twice on the list due to subtle differences (for example, Demons could " + "move next turn or not).\n\n" + "Press w, i, l, or m to choose which aspect of cells to change, " + "then just click on the cells and they will change. Press 'c' while " + "hovering over a cell to copy that cell, this copies all information about it. " + "When copying large areas or placing multi-tile monsters, it might be important where " + "on the cell you are clicking.\n\n" + "You can also press 0-9 to apply your changes to a greater radius. " + "This also affects the copy/paste feature, allowing to copy a larger area.\n\n" + "Press F2 to save the current map (and F3 to load it). If you try this after " + "a long game of HyperRogue (without using Orbs of Safety), the filesize will " + "be very large! " + "Note however that large structures, such as " + "Great Walls, large circles and horocycles, are destroyed by this.\n\n" + "Press 'b' to mark cells as boundaries. Such cells, and cells beyond " + "them, are not copied by the copy/paste feature, nor saved by the " + "save feature.\n\n", + + "V tomto módu můžeš editovat mapup.\n\n" + "POZOR: Používej na vlastní nebezpečí. Kombinace, které se v normální hře " + "nikdy nevyskytují, mohou fungovat nedefinovaným způsobem " + "(nefungovat, divně vypadat, generovat podivné zprávy nebo způsobit spadnutí hry).\n\n" + "Abys z tohoto editoru získal co nejvíce, " + "musíš vědět něco o tom, jak HyperRogue funguje \"pod kapotou\". " + "Každé políčko má čtyři atributy: typ kraje, typ zdi, typ netvora, a typ předmětu. " + "Ten samý typ zdi (především \"nic\", \"moře\" nebo \"oheň\") může vypadat nebo se chovat " + "trochu jinak podle toho, ve kterém kraji se nachází. Některé položky " + "mohou být v seznamu dvakrát díky drobným rozdílům (například Čerti mají dvě formy podle toho, " + "zda se v příštím kole mají pohnout nebo ne).\n\n" + "Klávesami 'w', 'i', 'l' a 'm' udáváš, který aspekt políček chceš změnit; " + "pak na políčko jednoduše klikni, a ono se změní. Stiskem klávesy 'c' zkopíruješ " + "políčko pod kurzorem (zkopírují se všechny informace o tomto políčku). " + "Při kopírování nebo vkládání vícepolíčkových netvorů může být důležité, kam přesně v políčku klikáš.\n\n" + "Své změny můžeš také aplikovat na větší oblast pomocí kláves 0-9, které nastavují poloměr. " + "To také ovlivňuje kopírování/vkládání, což ti umožní kopírovat větší oblast.\n\n" + "F2 uloží současnou mapu (a F3 ji nahraje). Pokud to uděláš po dlouhé hře HyperRogue (kde jsi nepoužil Sféru Bezpečnosti), " + "bude vzniklý soubor hodně velký! " + "Ovšem pozor -- velké struktury, jako jsou Velké zdi, velké kruhy a horocykly budou uložením a nahráním mapy zničeny.\n\n" + "Klávesou 'b' můžeš políčka označit jako hraniční. Tato políčka a políčka za nimi nebudou při operacích kopírování a " + "vkládání kopírovány a nebudou ani uloženy.\n\n" + ) + +// Princess Quest +//================ + +S( + "A mouse squeaks at you. It seems that it wants you to go somewhere. " + "That's interesting, what could you find here?\n\n" + "Note: in the part of the Palace that you are exploring during this " + "quest, the distribution of monsters, pressure plates, and items has been " + "changed somewhat, to make it a bit more suitable for less " + "experienced players. The number of monsters does not depend on the " + "number of Hypersian Rugs you have collected, and there are more " + "opening plates.\n\n" + "However, even with the normal distribution, it appears that it should be " + "always possible to reach your goal. If you want this challenge, " + "select it from the special game modes menu.", + + "Vykvíkla na tebe myška. Zdá se, že chce, aby ses někam vyda%l0. " + "To je zajímavé, copak tam asi najdeš?\n\n" + "Poznámka: V části Paláce, kterou budeš procházet při plnění této mise, " + "je poněkud upravené rozdělení netvorů, desek a předmětů, aby byla mise " + "o něco vhodnější i pro méně zkušené hráče. Počet netvorů nebude záviset na " + "počtu získaných Hyperských koberců a bude tu více otvíracích desek.\n\n" + "Nicméně, dosažení cíle by mělo být vždy možné i při normálním rozdělení. " + "Pokud si chceš tuto obtížnější misi vyzkoušet, vyber ji z menu speciálních herních módů.\n\n") + +S("\"When I visited the Palace, a mouse wanted me to go somewhere.\"", + "\"Když jsem navštívil Palác, byla tam myška, co chtěla, abych se někam vydal.\"") + +S("\"I wonder what was there...\"", "\"Copak tam asi bylo...?\"") + +N("Mouse", GEN_F, "Myška", "Myška", "Myšku", "Myškou") + +S("You hear a distant squeak!", "V dálce slyšíš zapištění!") +S("%The1 squeaks in a confused way.", "%1 zmateně piští.") +S("%The1 squeaks gratefully!", "%1 vděčně piští!"); +S("%The1 squeaks hopelessly.", "%1 zdrceně piští."); +S("%The1 squeaks in despair.", "%1 zoufale piští."); +S("%The1 squeaks sadly.", "%1 smutně piští."); +S("%The1 squeaks with hope!", "%1 nadějně piští!"); +S("%The1 squeaks happily!", "%1 šťastně piští!"); +S("%The1 squeaks excitedly!", "%1 vzrušeně piští!"); + +N("giant rug", GEN_O, "obří koberec", "obří koberce", "obří koberec", "obřím kobercem") + +S("This is the biggest Hypersian Rug you have ever seen! " + "Unfortunately, it is too large to take it as a trophy.", + "Tohle je ten největší Hyperský koberec, jaký jsi kdy vidě%l0! " + "Bohužel je ale příliš velký na to, aby sis ho moh%l0 vzít jako trofej.") + +N("Prince", GEN_M, "Princ", "Princové", "Prince", "Princem") +N("Princess", GEN_F, "Princezna", "Princezny", "Princeznu", "Princeznou") + +S("%1 takes %his1 revenge on %the2!", "%1 se mstí!") +S("\"That should teach you to take me seriously!\"", + "\"To by tě mělo naučit brát mě vážně!\"") + +S("%The1 kisses you, and begs you to bring %him1 away from here.", + "%1 tě políbi%l1 a prosí tě, abys ji odsud odved%l0.") + +S("\"I want my revenge. Stun a guard and leave him for me!\"", + "Chci se pomstít. Omrač nějakého strážce a nech mi ho!\"") + +S("\"That felt great. Thanks!\"", "\"To byl skvělý pocit. Děkuji!\"") + +S("\"Bring me out of here please!\"", "Prosím tě, odveď mě odsud!\"") + +S("%The1 kisses you, and thanks you for saving %him1.", + "%1 tě políbi%l1 a děkuje ti, že jsi %ho1 zachránil.") + +S("\"I have been trained to fight with a Hypersian scimitar, you know?\"", + "Jsem vycvičen%ý1 v boji s hyperskou šavlí, víš?\"") + +S("\"I would love to come to your world with you!\"", + "Chtě%l1 bych se s tebou vrátit do tvého světa!\"") + +S("\"Straight lines stay close to each other forever, this is so romantic!\"", + "\"Přímky, které navěky zůstávají blízko sebe, to je tak romantické!\"") + +S("\"Maps... Just like the world, but smaller... how is that even possible?!\"", + "\"Mapy... stejné jako svět, ale menší... jak je to vůbec možné?!\"") + +Orb("Love", "Lásky") +S("Love takes time, but it heals all wounds, and transcends time and space.\n\n" + "The Orb of Love is worth 30$$$, if you end the game with it.\n", + + "Láska chce čas, ale zahojí všechny rány a překoná čas i prostor.\n\n" + "Sféra lásky má cenu 30$$$, pokud ji máš u sebe na konci hry.\n") + +// Princess Challenge: + +S("%1 Challenge", "Mise: %1") +S("Save %the1 first to unlock this challenge!", "Pro aktivaci této mise musíš nejprve zachránit %a1!") +S("Welcome to %the1 Challenge!", "Vítej v Misi: %1!") +S("The more Hypersian Rugs you collect, the harder it is.", "Čím víc Hyperských koberců sebereš, tím obtížnější bude.") +S("Follow the Mouse and escape with %the1!", "Následuj Myšku a uteč s %abl1!") +S("Hardness frozen at %1.", "Obtížnost nastavená na: %1."); +S("Congratulations! Your score is %1.", "Gratulujeme! Tvé skóre je %1.") + +S("u = undo", "u = zpět") +S("f = flip %1", "f = překlopit %1") + +S("Failed to save map to %1", "Uložení mapy do %1 se nezdařilo") +S("Failed to load map from %1", "Nahrání mapy z %1 se nezdařilo") +S("save whom", "koho zachraňuješ") +S("other", "další") // other keys in the main menu + +// VERSION 7.4 + +// missing texts, refactored things, and rule changes +//==================================================== + +S("%The1 activates her Flash spell!", "%1 aktivova%l1 kouzlo Záblesk!") + +N("Fire", GEN_O, "Oheň", "Ohně", "Oheň", "Ohněm") +S("This cell is on fire. Most beings and items cannot survive.", + "Toto políčko hoří. Většina tvorů a předmětů zde nepřežije.") + +N("Eternal Fire", GEN_O, "Věčný Oheň", "Věčné Ohně", "Věčný Oheň", "Věčným Ohněm") +S("This fire never burns out.", "Tento oheň nikdy neuhasne.") + +S("Some rubble.", "Sutiny.") + +S("The Orb loses its power as it leaves the Land of Power!", + "Sféra opustila Kraj Moci a ztratila svou sílu!") + +S("%The1 fills the hole!", "%1 vyplni%l1 díru!") + +N("Tentacle+Ghost", GEN_M, "Chapadlo+Duch", "Chapadla+Duchové", "Chapadlo+Ducha", "Chapadlem+Duchem") + +// Land Overview +//=============== + +S("world overview", "přehled krajů") +S("or 'o' to see the world overview", "nebo stiskni 'o' pro přehled krajů") + +S("forbidden to find in %the1", "zakázaná %abl1") +S("too dangerous to use in %the1", "příliš nebezpečná %abl1") +S("useless in %the1", "k ničemu %abl1") +S("only native Orbs allowed in %the1", "%abl1 jsou povoleny pouze náležící Sféry") +S("this Orb is never unlocked globally (only hubs)", "tato Sféra není nikdy odemčena globálně (pouze v centrálních krajích)") +S("collect 25 %2 to unlock it in %the1", "získej 25x %2, abys ji odemkl %abl1") +S("collect 3 %2 to unlock it in %the1", "získej 3x %2, abys ji odemkl %abl1") +S("native in %the1 (collect 10 %2)", "standardní %abl1 (získej 10x %2)") +S("native in %the1 (collect 1 %2)", "standardní %abl1 (získej 1x %2)") +S("secondary in %the1 (collect 10 %3, or 25 %2)", "sekundární %abl1 (získej 10x %3 nebo 25x %2)") +S("the native Orb of %the1", "standardní Sféra %abl1") +S("this Orb appears on floors and is used by witches", "tato Sféra se objevuje na zemi a využívají ji čarodějnice czarownice") +S("a prized Orb, it appears only in cabinets", "cenná Sféra, která se objevuje pouze ve vitrínách") +S("this Orb never appears in %the1", "tato Sféra, se %abl1 nikdy neobjevuje") +S("Hub Land: orbs appear here if unlocked in their native land", "Centrální kraj: Sféry se zde objevují, pokud jsi je odemkl v jejich rodné krajině") +S("kill a monster, or collect 25 %2", "zabij netvora nebo získej 25x %2") + +S("Always available.\n", "Tento kraj je vždy k dispozici.\n") +S("Treasure required: %1 $$$.\n", "Potřebuješ %1 $$$.\n") +S("Accessible only from %the1.\n", "Tento kraj je dostupný pouze skrz %a1.\n") +S("Accessible only from %the1 (until finished).\n", "Tento kraj je dostupný pouze skrz %a1 (dokud ho nedohraješ).\n") + +S("Accessible only from %the1 or %the2.\n", "Tento kraj je dostupný pouze skrz %a1 nebo %a2.\n") + +S("Kills required: %1.\n", "Potřebuješ zabít %1 nepřátel.\n") +S("Finished lands required: %1 (collect 10 treasure)\n", + "Potřebuješ dokončit %1 krajů (získat v nich 10 pokladů)\n") + +S("Treasure required: %1 x %2.\n", "Potřebuješ %1 x %2.\n") + +S("Alternatively: kill a %1.\n", "Alternativně: zabij %a1.\n") + +S("Kills required: any Elemental (Living Fjord/Dead Caves).\n", + "Potřebuješ zabít libovolného Elementála (Živoucí fjord/Mrtvé jeskyně).") + +S("Variants of %the1 are always available in the Random Pattern Mode.", + "Varianty kraje '%1' jsou vždy k dispozici v Módu náhodných vzorů.") + +S("Variants of %the1 are available in the Random Pattern Mode after " + "getting a highscore of at least 10 %2.", + "Varianty kraje '%1' jsou dostupné v Módu náhodných vzorů po získání nejméně 10x %2.") + +S(" kills: %1", " zabito nepřátel: %1") +S(" $$$: %1", " $$$: %1") +S(" Hyperstone: %1/%2", " Hyperkamy: %1/%2") +S(" Hell: %1/9", " Peklo: %1/9") + +// improved editor + +S("vector graphics editor -- press F1 for help", "editor vektorové grafiki -- nápovědu zobrazíš stiskem F1") +S("pics to save/load:", "obrázky k uložení/nahrání:") +S("level to save/load:", "mapa k uložení/nahrání:") + +S("F4 = extension", "F4 = rozšíření") +S("Enter = back", "Enter = zpět") +S("SPACE = map/graphics", "SPACE = mapa/grafika") + +S("Emerald Pattern", "Smaragdový vzor") +S("Palace Pattern", "Palácový vzor") +S("Zebra Pattern", "Vzor 'Zebra'") +S("rotational symmetry", "rotační symetrie") +S("symmetry 0-1", "symetrie 0-1") +S("symmetry 0-2", "symetrie 0-2") +S("symmetry 0-3", "symetrie 0-3") + +S("display pattern codes (full)", "zobraz kódy vzoru (úplné)") +S("display pattern codes (simplified)", "zobraz kódy vzoru (zjednodušené)") +S("display only hexagons", "zobraz pouze šestiúhelníky") +S("display only heptagons", "zobraz pouze sedmiúhelníky") +S("predesigned patterns", "předem vytvořené vzory") + +S("Gameboard", "Herní desky") +S("random colors", "náhodné barvy") +S("emerald pattern", "smaragdový vzor") +S("four elements", "čtyři živly") +S("eight domains", "osm domén") +S("zebra pattern", "vzor 'zebra'") +S("three stripes", "tři pásy") +S("random black-and-white", "náhodný černobílý vzor") +S("p = paint", "p = obarvit") +S("r = regular", "r = vzory") + +S( + "In this mode you can draw your own player characters, " + "floors, monsters, and items. Press 'e' while hovering over " + "an object to edit it. Start drawing shapes with 'n', and " + "add extra vertices with 'a'. Press 0-9 to draw symmetric " + "pictures easily. More complex pictures can " + "be created by using several layers ('l'). See the edges of " + "the screen for more keys.", + + "V tomto módu si můžeš nakreslit vlastní postavy, podlahu, netvory " + "a předměty. Objekt můžeš editovat tak, že na něj najedeš myší a " + "stiskneš 'e'. 'n' začne kreslit tvar a 'a' přidává nové vrcholy. " + "Klávesy 0-9 umožňují snadnou kresbu symetrických obrázků. Složitější " + "obrázky je možné vytvořit s použitím ně kolika vrstev ('l'). Další " + "ovládací klávesy můžeš najít na okrajích obrazovky.") + +S( + "Press 'r' to choose a regular pattern. When a pattern is on, " + "editing a cell automatically edits all cells which are " + "equivalent according to this pattern. You can choose from " + "several patterns, and choose which symmetries matter " + "for equivalence. Also, you can press Space to switch between " + "the map and graphics editor quickly -- note that editing floors " + "with the graphics editor also adheres to the pattern.", + + "Stiskem klávesy 'r' můžeš vybrat pravidelný vzor. Když je vzor " + "zapnutý, editace buňky automaticky ovlivní i všechny ostatní buňky, " + "které jsou podle tohoto vzoru ekvivalentní. Můžeš si vybrat " + "z několika možných vzorů, a také to, které symetrie budou důležité " + "pro ekvivalenci. Také můžeš rychle přepínat mezerníkem mezi " + "editorem mapy a grafiky -- i editování podlahy grafickým editorem " + "se řídí pravidly vzoru.") + +S("monster", "netvor") +S("item", "předmět") +S("floor", "podlaha") +S("hexagonal", "šestiúhelníky") +S("heptagonal", "sedmiúhelníky") +S("floor/pattern", "podlaha/vzor") + +S("l = layers: %1", "l = vrstvy: %1") +S("1-9 = rotations: %1", "1-9 = rotace: %1") +S("0 = symmetry", "0 = symetrie") +S("0 = asymmetry", "0 = asymetrie") +S("%1 vertices", "vrcholy: %1") +S("a = add v", "a = přidej v") +S("m = move v", "m = přesuň v") +S("d = delete v", "d = vymaž v") +S("c = readd v", "c = znovu přidej v") +S("b = reorder", "b = změň uspořádání") +S("t = shift", "t = přesuň") +S("y = spin", "y = otoč") + +S("'n' to start", "n = start") +S("z = zoom in", "z = přiblížení") +S("o = zoom out", "o = oddálení") +S("g = grid", "g = síť") +S("e = edit this", "e = editace") + +S("x: %1", "x: %1") +S("y: %1", "y: %1") +S("z: %1", "z: %1") +S("r: %1", "r: %1") +S("ϕ: %1°", "ϕ: %1°") + +S("A fake Land with colored floors.", + "Falešný kraj s barevnou podlahou.") + +S("random pattern mode", "mód náhodných vzorů") + +// Ivory Tower +//============= + +N("Ivory Tower", GEN_F, "Věž ze slonové kosti", "Věže ze slonové kosti", "Věž ze slonové kosti", "ve Věži ze slonové kosti") + +S( + "Powerful wizards claimed this part of the world, to perform their magical " + "experiments in peace and solitude. They have changed the direction of gravity, " + "to make it even harder for intruders to reach them.\n\n" + "Gravity works as follows: cells are unstable if they are empty, and there is " + "no cell immediately below them which contains a wall. It is impossible to move " + "from one unstable cell to another, except if moving down.", + + "Tuto část světa si pro sebe zabrali mocní mágové, aby zde mohli v klidu a osamění " + "provádět své magické experimenty. Změnili směr gravitace, aby bylo pro vetřelce " + "ještě obtížnější se k nim dostat.\n\n" + "Gravitace funguje následovně: prázdné políčko, pod kterým není žádné políčko se zdí, " + "je 'nestabilní'. Není dovoleno pohybovat se z jednoho nestabilního políčka do druhého, " + "leda směrem dolů." + ) + +N("Servant", GEN_M, "Služebník", "Služebníci", "Služebníka", "Služebníkem") +S("A simple servant of the master of the Ivory Tower.", + "Prostý služebník pána Věže ze slonové kosti.") + +N("Gargoyle", GEN_O, "Chrlič", "Chrliče", "Chrlič", "Chrličem") +N("stone gargoyle", GEN_O, "kamenný chrlič", "kamenné chrliče", "kamenného chrliče", "kamenným chrličem") +N("stone gargoyle floor", GEN_F, "podlaha z chrliče", "podlahy z chrličů", "podlahu z chrliče", "podlahou z chrliče") +N("stone gargoyle bridge", GEN_O, "most z chrliče", "mosty z chrličů", "most z chrliče", "mostem z chrliče") + +S( + "A being made of stone, who likes high buildings. It becomes normal stone when " + "killed, but only if next to something stable -- otherwise it falls.", + "Kamenná bytost, která má ráda vysoké budovy. Po smrti se promění v obyčejný kámen, " + "ale pouze tehdy, když je vedle něčeho stabilního -- jinak spadne.") + +N("Ivory Figurine", GEN_F, "Figurka", "Figurky", "Figurku", "Figurkou") + +S("A beautiful figurine, made of ivory. Figurines close to the base of the Tower " + "tend do disappear after you have collected many of them.", + "Nádherná figurka ze slonové kosti. Figurky poblíž základů Věže mají tendenci " + "mizet, pokud jich získáš hodně.") + +N("Platform", GEN_F, "Plošinka", "Plošinky", "Plošinku", "Plošinkou") +S("You can stand here.", "Na této plošince můžeš stát.") + +N("ladder", GEN_O, "žebřík", "žebříky", "žebřík", "žebříkem") +S("You can use this ladder to climb the Tower.", + "Po tomto žebříku můžeš lézt na Věž.") + +Orb("Matter", "Hmoty") + +S("This Orb allows to temporarily create impassable matter, either to block paths or " + "to build bridges across chasms and waters.", + "Tato Sféra ti umožňuje dočasně vytvářet neprostupnou hmotu, kterou můžeš zatarasit " + "cestu nebo využít jako most přes propasti nebo přes vodu.") + +N("temporary wall", GEN_F, "dočasná zeď", "dočasné zdi", "dočasnou zeď", "dočasnou zdí") +N("temporary floor", GEN_F, "dočasná podlaha", "dočasné podlahy", "dočasnou podlahu", "dočasnou podlahou") +N("temporary bridge", GEN_O, "dočasný most", "dočasné mosty", "dočasný most", "dočasným mostem") + +S("This structure will disappear after some time.", "Tato struktura za nějaký čas zmizí.") + +S("Nothing to stand on here!", "Není tu na čem stát!") +S("Gravity does not allow this!", "Tohle ti gravitace nedovolí!") + +// Elemental Planes +//================== + +N("Elemental Planes", GEN_F, "Elementální roviny", "Elementální roviny", "Elementální roviny", "v Elementálních rovinách") +N("Plane of Fire", GEN_F, "Rovina Ohně", "Roviny Ohně", "Rovinu Ohně", "v Rovině Ohně") +N("Plane of Earth", GEN_F, "Rovina Země", "Roviny Země", "Rovinu Země", "v Rovině Země") +N("Plane of Air", GEN_F, "Rovina Vzduchu", "Roviny Vzduchu", "Rovinu Vzduchu", "v Rovině Vzduchu") +N("Plane of Water", GEN_F, "Rovina Vody", "Roviny Vody", "Rovinu Vody", "v Rovině Vody") + +S("The Elemental Planes are divided into four subzones: Planes of Fire, Water, Air, and Earth. " + "You need to collect a Shard from each Plane to construct an Elemental Gem. " + "It is dangerous to collect too many Shards of the same type without constructing a Gem.", + + "Elementální roviny se dělí na čtyři subzóny: Rovinu Ohně, Vody, Vzduchu a Země. " + "Musíš v každé z Rovin najít Úlomek, ze kterých pak vytvoříš Elementální drahokam. " + "Pozor, je nebezpečné mít příliš mnoho Úlomků stejného typu a nepoužít je k sestavení Drahokamu!" + ) + +N("Fire Elemental", GEN_M, "Elementál Ohně", "Elementálové Ohně", "Elementála Ohně", "Elementálem Ohně") + +S("This monster leaves a trail of fire behind.", + "Tento netvor za sebou zanechává ohnivou stopu.") + +N("Air Elemental", GEN_M, "Elementál Vzduchu", "Elementálové Vzduchu", "Elementála Vzduchu", "Elementálem Vzduchu") + +S("An Air Elemental looks like a live tornado. Once you are three (or less) cells from it, " + "it is impossible to move closer, due to strong winds. You can stand and wait, though. " + "This also affects most monsters.", + + "Elementál Vzduchu vypadá jako oživlé tornádo. Pokud jsi od něj tři nebo méně políček, " + "silný vítr ti brání v tom, aby ses k němu přiblížil. Můžeš ovšem stát a čekat. " + "Tento efekt také ovlivňuje většinu netvorů.") + +N("Fire Shard", GEN_O, "Úlomek Ohně", "Úlomky Ohně", "Úlomek Ohně", "Úlomkem Ohně") +N("Air Shard", GEN_O, "Úlomek Vzduchu", "Úlomky Vzduchu", "Úlomek Vzduchu", "Úlomkem Vzduchu") +N("Water Shard", GEN_O, "Úlomek Vody", "Úlomky Vody", "Úlomek Vody", "Úlomkem Vody") +N("Earth Shard", GEN_O, "Úlomek Země", "Úlomky Země", "Úlomek Země", "Úlomkem Země") +N("Elemental Gem", GEN_O, "Elementální drahokam", "Elementální drahokamy", "Elementální drahokam", "Elementálním drahokamem") + +Orb("Summoning", "Vyvolání") + +S( + "This orb allows you to summon monsters. Usually, they are either Elementals or " + "native creatures. While the monsters do not like being summoned, and will " + "attack you once they recover from summoning sickness, such summoning " + "often has its uses.", + "Tato Sféra ti umožňuje vyvolávat netvory. Obvykle se jedná buď o Elementály nebo " + "o domorodé obyvatele kraje, kde ji použiješ. Netvoři nejsou vyvoláním nijak nadšeni " + "a poté, co se zorientují, na tebe zaútočí, ale i tak má vyvolávání často své využití." + ) + +N("limestone wall", GEN_F, "vápencová stěna", "vápencové stěny", "vápencovou stěnu", "vápencovou stěnou") + +S("Simply a wall. Mostly.", "Po prostu ściana. W zasadzie.") + +// Zebra +//======= + +N("Zebra", GEN_F, "Zebra", "Zebry", "Zebru", "v Zebře") +S("Everything in this Land has black and white stripes.", + "Všechno v tomto kraji má černé a bílé pruhy.") + +N("Striped Dog", GEN_M, "Pruhovaný pes", "Pruhovaní psi", "Pruhovaného psa", "Pruhovaným psem") +S("A predator native to the Zebra.", "Predátor pocházející ze Zebry.") + +N("Onyx", GEN_O, "Onyx", "Onyxy", "Onyx", "Onyxem") +S("A black gem with white stripes. It is beautiful.", "Černý drahokam s bílými pásky. Velice krásný.") + +// Crossroads III +//================ + +N("Crossroads III", GEN_F, "Křižovatka III", "Křižovatky III", "Křižovatku III", "na Křižovatc III") + +S("An alternate layout of the Crossroads. Great Walls cross here at right angles.", + "Alternativní uspořádání Křižovatky. Velké zdi se tu protínají v pravých úhlech.") + +// Steam achievements: + +/* + "NEW_ACHIEVEMENT_5_12_NAME" "Došel jsi do Věže ze slonové kosti" + "NEW_ACHIEVEMENT_5_12_DESC" "Najdi a získej Figurku." + "NEW_ACHIEVEMENT_5_13_NAME" "Služebník" + "NEW_ACHIEVEMENT_5_13_DESC" "Získej 10 Figurek." + "NEW_ACHIEVEMENT_5_14_NAME" "Chrlič" + "NEW_ACHIEVEMENT_5_14_DESC" "Získej 25 Figurek." + "NEW_ACHIEVEMENT_5_15_NAME" "Pán Věže" + "NEW_ACHIEVEMENT_5_15_DESC" "Získej 50 Figurek." + "NEW_ACHIEVEMENT_5_16_NAME" "Došel jsi do Zebry" + "NEW_ACHIEVEMENT_5_16_DESC" "Najdi a získej Onyx." + "NEW_ACHIEVEMENT_5_17_NAME" "Pruhovaný pes" + "NEW_ACHIEVEMENT_5_17_DESC" "Získej 10 Onyxů." + "NEW_ACHIEVEMENT_5_18_NAME" "Skvrnitý pes" + "NEW_ACHIEVEMENT_5_18_DESC" "Získej 25 Onyxů." + "NEW_ACHIEVEMENT_5_19_NAME" "Kostkovaný pes" + "NEW_ACHIEVEMENT_5_19_DESC" "Získej 50 Onyxů." + "NEW_ACHIEVEMENT_5_20_NAME" "Elementalista" + "NEW_ACHIEVEMENT_5_20_DESC" "Sestav Elementální drahokam." + "NEW_ACHIEVEMENT_5_21_NAME" "Nižší elementál" + "NEW_ACHIEVEMENT_5_21_DESC" "Sestav 10 Elementálních drahokamů." + "NEW_ACHIEVEMENT_5_22_NAME" "Vyšší elementál" + "NEW_ACHIEVEMENT_5_22_DESC" "Sestav 25 Elementálních drahokamů." + "NEW_ACHIEVEMENT_5_23_NAME" "Pán elementů" + "NEW_ACHIEVEMENT_5_23_DESC" "Sestav 50 Elementálních drahokamů." +*/ + +S("Cannot create temporary matter on a monster!", "Dočasnou hmotu nelze vytvořit na netvorovi!") +S("Cannot create temporary matter on an item!", "Dočasnou hmotu nelze vytvořit na předmětu!") +S("Cannot create temporary matter here!", "Zde nelze vytvořit dočasnou hmotu!") +S("Cannot summon on a monster!", "Na políčko s netvorem nelze nic vyvolat!") +S("No summoning possible here!", "Sem se nic vyvolat nedá!") + +S("You summon %the1!", "Vyvola%l1 jsi %a1!") + +S("F4 = file", "F4 = soubor") + +#undef Orb diff --git a/language-de.cpp b/language-de.cpp index fb684b48..66ff9b58 100644 --- a/language-de.cpp +++ b/language-de.cpp @@ -24,116 +24,131 @@ // (in Polish just 4 of 14 forms are used, and this is probably similar in other // languages). +// Note from Arri: + +// Each noun has its singular form (%1), plural form (%P1), and accusative (%a1) given. +// The types of nouns are GEN_M (masculine), GEN_F (feminine), and GEN_N (neuter). +// For land names, "in/on" is given instead of accusative. + +// %Der1 means Der if GEN_M %der1 is the same, but lowercase (der, die, das) +// Die if GEN_F +// Das if GEN_N + +// %den1 means den if GEN_M +// die if GEN_F +// das if GEN_N + // monsters -N("Icewolf", GEN_M, "Eiswolf", "Eiswölfe", "Eiswolf", "Eiswolf") -N("Ranger", GEN_M, "Wildhüter", "Wildhüter", "Wildhüter", "Wildhüter") -N("Rock Troll", GEN_M, "Höhlentroll", "Höhlentrolle", "Höhlentroll", "Höhlentroll") -N("Goblin", GEN_M, "Höhlen Kobold", "Höhlen Kobolde", "Höhlen Kobold", "Höhlen Kobold") -N("Sand Worm", GEN_M, "Sand-Wurm-Kopf", "Sand-Wurm-Köpfe", "Sand-Wurm-Kopf", "Sand-Wurm-Kopf") -N("Sand Worm Tail", GEN_M, "Sand-Wurm-Schwanz", "Sand-Wurm-Schwänze", "Sand-Wurm-Schwanz", "Sand-Wurm-Schwanz") -N("Sand Worm W", GEN_M, "Sand-Wurm-Kopf W", " Sand-Wurm-Köpfe W", " Sand-Wurm-Kopf W", " Sand-Wurm-Kopf W") -N("Sand Worm M", GEN_M, " Sand-Wurm-Kopf M", "Sand-Wurm-Köpfe M", " Sand-Wurm-Kopf M", " Sand-Wurm-Kopf M") -N("Desert Man", GEN_M, "Wüstenbewohner", "Wüstenbewohner", "Wüstenbewohner", "Wüstenbewohner") -N("Ivy Root", GEN_F, "Efeu Wurzel", "Efeu Wurzeln", "Efeu Wurzel", "Efeu Wurzel") -N("Active Ivy", GEN_M, "Aktywny Bluszcz", "Aktywne Bluszcze", "Aktywny Bluszcz", "Aktywnym Bluszczem") -N("Ivy Branch", GEN_M, "Efeu Zweig", "Efeu Zweige", "Efeu Zweig", "Efeu Zweig") -N("Dormant Ivy", GEN_M, "Ruhende Efeu", "Ruhenden Efeu", "Ruhenden Efeu", "Ruhenden Efeu") -N("Ivy N", GEN_M, "Efeu N", " Efeu N", " Efeu N", "Efeu N") -N("Ivy D", GEN_M, " Efeu D", " Efeu D", " Efeu D", "Efeu D") -N("Giant Ape", GEN_M, "Riesige Menschenaffe", "Riesigen Menschenaffen", "Riesigen Menschenaffe", "Riesigen Menschenaffe") -N("Slime Beast", GEN_M, "Schleim Monster", "Schleim Monster", "Schleim Monster", "Schleim Monster") -N("Mirror Image", GEN_S, "Spiegelbild", "Spiegelbilder", "Spiegelbild", "Spiegelbild") -N("Mirage", GEN_F, "Trugbild", "Trugbilder", "Trugbild", "Trugbild") -N("Golem", GEN_M, "Golem", "Golems", "Golem", "Golem") -N("Eagle", GEN_M, "Adler", "Adler", "Adler", "Adler") -N("Seep", GEN_M, "Sicker", "Sicker", "Sicker", "Sicker") -N("Zombie", GEN_M, "Zombie", "Zombies", "Zombie", "Zombie") -N("Ghost", GEN_M, "Geist", "Geister", "Geist", "Geist") -N("Necromancer", GEN_M, "Totenbeschwörer", "Totenbeschwörer", "Totenbeschwörer", "Totenbeschwörer") -N("Shadow", GEN_M, "Schatten", "Schatten", "Schatten", "Schatten") -N("Tentacle", GEN_M, "Tentakel", "Tentakeln", "Tentakel", "Tentakel") -N("Tentacle Tail", GEN_M, "Tentakel", "Tentakeln", "Tentakel", "Tentakel") -N("Tentacle W", GEN_M, " Tentakel W", " Tentakeln W", " Tentakel W", " Tentakel W") -N("Tentacle M", GEN_M, " Tentakel M", " Tentakeln M", " Tentakel M", " Tentakel M") -N("Cultist", GEN_M, "Okkultist", "Okkultisten", "Okkultist", "Okkultist") -N("Fire Cultist", GEN_M, "Feuer Kultist", "Feuer Kultisten", "Feuer Kultist", "Feuer Kultist") -N("Greater Demon", GEN_M, "Grosser Demon", "Grossen Demonen", "Grossen Demon", "Grossen Demon") -N("Lesser Demon", GEN_M, "Kleine Demon", "Kleinen Demonen", "Kleinen Demon", "Kleinen Demon") -N("Ice Shark", GEN_M, "Eishai", "Eishaie", "Eishai", "Eishai") -N("Running Dog", GEN_M, "Rennende Hund", "Rennenden Hunde", "Rennenden Hund", "Rennenden Hund") -N("Demon Shark", GEN_M, "Demonenhai", "Demonenhaie", "Demonenhai", "Demonenhai") -N("Fire Fairy", GEN_F, "Feuerfee", "Feuerfeen", "Feuerfee", "Feuerfee") -N("Crystal Sage", GEN_M, "Krytsal Weiser", "Krytsal Weisen", "Krytsal Weisen", "Krytsal Weisen") -N("Hedgehog Warrior", GEN_M, "Igelkrieger", "Igelkrieger", "Igelkrieger", "Igelkrieger") -N("Tentacle (withdrawing)", GEN_M, "Tentakel (zurückziehend)", "Tentakeln (zurückziehend)", "Tentakel (zurückziehend)", "Tentakel (zurückziehend)" +N("Icewolf", GEN_M, "Eiswolf", "Eiswölfe", "Eiswolf") +N("Yeti", GEN_M, "Yeti", "Yetis", "Yeti") +N("Ranger", GEN_M, "Wildhüter", "Wildhüter", "Wildhüter") +N("Rock Troll", GEN_M, "Höhlentroll", "Höhlentrolle", "Höhlentroll") +N("Goblin", GEN_M, "Höhlen-Kobold", "Höhlen-Kobolde", "Höhlen-Kobold") +N("Sand Worm", GEN_M, "Sandwurm-Kopf", "Sandwurm-Köpfe", "Sandwurm-Kopf") +N("Sand Worm Tail", GEN_M, "Sandwurm-Schwanz", "Sandwurm-Schwänze", "Sandwurm-Schwanz") +N("Sand Worm W", GEN_M, "Sandwurm-Kopf W", "Sandwurm-Köpfe W", "Sandwurm-Kopf W") +//N("Sand Worm M", GEN_M, "Sandwurm-Kopf M", "Sandwurm-Köpfe M", "Sandwurm-Kopf M") +N("Desert Man", GEN_M, "Wüstenbewohner", "Wüstenbewohner", "Wüstenbewohner") +N("Ivy Root", GEN_F, "Efeu-Wurzel", "Efeu-Wurzeln", "Efeu-Wurzel") +N("Active Ivy", GEN_M, "Aktiver Efeu", "Aktive Efeu", "Aktiven Efeu") +N("Ivy Branch", GEN_M, "Efeu-Zweig", "Efeu-Zweige", "Efeu-Zweig") +N("Dormant Ivy", GEN_M, "Ruhender Efeu", "Ruhende Efeu", "Ruhenden Efeu") +N("Ivy N", GEN_M, "Efeu N", "Efeu N", "Efeu N") +N("Ivy D", GEN_M, " Efeu D", "Efeu D", "Efeu D") +N("Giant Ape", GEN_M, "Riesiger Menschenaffe", "Riesige Menschenaffen", "Riesigen Menschenaffen") +N("Slime Beast", GEN_M, "Schleim-Monster", "Schleim-Monster", "Schleim-Monster") +N("Mirror Image", GEN_N, "Spiegelbild", "Spiegelbilder", "Spiegelbild") +N("Mirage", GEN_N, "Trugbild", "Trugbilder", "Trugbild") +N("Golem", GEN_M, "Golem", "Golems", "Golem") +N("Eagle", GEN_M, "Adler", "Adler", "Adler") +N("Seep", GEN_M, "Sicker", "Sicker", "Sicker") +N("Zombie", GEN_M, "Zombie", "Zombies", "Zombie") +N("Ghost", GEN_M, "Geist", "Geister", "Geist") +N("Necromancer", GEN_M, "Totenbeschwörer", "Totenbeschwörer", "Totenbeschwörer") +N("Shadow", GEN_M, "Schatten", "Schatten", "Schatten") +N("Tentacle", GEN_M, "Tentakel", "Tentakel", "Tentakel") +N("Tentacle Tail", GEN_M, "Tentakel", "Tentakel", "Tentakel") +N("Tentacle W", GEN_M, " Tentakel W", " Tentakel W", " Tentakel W") +//N("Tentacle M", GEN_M, " Tentakel M", " Tentakel M", " Tentakel M") +N("Cultist", GEN_M, "Okkultist", "Okkultisten", "Okkultist") +N("Fire Cultist", GEN_M, "Feuer-Okkultist", "Feuer-Okkultisten", "Feuer-Okkultist") +N("Greater Demon", GEN_M, "Großer Dämon", "Großen Dämonen", "Großen Dämon") +N("Lesser Demon", GEN_M, "Kleiner Dämon", "Kleine Dämonen", "Kleinen Dämon") +N("Ice Shark", GEN_M, "Eishai", "Eishaie", "Eishai") +N("Running Dog", GEN_M, "Rennender Hund", "Rennende Hunde", "Rennenden Hund") +N("Demon Shark", GEN_M, "Dämonenhai", "Dämonenhaie", "Dämonenhai") +N("Fire Fairy", GEN_F, "Feuerfee", "Feuerfeen", "Feuerfee") +N("Crystal Sage", GEN_M, "Kristall-Weiser", "Kristall-Weise", "Kristall-Weisen") +N("Hedgehog Warrior", GEN_M, "Igelkrieger", "Igelkrieger", "Igelkrieger") +N("Tentacle (withdrawing)", GEN_M, "Zurückziehender Tentakel", "Zurückziehende Tentakel", "Zurückziehenden Tentakel") // items -N("Ice Diamond", GEN_M, "Eisdiamant", "Eisdiamanten", "Eisdiamant", "Eisdiamant") -N("Gold", GEN_S, "Gold", "-", "Gold", "Gold") -N("Spice", GEN_S, "Gewürz", "Gewürze", "Gewürz", "Gewürz") -N("Ruby", GEN_M, "Rubin", "Rubine", "Rubin", "Rubin") -N("Elixir of Life", GEN_S, "Elixier des lebens", "Elixiere des lebens", "Elixier des lebens", "Elixier des lebens") -N("Shard", GEN_F, "Scherbe", "Scherben", "Scherbe", "Scherbe") -N("Necromancer's Totem", GEN_M, "Toten-Stab", "Toten-Stäbe", "Toten-Stab", "Toten-Stab") -N("Demon Daisy", GEN_S, "Demonenblümchen", "Demonenblümchen", "Demonenblümchen", "Demonenblümchen") -N("Statue of Cthulhu", GEN_F, "Statue von Cthulhu", "Statuen von Cthulhu", "Statue von Cthulhu", "Statue von Cthulhu") -N("Phoenix Feather", GEN_N, "Feder des Phönix", "Feder des Phönix", "Feder des Phönix", "Feder des Phönix") -N("Ice Sapphire", GEN_M, "Eissaphir", "Eissaphire", "Eissaphir", "Eissaphir") -N("Hyperstone", GEN_M, "Hyperstein", "Hypersteine", "Hyperstein", "Hyperstein") -N("Key", GEN_M, "Schlüssel", "Schlüssel", "Schlüssel", "Schlüssel") -N("Dead Orb", GEN_F, "Tote Perle", "Tote Perlen", "Tote Perle", "Tote Perle") -N("Fern Flower", GEN_F, "Farnblüte", "Farnblüten", "Farnblüte", "Farnblüte") -N("Orb of Yendor", GEN_F, "Perle von Yendor", "Perlen von Yendor", "Perle von Yendor", "Perle von Yendor") +N("Ice Diamond", GEN_M, "Eisdiamant", "Eisdiamanten", "Eisdiamanten") +N("Gold", GEN_N, "Gold", "Gold", "Gold") +N("Spice", GEN_N, "Gewürz", "Gewürze", "Gewürz") +N("Ruby", GEN_M, "Rubin", "Rubine", "Rubin") +N("Elixir of Life", GEN_N, "Elixier des Lebens", "Elixiere des Lebens", "Elixier des Lebens") +N("Shard", GEN_F, "Scherbe", "Scherben", "Scherbe") +N("Necromancer's Totem", GEN_N, "Totem der Toten", "Totems der Toten", "Totem der Toten") +N("Demon Daisy", GEN_N, "Dämonenblümchen", "Dämonenblümchen", "Dämonenblümchen") +N("Statue of Cthulhu", GEN_F, "Statue von Cthulhu", "Statuen von Cthulhu", "Statue von Cthulhu") +N("Phoenix Feather", GEN_F, "Phönix-Feder", "Phönix-Federn", "Phönix-Feder") +N("Ice Sapphire", GEN_M, "Eis-Saphir", "Eis-Saphire", "Eis-Saphir") +N("Hyperstone", GEN_M, "Hyperstein", "Hypersteine", "Hyperstein") +N("Key", GEN_M, "Schlüssel", "Schlüssel", "Schlüssel") +N("Dead Orb", GEN_F, "Tote Perle", "Tote Perlen", "Tote Perle") +N("Fern Flower", GEN_F, "Farnblüte", "Farnblüten", "Farnblüte") +N("Orb of Yendor", GEN_F, "Perle von Yendor", "Perlen von Yendor", "Perle von Yendor") // orbs: we are using a macro here -#define Orb(E, P) N("Orb of "E, GEN_F, "Perle "D, "Perlen "D, "Perle"D, "Perle"D) +#define Orb(E, P) N("Orb of "E, GEN_F, "Perle "P, "Perlen "P, "Perle "P) Orb("Storms", "des Donners") Orb("Flash", "des Blitzes") Orb("Winter", "des Winters") Orb("Speed", "der Geschwindigkeit") Orb("Life", "des Lebens") Orb("Shielding", "des Schutzes") -Orb("Teleport", "des Teleportierens") +Orb("Teleport", "des Teleports") Orb("Safety", "der Sicherheit") Orb("Thorns", "der Dornen") // terrain features -N("none", GEN_O, "keines", "keines", "keines", "keines") -N("ice wall", GEN_F, "Eiswand", "Eiswände", "Eiswand", "Eiswand") -N("great wall", GEN_F, "Grosse Mauer", "Grosse Mauern", "Grosse Mauer", "Grosse Mauer") -N("red slime", GEN_F, "roter Schleim", "rote Schleime", "roten Schleim", "roten Schleim") -N("blue slime", GEN_F, "blaue Schleim", "blauen Schleime", "blauen Schleim", "blauen Schleim") -N("living wall", GEN_F, "Lebende Wand", "Lebenden Wände", "Lebende Wand", "Lebenden Wand") -N("living floor", GEN_M, "Lebende Boden", "Lebenden Böden", "Lebenden Boden", "Lebenden Boden") -N("dead troll", GEN_M, "tote Troll" ,"toten Trolle", "toten Troll", "toten Troll") -N("sand dune", GEN_F, "Sanddüne", "Sanddünen", "Sanddüne", "Sanddüne") -N("Magic Mirror", GEN_M, "Magische Spiegel", "Magischen Spiegel", "Magischen Spiegel", "Magischen Spiegel") -N("Cloud of Mirage", GEN_F, "Wolke des Trugbildes", "Wolken der Trugbilder", "Wolke des Trugbildes", "Wolke des Trugbildes") -N("Thumper", GEN_M, "Pseudoschild", "Pseudoschilde", "Pseudoschild", "Pseudoschild") -N("Bonfire", GEN_N, "Feuer", "Feuer", "Feuer", "Feuer") -N("ancient grave", GEN_S, "alte Grab", "alten Gräb", "alten Grab", "alten Grab") -N("fresh grave", GEN_S, "frische Grab", "frischen Gräber", "frischen Grab", "frischen Grab") -N("column", GEN_F, "Säule", "Säule", "Säule", "Säule") -N("lake of sulphur", GEN_M, "Schwefelsee", "Schwefelseen", "Schwefelsee", "Schwefelsee") -N("lake", GEN_M, "See", "Seen", "See", "See") -N("frozen lake", GEN_M, "gefrorene See", "gefrorenen Seen", "gefrorenen See", "gefrorenen See") -N("chasm", GEN_M, "Abgrund", "Abgründe", "Abgrund", "Abgrund") -N("big tree", GEN_N, "grosser Baum", "grossen Bäume", "grossen Baum", "grossen Baum") -N("tree", GEN_N, "Baum", "Bäume", "Baum", "Baum") +N("none", GEN_N, "keines", "keines", "keines") +N("ice wall", GEN_F, "Eiswand", "Eiswände", "Eiswand") +N("great wall", GEN_F, "Große Mauer", "Große Mauern", "Große Mauer") +N("red slime", GEN_M, "Roter Schleim", "Rote Schleime", "Roten Schleim") +N("blue slime", GEN_M, "Blaue Schleim", "Blaue Schleime", "Blauen Schleim") +N("living wall", GEN_F, "Lebende Wand", "Lebende Wände", "Lebende Wand") +N("living floor", GEN_M, "Lebender Boden", "Lebende Böden", "Lebenden Boden") +N("dead troll", GEN_M, "Toter Troll" ,"Tote Trolle", "Toten Troll") +N("sand dune", GEN_F, "Sanddüne", "Sanddünen", "Sanddüne") +N("Magic Mirror", GEN_M, "Magischer Spiegel", "Magische Spiegel", "Magischen Spiegel") +N("Cloud of Mirage", GEN_F, "Trugbild-Wolke", "Trugbild-Wolken", "Trugbild-Wolke") +N("Thumper", GEN_M, "Thumper", "Thumper", "Thumper") +N("Bonfire", GEN_N, "Feuer", "Feuer", "Feuer") +N("ancient grave", GEN_N, "Altes Grab", "Alte Gräber", "Alte Grab") +N("fresh grave", GEN_N, "Frisches Grab", "Frische Gräber", "Frische Grab") +N("column", GEN_F, "Säule", "Säulen", "Säule") +N("lake of sulphur", GEN_M, "Schwefelsee", "Schwefelseen", "Schwefelsee") +N("lake", GEN_M, "See", "Seen", "See") +N("frozen lake", GEN_M, "gefrorener See", "gefrorene Seen", "gefrorenen See") +N("chasm", GEN_M, "Abgrund", "Abgründe", "Abgrund") +N("big tree", GEN_N, "Großer Baum", "Große Bäume", "Großen Baum") +N("tree", GEN_N, "Baum", "Bäume", "Baum") // lands -N("great wall", GEN_F, "Grosse Mauer", "Grosse Mauern", "Grosse Mauer", "Grosse Mauer") -N("Crossroads", GEN_F, "Kreuzung", "Kreuzungen", "Kreuzung", "Kreuzung") -N("Desert", GEN_F, "Wüste", "Wüste", "Wüste", "Wüste") -N("Icy Land", GEN_N, "eisige Land", "eisigen Länder", "eisigen Land", "eisigen Land") -N("living wall", GEN_F, "Lebende Wand", "Lebenden Wände", "Lebende Wand", "Lebenden Wand") -N("Jungle", GEN_M, "Jungel", "Jungeln", "Jungel", "Jungel") -N("Alchemist Lab", GEN_N, "Labor", "Labore", "Labor", "Labor") -N("Mirror Land", GEN_N, "Spiegelland", "Spiegelländer", "Spiegelland", "Spiegelland") -N("Graveyard", GEN_M, "Friedhof", "Friedhöffe", "Friedhof", "Friedhof") -N("R'Lyeh", GEN_N, "R'Lyeh", "R'Lyeh", "R'Lyeh", " R'Lyeh") -N("Hell", GEN_F, "Hölle", "Höllen", "Hölle", "Hölle") -N("Cocytus", GEN_M, "Kocyt", "Kocyt", "Kocytu", "w Kocycie") -N("Land of Eternal Motion", GEN_N, "Land der ewigen Bewegung", "Länder der ewigen Bewegung", "Land der ewigen Bewegung", "Land der ewigen Bewegung") -N("Dry Forest", GEN_M, "trockene Wald", "trockenen Wälder", "trockenen Wald", "trockenen Wald") -N("Game Board", GEN_N, "Spielbrett", "Spielbretter", "Spielbrett", "Spielbrett") +N("Great Wall", GEN_F, "Große Mauer", "Große Mauern", "auf der Großen Mauer") +N("Crossroads", GEN_F, "Kreuzung", "Kreuzungen", "auf der Kreuzung") +N("Desert", GEN_F, "Wüste", "Wüste", "in der Wüste") +N("Icy Land", GEN_N, "Eisiges Land", "Eisige Länder", "im Eisigen Land") +N("Living Cave", GEN_F, "Lebende Höhle", "Lebende Höhlen", "in der Lebenden Höhle") +N("Jungle", GEN_M, "Dschungel", "Dschungel", "im Dschungel") +N("Alchemist Lab", GEN_N, "Labor", "Labor", "im Labor") +N("Mirror Land", GEN_N, "Land der Spiegel", "Länder der Spiegel", "im Land der Spiegel") +N("Graveyard", GEN_M, "Friedhof", "Friedhöfe", "im Friedhof") +N("R'Lyeh", GEN_N, "R'Lyeh", "R'Lyeh", "in R'Lyeh") +N("Hell", GEN_F, "Hölle", "Höllen", "in der Hölle") +N("Cocytus", GEN_M, "Kokytos", "Kokytos", "im Kokytos") +N("Land of Eternal Motion", GEN_N, "Land der Bewegung", "Länder der Bewegung", "im Land der Bewegung") +N("Dry Forest", GEN_M, "Trockener Wald", "Trockene Wälder", "im Trockenen Wald") +N("Game Board", GEN_N, "Spielbrett", "Spielbretter", "auf dem Spielbrett") // Game messages @@ -147,288 +162,290 @@ N("Game Board", GEN_N, "Spielbrett", "Spielbretter", "Spielbrett", "Spielbrett") // %Å‚1 is replaced by "Å‚", "Å‚o" or "Å‚a", depending on the gender of %1 // %Å‚eÅ›0 adds "Å‚eÅ›" or "Å‚aÅ›" depending on the gender of the player +// Each noun has its singular form (%1), plural form (%P1), and accusative (%a1) given. + // Use whatever %xxx# codes you need for your language. Of course, // tell me how your codes should be expanded. -S("You kill the %1.", "Du tötest %den1 %a1.") -S("You would be killed by the %1!", "Du würdest von %den1 %a1 getötet werden!") -S("The %1 would get you!", "%Der1 %n1 würde dich fangen!") -S("The %1 destroys the %2!", "%Der1 %n1 zerstört %den2 %a2!") -S("The %1 eats the %2!", "%Der1 %n1 frisst %den2 %a2!") -S("The ivy destroys the %1!", "Das Efeu zerstört %den1 %a1!") -S("The %1 claws the %2!", "%Der1 %n1 kratzt %den2 %a2!") -S("The %1 scares the %2!", "%Der1 %n1 erschreckt %den2 %a2!") -S("The %1 melts away!", "%Der1 %n1 schmilzt!") -S("The %1 stabs the %2.", "%Der1 %n1 ersticht %den2 %a2.") -S("You stab the %1.", "Du erstichst %den1 %a1.") +S("You kill %the1.", "Du tötest %den1 %a1.") +S("You would be killed by %the1!", "%Der1 %1 würde dich töten!") +S("%The1 would get you!", "%Der1 %1 würde dich fangen!") +S("%The1 destroys %the2!", "%Der1 %1 zerstört %den2 %a2!") +S("%The1 eats %the2!", "%Der1 %1 frisst %den2 %a2!") +S("The ivy destroys %the1!", "Der Efeu zerstört %den1 %a1!") +S("%The1 claws %the2!", "%Der1 %1 kratzt %den2 %a2!") +S("%The1 scares %the2!", "%Der1 %1 erschreckt %den2 %a2!") +S("%The1 melts away!", "%Der1 %1 schmilzt!") +S("%The1 stabs %the2.", "%Der1 %1 ersticht %den2 %a2.") +S("You stab %the1.", "Du erstichst %den1 %a1.") -S("You cannot attack the %1 directly!", "Du kannst %den1 %a1 nicht direkt angreifen!") -S("Stab them by walking around them.", "Ersteche sie indem du um sie herumläufst.") +S("You cannot attack %the1 directly!", "Du kannst %den1 %a1 nicht direkt angreifen!") +S("Stab them by walking around them.", "Ersteche ihn, indem du um ihn herumläufst.") -S("You feel more experienced in demon fighting!", "Du fühlst dich besser erfahren in Dämonenbekämpfung!") +S("You feel more experienced in demon fighting!", "Du fühlst dich besser im Dämonen bekämpfen!") S("Cthulhu withdraws his tentacle!", "Cthulhu zieht sein Tentakel zurück!") -S("The sandworm explodes in a cloud of Spice!", "Der Sandwurm explodiert in eine Wolke von Gewürzen!") -S("The %1 is confused!", "%Der1 %n1 ist verwirrt.") -S("The %1 raises some undead!", "%Der1 %n1 erweckt die Toten!") -S("The %1 throws fire at you!", "%Der1 n1 wirft Feuer nach dir!") -S("The %1 shows you two fingers.", "%Der1 %n1 zeigt dir zwei Finger.") -S("You wonder what does it mean?", "Du wunderst dich was es bedeutet.") -S("The %1 shows you a finger.", "%Der1 %n1 zeigt dir ein Finger.") -S("You think about possible meanings.", "Du denkst über mögliche Bedeutungen.") -S("The %1 moves his finger downwards.", "%Der1 %n1 bewegt sein Finger nach unten.") -S("Your brain is steaming.", "Dein Hirn dampft.") -S("The %1 destroys the %2!", "%Der1 %n1 zerstört %den2 %a2!") -S("You join the %1.", "PoÅ‚Ä…czy%Å‚eÅ›0 siÄ™ z %abl1.") -S("Two of your images crash and disappear!", "Zwei %np1 stürzen gegeneinander!") -S("The %1 breaks the mirror!", "%Der1 %n1 zerstört den Spiegel!") -S("The %1 disperses the cloud!", "%Der1 %n1 verstreut die Wolke!") -S("You activate the Flash spell!", "Du aktivierst den Blitzzauber!") -S("You activate the Lightning spell!", "Du aktivierst den Donnerzauber!") -S("Ice below you is melting! RUN!", "Das Eis unter dir schmilzt! RENNE!") -S("This spot will be burning soon! RUN!", "Dieser Ort wird bald brennen! RENNE!") -S("The floor has collapsed! RUN!", "Der Boden ist zusammengebrochen! RENNE!") +S("The sandworm explodes in a cloud of Spice!", "Der Sandwurm explodiert in einer Wolke von Gewürzen!") +S("%The1 is confused!", "%Der1 %1 ist verwirrt.") +S("%The1 raises some undead!", "%Der1 %1 erweckt die Toten!") +S("%The1 throws fire at you!", "%Der1 %1 wirft Feuer nach dir!") +S("%The1 shows you two fingers.", "%Der1 %1 zeigt dir zwei Finger.") +S("You wonder what does it mean?", "Du wunderst dich, was es bedeutet...") +S("%The1 shows you a finger.", "%Der1 %1 zeigt dir einen Finger.") +S("You think about possible meanings.", "Du denkst über mögliche Bedeutungen nach...") +S("%The1 moves his finger downwards.", "%Der1 %1 bewegt seinen Finger nach unten.") +S("Your brain is steaming.", "Dein Hirn dampft!") +S("%The1 destroys %the2!", "%Der1 %1 zerstört %den2 %a2!") +S("You join %the1.", "Du führst die %P1 zusammen.") +S("Two of your images crash and disappear!", "Zwei %P1 stürzen gegeneinander!") +S("%The1 breaks the mirror!", "%Der1 %1 zerstört den Spiegel!") +S("%The1 disperses the cloud!", "%Der1 %1 verstreut die Wolke!") +S("You activate the Flash spell!", "Du aktivierst den Blitz-Zauber!") +S("You activate the Lightning spell!", "Du aktivierst den Donner-Zauber!") +S("Ice below you is melting! RUN!", "Das Eis unter dir schmilzt - LAUF!") +S("This spot will be burning soon! RUN!", "Dieser Ort wird bald brennen - LAUF!") +S("The floor has collapsed! RUN!", "Der Boden ist zusammengebrochen - LAUF!") S("You need to find the right Key to unlock this Orb of Yendor!", - "Du musst den richtigen Schlüssel finden um die Perle von Yendor zu öffnen!") + "Du musst den richtigen Schlüssel finden, um die Perle von Yendor zu öffnen!") S("You fall into a wormhole!", "Du fällst in ein Wurmloch!") -S("You activate the %1.", "Du aktivierst %den1 %a1.") -S("No room to push the %1.", "Kein Raum um %den1 %a1 zu schieben.") -S("You push the %1.", "Du schiebst %den1 %a1.") -S("You start cutting down the tree.", "Du fängst an den Baum zu schneiden.") +S("You activate %the1.", "Du aktivierst %den1 %a1.") +S("No room to push %the1.", "Kein Platz um %den1 %a1 zu schieben.") +S("You push %the1.", "Du schiebst %den1 %a1.") +S("You start cutting down the tree.", "Du fängst an, den Baum zu schneiden.") S("You cut down the tree.", "Du schneidest den Baum.") S("You cannot attack Sandworms directly!", "Du kannst Sandwürmer nicht direkt angreifen!") -S("You cannot attack Tentacles directly!", "Du kannst Tentakeln nicht direkt angreifen!") +S("You cannot attack Tentacles directly!", "Du kannst Tentakel nicht direkt angreifen!") S("You cannot defeat the Shadow!", "Du kannst den Schatten nicht besiegen!") -S("You cannot defeat the Greater Demon yet!", "Du kannst den Grossen Demon noch nicht besiegen!") +S("You cannot defeat the Greater Demon yet!", "Du kannst den Großen Dämon noch nicht besiegen!") S("That was easy, but groups could be dangerous.", "Das war einfach, aber Gruppen könnten gefährlich sein.") -S("Good to know that your fighting skills serve you well in this strange world.", "Gut zu wissen das deine Kampfkünste dir in dieser ungewöhnlichen Welt gut helfen.") -S("You wonder where all these monsters go, after their death...", "Du wunderst dich wo all diese Monster nach ihrem Tot hingehen...") +S("Good to know that your fighting skills serve you well in this strange world.", "Gut zu wissen, dass deine Kampfkünste dir in dieser ungewöhnlichen Welt helfen.") +S("You wonder where all these monsters go, after their death...", "Du wunderst dich, wo all diese Monster nach ihrem Tod hingehen...") S("You feel that the souls of slain enemies pull you to the Graveyard...", "Du hast das Gefühl, dass die Seelen gefallener Gegner dich zum Friedhof führen...") S("Wrong color!", "Falsche Farbe!") -S("You cannot move through the %1!", "Du kannst nicht durch %den1 %a1 gehen!") -S("The %1 would kill you there!", "%Der1 %n1 würde dich dort töten!") -S("Wow! %1! This trip should be worth it!", "Wow, %n1! Dieser trip sollte es Wert sein!") -S("For now, collect as much treasure as possible...", "Für jetzt, sammle so viele Schätze wie möglich ein...") -S("Prove yourself here, then find new lands, with new quests...", "Beweise dich hier, finde dann neue Länder, mit neuen Herausforderungen...") +S("You cannot move through %the1!", "Du kannst nicht durch %den1 %a1 gehen!") +S("%The1 would kill you there!", "%Der1 %1 würde dich dort töten!") +S("Wow! %1! This trip should be worth it!", "Wow, %1! Diese Reise sollte es wert sein!") +S("For now, collect as much treasure as possible...", "Aber sammle vorerst so viele Schätze wie möglich ein.") +S("Prove yourself here, then find new lands, with new quests...", "Beweise dich hier - dann suche neue Länder, mit neuen Herausforderungen...") S("You collect your first %1!", "Du sammelst dein erstes %a1 ein!") S("You have found the Key! Now unlock this Orb of Yendor!", "Du hast den Schlüssel gefunden! Jetzt musst du die Perle von Yendor finden und öffnen!") S("This orb is dead...", "Diese Perle ist tot...") -S("Another Dead Orb.", "Eine weitere tote Perle.") -S("You have found the %1!", "Du hast %den1 %a1 gefunden!") -S("You feel that the %2 becomes more dangerous.", "Du spürst, dass %der2 %n2 gefährlicher wird.") -S("With each %1 you collect...", "Mit...") -S("Are there any magical orbs in the %1?...", "Gibt es irgenwelche magischen Perlen in %dem1 %d1?") -S("You feel that the %1 slowly becomes dangerous...", "Du spürst wie %der1 %n1 langsam gefährlich wird...") +S("Another Dead Orb.", "Noch eine tote Perle.") +S("You have found %the1!", "Du hast %den1 %a1 gefunden!") +S("You feel that %the2 become%s2 more dangerous.", "Du spürst, dass %der2 %2 gefährlicher wird,") +S("With each %1 you collect...", "mit jedem %a1, das du sammelst...") +S("Are there any magical orbs in %the1?...", "Gibt es irgendwelche magischen Perlen in %dem1 %d1?") +S("You feel that %the1 slowly become%s1 dangerous...", "Du spürst wie %der1 %1 langsam gefährlich wird...") S("Better find some other place.", "Such dir lieber einen anderen Ort.") -S("You have a vision of the future, fighting demons in Hell...", "Masz wizjÄ™ przyszÅ‚oÅ›ci, w której walczysz z demonami w Piekle...") -S("With this Elixir, your life should be long and prosperous...", "Mit diesem Elixir sollte dein Leben lang und wohlhabend sein...") -S("The Necromancer's Totem contains hellish incantations...", "Der Toten-stab enthält höllische Zauberformeln...") +S("You have a vision of the future, fighting demons in Hell...", "Du hast eine Vision der Zukunft... du bekämpfst Dämonen in der Hölle...") +S("With this Elixir, your life should be long and prosperous...", "Mit diesem Elixier sollte dein Leben lang und wohlhabend sein...") +S("The Necromancer's Totem contains hellish incantations...", "Das Totem der Toten enthält höllische Zauberformeln...") S("The inscriptions on the Statue of Cthulhu point you toward your destiny...", "Die Gravuren auf der Statue von Cthulhu erzählen von deinen Schicksal...") -S("Still, even greater treasures lie ahead...", "Trotzdem, es erwarten dich immer noch grössere Schätze...") -S("You collect the %1.", "Du sammelst %den1 %a1.") +S("Still, even greater treasures lie ahead...", "Und dennoch erwarten dich immer grössere Schätze...") +S("You collect %the1.", "Du sammelst %den1 %a1.") S("CONGRATULATIONS!", "GLÜCKWUNSCH!") -S("Collect treasure to access more different lands...", "Sammle Schätze ein um neue Länder zu erreichen...") -S("You feel that you have enough treasure to access new lands!", "Du hast das Gefühl, dass du genug Schätze hast um neue Länder zu erreichen!") -S("Collect more treasures, there are still more lands waiting...", "Sammle mehr Schätze ein, es gibt immer noch Länder welche auf dich warten...") -S("You feel that the stars are right, and you can access R'Lyeh!", "Du hast das Gefühl, dass die Sterne richtig angeordnet sind und R'Lyeh erreichen kannst!") -S("Kill monsters and collect treasures, and you may get access to Hell...", "Töte Monster und sammle Schätzte ein, und vielleicht kriegst du Zugang zur Hölle...") -S("To access Hell, collect 10 treasures each of 9 kinds...", "Um die Hölle zu erreichen, sammle 10 Schätze in 9 verschiedene Ländern...") -S("Abandon all hope, the gates of Hell are opened!", "Gib alle Hoffnung auf, die Tore zur Hölle sind offen!") +S("Collect treasure to access more different lands...", "Sammle Schätze ein, um neue Länder zu erreichen...") +S("You feel that you have enough treasure to access new lands!", "Du hast das Gefühl, dass du genug Schätze hast, um neue Länder zu erreichen!") +S("Collect more treasures, there are still more lands waiting...", "Sammle mehr Schätze ein, es gibt immer noch Länder, die nur auf dich warten...") +S("You feel that the stars are right, and you can access R'Lyeh!", "Du hast das Gefühl, dass die Sterne richtig geordnet sind... und du R'Lyeh erreichen kannst!") +S("Kill monsters and collect treasures, and you may get access to Hell...", "Töte Monster und sammle Schätze ein - vielleicht kannst du zur Hölle...") +S("To access Hell, collect 10 treasures each of 9 kinds...", "Um die Hölle zu erreichen, sammle 10 Schätze von 9 Arten...") +S("Abandon all hope, the gates of Hell are opened!", "Gib alle Hoffnung auf - die Tore zur Hölle sind offen!") S("And the Orbs of Yendor await!", "Und die Perlen von Yendor erwarten dich!") -S("You switch places with the %1.", "Du tauscht Plätze mit .") +S("You switch places with %the1.", "Du tauscht Plätze mit %dem %a1.") -S("You rejoin %the1.", "Połączy%łeś1 się z %abl1.") -S("The mirror shatters!", "Lustro pęka!") -S("The cloud turns into a bunch of images!", "Chmura zamienia się w obrazy!") -S("The slime reacts with %the1!", "Maź reaguje z %abl1!") -S("You drop %the1.", "Porzuci%łeś0 %a1.") -S("You feel great, like a true treasure hunter.", "Czujesz się świenie, jak prawdziwy łowca skarbów.") -S("Your eyes shine like gems.", "Twoje oczy błyszczą jak klejnoty.") -S("Your eyes shine as you glance at your precious treasures.", "Twoje oczy błyszczą, gdy patrzysz na swoje skarby.") -S("You glance at your great treasures.", "Patrzysz na swoje wspaniałe skarby.") -S("You glance at your precious treasures.", "Patrzysz na swoje drogocenne skarby.") -S("You glance at your precious treasure.", "Patrzysz na swój drogocenny skarb.") -S("Your inventory is empty.", "Nie masz żadnych skarbów.") -S("You teleport to a new location!", "Teleportujesz się do nowego miejsca!") -S("Could not open the score file: ", "Nie udało się otworzyć pliku: ") -S("Game statistics saved to %1", "Statystyki gry zapisane do %1") -S("Game loaded.", "Gra odczytana.") -S("You summon some Mimics!", "Przywoła%łeś0 Miraże!") -S("You summon a golem!", "Przywoła%łeś0 Golema!") -S("You will now start your games in %1", "Będziesz zaczynał grę %abl1") -S("Activated the Hyperstone Quest!", "Aktywowałeś Misję Hiperkamień!") -S("Orb power depleted!", "Zabrano sfery mocy!") -S("Orbs summoned!", "Sfery mocy przywołane!") -S("Orb power gained!", "Zdobyta moc!") -S("Dead orbs gained!", "Zdobyte Martwe Sfery!") -S("Orb of Yendor gained!", "Zdobyta Sfera Yendoru!") -S("Treasure gained!", "Skarb zdobyty!") -S("Lots of treasure gained!", "Mnóstwo skarbów zdobyte!") -S("You summon a sandworm!", "Przywoła%łeś0 Czerwia!") -S("You summon an Ivy!", "Przywoła%łeś0 Bluszcz!") -S("You summon a monster!", "Przywoła%łeś0 potwora!") -S("You summon some Thumpers!", "Przywoła%łeś0 dudniki!") -S("You summon a bonfire!", "Przywoła%łeś0 ognisko!") -S("Treasure lost!", "Skarb utracony!") -S("Kills gained!", "Zdobyto trupy!") -S("Activated Orb of Safety!", "Aktywowano Sferę Bezpieczeństwa!") -S("Teleported to %1!", "Przeniesiono w %abl1") +S("You rejoin %the1.", "Du vereinst %die1 %a1.") +S("The mirror shatters!", "Der Spiegel zerbricht!") +S("The cloud turns into a bunch of images!", "Die Wolke wandelt sich zu vielen Bildern!!") +S("The slime reacts with %the1!", "Der Schleim reagiert mit %dem %1!") +S("You drop %the1.", "Du lässt %den %a1 fallen.") +S("You feel great, like a true treasure hunter.", "Du fühlst dich toll - wie ein wahrer Schatzjäger.") +S("Your eyes shine like gems.", "Deine Augen leuchten wie Edelsteine.") +S("Your eyes shine as you glance at your precious treasures.", "Deine Augen leuchten, als du deine wunderbaren Schätze betrachtest.") +S("You glance at your great treasures.", "Du blickst auf deine tollen Schätze.") +S("You glance at your precious treasures.", "Du schaust auf deine hübschen Schätze.") +S("You glance at your precious treasure.", "Du untersuchst deine glänzenden Schätze.") +S("Your inventory is empty.", "Du besitzt nichts...") +S("You teleport to a new location!", "Du teleportierst dich an einen neuen Ort!!") +S("Could not open the score file: ", "Konnte die Highscore-Datei nicht öffnen: ") +S("Game statistics saved to %1", "Statistiken nach %1 gespeichert") +S("Game loaded.", "Spiel geladen.") +S("You summon some Mimics!", "Du beschwörst ein paar Mimics!") +S("You summon a golem!", "Du beschwörst einen Golem!") +S("You will now start your games in %1", "Du startest deine Spiele von nun an %a1") +S("Activated the Hyperstone Quest!", "Hyperstein-Quest aktiviert!") +S("Orb power depleted!", "Die Perle hat keine Kraft mehr!") +S("Orbs summoned!", "Perlen beschworen!") +S("Orb power gained!", "Perlen-Kraft erhalten!") +S("Dead orbs gained!", "Tote Perlen erhalten!") +S("Orb of Yendor gained!", "Perle von Yendor erhalten!!") +S("Treasure gained!", "Schatz erhalten!") +S("Lots of treasure gained!", "Verdammt viele Schätze erhalten!") +S("You summon a sandworm!", "Du beschwrörst einen Sandwurm!") +S("You summon an Ivy!", "Du beschwörst einen Efeu!") +S("You summon a monster!", "Du beschwörst ein Monster!") +S("You summon some Thumpers!", "Du platzierst einige Thumper!") +S("You summon a bonfire!", "Du platzierst ein Leuchtfeuer!") +S("Treasure lost!", "Schatz verloren!") +S("Kills gained!", "Kills erhalten!") +S("Activated Orb of Safety!", "Perle der Sicherheit aktiviert!") +S("Teleported to %1!", "Nach %1 teleportiert!") -S("Welcome to HyperRogue", "Witaj w HyperRogue") -S(" for Android", " na Android") -S(" for iOS", " na iOS") -S("! (version %1)\n\n", "! (wersja %1)\n\n") -S(" (press ESC for some hints about it).", " (naciśnij ESC by dostać wskazówki).") -S("Press 'c' for credits.", "Naciśnij 'c' by obejrzeć autorów") +S("Welcome to HyperRogue", "Willkommen bei HyperRogue") +S(" for Android", " ...für Android") +S(" for iOS", " ...für iOS") +S("! (version %1)\n\n", "! (Version %1)\n\n") +S(" (press ESC for some hints about it).", " (Drücke ESC für ein paar Tipps darüber).") +S("Press 'c' for credits.", "Drücke C für die Credits") S("game design, programming, texts and graphics by Zeno Rogue \n\n", - "projekt, programowanie, teksty i grafika: Zeno Rogue \n\n") -S("add credits for your translation here", "Teksty i tłumaczenie: Zeno Rogue\n\n") -S(" (touch to activate)", " (dotknij, by aktywować)") -S(" (expired)", " (wyczerpany)") -S(" [%1 turns]", " [kolejek: %1]") -S(", you", ", Ty") -S("0 = Klein model, 1 = Poincaré model", "0 = model Kleina, 1 = model Poincaré") -S("you are looking through it!", "patrzysz przez hiperboloidę!") -S("simply resize the window to change resolution", "po prostu zmień rozmiar okna") -S("[+] keep the window size, [-] use the screen resolution", "[+] zachowaj rozmiar okna, [-] użyj rozdzielczości ekranu") -S("+5 = center instantly, -5 = do not center the map", "+5 = centruj natychmiast, -5 = nie centruj") -S("press Space or Home to center on the PC", "naciśnij Space lub Home, by wycentrować na postaci") -S("You need special glasses to view the game in 3D", "Potrzebujesz specjalnych okularów, by oglądać grę w 3D") -S("You can choose one of the several modes", "Możesz wybrać jeden z kilku trybów") + "Spieldesign, Code, Texte und Grafiken: Zeno Rogue \n\n") +S("add credits for your translation here", "Deutsche Übersetzung: Jeffrey Smith und Arriator \n\n") +S(" (touch to activate)", " (zum Aktivieren tippen)") +S(" (expired)", " (abgelaufen)") +S(" [%1 turns]", " [%1 Runden]") +S(", you", ", du") +S("0 = Klein model, 1 = Poincaré model", "0 = Klein-Modell, 1 = Poincaré-Modell") +S("you are looking through it!", "Du siehst durch!") +S("simply resize the window to change resolution", "Einfach das Fenster vergrößern, um die Auflösung zu ändern") +S("[+] keep the window size, [-] use the screen resolution", "[+] Fenstergröße behalten, [-] Bildschirmauflösung verwenden") +S("+5 = center instantly, -5 = do not center the map", "+5 = sofort zentrieren, -5 = nicht zentrieren") +S("press Space or Home to center on the PC", "Drücke LEER oder Pos1 um den Spieler zu fokussieren") +S("You need special glasses to view the game in 3D", "Du brauchst 3D-Brillen für den 3D-Modus") +S("You can choose one of the several modes", "Du kannst einen dieser Modi wählen") S("ASCII", "ASCII") -S("black", "czarny") -S("plain", "prosty") +S("black", "schwarz") +S("plain", "platt") S("Escher", "Escher") -S("items only", "tylko przedmioty") -S("items and monsters", "przedmioty i potwory") -S("no axes", "bez osi") +S("items only", "Gegenstände") +S("items and monsters", "Gegenstände + Monster") +S("no axes", "keine Achsen") S("auto", "auto") -S("light", "lekki") -S("heavy", "gruby") -S("The axes help with keyboard movement", "Osie pomagają, gdy gramy na klawiaturze") -S("Config file: %1", "Plik konfiguracyjny: %1") -S("joystick mode: automatic (release the joystick to move)", "tryb dżojstika: automatyczny (puść by ruszyć)") -S("joystick mode: manual (press a button to move)", "tryb dżojstika: ręczny (naciśnij przycisk)") -S("Reduce the framerate limit to conserve CPU energy", "Ogranicz fps, by oszczędzać energię") -S("Press F1 or right click for help", "Wciśnij F1 lub kliknij prawym, by uzyskać pomoc") -S("No info about this...", "Brak informacji o tym...") -S("Press Enter or F10 to save", "Wciśnij Enter lub F10, by zapisać i wyjść") -S("Press Enter or F10 to quit", "Wciśnij Enter lub F10, by wyjść z gry") -S("or 'r' or F5 to restart", "lub 'r' lub F5, by zacząć od początku") -S("or 't' to see the top scores", "lub 't' by zobaczyć najlepsze wyniki") -S("or another key to continue", "lub inny klawisz, by kontynuować") -S("It is a shame to cheat!", "Wstyd oszukiwać!") -S("Showoff mode", "Tryb pokazowy") -S("Quest status", "Stan misji") -S("GAME OVER", "KONIEC GRY") -S("Your score: %1", "Twój wynik: %1") -S("Enemies killed: %1", "Potwory pokonane: %1") -S("Orbs of Yendor found: %1", "Znalezione Sfery Yendoru: %1") -S("Collect 30 $$$ to access more worlds", "Znajdź 30 $$$ by iść do nowych krain") -S("Collect at least 10 treasures in each of 9 types to access Hell", "Znajdź po 10 skarbów w 9 typach, by się dostać do Piekła") -S("Collect at least 10 Demon Daisies to find the Orbs of Yendor", "Znajdź 10 Czarciego Ziela, by znaleźć Sfery Yendoru") -S("Hyperstone Quest: collect at least 10 %1 in %the2", "Misja alternatywna: znajdź co najmniej 10 skarbów %abl2") -S("Hyperstone Quest completed!", "Misja alternatywna zakończona!") -S("Look for the Orbs of Yendor in Hell or in the Crossroads!", "Szukaj Sfer Yendoru w Piekle albo na Skrzyżowaniu!") -S("Unlock the Orb of Yendor!", "Otwórz Sferę Yendoru!") -S("Defeat 100 enemies to access the Graveyard", "Pokonaj 100 przeciwników, by trafić na Cmentarz") -S("(press ESC during the game to review your quest)", "(naciśnij ESC w trakcie gry, by zobaczyć stan swojej misji)") -S("you have cheated %1 times", "liczba oszustw: %1") -S("%1 turns (%2)", "kolejek: %1 (%2)") -S("last messages:", "ostatnie wiadomości: ") -S("time elapsed", "czas") -S("date", "data") -S("treasure collected", "zdobyte skarby") -S("total kills", "łączne zabicia") -S("turn count", "liczba kolejek") -S("cells generated", "wygenerowane pola") -S("t/left/right - change display, up/down - scroll, s - sort by", "lewo/prawo - zmiana, góra/dół - przewijanie, s - sortowanie") -S("kills", "zab") -S("time", "czas") -S("ver", "wer") +S("light", "leicht") +S("heavy", "schwer") +S("The axes help with keyboard movement", "Die Achsen helfen mit der Tastatursteuerung") +S("Config file: %1", "Config-Datei: %1") +S("joystick mode: automatic (release the joystick to move)", "Joystick: Automatisch (loslassen zum Bewegen)") +S("joystick mode: manual (press a button to move)", "Joystick: Manuell (Knopf drücken zum Bewegen)") +S("Reduce the framerate limit to conserve CPU energy", "Framerate-Limit reduzieren (spart CPU-Energie)") +S("Press F1 or right click for help", "Drücke F1 oder Rechtsklick für Hilfe") +S("No info about this...", "Keine Info hierüber...") +S("Press Enter or F10 to save", "Drücke Enter oder F10 zum Speichern") +S("Press Enter or F10 to quit", "Drücke Enter oder F10 zum Beenden") +S("or 'r' or F5 to restart", "oder R oder F5 zum Neustarten") +S("or 't' to see the top scores", "oder T für die Highscore-Liste") +S("or another key to continue", "oder irgendeine andere Taste zum Weitermachen") +S("It is a shame to cheat!", "Cheaten ist eine Schande!") +S("Showoff mode", "Angeber-Modus") +S("Quest status", "Quest-Status") +S("GAME OVER", "GAME OVER") +S("Your score: %1", "Punkte: %1") +S("Enemies killed: %1", "Kills: %1") +S("Orbs of Yendor found: %1", "Perlen von Yendor gefunden: %1") +S("Collect 30 $$$ to access more worlds", "Sammle 30 $$$ für neue Länder") +S("Collect at least 10 treasures in each of 9 types to access Hell", "Sammle 10 Schätze von 9 Arten für die Hölle") +S("Collect at least 10 Demon Daisies to find the Orbs of Yendor", "Sammle 10 Dämonenblümchen für die Perlen von Yendor") +S("Hyperstone Quest: collect at least 10 %1 in %the2", "Hyperstein-Quest: Sammle 10 %1 %a2") +S("Hyperstone Quest completed!", "Hyperstein-Quest abgeschlossen!") +S("Look for the Orbs of Yendor in Hell or in the Crossroads!", "Suche nach Perlen von Yendor in der Hölle oder Kreuzung!") +S("Unlock the Orb of Yendor!", "Öffne die Perle von Yendor!") +S("Defeat 100 enemies to access the Graveyard", "Töte 100 Feinde für den Friedhof") +S("(press ESC during the game to review your quest)", "(Drücke ESC während du spielst, um deine Quest anzuzeigen)") +S("you have cheated %1 times", "Du hast %1-mal Cheats benutzt") +S("%1 turns (%2)", "%1 Runden (%2)") +S("last messages:", "letzte Erinnerungen: ") +S("time elapsed", "Zeit") +S("date", "Datum") +S("treasure collected", "Gesammelte Schätze") +S("total kills", "Gesamt-Kills") +S("turn count", "Runden") +S("cells generated", "Generierte Zellen") +S("t/left/right - change display, up/down - scroll, s - sort by", "T/Links/Rechts - Anzeige ändern, Oben/Unten - Scrollen, S - Sortieren nach") +S("kills", "Kills") +S("time", "Zeit") +S("ver", "Ver.") S("SORT", "SORT") -S("PLAY", "GRA") -S("Your total wealth", "Twoje łączne bogactwo") -S("treasure collected: %1", "zdobyte skarby: %1") -S("objects found: %1", "znalezione przedmioty: %1") -S("orb power: %1", "moc: %1") -S(" (click to drop)", " (naciśnij by porzucić)") -S("You can also scroll to the desired location and then press 't'.", "Możesz też przewinąć do miejsca docelowego i wcisnąć 't'.") +S("PLAY", "START") +S("Your total wealth", "Dein Gesamt-Reichtum") +S("treasure collected: %1", "Schätze gesammelt: %1") +S("objects found: %1", "Objekte gefunden: %1") +S("orb power: %1", "Perlen-Kraft: %1") +S(" (click to drop)", " (Klicke zum Fallenlassen)") +S("You can also scroll to the desired location and then press 't'.", "Du kannst auch an die gewünschte Position scrollen und T drücken.") S("Thus, it is potentially useful for extremely long games, which would eat all the memory on your system otherwise.\n", - "Jest więc to użyteczne w bardzo długich grach, które inaczej by zjadły całą pamięć.") -S("You can touch the Dead Orb in your inventory to drop it.", "Dotknij Martwej Sfery na liście, by ją porzucić.") -S("This might be useful for Android devices with limited memory.", "To może się przydać, gdy Twoje urządzenie ma mało pamięci.") -S("You can press 'g' or click them in the list to drop a Dead Orb.", "Wciśnij 'g' lub kliknij Martwe Sfery na liście, by je porzucić.") -S("frames per second", "klatki na sekundę") -S("monsters killed: %1", "pokonane potwory: %1") -S("Drawing %1 (layer %2), F1 for help", "Rysujemy %1 (warstwa %2), F1 - pomoc") -S("hepta floor", "podłoga hepta") -S("hexa floor", "podłoga hex") -S("character", "postać") -S("ESC for menu/quest", "ESC - menu/misja") -S("vector graphics editor", "edytor grafiki wektorowej") -S("cheat mode", "tryb oszusta") -S("heptagonal game board", "plansza do gry z siedmiokątów") -S("triangular game board", "plansza do gry z trójkątów") -S("HyperRogue game board", "plansza do gry HyperRogue") -S("first page [Space]", "pierwsza strona [Space]") -S("exit configuration", "wyjdź z konfiguracji") -S("Configuration:", "Konfiguracja:") -S("video resolution", "rozdzielczość obrazu") -S("fullscreen mode", "tryb pełnoekranowy") -S("animation speed", "prędkość animacji") -S("dist from hyperboloid ctr", "odległość od centrum hiperboloidy") -S("scale factor", "współczynnik skali") -S("wall display mode", "tryb pokazywania ścian") -S("monster display mode", "tryb pokazywania potworów") -S("cross display mode", "tryb pokazywania osi") -S("background music volume", "głośność muzyki tła") -S("OFF", "WYŁ") -S("ON", "WŁ") -S("distance between eyes", "odległość między oczami") -S("framerate limit", "ograniczenie na fps") -S("joystick mode", "tryb dżojstika") -S("automatic", "automatyczny") -S("manual", "ręczny") -S("language", "język") -S("EN", "PL") -S("player character", "postać gracza") -S("male", "mężczyzna") -S("female", "kobieta") -S("use Shift to decrease and Ctrl to fine tune ", "użyj Shift by zmniejszyć, Ctrl by zwiększyć dokładność") -S("(e.g. Shift+Ctrl+Z)", " (na przykład Shift+Ctrl+Z)") -S("the second page [Space]", "druga strona [Space]") -S("special features [Space]", "opcje specjalne [Space]") -S("exit configuration", "wyjdź z konfiguracji") -S("see the help screen", "obejrzyj ekran pomocy") -S("save the current config", "zapisz obecną konfigurację") -S("(v) config", "(v) ust.") -S("Screenshot saved to %1", "Zrzut ekranu zapisany do %1") -S("You need an Orb of Teleport to teleport.", "Potrzebujesz Sfery Teleportacji, by to zrobić.") -S("Use arrow keys to choose the teleport location.", "Użyj strzałek, by wybrać cel teleportacji.") -S("openGL mode enabled", "włączono tryb OpenGL") -S("openGL mode disabled", "wyłączono tryb OpenGL") -S("openGL & antialiasing mode", "openGL i antialiasing") -S("anti-aliasing enabled", "włączono anti-aliasing") -S("anti-aliasing disabled", "wyłączono anti-aliasing") -S("You activate your demonic powers!", "Aktywowałeś moce demoniczne!") + "Ist also potentiell nützlich für extrem lange Spiele, die sonst den Arbeitsspeicher deines Systems frittieren würden.") +S("You can touch the Dead Orb in your inventory to drop it.", "Du kannst die tote Perle in deinem Inventar berühren, um sie fallenzulassen..") +S("This might be useful for Android devices with limited memory.", "Könnte für Android-Geräte mit begrenztem Speicher nützlich sein.") +S("You can press 'g' or click them in the list to drop a Dead Orb.", "Du kannst G drücken (oder sie in der Liste anklicken) um eine tote Perle fallenzulassen.") +S("frames per second", "FPS") +S("monsters killed: %1", "Kills: %1") +S("Drawing %1 (layer %2), F1 for help", "Zeichne %1 (Schicht %2), F1 für Hilfe") +S("hepta floor", "Heptagonaler Boden") +S("hexa floor", "Hexagonaler Boden") +S("character", "Character") +S("ESC for menu/quest", "ESC für Menü/Quest") +S("vector graphics editor", "Vektoren-Grafiken-Editor") +S("cheat mode", "Cheats") +S("heptagonal game board", "Heptagonales Spielbrett") +S("triangular game board", "Triangulares Spielbrett") +S("HyperRogue game board", "HyperRogue-Spielbrett") +S("first page [Space]", "Erste Seite [LEER]") +S("exit configuration", "Einstellungen verlassen") +S("Configuration:", "Einstellungen:") +S("video resolution", "Video-Auflösung") +S("fullscreen mode", "Vollbild") +S("animation speed", "Animations-Geschwindigkeit") +S("dist from hyperboloid ctr", "Entf. vom hyperbolischen Zentrum") +S("scale factor", "Skalierungs-Faktor") +S("wall display mode", "Anzeige-Modus (Wände)") +S("monster display mode", "Anzeige-Modus (Monster)") +S("cross display mode", "Anzeige-Modus (Kreuz)") +S("background music volume", "Hintergrundmusik") +S("OFF", "AUS") +S("ON", "EIN") +S("distance between eyes", "Augen-Abstand") +S("framerate limit", "Framerate-Limit") +S("joystick mode", "Joystick") +S("automatic", "automatisch") +S("manual", "manuell") +S("language", "Sprache") +S("EN", "DE") +S("player character", "Charakter") +S("male", "männlich") +S("female", "weiblich") +S("use Shift to decrease and Ctrl to fine tune ", "Shift zum Verringen, Strg zum feinen") +S("(e.g. Shift+Ctrl+Z)", "Ändern (z.B. Strg+Shift+Z)") +S("the second page [Space]", "Zweite Seite [LEER]") +S("special features [Space]", "Spezial-Zeug [LEER]") +S("exit configuration", "Einstellungen verlassen") +S("see the help screen", "siehe Hilfe-Bildschirm") +S("save the current config", "momentane Einstellungen speichern") +S("(v) config", "(v) Konfig.") +S("Screenshot saved to %1", "Screenshot nach %1 gespeichert") +S("You need an Orb of Teleport to teleport.", "Du brauchst eine Perle um dich zu teleportieren.") +S("Use arrow keys to choose the teleport location.", "Benutze die Pfeiltasten um dein Teleport-Ziel zu wählen.") +S("openGL mode enabled", "OpenGL aktiviert") +S("openGL mode disabled", "OpenGL deaktiviert") +S("openGL & antialiasing mode", "OpenGL & Anti-Aliasing") +S("anti-aliasing enabled", "Anti-Aliasing aktiviert") +S("anti-aliasing disabled", "Anti-Aliasing deaktiviert") +S("You activate your demonic powers!", "Du aktivierst deine dämonischen Kräfte!") // Steam achievement messages -S("New Achievement:", "Nowe osiągnięcie:") -S("Your total treasure has been recorded in the Steam Leaderboards.", "Twój wynik został zapisany w rankingach Steam.") -S("Congratulations!", "Gratulacje!") -S("You have improved your total high score and %1 specific high scores!", "Poprawi%łeś0 swój ogólny najlepszy wynik oraz %1 z wyników szczegółowych!") -S("You have improved your total and '%1' high score!", "Poprawi%łeś0 swój wynik ogólny, oraz swój wynik w kategorii '%P1!'") -S("You have improved your total high score on Steam. Congratulations!", "Poprawi%łeś0 swój ogólny najlepszy wynik na Steam. Gratulacje!") -S("You have improved %1 of your specific high scores!", "Poprawi%łeś0 %1 z wyników szczegółowych!") -S("You have improved your '%1' high score on Steam!", "Poprawi%łeś0 swój wynik w kategorii '%P1' na Steam!") -S("You have collected 10 treasures of each type.", "Znalaz%łeś0 10 skarbów każdego typu.") -S("This is your first victory!", "To Twoje pierwsze zwycięstwo!") -S("This has been recorded in the Steam Leaderboards.", "To zostało zapisane w Rankingach Steam.") -S("The faster you get here, the better you are!", "Im szybciej to osiągniesz, tym lepiej!") -S("You have improved both your real time and turn count. Congratulations!", "Poprawi%łeś0 swój najlepszy czas rzeczywisty i liczbę ruchów. Gratulacje!") -S("You have used less real time than ever before. Congratulations!", "Zajęło to mniej czasu rzeczywistego, niż wcześniej. Gratulacje!") -S("You have used less turns than ever before. Congratulations!", "Zajęło to mniej kolejek, niż kiedykolwiek wcześniej. Gratulacje!") +S("New Achievement:", "Neuer Erfolg:") +S("Your total treasure has been recorded in the Steam Leaderboards.", "Deine Gesamt-Schätze wurden in die Steam Highscore-Liste aufgenommen.") +S("Congratulations!", "Gratulation!") +S("You have improved your total high score and %1 specific high scores!", "Du hast deinen Gesamt-Highscore und %1 spezifische Highscores verbessert!") +S("You have improved your total and '%1' high score!", "Du hast deinen Gesamt-Highscore und '%1' Highscore verbessert!") +S("You have improved your total high score on Steam. Congratulations!", "Du hast deinen Gesamt-Highscore auf Steam verbessert! Gratulation!") +S("You have improved %1 of your specific high scores!", "Du hast %1 deiner spezifischen Highscores verbessert!") +S("You have improved your '%1' high score on Steam!", "Du hast deinen Highscore bei '%1' auf Steam verbessert!") +S("You have collected 10 treasures of each type.", "Du hast 10 Schätze jedes Typs gesammelt.") +S("This is your first victory!", "Dies ist dein erster Sieg!") +S("This has been recorded in the Steam Leaderboards.", "Dies wurde in den Steam-Highscores vermerkt.") +S("The faster you get here, the better you are!", "Je schneller du es hierher schaffst, desto besser bist du!") +S("You have improved both your real time and turn count. Congratulations!", "Du hast sowohl weniger Echtzeit als auch Runden als je zuvor benötigt. Gratulation!") +S("You have used less real time than ever before. Congratulations!", "Du hast weniger Echtzeit als je zuvor benötigt. Gratulation!") +S("You have used less turns than ever before. Congratulations!", "Du hast sowohl weniger Runden als je zuvor benötigt. Gratulation!") // help texts. These are separated into multiple lines just for convenience, // you don't have to follow. @@ -439,10 +456,10 @@ S( "monsters come to hunt you, as long as you are in the same land type. The " "Orbs of Yendor are the ultimate treasure; get at least one of them to win the game!", - "Trafi%łeś0 do dziwnej, nieeuklidesowej krainy. Zdobądź jak najwięcej skarbów, " - "zanim potwory Ciebie dopadną. Im więcej zdobędziesz skarbów, tym więcej potworów " - "w danej krainie na Ciebie poluje. Sfery Yendora są skarbem ostatecznym: zdobądź " - "Sferę Yendora, by wygrać grę!" + "Du wurdest in einer seltsamen, nicht-euklidischen Welt gefangen... Sammle soviel Schätze " + "wie du kannst - bevor dich die Monster fangen. Je mehr Schätze du hast, umso mehr Monster " + "werden dich jagen - solange du das Land nicht verlässt. Die " + "Perlen von Yendor sind der ultimative Schatz - sammle mindestens eine um zu gewinnen!" ) S( @@ -450,30 +467,28 @@ S( "The monster could also kill you by moving into your location, but the game " "automatically cancels all moves which result in that.\n\n", - "Większość przeciwników zabijasz poprzez wejście na zajmowane przez nie pole. " - "Przeciwnik może Ciebie zabić w ten sam sposób, ale gra automatycznie zabrania " - "ruchów, które by do tego prowadziły.\n\n") + "Du kannst die meisten Monster bekämpfen, indem du dich an ihre Position begibst. " + "Besagtes Monster könnte dich auch töten, indem es sich an deine Position begibt - " + "aber das Spiel lässt dies nicht zu.\n\n") S( "Usually, you move by touching somewhere on the map; you can also touch one " "of the four buttons on the map corners to change this (to scroll the map " "or get information about map objects). You can also touch the " "numbers displayed to get their meanings.\n", - "Zazwyczaj poruszasz się przez dotknięcie pola na mapie; możesz również " - "dotknąć jednego z przycisków w rogach, by to zmienić (by przewijać mapę albo " - "zdobyć informacje). Możesz też dotknąć liczb na ekranie, by poznać ich " - "znaczenie.\n") + "Normalerweise bewegst du dich durch Tippen auf die Karte; du kannst aber auch einen der " + "vier Knöpfe in den Ecken antippen um dies zu ändern (um die Karte zu scrollen oder Infos " + "über Objekte zu bekommen). Du kannst auch die Zahlen antippen um ihre Bedeutung zu erfahren.\n") S("Move with mouse, num pad, qweadzxc, or hjklyubn. Wait by pressing 's' or '.'. Spin the world with arrows, PageUp/Down, and Home/Space. " "To save the game you need an Orb of Safety. Press 'v' for config, ESC for the quest status and menu.\n\n", - "Ruszasz się myszą, klawiaturą numeryczną, qweadzxc, lub hjklyubn. Czekasz naciskając 's' lub '.'. " - "Obracasz świat strzałkami, PgUp/Dn, lub Home/Space. Naciśnij 'v' by zmienić ustawienia, ESC " - "by zobaczyć stan misji i menu.\n\n") + "Bewege dich mit der Maus, dem Numpad, QWEADZXC, oder HJKLYUBN. Warte mit S oder '.'. Drehe die Welt mit den Pfeiltasten, PgUp/PgDn, und Pos1/Space." + "Um zu speichern, benötigst du eine Perle der Sicherheit. Drücke V für Einstellungen, ESC für den Quest-Status und das Menü.\n\n") -S("See more on the website: ", "Więcej na stronie: ") +S("See more on the website: ", "Mehr auf der Website: ") S("special thanks to the following people for their bug reports, feature requests, porting, and other help:\n\n%1\n\n", - "Szczególne podziękowania dla poniższych osób za zgłoszone przez nich błędy, pomysły, porty i inną pomoc:\n\n%1\n\n") + "Besonderer Dank gebührt diesen Leuten für ihre Bug Reports, Feature-Anfragen, Ports, und andere Hilfe:\n\n%1\n\n") S( "The total value of the treasure you have collected.\n\n" @@ -482,35 +497,33 @@ S( "causes more enemies to hunt you in its native land.\n\n" "Orbs of Yendor are worth 50 $$$ each.\n\n", - "Łączna wartość Twoich skarbów.\n\n" - "Każda kraina zawiera specyficzny dla niej skarb, wart 1 $$$; " - "Twoim celem jest zebranie jak najwięcej skarbów, ale każdy " - "znaleziony skarb powoduje, że w jego krainie więcej potworów na Ciebie poluje.\n\n" - "Sfery Yendoru są warte po 50 $$$.\n\n") + "Der Gesamtwert deiner Schätze.\n\n" + "Jedes Land hat einen eigenen Schatztyp, der 1 $$$ wert ist. " + "Dein Ziel ist soviel Schätze wie möglich zu sammeln -- aber jeder Schatz, den du findest " + "erzeugt mehr Feinde in seinem Heimatland.\n\n" + "Perlen von Yendor sind 50 $$$ pro Stück wert.\n\n") S( "The higher the number, the smoother the animations in the game. " "If you find that animations are not smooth enough, you can try " "to change the options ", - "Im większa liczba, tym płynniejsze są animacje. Jeśli animacja nie " - "jest dostatecznie płynna, spróbuj zmienić opcje") + "Je höher die Zahl, desto flüssiger sind die Animationen. Sind sie nicht flüssig genug, " + "versuche die Optionen zu ändern ") S("(Menu button) and select the ASCII mode, which runs much faster. " "Depending on your device, turning the OpenGL mode on or off might " "make it faster, slower, or cause glitches.", - "(Menu), tryb ASCII działa dużo szybciej. Tryb OpenGL również wpływa " - "na jakość grafiki." + "(Im Menü) Versuche den ASCII-Modus zu aktivieren - der läuft viel schneller!" + "Je nach Gerät kann der OpenGL-Modus das Spiel verschnellern, verlangsamen, oder Glitches hervorrufen." ) S("(in the MENU). You can reduce the sight range, this should make " "the animations smoother.", - "(w MENU). Możesz zmniejszyć zasięg widzenia, dzięki temu animacje " - "będą płynniejsze.") + "(im Menü) wie die Sichtweite zu reduzieren, das sollte die Animation flüssiger machen.") S("(press v) and change the wall/monster mode to ASCII, or change " "the resolution.", - "(naciśnij 'v') i zmień tryb ścian/potworów na ASCII, albo zmień " - "rozdzielczość.") + "(drücke V) wie den 'Wand/Monster'-Modus auf ASCII zu schalten, oder die Auflösung zu ändern.") S( "In this mode you can draw your own player character and floors. " @@ -522,14 +535,14 @@ S( "s - save in C++ format (but cannot be loaded yet without editing source)\n\n" "z - zoom, o - Poincaré model\n", - "W tym trybie możesz narysować swoją własną postać albo podłogę. " - "Głównie w celu rozwijania gry, ale Ty też możesz się pobawić.\n\n" - "f - podłoga, p - gracz (powtarzaj, by zmienić warstwę)\n\n" - "n - nowy kształt, u - skopiuj standardową postać gracza\n\n" - "1-9 - symetrie obrotowe, 0 - symetria osiowa\n\n" - "wskaż myszą i: a - dodaj punkt, m - przesuń najbliższy punkt, d - skasuj najbliższy punkt, c - powtórz najbliższy punkt, b - po najbliższym\n\n" - "s - zapisz w formacie C++ (niestety obecnie nie można wczytać bez edytowania źródeł gry)\n\n" - "z - powiększenie, o - model Poincaré\n") + "Hier kannst du deine eigenen Spielfiguren/Bodenplatten zeichnen. " + "Eigentlich zur Entwicklung, aber hab Spaß.\n\n" + "f - Boden, p - Spieler (wiederholt für Schichten)\n\n" + "n - neue Form, u - kopiere die Körperform des Spielers\n\n" + "1-9 - Dreh-Symmetrie, 0 - Achsen-Symmetrie umschalten\n\n" + "Maus darüber und: a - Punkt hinzufügen, m - Nächsten Punkt verschieben, d - Nächsten Punkt löschen, c - Nächsten Punkt kopieren, b - Nach Nächstem Punkt hinzufügen\n\n" + "s - im C++-Format speichern (kannst du aber noch nicht laden, ohne Quellcode zu ändern)\n\n" + "z - Zoom, o - Poincaré-Modell\n") S( "These huge monsters normally live below the sand, but your movements have " @@ -537,25 +550,24 @@ S( "weapons, but you can defeat them by making them unable to move. " "This also produces some Spice. They move two times slower than you.", - "Te wielkie stworzenia normalnie żyją pod pustynnym piaskiem, ale Twoja obecność " - "na pustyni spowodowała ich wyjście na powierzchnię. Są za duże, byś m%ógł0 je " - "zaatakować swoją bronią, ale zginą, jeśli nie będą mogły się ruszyć -- to " - "produkuje także trochę Przyprawy. Czerwie ruszają się 2 razy wolniej od Ciebie.") + "Diese riesigen Monster leben normalerweise unter dem Sand, aber deine Bewegungen haben sie " + "geweckt. Sie sind zu groß, als dass du sie mit deinen Waffen erschlagen könntest, " + "aber du kannst sie besiegen -- indem du ihre Bewegung verhinderst. " + "Dies produziert auch etwas Gewürz. Sie bewegen sich halb so schnell wie du.") S("The tentacles of Cthulhu are like sandworms, but longer. " "They also withdraw one cell at a time, instead of exploding instantly.", - "Macki Cthulhu są podobne do Pustynnych Czerwi, ale dłuższe. " - "W przeciwieństwie do nich, nie eksplodują po zablokowaniu, tylko cofają się " - "pod ziemię, po 1 polu na kolejkę.") + "Die Tentakel von Cthulhu sind wie Sandwürmer - nur länger. " + "Anstatt zu explodieren, ziehen sie sich zurück - eine Zelle nach der anderen.") S( "A huge plant growing in the Jungle. Each Ivy has many branches, " "and one branch grows per each of your moves. Branches grow in a clockwise " "order. The root itself is vulnerable.", - "Wielka roślina z dżungli. Bluszcz zazwyczaj ma wiele gałęzi, po każdym Twoim " - "ruchu jedna z nich rośnie. Gałęzie rosną w kolejnosci zegarowej. Sam korzeń " - "nie atakuje, zatem goły korzeń łatwo ściąć.\n") + "Eine riesige Pflanze, die im Dschungel wächst. Jeder Efeu hat viele Zweige, " + "und jedes Mal, wenn du dich bewegst, wächst einer. Sie wachsen im Uhrzeigersinn. " + "Die Wurzel selbst ist verwundbar.\n") S("The Alchemists produce magical potions from pools of blue and red slime. You " "can go through these pools, but you cannot move from a blue pool to a red " @@ -564,12 +576,12 @@ S("The Alchemists produce magical potions from pools of blue and red slime. You "Slime beasts also have to keep to their own color, " "but when they are killed, they explode, destroying items and changing " "the color of the slime and slime beasts around them.", - "Alchemicy produkują magiczne napoje z niebieskiej i czerwonej mazi. Możesz " - "poruszać się poprzez maź, ale nie możesz przesunąć się z pola niebieskiego " - "na czerwone, ani z powrotem. Pola zawierające przedmioty są bezbarwne, " - "jak zabierzemy przedmiot, to zmieniają kolor na kolor pola, na którym " - "gracz był wcześniej. Maziste Stwory również ograniczone są do swojego koloru. " - "Gdy je zabijesz, eksplodują, niszcząc przedmioty i zmieniając kolor mazi wokół nich.\n") + "Die Alchemisten produzieren magische Tränke aus Lachen von blauem und rotem Schleim. " + "Du kannst durch sie hindurchgehen, aber du kannst nicht von Blau zu Rot wechseln, oder von " + "Rot zu Blau. Lachen mit Gegenständen darin sind farblos, und werden zu der Farbe, auf der " + "du schreitest, sobald diese aufgehoben werden. Schleimmonster müssen auch auf ihrer Farbe " + "bleiben - außer sie sterben, dann explodieren sie nämlich und zerstören Gegenstände, und " + "ändern die Farbe von Schleim und Schleimmonstern um sie herum.\n") S( "These creatures are slow, but very powerful... more powerful than you. " @@ -578,23 +590,22 @@ S( "Each 10 lesser demons you kill, you become powerful enough to kill all the greater " "demons on the screen, effectively turning them into lesser demons.", - "Te demony są powolne, ale bardzo silne... silniejsze od Ciebie. " - "Potrzebujesz zdobyć trochę doświadczenia, zanim będziesz w stanie je pokonać. " - "Nawet wtedy, przyjdą jeszcze silniejsze demony...\n\n" - "Za każdym razem, gdy pokonasz 10 mniejszych demonów, stajesz się dostatecznie silny, " - "by pokonać wszystkie Wielkie Demony na ekranie. Stają się one w tym momencie " - "Mniejszymi Demonami.") + "Diese Kreaturen sind langsam, aber sehr mächtig... mächtiger als du. " + "Du brauchst Erfahrung im Kampf gegen Dämonen, bevor du diesen entgegentrittst. " + "Und sogar dann kannst du vielleicht diesen töten, aber dann kommen noch stärkere...\n\n" + "Jedes Mal, wenn zu 10 Kleine Dämonen tötest, wirst du stark genug, um alle Großen Dämonen " + "auf dem Bildschirm zu töten (du verwandelst sie in Kleine Dämonen). ") S("These creatures are slow, but they often appear in large numbers.", - "Te demony są powolne, ale często pojawiają się w dużych ilościach.") + "Diese Geschöpfe sind langsam - aber tauchen oft in Gruppen auf.") S("A big monster from the Living Caves. A dead Troll will be reunited " "with the rocks, causing some walls to grow around its body.", - "Duży stwór z Żyjących Jaskiń. Martwy Troll połączy się ze skałą, " - "powodując rozrost skał wokół jego ciała.") + "Ein großes Monster aus den Lebenden Höhlen. Ein toter Troll wird eins mit dem Gestein, " + "was dazu führt, dass er von Wänden umgeben wird.") S("Huge, impassable walls which separate various lands.", - "Wielkie ściany, które oddzielają od siebie poszczególne krainy.") + "Gigantische, undurchdringbare Wände, die die verschiedenen Länder voneinander trennen.") S( "This cave contains walls which are somehow living. After each turn, each cell " @@ -602,11 +613,10 @@ S( "currently of a different type than the majority of cells around it, it switches. " "Items count as three floor cells, and dead Trolls count as five wall cells. " "Some foreign monsters also count as floor or wall cells.\n", - "Ściany tej jaskini sa żywe. W każdej kolejce, każde pole liczy, ile wokół niego " - "jest pól ściany i pól ziemi, i jeśli jest innego typu niż większość pól wokół " - "niego, to zmienia typ na przeciwny. Przedmioty liczą się jako 3 pola ziemi, " - "martwe Trolle jako 5 pól ściany. Niektóre potwory z innych krain również liczą się " - "jako ziemia lub ściana.\n") + "Diese Höhle enthält Wände, die (mehr oder weniger) leben. Nach jedem Zug zählt jede Zelle " + "die Zahl von Wänden und Böden um sich ab - und wenn sie der Minderheit entspricht, wechselt sie. " + "Gegenstände zählen als drei Böden, und tote Trolle zählen als fünf Wände. " + "Manche fremden Monster zählen auch als Böden oder Wände.\n") S( "This forest is quite dry. Beware the bushfires!\n" @@ -614,242 +624,234 @@ S( "rises once per turn for each fire nearby, and becomes fire itself " "when its temperature has risen 10 times.\n" "You can also cut down the trees. Big trees take two turns to cut down.", - "Ta puszcza jest wyschnięta. Uważaj na pożary!\n" - "Sąsiednie drzewa zajmują się ogniem w następnej kolejce. Temperatura " - "pola bez drzewa rośnie o 1 na kolejkę z każdym ogniem w sąsiedztwie, i gdy " - "wzrośnie do 10, to pole również staje się ogniem.\n" - "Możesz też ścinać drzewa. Ścięcie dużego drzewa zajmuje dwie kolejki." + "Dieser Wald ist ziemlich trocken. Vorsicht, Waldbrand!\n" + "Bäume fangen im nächsten Zug Feuer. Die Temperatur von Gras steigt jeden Zug für jedes Feuer in der Nähe, " + "und wird selbst zu Feuer wenn dies 10-mal geschehen ist.\n" + "Du kannst auch die Bäume fällen. Große Bäume brauchen zwei Züge dafür." ) S("A big and quite intelligent monster living in the Icy Land.", - "Duża i całkiem inteligentna bestia z Krainy Lodu.") + "Ein großes - und ziemlich intelligentes - Monster des Eisigen Landes.") S( "A nasty predator from the Icy Land. Contrary to other monsters, " "it tracks its prey by their heat.", - "Niebezpieczny drapieżnik z Krainy Lodu. W przeciwieństwie do innych " - "stworów, śledzi ofiarę po jej cieple.") + "Ein ziemlich fieser Jäger des Eisigen Landes. Anders als andere Monster, finden diese ihre Beute anhand ihrer Temperatur.") S("Rangers take care of the magic mirrors in the Land of Mirrors. " "They know that rogues like to break these mirrors... so " "they will attack you!", - "Strażnicy chronią luster w Krainie Luster. Wiedzą, że złodzieje lubią " - "rozbijać lustra... także spodziewaj się ataku!") + "Ranger nehmen die Spiegel im Land der Spiegel in Schutz. Sie wissen, dass Schurken wie du " + "gerne die Spiegel zerbrechen - also greifen sie dich an!") S("A nasty creature native to the Living Caves. They don't like you " "for some reason.", - "Brzydki stwór z Żywych Jaskiń. Jakoś Ciebie nie lubi.") + "Ein fieses Geschöpf, das in den Lebenden Höhlen haust. Irgendwie können sie dich nicht leiden.") S("A tribe of men native to the Desert. They have even tamed the huge Sandworms, who won't attack them.", - "Plemię ludzi żyjących na Pustyni. Oswoili oni Pustynne Czerwie, dzięki czemu żyją razem pokojowo.") + "Ein Menschenstamm, der in der Wüste lebt. Sie zähmten sogar die gigantischen Sandwürmer, die ihnen nichts tun.") -S("This giant ape thinks that you are an enemy.", "Ta małpa uważa, że jesteś jej przeciwnikiem.") +S("This giant ape thinks that you are an enemy.", "Dieser Affe glaubt, du bist sein Feind.") -S("A magical being which copies your movements.", "Magiczna istota kopiująca Twoje ruchy.") +S("A magical being which copies your movements.", "Ein magisches Wesen, das deine Bewegungen kopiert.") S("A magical being which copies your movements. " "You feel that it would be much more useful in an Euclidean space.", - "Magiczna istota kopiująca Twoje ruchy. W przestrzeni euklidesowej byłaby dużo bardziej przydatna.") + "Ein magisches Wesen, das deine Bewegungen kopiert.\n" + "Du hast das Gefühl, als wären sie in einer euklidischen Umgebung viel nützlicher.") S("You can summon these friendly constructs with a magical process.", - "Przyjazna konstrukcja, tworzona poprzez magiczny proces.") + "Du kannst diese freundlichen Steinriesen mit einem magischen Prozess beschwören.") S("A majestic bird, who is able to fly very fast.", - "Ten majestatyczny ptak bardzo szybko lata.") + "Ein majestätischer Vogel - der auch sehr schnell fliegt.") S("A monster who is able to live inside the living cave wall.", - "Sączaki żyją w ściane Żywej Jaskini.") + "Ein Monster, das innerhalb der Lebenden Wände leben kann.") -S("A typical Graveyard monster.", "Typowy cmentarny stwór.") +S("A typical Graveyard monster.", "Ein typisches Friedhof-Monster.") S("A typical monster from the Graveyard, who moves through walls.\n\n" "There are also wandering Ghosts. They will appear " "if you do not explore any new places for a long time (about 100 turns). " "They can appear anywhere in the game.", - "Typowy cmentarny stwór. Może przechodzić przez ściany.\n\n" - "Są też błądzące Duchy, które pojawiają się, gdy nie zwiedzasz " - "nowych miejsc przez długi czas (około 100 kolejek). Duchy te " - "mogą pojawić się w dowolnym miejscu w grze." + "Ein Monster, das typisch für den Friedhof ist - und sich durch Wände bewegen kann.\n\n" + "Es gibt auch Wandernde Geister - diese erschinen, wenn du dich lange (um die 100 Züge) " + "am selben Ort aufhältst. Sie können auch überall auftauchen." ) S("Necromancers can raise ghosts and zombies from fresh graves.", - "Nekromanci wzbudzają duchy i zombie ze świeżych grobów.") + "Totenbeschwörer können Geister und Zombies aus frischen Gräbern hervorrufen.") S("A creepy monster who follows you everywhere in the Graveyard.", - "Ten odrażający potwór chodzi za Tobą po cmentarzu!") + "Ein gruseliges Monster. Es folgt dir durch den ganzen Friedhof!") S("People worshipping Cthulhu. They are very dangerous.", - "Wyznawcy Cthulhu, bardzo niebiezpieczni.") + "Verehrer Cthulhus. Sie sind sehr gefährlich.") S("People worshipping Cthulhu. This one is especially dangerous, " "as he is armed with a weapon which launches fire from afar.", - "Wyznawcy cthulhu. Ten jest szczególnie niebezpieczny, bo " - "może z odległości rozpalić ogień w Twojej okolicy.") + "Verehrer Cthulhus. Dieser hier ist besonders gefährlich - er besitzt eine Waffe, die aus " + "der Ferne Feuer schleudern kann.") S("This dangerous predator has killed many people, and has been sent to Cocytus.", - "Ten niebezpieczny drapieżnik zabił wielu ludzi, i został zesłany do Kocytu.") + "Dieser gefürchtete Jäger hat schon vielen das Leben gekostet, und wurde deshalb nach Kokytos entsandt.") S("This white dog is able to run all the time. It is the only creature " "able to survive and breed in the Land of Eternal Motion.", - "Ten biały piesek jest w stanie biegać przez całe swoje życie. Jest to jedyne " - "stworzenie, które jest w stanie przeżyć w Krainie Wiecznego Ruchu.") + "Dieser weiße Hund kann die ganze Zeit rennen! Deshalb ist es die einzige Kreatur, die im " + "Land der Ewigen Bewegung überleben, und sich vermehren kann.") S("Demons of Hell do not drown when they fall into the lake in Cocytus. " "They turn into demonic sharks, enveloped in a cloud of steam.", - "Demony nie topią się, gdy wpadną w jezioro Kocyt. Zamieniają się " - "w demoniczne rekiny, otoczone chmurą pary.") + "Dämonen aus der Hölle ertrinken nicht, wenn sie in den See von Kokytos fallen. Stattdessen " + "werden sie zu Dämonenhaien - eingewickelt in eine Wolke aus Dampf.") S("These fairies would rather burn the forest, than let you get some Fern Flowers. " "The forest is infinite, after all...\n\n" "Fire Fairies transform into fires when they die.", - "Rusałki wolą spalić las, niż pozwolić Ci zdobyć Kwiaty Paproci. W końcu " - "las jest nieskończony...\n\n" - "Rusałki zamieniają się w ogień, gdy giną.") + "Diese Feen würden eher den ganzen Wald abfackeln, als dich Farnblüten sammeln zu lassen. " + "Der Wald ist schließlich grenzenlos...\n\n" + "Sie werden selbst zu Feuern, wenn sie sterben.") S("These warriors of the Forest wield exotic weapons called hedgehog blades. " "These blades protect them from a frontal attack, but they still can be 'stabbed' " "easily by moving from one place next to them to another.", - "Ci wojownicy z Puszczy walczą egzotyczną bronią, Jeżowym Ostrzem. " - "Ostrza te bronią je przed atakiem z frontu, ale za to możesz ich łatwo 'dźgnąć' " - "poprzez przejście z jednego pola sąsiadującego z nimi na inne.") + "Diese Krieger besitzen exotische Waffen - die Igelklingen. " + "Diese schützen sie vor frontalen Attacken, aber Igelkrieger können dennoch 'erstochen' werden - indem du dich an einen Ort neben oder hinter sie begibst.") S("This being radiates an aura of wisdom. " "It is made of a beautiful crystal, you would love to take it home. " "But how is it going to defend itself? Better not to think of it, " "thinking causes your brain to go hot...\n\n" "Crystal Sages melt at -30 °C, and they can rise the temperature around you from afar.", - "Ta istota promieniuje mądrością. Jest zrobiona z pięknego kryształu, na pewno " - "bardzo cennego. Ciekawe, jak zamierza się przed Tobą bronić? Lepiej o tym nie myśleć, " - "myślenie za bardzo Ciebie rozgrzewa...\n\n" - "Kryształowi Mędrcy topią się w -30 °C, i powodują wzrost temperatury wokół Ciebie.") + "Dieses Wesen strahlt eine Aura aus Weisheit aus. Es besteht aus einem schönen Kristall, " + "am liebsten würdest du es mit nach Hause nehmen... Nur, wie verteidigt es sich? Besser " + "nicht daran denken... Denken gibt dir Kopfschmerzen...\n\n" + "Kristallweisen schmelzen bei -30 °C, und können deine Temperatur aus der Ferne steigern.") -S("Cold white gems, found in the Icy Land.", "Zimne białe kamienie z Krainy Lodu.") +S("Cold white gems, found in the Icy Land.", "Kalte, weiße Edelsteine aus den Eisigen Ländern.") S("An expensive metal from the Living Caves. For some reason " "gold prevents the living walls from growing close to it.", - "Drogocenny metal z Żyjących Jaskiń. Złoto utrudnia wzrost ścian wokół niego.") + "Ein teures Metall aus den Lebenden Höhlen. Aus irgendeinem Grund verhindert Gold, dass Lebende Wände in seiner Nähe entstehen.") S("A rare and expensive substance found in the Desert. " "It is believed to extend life and raise special psychic powers.", - "Rzadka i droga substancja z Pustyni. Podobno wydłuża życie i daje moce psychiczne.") + "Eine seltene, teure Substanz aus der Wüste. Man sagt, es verlängert das Leben und verleiht besondere, psychische Kräfte.") -S("A beautiful gem from the Jungle.", "Piękny klejnot z Dżungli.") +S("A beautiful gem from the Jungle.", "Ein schöner Edelstein aus dem Dschungel.") S( "A wonderful beverage, apparently obtained by mixing red and blue slime. You definitely feel more " "healthy after drinking it, but you still fell that one hit of a monster is enough to kill you.", - "Cudowny napój, powstały z mieszania czerwonej i niebieskiej mazi. Po jej wypiciu czujesz " - "się zdecydowanie lepiej, ale wciąż jedno uderzenie potwora może Ciebie powalić.") + "Ein wundervolles Getränk, entstanden aus der Mischung blauen und roten Schleims. Du fühlst dich gesünder nach seinem Genuss - und dennoch zerbrechlich genug, dass dich ein Schlag eines Monsters töten könnte. ") S("A piece of a magic mirror, or a mirage cloud, that can be used for magical purposes. Only mirrors and clouds " "in the Land of Mirrors leave these.", - "Odłamek szkła z magicznego lustra, albo fragment mirażowej chmury. Może zostać użyty do magii. " - "Tylko lustra i chmury z Krainy Luster zostawiają odłamki.") + "Ein Stück eines Spiegels oder Trugbilds, das für magische Zwecke brauchbar ist. " + "Spiegel und Wolken im Land der Spiegel hinterlassen diese.") S("These sinister totems contain valuable gems.", - "Ten złowieszczy totem zawiera cenne klejnoty.") + "Diese schaurigen Totems enthalten wertvolle Edelsteine.") S("These star-shaped flowers native to Hell are a valuable alchemical component.", - "Ta piekielna roślina w kształcie gwiazdy jest cennym składnikiem alchemicznym.") + "Diese sternförmigen Blumen, der Hölle heimisch, sind eine wertvolle alchemistische Komponente.") S("This statue is made of materials which cannot be found in your world.", - "Ta statua jest zrobiona z materiałów, których nie ma w Twoim świecie.") + "Diese Statue ist aus Materialien, die in deiner Welt nicht existieren.") S("One of few things that does not cause the floor in the Land of Eternal Motion to collapse. Obviously they are quite valuable.", - "Pióro Feniksa jest tak lekie, że podłoga z Krainy Wiecznego Ruchu pod nim nie spada. " - "Takie pióra muszą być bardzo cenne.") + "Eines der wenigen Dinge, die den Boden im Land der Ewigen Bewegung nicht einstürzen lassen. Sie sind offensichtlich sehr wertvoll.") -S("Cold blue gems, found in the Cocytus.", "Zimne niebieskie kamienie, znajdowane na zamarźniętym Kocycie.") +S("Cold blue gems, found in the Cocytus.", "Kalte, blaue Edelsteine aus dem Kokytos.") S("These bright yellow gems can be found only by those who have mastered the Crossroads.", - "Te jasne, żółte klejnoty mogą znaleźć tylko mistrze Skrzyżowań.") + "Diese hellen, gelben Edelsteine können nur von denen gesehen werden, die die Kreuzung meisterten.") S("That's all you need to unlock the Orb of Yendor! Well... as long as you are able to return to the Orb that this key unlocks...\n\n" "Each key unlocks only the Orb of Yendor which led you to it.", - "To jest to, czego potrzebujesz, by otworzyć Sferę Yendoru! O ile umiesz do niej trafić...\n" - "Każdy klucz otwiera tylko jedną Sferę, która Ciebie do niego doprowadziła.") + "Das ist alles, was du brauchst, um die Perle von Yendor zu entsperren! ...solange du wieder zurückfindest...\n" + "Jeder Schlüssel entsperrt nur die Perle von Yendor, die dich zu ihm geführt hat.") S("These orbs can be found in the Graveyard. You think that they were once powerful magical orbs, but by now, their " "power is long gone. No way to use them, you could as well simply drop them...\n\n", - "Na cmentarzu jest mnóstwo tych sfer. Chyba były to kiedyś potężne magiczne kule, ale ich " - "moc dawno przeminęła. Nie ma jak ich użyć, także może lepiej je po prostu zostawić...\n\n") + "Diese Perlen sind aus dem Friedhof. Du schätzt, sie waren einst mächtig, aber vor langer Zeit schwand ihre Kraft. " + "Es gibt keinen Weg sie zurückzuholen, du könntest die Perlen auch einfach dalassen...\n\n") S( "This wonderful Orb can only be collected by those who have truly mastered this hyperbolic universe, " "as you need the right key to unlock it. Luckily, your psychic abilities will let you know " "where the key is after you touch the Orb.", - "Ta cudowna sfera może być zdobyta tylko przez prawdziwych mistrzów tego świata. " - "By ją otworzyć, potrzebujesz klucza. Na szczęście Twoje moce psychiczne powiedzą Ci, " - "gdzie jest klucz, gdy dotkniesz Sfery.") + "Diese wundervolle Perle kann nur von denen gesammelt werden, die dieses hyperbolische Universum komplett gemeistert haben, da du den richtigen Schlüssel benötigst, um ihre Macht zu entfesseln. " + "Deine psychischen Fähigkeiten erlauben es dir, zu sehen, wo sich der Schlüssel befindet, nachdem du die Kugel berührt hast.") S( "This orb can be used to invoke the lightning spell, which causes lightning bolts to shoot from you in all directions.", - "Ta sfera pozwala rzucić czar Błyskawica, który powoduje wystrzelenie błyskawicy w każdym kierunku.") + "Du kannst diese Perle verwenden um einen Blitz-Zauber zu wirken, der Blitze in sämtliche Richtungen um dich verschießt.") S("This orb can be used to invoke a flash spell, which destroys almost everything in radius of 2.", - "Ta sfera pozwala rzucić czar Błysk, który niszczy wszystko w promieniu 2.") + "Du kannst diese Perle verwenden um einen Leucht-Zauber zu wirken, der fast alles zerstört, was in einem Radius von 2 um dich ist.") S("This orb can be used to invoke a wall of ice. It also protects you from fires.", - "Ta sfera zostawia za Tobą ścianę lodu, a także chroni Ciebie przed ogniem.") + "Du kannst diese Perle verwenden um einen Eis-Zauber zu wirken, der eine Wand aus Eis hervorruft. Die Perle schützt dich auch vor Feuer.") S("This orb can be used to move faster for some time.", - "Ta sfera powoduje, że przez pewien czas poruszasz się szybciej.") + "Du kannst diese Perle verwenden um einen Hermes-Zauber zu wirken, der dich einige Zeit lang beschleunigt.") S("This orb can be used to summon friendly golems. It is used instantly when you pick it up.", - "Ta sfera przywołuje przyjazne golemy. Jest natychmiast używana w momencie podniesienia.") + "Du kannst diese Perle verwenden um einen Stein-Zauber zu wirken, der freundliche Golems beschwört. (Sie wird sofort verwendet, wenn du sie aufhebst)") -S("This orb can protect you from damage.", "Ta sfera chroni Ciebie przed obrażeniami od potworów.") +S("This orb can protect you from damage.", "Du kannst diese Perle verwenden um dich vor Schaden zu schützen.") S("This orb lets you instantly move to another location on the map. Just click a location which " "is not next to you to teleport there. ", - "Ta sfera pozwala Ci natychmiast przenieść się do innego miejsca na mapie. Wystarczy " - "kliknąć pole, które nie jest obok Ciebie.") + "Du kannst diese Perle verwenden um einen Teleport-Zauber zu wirken. Klicke auf einen Ort, der nicht neben dir ist, um dich dorthin zu teleportieren. (Die Perle wird dabei verbraucht)") S("This orb lets you instantly move to a safe faraway location. Knowing the nature of this strange world, you doubt " "that you will ever find the way back...\n\n" "Your game will be saved if you quit the game while the Orb of Safety is still powered.\n\n" "Technical note: as it is virtually impossible to return, this Orb recycles memory used for the world so far (even if you do not use it to save the game). ", - "Ta sfera pozwala Ci natychmiast przenieść się do bezpiecznego miejsca. Znając naturę tego " - "świata, zapewne nigdy nie trafisz z powrotem...\n\n" - "Jeśli wyjdziesz z gry podczas gdy Sfera Bezpieczeństwa wciąż ma moc, gra zostanie zapisana.\n\n" - "Uwaga techniczna: nawet jeśli nie zapiszesz gry, ta sfera czyści całą pamięć o świecie gry. ") + "Du kannst diese Perle verwenden um dich an einen weit entfernten, sicheren Ort zu bewegen. Dank der Weise dieser Welt bezweifelst du, dass du je zurückfindest...\n\n" + "Dein Spiel wird gespeichert, wenn du es beendest während die Perle der Sicherheit noch beikräften ist.\n\n" + "(Technische Anmerkung: Da es wirklich unmöglich ist, zurückzukehren, lässt diese Perle den Speicher, den die Welt bis jetzt braucht, neu durchlaufen - sogar wenn du sie nicht verwendest, um zu speichern.)") S("This orb allows attacking Hedgehog Warriors directly, as well as stabbing other monsters.\n", - "Ta sfera pozwala bezpośrednio atakować Wojowników-Jeże, a także dźgać pozostałych przeciwników.\n") + "Du kannst diese Perle verwenden um Igelkrieger direkt anzugreifen, und andere Monster zu 'erstechen'.\n") S("This flower brings fortune to the person who finds it.\n", - "Ta roślina daje szczęście temu, kto je znajdzie.\n") + "Diese Blume bringt seinem Finder Glück.\n") -S("Ice Walls melt after some time has passed.", "Lodowe ściany topią się po pewnym czasie.") +S("Ice Walls melt after some time has passed.", "Eiswände schmelzen nach gewisser Zeit.") -S("A natural terrain feature of the Desert.", "Naturalny teren z Pustyni.") +S("A natural terrain feature of the Desert.", "Eine natürliche Terrain-Form der Wüste.") S("You can go inside the Magic Mirror, and produce some mirror images to help you.", - "Możesz wejść w Magiczne Lustro, by Twoje odbicia z niego wyszły i Ci pomogły.") + "Du kannst den Spiegel betreten, um Spiegelbilder zu erzeugen, die dir helfen.") S( "Tiny droplets of magical water. You see images of yourself inside them. " "Go inside the cloud, to make these images help you.", - "Malutkie kropelki magicznej wody, w których widać Twój obraz. Wejdź do środka chmury, " - "by te obrazy Ci pomogły.") + "Kleine Tropfen aus magischem Wasser, in dem du dich selbst sehen kannst. " + "Betrete den Dampf, um diese Bilder real werden zu lassen.") S("A device that attracts sandworms and other enemies. You need to activate it.", - "To urządzenie przyciąga czerwie i innych przeciwników. Musisz je aktywować.") + "Ein Gerät, das Sandwürmer und andere Feinde anzieht. Allerdings musst du es einschalten.") S("A heap of wood that can be used to start a fire. Everything is already here, you just need to touch it to fire it.", - "Stos drewna. Wszystko gotowe, wystarczy podpalić.") + "Ein Haufen Holz, den du verwenden kannst, um ein Feuer zu machen. Alles ist schon da - du musst das Feuer schon fast nur berühren, und es brennt.") -S("An ancient grave.", "Stary grób.") +S("An ancient grave.", "Ein uraltes Grab.") -S("A fresh grave. Necromancers like those.", "Świeży grób. Nekromanci to lubią.") +S("A fresh grave. Necromancers like those.", "Ein frisches Grab. Totenbeschwörer mögen die.") -S("A piece of architecture typical to R'Lyeh.", "Architektura typowa dla R'Lyeh.") +S("A piece of architecture typical to R'Lyeh.", "Ein Stück R'Lyeh-typische Architektur.") -S("An impassable lake in Cocytus.", "Nie możesz przejść przez Jezioro Kocyt.") +S("An impassable lake in Cocytus.", "Ein undurchdringbarer See in Kokytos.") -S("You can walk on it... but beware.", "Możesz tu przejść, ale uważaj!") +S("You can walk on it... but beware.", "Du kannst darauf gehen... aber pass auf.") -S("It was a floor... until something walked on it.", "Tu kiedyś była podłoga, ale coś po niej przeszło.") +S("It was a floor... until something walked on it.", "Das WAR mal Boden. Dann ist was darauf gegangen.") S( "This land is a quick gateway to other lands. It is very easy to find other lands " @@ -859,100 +861,91 @@ S( "and other land types bring magical orbs.\n\n" "A special treasure, Hyperstone, can be found on the Crossroads, but only " "after you have found 10 of every other treasure.", - "Ta kraina jest szybkim przejściem do pozostałych krain. Bardzo łatwo dostać się " - "stąd do pozostałych krain. Również potwory z tych krain łatwo tutaj wejdą!\n\n" - "Możesz znaleźć magiczne przedmioty na Skrzyżowaniu, jeśli zdoby%łeś0 wystarczająco " - "wiele skarbów w ich rodzinnych krainach. Są to sfery, magiczne lustra i chmury.\n\n" - "Specyficzne skarby Skrzyżowań, Hiperkamienie, można znaleźć na Skrzyżowaniu, ale tylko " - "po znalezieniu 10 jednostek każdego innego skarbu.") + "Dieses Land ist eine Art Schnellreise zu anderen Ländern. Es ist sehr einfach, diese von hier aus zu finden - das bedeutet, dass hier auch Monster aus den meisten anderen Ländern hier sein können!\n\n" + "Solange du genug Schätze in den Ländern gefunden hast, erscheinen magische Gegenstände in der Kreuzung. Das Land der Spiegel bringt Spiegel und Wolken, und andere Länder bringen magische Perlen.\n\n" + "Ein besonderer Schatz - der Hyperstein - ist hier auffindbar, aber du musst erst 10 von allen anderen Schätzen haben.") S("A hot land, full of sand dunes, mysterious Spice, and huge and dangerous sand worms.", - "Gorąca ziemia, pełna wydm, tajemniczej Przyprawy, i wielkich Pustynnych Czerwi.") + "Ein heißes Land, voller Sanddünen, geheimnisvollem Gewürz, und riesigen sowie gefährlichen Sandwürmern.") S( "A very cold land, full of ice walls. Your mere presence will cause these ice walls to " "melt, even if you don't want it.", - "Bardzo zimna kraina, pełna lodowych ścian. Wystarczy Twoja obecność, by te ściany " - "się roztopiły. Nawet, jak tego nie chcesz.") + "Ein ziemlich kaltes Land, voller Eiswände. Deine Gegenwart allein wird sie allerdings zum Schmelzen bringen - ob du willst oder nicht.") S("A land filled with huge ivy plants and dangerous animals.", - "Kraina pełna wielkiego pnącego bluszczu i niebezpiecznych bestii.") + "Ein Land voll mit Efeu und gefährlichen Tieren.") S("A strange land which contains mirrors and mirages, protected by Mirror Rangers.", - "Dziwna kraina, gdzie można znaleźć magiczne lustra i chmury, bronione przez " - "Strażników Luster.") + "Ein seltsames Land mit Spiegelbildern und Trugbildern, die von den Rangern geschützt werden.") S("All the monsters you kill are carried to this strange land, and buried. " "Careless Rogues are also carried here...", - "Pochowane są tu wszystkie potwory, które zabijasz. A także poszukiwacze skarbów, którzy " - "nie uważali...") + "Alle Monster, die du tötest, werden hier begraben. Genauso wie achtlose Schurken...") S("An ancient sunken city which can be reached only when the stars are right.\n\n" "You can find Temples of Cthulhu in R'Lyeh once you collect five Statues of Cthulhu.", - "Prastare zatopione miasto, do którego można dostać się tylko, gdy gwiazdy są " - "na swoich miejscach.\n\n" - "Po znalezieniu 5 Statuetek Cthulhu możesz w R'Lyeh trafić na Świątynie Cthulhu.") + "Eine antike, versunkene Stadt, die du nur erreichen kannst, wenn die Sterne gut liegen.\n\n" + "Du findest Tempel von Cthulhu in R'Lyeh - sobald du fünf Cthulhu-Statuen hast.") S("A land filled with demons and molten sulphur. Abandon all hope ye who enter here!", - "Kraina pełna demonów i stopionej siarki. Ty, który wchodzisz, żegnaj się z nadzieją!") + "Ein Land voller Dämonen und geschmolzenem Schwefel. Verliere alle Hoffnung, wer hier eintritt!") S("This frozen lake is a hellish version of the Icy Land. Now, your body heat melts the floor, not the walls.", - "Zamarznięte jezioro. Piekielna wersja Krainy Lodu, w której ciepło Twojego ciała topi ziemię pod Tobą, a nie " - "ściany.") + "Dieser gefrorene See ist wie eine höllische Version des Eisigen Lands. Hier schmilzt deine Körperwärme den Boden, nicht die Wände.") S("A land where you cannot stop, because every piece of floor is extremely unstable. Only monsters who " "can run forever are able to survive there, and only phoenix feathers are so light that they do not disturb " "the floor.\n", - "Kraina, w której nie możesz przestać się ruszać, bo każdy fragment podłogi jest bardzo niestabilna. " - "Jedynie stworzenia będące w stanie wiecznie się ruszać mogą tu przeżyć, i jedynie pióra feniksa " - "są na tyle lekkie, by nie zaburzyć podłogi.") + "Ein Land, in dem du nicht stehen bleiben darfst - denn jedes Stück Boden ist extrem instabil. Nur Monster, die ewig laufen können, sind auch in der Lage, hier zu überleben. " + "Nur Phönixfedern sind leicht genug, den Boden nicht zu erschüttern.\n") -S("Affects looks and grammar", "Wpływa na wygląd i gramatykę") +S("Affects looks and grammar", "Aussehen und Grammatik") -S("first joystick: movement threshold", "dżojstik 1: próg ruchu") -S("first joystick: execute movement threshold", "dżojstik 1: próg wykonania ruchu") -S("second joystick: pan threshold", "dżojstik 2: próg przewijania") -S("second joystick: panning speed", "dżojstik 2: prędkość przewijania") -S("%The1 is frozen!", "%1 zamarzł%oa1!") -S("%The1 burns!", "%1 się spalił%oa1!") -S("message flash time", "czas pokazywania wiadomości") +S("first joystick: movement threshold", "Joystick 1: Bewegungsgrenze") +S("first joystick: execute movement threshold", "Joystick 1: Bewegung-Ausführen-Grenze") +S("second joystick: pan threshold", "Joystick 2: Scroll-Grenze") +S("second joystick: panning speed", "Joystick 2: Scroll-Geschwindigkeit") +S("%The1 is frozen!", "%Der1 %1 ist eingefroren!") +S("%The1 burns!", "%Der1 %1 brennt!") +S("message flash time", "Nachrichten-Zeit") -S("skin color", "kolor skóry") -S("weapon color", "kolor broni") -S("hair color", "kolor włosów") -S("dress color", "kolor sukienki") -S("Shift=random, Ctrl=mix", "Shift=losowo, Ctrl=miks") +S("skin color", "Hautfarbe") +S("weapon color", "Waffen-Farbe") +S("hair color", "Haarfarbe") +S("dress color", "Kleidungs-Farbe") +S("Shift=random, Ctrl=mix", "Shift=Zufällig, Ctrl=Mischen") -S("Euclidean mode", "tryb euklidesowy") -S("Return to the hyperbolic world", "powrót na hiperboloidę") -S("Choose from the lands visited this game.", "Wybierz spośród odwiedzonych krain.") -S("Scores and achievements are not", "Wyniki i osiągnięcia nie są"); -S("saved in the Euclidean mode!", "zapamiętywane w tym trybie!"); +S("Euclidean mode", "Euklidischer Modus") +S("Return to the hyperbolic world", "Zur hyperbolischen Welt zurückkehren") +S("Choose from the lands visited this game.", "Wähle aus den Ländern, die diese Sitzung besucht wurden.") +S("Scores and achievements are not", "PUNKTE UND ERRUNGENSCHAFTEN WERDEN IM"); +S("saved in the Euclidean mode!", "EUKLIDISCHEN MODUS NICHT GESPEICHERT!"); // Android buttons (some are not translated because there are no good short words in Polish) -S("MOVE", "RUCH") -S("BACK", "OK") -S("DRAG", "DRAG") +S("MOVE", "GEHE") +S("BACK", "RÜCK") +S("DRAG", "ZIEH") S("INFO", "INFO") -S("MENU", "MENU") -S("QUEST", "MISJA") -S("HELP", "POMOC") -S("NEW", "NOWA") -S("PLAY", "GRAJ") -S("SHARE", "SHARE") -S("HyperRogue for Android", "HyperRogue dla Android") -S("Date: %1 time: %2 s ", "Data: %1 czas: %2 s ") -S("distance: %1\n", "odległość: %1\n") -S("Cheats: ", "Oszustwa: ") -S("Score: ", "Wynik: ") -S("Kills: ", "Zabicia: ") -S("Retrieving scores from Google Leaderboards...", "Ściągam wyniki z rankingów Google...") -S("Scores retrieved.", "Wyniki ściągnięte.") +S("MENU", "MENÜ") +S("QUEST", "QUEST") +S("HELP", "HILFE") +S("NEW", "NEU") +S("PLAY", "SPIELE") +S("SHARE", "TEILE") +S("HyperRogue for Android", "HyperRogue für Android") +S("Date: %1 time: %2 s ", "Datum: %1 Zeit: %2 s ") +S("distance: %1\n", "Distanz: %1\n") +S("Cheats: ", "Cheats: ") +S("Score: ", "Punkte: ") +S("Kills: ", "Kills: ") +S("Retrieving scores from Google Leaderboards...", "Hole Rekorde aus Google Leaderboards...") +S("Scores retrieved.", "Rekorde erhalten.") -S("Your total treasure has been recorded in the Google Leaderboards.", "Twój wynik został zapisany w rankingach Google.") -S("You have improved your total high score on Google. Congratulations!", "Poprawi%łeś0 swój ogólny najlepszy wynik na Google. Gratulacje!") -S("You have improved your '%1' high score on Google!", "Poprawi%łeś0 swój wynik w kategorii '%P1' na Google!") -S("This has been recorded in the Google Leaderboards.", "To zostało zapisane w Rankingach Google.") +S("Your total treasure has been recorded in the Google Leaderboards.", "Deine Gesamt-Schätze wurden in die Google Leaderboards aufgenommen.") +S("You have improved your total high score on Google. Congratulations!", "Du hast deinen Gesamt-Rekord auf Google verbessert! Gratulation!") +S("You have improved your '%1' high score on Google!", "Du hast deinen '%P1'-Rekord auf Google verbessert!") +S("This has been recorded in the Google Leaderboards.", "Dies wurde in die Google Leaderboards aufgenommen.") // this text changed a bit: @@ -961,53 +954,51 @@ S("Ever wondered how some boardgame would look on the hyperbolic plane? " "Enter = pick up an item (and score), space = clear an item\n" "Other keys place orbs and terrain features of various kinds\n" "In the periodic editor, press 0-4 to switch walls in different ways\n", - "Zastanawia%łeś0 się może, jak jakaś gra planszowa wyglądałaby na płaszczyźnie " - "hiperbolicznej? Ja się zastanawiałem nad Go, i postanowiłem to sprawdzić. Teraz " - "Ty też możesz sprawdzić!\n" - "Enter = podnieś przedmiot, space = zabierz przedmiot\n" - "Pozostałe klawisze kładą różnego rodzaju przedmioty\n" - "W edytorze okresowym, klawisze 0-4 zmieniają ściany na różne sposoby") + "Hast du dich je gewundert, wie ein Brettspiel auf der hyperbolischen Ebene aussehen würde? " + "Ich habe mich über Go gewundert - und dieses Feature erstellt. Probiere es selbst!\n" + "Enter = Gegenstand aufheben (und punkten), [LEER] = Gegenstand löschen\n" + "Andere Tasten erzeugen alles mögliche an Perlen und Terrain-Formen\n" + "Im periodischen Editor kannst du 0-4 verwenden um die Wände zu verändern\n") -S("Periodic Editor", "Edytor okresowy") +S("Periodic Editor", "Periodischer Editor") // also translate this line: // "In the periodic editor, press 0-4 to switch walls in different ways\n", +// "Im periodischen Editor kannst du 0-4 verwenden um die Wände zu verändern\n" -S("Collect 60 $$$ to access even more lands", "Znajdź 60 $$$ by iść do kolejnych krain") +S("Collect 60 $$$ to access even more lands", "Sammle 60 $$$ um noch mehr Länder zu besuchen.") // Emerald Mine -N("Emerald Mine", GEN_F, "Kopalnia Szmaragdów", "Kopalnie Szmaragdów", "Kopalnię Szmaragdów", "w Kopalni Szmaragdów") -N("Pikeman", GEN_M, "Pikinier", "Pikinierzy", "Pikiniera", "Pikinierem") -N("Flail Guard", GEN_M, "Strażnik z cepem", "Strażnicy z cepami", "Strażnika z cepem", "Strażnikiem z cepem") -N("Miner", GEN_M, "Górnik", "Górnicy", "Górnika", "Górnikiem") -N("Emerald", GEN_O, "Szmaragd", "Szmaragdy", "Szmaragd", "Szmaragdem") +N("Emerald Mine", GEN_F, "Smaragdmine", "Smaragdminen", "in der Smaragdmine") +N("Pikeman", GEN_M, "Pikenier", "Pikeniere", "Pikenier") +N("Flail Guard", GEN_M, "Morgenstern-Wächter", "Morgenstern-Wächter", "Morgenstern-Wächter") +N("Miner", GEN_M, "Minenarbeiter", "Minenarbeiter", "Minenarbeiter") +N("Emerald", GEN_M, "Smaragd", "Smaragde", "Smaragd") -Orb("the Mind", "Psychiki") +Orb("the Mind", "der Psyche") S( "Evil people are mining for emeralds in this living cave. " "It does not grow naturally, but it is dug out in a regular " "pattern, which is optimal according to the evil engineers.", - "Źli ludzie szukają szmaragdów w tej żywej jaskini. " - "Nie rośnie ona naturalnie -- ludzie wykopują regularne " - "wzory, które, zgodnie z oceną złych inżynierów, są 'optymalne'. ") + "Böse Leute bauen Smaragde in dieser lebenden Höhle ab. " + "Sie ensteht nicht natürlich, sondern ist gemustert ausgegraben. " + "Dies sehen die bösen Ingenieure als \"optimal\" an.") S( "Miners have special tools for dealing with the Living Cave. " "When they die, these tools activate, destroying the living cave " "around them.", - "Górnicy mają specjalne narzędzia do kopania w Żywych Jaskiniach. " - "Kiedy giną, te narzędzia się uruchamiają, powodując, że żywa " - "jaskinia wokół nich obumiera.") + "Minenarbeiter haben spezielle Werkzeuge für den Umgang mit der Lebenden Höhle. " + "Sterben sie, werden diese aktiviert, was die Höhle um sie einbrechen lässt.") S( "When Pikemen move, they attack all cells which are now adjacent to them. " "Luckily, they can be killed in the same way.\n\n" "They never move if this would attack their friends.", - "Kiedy Pikinier się rusza, atakuje wszystkie komórki, z którymi sąsiaduje " - "po wykonaniu ruchu. Na szczęście, jego samego można pokonać taką samą " - "metodą.\n\n" - "Pikinier się nie rusza, jeśli by w ten sposób zaatakował przyjaciela.") + "Bewegen sich Pikeniere, greifen sie alle jetzt umliegenden Zellen an. " + "Glücklicherweise können sie genauso getötet werden.\n\n" + "Sie bewegen sich nicht wenn sie so ihre Freunde angreifen würden.") S( "This guard of the Emerald Mine is wielding a huge flail. " @@ -1015,88 +1006,86 @@ S( "Luckily, you have learned a trick: if you step away from him, " "he will hit himself with the flail!", - "Ten strażnik Kopalni Szmaragdów jest uzbrojony w wielki cep bojowy. " - "Nie możesz go zaatakować bezpośrednio, bo cep by Ciebie uderzył. " - "Na szczęście, znasz sztuczkę: jak się od niego odsuniesz, " - "strażnik uderzy cepem samego siebie!") + "Dieser Wächter der Smaragdmine hat einen riesigen Morgenstern. " + "Ihn direkt anzugreifen wäre dämlich - der Stern würde dich treffen. " + "Allerdings kannst du von ihm wegtreten. Dann trifft er sich selbst!") -S("A precious green gem from the Emerald Mines.", "Cenny klejnot z Kopalni Szmaragdów.") +S("A precious green gem from the Emerald Mines.", "Ein schöner, grüner Stein aus den Smaragdminen.") -S("%The1 pierces %the2!", "%1 przebi%ł1 %a2!") +S("%The1 pierces %the2!", "%Der1 durchdringt %den2 %a2!") S("Make him hit himself by walking away from him.", - "Odejdź od niego, by sam się zaatakował.") + "Bringe ihn dazu, sich selbst zu treffen (geh von ihm weg).") S("This orb allows you to instantly kill a non-adjacent enemy by clicking it. " "Each use drains 30 charges.", - "Ta sfera pozwala natychmiastowo zabić niesąsiadującego przeciwnika (klikając go). " - "Każde użycie zmniejsza poziom naładowania o 30.") + "Diese Perle erlaubt es dir, sofort einen nicht-angrenzenden Feind zu töten, indem du auf ihn klickst. " + "Jede Verwendung verbraucht 30 Ladungen.") -S("%The1 is immune to mental blasts!", "%1 jest odporn%y1 na atak psychiczny!") -S("You kill %the1 with a mental blast!", "Zabi%łeś1 %a2 mocą psychiczną!") +S("%The1 is immune to mental blasts!", "%Der1 ist immun gegen mentale Korruption!") +S("You kill %the1 with a mental blast!", "Du tötest %den1 %a1 mit mentaler Korruption!") // Vineyard -N("Vineyard", GEN_F, "Winnica", "Winnice", "Winnicę", "w Winnicy") -N("Vine Beast", GEN_M, "Winny Stwór", "Winne Stwory", "Winnego Stwora", "Winnym Stworem") -N("Vine Spirit", GEN_M, "Winny Duszek", "Winne Duszki", "Winnego Duszka", "Winnym Duszkiem") -N("vine", GEN_F, "winorośl", "winorośle", "winorośl", "winoroślą") -N("partial fire", GEN_M, "częściowy ogień", "częściowe ognie", "częściowy ogień", "częściowym ogniem") -N("Wine", GEN_N, "Wino", "Wina", "Wino", "Winem") +N("Vineyard", GEN_M, "Weingarten", "Weingärten", "im Weingarten") +N("Vine Beast", GEN_F, "Reben-Bestie", "Reben-Bestien", "Reben-Bestie") +N("Vine Spirit", GEN_M, "Reben-Seele", "Reben-Seelen", "Reben-Seele") +N("vine", GEN_F, "Rebe", "Reben", "Rebe") +N("partial fire", GEN_N, "partielles Feuer", "partielle Feuer", "partielle Feuer") +N("Wine", GEN_M, "Wein", "Wein", "Wein") -S( "This cell is partially on fire.", "To pole częściowo się pali.") +S( "This cell is partially on fire.", "Diese Zelle brennt teilweise.") S( "The Vineyard is filled with vines. A very dense pattern of straight lines here...\n\n" "Vine Beasts and Vine Spirits change vine cells to grass, and vice versa.", - "Winnica jest wypełniona winoroślami. Bardzo gęsta siatka linii prostych...\n\n" - "Winne Bestie i Duszki zmieniają winorośle w trawę i z powrotem.") + "Der Weingarten ist voller Reben. Hier gibt es viele gerade Linien...\n\n" + "Reben-Bestien und Reben-Seelen ändern Zellen von Reben zu Gras, und umgekehrt.") S("A vine is growing here... but only on a half of the cell. How is that even possible?!" "Most monsters cannot move from this cell to the cell containing the other half. " "Vine spirits can move only to the adjacent cells which are also adjacent to the " "other half.", - "Tu rośnie winorośl... ale tylko na połowie pola. Jak to w ogóle jest możliwe?!" - "Większość stworzeń nie może ruszyć się z tego pola na pole zawierające drugą połowę " - "winorośli. Winne duszki mogą się ruszyć tylko na te sąsiednie pola, które sąsiadują " - "także z drugą połową.") + "Hier wächst eine Rebe... AUF DER HALBEN ZELLE?! WIE IST DAS MÖGLICH!?" + "Die meisten Monster können sich nicht von dieser Zelle aus auf die bewegen, die die andere Hälfte enthält. " + "Reben-Seelen können sich nur auf angrenzende Zellen bewegen, die auch der anderen Hälfte anliegen. " + "(Klingt kompliziert, oder?)") S( "A beast made of vines!\n\n" - "Vine Beasts turn into vines when they dies.", - "Stworzenie zrobione z winorośli!\n\n" - "Winne Stwory zmieniają się w winorośle, gdy giną.") + "Vine Beasts turn into vines when they die.", + "Eine Bestie aus Reben!\n\n" + "Wird zu Reben, wenn sie stirbt.") S( "A spirit living in the vines!\n\n" "Vine Spirits destroy the vines when they die.", - "Duch żyjący w winoroślach!\n\n" - "Winne Duszki niszczą winorośle, gdy giną.") + "Eine Seele in den Reben!\n\n" + "Zerstört die Reben, wenn sie stirbt.") S("Wine grown under hyperbolic sun would be extremely prized in your home location.", - "Wino uprawiane pod hiperbolicznym słońcem, byłoby bardzo cenne w Twojej " - "krainie.") + "Wein, der unter hyperbolischer Sonne wächst, könnte in deiner Heimatwelt ziemlich viel wert sein.") S("This orb allows one to pass through all kinds of walls and chasms.", - "Ta sfera pozwala przechodzić przez wszelkie ściany i przepaście.") + "Diese Perle erlaubt es, durch sämtliche Wände und über Abgründe zu segeln.") S("You cannot attack through the Vine!", - "Nie możesz atakować poprzez winorośl!") + "Du kannst durch die Reben nicht angreifen!") -Orb("Aether", "Eteru") +Orb("Aether", "des Aethers") // Dead Caves -N("Dead Cave", GEN_F, "Martwa Jaskinia", "Martwe Jaskinie", "Martwą Jaskinię", "w Martwej Jaskini") -N("Dark Troll", GEN_M, "Mroczny Troll", "Mroczne Trolle", "Mrocznego Trolla", "Mrocznym Trollem") -N("Earth Elemental", GEN_M, "Żywiołak", "Żywiołaki", "Żywiołaka", "Żywiołakiem") -N("dead wall", GEN_F, "martwa ściana", "martwe ściany", "martwą ścianę", "martwą ścianą") -N("dead floor", GEN_F, "martwa ziemia", "martwe ziemie", "martwą ziemię", "martwą ziemią") -N("rubble", GEN_O, "gruz", "gruzy", "gruz", "gruzem") -N("Silver", GEN_N, "Srebro", "Srebra", "Srebro", "Srebrem") +N("Dead Cave", GEN_F, "Tote Höhle", "Tote Höhlen", "in der Toten Höhle") +N("Dark Troll", GEN_M, "Dunkler Troll", "Dunkle Trolle", "Dunklen Troll") +N("Earth Elemental", GEN_M, "Erd-Elementar", "Erd-Elementare", "Erd-Elementar") +N("dead wall", GEN_F, "tote Wand", "tote Wände", "tote Wand") +N("dead floor", GEN_F, "toter Boden", "tote Böden", "toten Boden") +N("rubble", GEN_N, "Geröll", "Geröll", "Geröll") +N("Silver", GEN_N, "Silber", "Silber", "Silber") -S("A precious metal from the Dead Caves.", "Drogocenny metal z Martwej Jaskini.") +S("A precious metal from the Dead Caves.", "Ein wertvolles Metall aus den toten Höhlen.") -S( "A Troll without the power of Life.", "Troll bez mocy Życia.") +S( "A Troll without the power of Life.", "Ein Troll ohne die Macht des Lebens.") S( "A rare unliving construct from the Dead Caves. " @@ -1104,95 +1093,94 @@ S( "an impassable wall behind it. You suppose that this impassable wall helps it to " "escape from some threats. You hope you won't meet these threats...", - "Rzadka konstrukcja z Martwych Jaskiń. " - "Natychmiast niszczy skalne ściany przy jego trasie, i tworzy " - "za sobą ścianę skały. Przypuszczasz, że ta ściana pomaga mu " - "uciekać przed jakimiś zagrożeniami. Masz nadzieję, że nie spotkasz tych " - "zagrożeń...") + "Ein seltenes, unlebendes Geschöpf aus den Toten Höhlen. " + "Es zerstört sofort Höhlenwände, die ihm im Weg sind, und hinterlässt " + "undurchdringbare Wände, die (so vermutest du) bei der Flucht verhelfen sollen. " + "Hoffentlich wirst du nicht sehen, wovor es flieht...") -S("%The1 punches %the2!", "%1 uderzy%ł1 %a2!") -S("%The1 is destroyed by the forces of Life!", "Siły Życia zniszczyły %a1!") +S("%The1 punches %the2!", "%Der1 schlägt %den2 %a2!") +S("%The1 is destroyed by the forces of Life!", "Die Kräfte des Lebens zerstören %den1 %a1!") S( "Somehow, this cave has not received the spark of Life yet.", - "Dziwnym trafem, ta jaskinia jeszcze nie zdobyła iskry Życia.") + "Diese Höhle hat irgendwie noch nicht den Funken des Lebens erhalten.") // Hive -N("Hive", GEN_N, "Mrowisko", "Mrowiska", "Mrowisko", "w Mrowisku") -N("Red Hyperbug", GEN_M, "Czerwony Hiperinsekt", "Czerwone Hiperinsekty", "Czerwonego Hiperinsekta", "Czerwonym Hiperinsektem") -N("Green Hyperbug", GEN_M, "Zielony Hiperinsekt", "Zielone Hiperinsekty", "Zielonego Hiperinsekta", "Zielonym Hiperinsektem") -N("Blue Hyperbug", GEN_M, "Niebieski Hiperinsekt", "Niebieskie Hiperinsekty", "Niebieskiego Hiperinsekta", "Niebieskim Hiperinsektem") -N("Royal Jelly", GEN_N, "Królewskie Mleczko", "Królewskie Mleczka", "Królewskiego Mleczka", "Królewskim Mleczkiem") -N("weird rock", GEN_N, "dziwna skała", "dziwne skały", "dziwną skałę", "dziwną skałą") +N("Hive", GEN_M, "Stock", "Stöcke", "im Stock") +N("Red Hyperbug", GEN_M, "Roter Hyperkäfer", "Rote Hyperkäfer", "Roten Hyperkäfer") +N("Green Hyperbug", GEN_M, "Grüner Hyperkäfer", "Grüne Hyperkäfer", "Grünen Hyperkäfer") +N("Blue Hyperbug", GEN_M, "Blauer Hyperkäfer", "Blaue Hyperkäfer", "Blauen Hyperkäfer") +N("Royal Jelly", GEN_N, "Königliches Gelee", "Königliche Gelees", "Königliche Gelee") +N("weird rock", GEN_M, "Seltsamer Stein", "Seltsame Steine", "Seltsamen Stein") -Orb("Invisibility", "Niewidzialności") +Orb("Invisibility", "der Transparenz") S("A weirdly colored rock. Hyperentomologists claim that the " "Hyperbug armies use these rocks to navigate back home after a victorious battle.", - "Ta skała ma dziwny kolor. Hiperentomolodzy twierdzą, że roje Hiperinsektów " - "używają tych skał do nawigacji, by wrócić do domu po wygranej bitwie.") + "Ein seltsam gefärbter Stein. Hyperentomologen behaupten, die Hyperkäfer-Armeen " + "verwenden sie, um nach einer siegreichen Schlacht nach Hause zu finden.") -S("%The1 fights with %the2!", "%1 zaatakował %a2!") +S("%The1 fights with %the2!", "%Der1 %1 bekämpft %den2 %a2!") S("The Hive is filled with Hyperbugs. They are huge insects which look a bit like " "ants, a bit like bees, and a bit like roaches. " "They live in circular nests, and an army of Hyperbugs will attack any intruder, " "including you and enemy Hyperbugs. Will you manage to get to the " "heart of such a nest, and get the precious Royal Jelly?", - "Mrowisko jest wypełnione Hiperinsektami. Te wielkie owady wyglądają trochę jak " - "mrówki, trochę jak pszczoły, trochę jak karaluchy. Żyją w okrągłych gniazdach, " - "i atakują każdego najeźdźcę, łącznie z Tobą i wrogimi hiperinsektami. " - "Czy uda Ci się dotrzeć do serca roju, i zdobyć cenne królewskie mleczko?") + "Der Stock ist randvoll mit Hyperkäfern - riesige Insekten, die etwas wie Ameisen, " + "Bienen, und Kakerlaken aussehen. Sie leben in kreisförmigen Nestern, und eine Armee " + "von ihnen greift sämtliche Eindringlinge an (auch dich und andere Hyperkäfer). " + "Schaffst du es zum Zentrum eines Nests, und das Königliche Gelee zu holen?") S("This is what Hyperbug Queens eat. Very tasty and healthy.", - "Pożywienie Królowej Hiperinsektów, bardzo smaczne i zdrowe.") + "Dieses Gelee wird hauptsächlich von Hyperkäfer-Königinnen genossen. Sehr schmackhaft und gesund.") S("When you have this Orb, most monsters won't see you, unless " "you are standing still, attacking, or picking up items.", - "Kiedy masz Sferę Niewidzialności, większość potworów Ciebie nie widzi, " - "chyba że stoisz w miejscu, atakujesz, albo podnosisz przedmioty.") + "Besitzt du diese Perle, sehen dich die meisten Monster nicht - " + "es sei denn, du stehst still, greifst an, oder hebst Gegenstände auf.") -Orb("Earth", "Ziemi") +Orb("Earth", "der Erde") S("This orb lets you go through living walls. It also has powers in some of the other lands.", - "Ta sfera pozwala Ci przechodzić przez żywą ścianę. Ma też moce w niektórych z pozostałych krain.") + "Diese Perle erlaubt es dir, dich durch lebende Wände zu bewegen - und einige andere Sachen in anderen Ländern zu machen.") // Land of Power -N("Land of Power", GEN_F, "Kraina Mocy", "Krainy Mocy", "Krainą Mocy", "w Krainie Mocy") -N("Witch Apprentice", GEN_F, "Uczennica", "Uczennice", "Uczennicę", "Uczennicą") -N("Speed Witch", GEN_F, "Czarownica Szybka", "Czarownice Szybkie", "Czarownicę Szybką", "Czarownicą Szybką") -N("Flash Witch", GEN_F, "Czarownica Błysku", "Czarownice Błysku", "Czarownicę Błysku", "Czarownicą Błysku") -N("Fire Witch", GEN_F, "Czarownica Ognia", "Czarownice Ognia", "Czarownicę Ognia", "Czarownicą Ognia") -N("Aether Witch", GEN_F, "Czarownica Eteru", "Czarownice Eteru", "Czarownicę Eteru", "Czarownicą Eteru") -N("Winter Witch", GEN_F, "Czarownica Zimy", "Czarownice Zimy", "Czarownicę Zimy", "Czarownicą Zimy") -N("Evil Golem", GEN_M, "Zły Golem", "Złe Golemy", "Złego Golema", "Złym Golemem") -N("Powerstone", GEN_M, "Kamień Mocy", "Kamienie Mocy", "Kamień Mocy", "Kamieniem Mocy") -N("crystal cabinet", GEN_F, "kryształowa gablota", "kryształowe gabloty", "kryształową gablotę", "kryształową gablotą") +N("Land of Power", GEN_N, "Land der Macht", "Länder der Macht", "im Land der Macht") +N("Witch Apprentice", GEN_M, "Hexenlehrling", "Hexenlehrlinge", "Hexenlehrling") +N("Speed Witch", GEN_F, "Geschwindigkeits-Hexe", "Geschwindigkeits-Hexen", "Geschwindigkeits-Hexe") +N("Flash Witch", GEN_F, "Blitz-Hexe", "Blitz-Hexen", "Blitz-Hexe") +N("Fire Witch", GEN_F, "Feuer-Hexe", "Feuer-Hexen", "Feuer-Hexe") +N("Aether Witch", GEN_F, "Aether-Hexe", "Aether-Hexen", "Aether-Hexe") +N("Winter Witch", GEN_F, "Winter-Hexe", "Winter-Hexen", "Winter-Hexe") +N("Evil Golem", GEN_M, "Böser Golem", "Böse Golems", "Bösen Golem") +N("Powerstone", GEN_M, "Macht-Stein", "Macht-Steine", "Macht-Stein") +N("crystal cabinet", GEN_N, "Kristall-Kabinett", "Kristall-Kabinette", "Kristall-Kabinett") S("When you have this Orb, you will leave a trail of fire behind you.", - "Kiedy masz Sferę Ognia, zostawiasz za sobą ognistą ścieżkę.") + "Mit dieser Perle hinterlässt du eine Spur aus Feuer hinter dir.") S( "A Witch without any special powers. But watch out! She will " "pick up any basic Orbs on her path, and use their powers.", - "Czarownica bez specjalnych mocy. Uważaj! Może ona podnieść " - "dowolną podstawową Sferę na swojej drodze, i użyć jej mocy.") + "Eine Hexe ohne besondere Kräfte. Sie wird allerdings jegliche Perlen in " + "ihrer Nähe aufhebene, und ihre verwenden.") S( "A Witch with a Speed spell. She moves twice as fast as you. Unless you " "have an Orb of Speed too, of course!", - "Czarownica z czarem Szybkości. Rusza się dwa razy szybciej od Ciebie. " - "Chyba że Ty też masz Sferę Szybkości!") + "Eine Hexe mit einem Geschwindigkeits-Zauber. Sie bewegt sich doppelt so schnell wie du. " + "Außer natürlich, du hast auch eine Perle der Geschwindigkeit!") S( "A Witch with a Fire spell. She will leave a trail of fire behind her.", - "Czarownica z czarem Ogień. Zostawia za sobą płonącą ścieżkę.") + "Eine Hexe mit einem Feuer-Zauber. Sie hinterlässt eine Spur aus Feuer.") S( "A Witch with a Winter spell. She is able to move through fire.", - "Czarownica z czarem Zima. Może przechodzić przez ogień.") + "Eine Hexe mit einem Winter-Zauber. Sie kann durch Feuer gehen.") S( "A Witch with an Aether spell. She is able to move through fire and walls.", - "Czarownica z czarem Eter. Może przechodzić przez ogień i ściany.") + "Eine Hexe mit einem Aether-Zauber. Sie kann durch Feuer und Wände gehen.") S( "Somebody has summoned these evil constructs with a magical process.", - "Wroga konstrukcja, tworzona poprzez magiczny proces.") + "Jemand hat diese bösen Konstrukte mit einem magischen Ritual beschworen.") S( "The Land of Power is filled with everburning fire, magical Orbs, and guarded by " "witches and golems. There are basic orbs lying everywhere, and more prized ones " @@ -1200,34 +1188,29 @@ S( "The Land of Power is filled with everburning fire, magical Orbs, and guarde "Witches are allowed to use all the powers of the " "basic orbs against intruders. These powers never expire, but a Witch " "can use only one power at a time (not counting Orbs of Life).\n\n" - "Witches and Golems don't pursue you into other Lands. Also, most Orb powers" + "Witches and Golems don't pursue you into other Lands. Also, most Orb powers " "are drained when you leave the Land of Power.", - "Kraina Mocy jest wypełniona wiecznie płonącym ogniem, magicznymi Sferami, " - "i strzeżona przez Czarownice i golemy. Podstawowe Sfery walają się wszędzie, a " - "te bardziej cenne są trzymane w kryształowych gablotach.\n\n" - "Czarownice używają wszystkich mocy podstawowych Sfer przeciwko intruzom. " - "Ich moce nigdy nie przemijają, ale Czarownica może używać naraz tylko jednej " - "mocy (nie licząc Sfer Życia).\n\n" - "Czarownice i Golemy nie gonią Ciebie do innych krain. Większość Sfer " - "traci swoją moc, gdy opuszczasz Krainę Mocy.") + "Das Land der Macht ist voll mit ewigen Flammen, magischen Perlen, und wird von Hexen und Golems bewacht. Überall liegen einfache Perlen, und wertvollere werden in Kristall-Kabinetten gehalten.\n\n" + "Hexen dürfen alle Perlen-Kräfte gegen Angreifer einsetzen. Diese laufen nie aus, allerdings kann eine Hexe (mit Ausnahme der Perle des Lebens) jederzeit nur eine besitzen.\n\n" + "Hexen und Golems verfolgen dich nicht in andere Länder. Außerdem werden die meisten Kräfte von dir genommen, sobald du das Land verlässt.") S( "Witches use these crystal cabinets to protect Powerstones, as well as the more " "expensive Orbs. They are partially protected from thieves: they are too strong " "to be smashed by conventional attacks, and if you try to steal the item " "using an Orb of Aether, your Aether power will be completely drained.", - "Czarownice używają tych kryształowych gablot, by chronić Kamienie Mocy oraz bardziej " - "cenne Sfery. Gabloty są częściowo chronione przed kradzieżą: są zbyt mocne, " - "by je rozbić konwencjonalnymi atakami, a jeśli spróbujesz ukraść przedmiot " - "używając Sfery Eteru, Twoja moc Eteru zostanie całkowicie wyczerpana.") + "Hexen verwenden diese Kristall-Kabinette um Macht-Steine, und die teureren " + "Perlen zu schützen. Sie sind teilweise diebstahlsicher: zu stark, um von " + "normalen Angriffen zerschmettert zu werden - und versuchst du, den Inhalt " + "mit einem Aether-Zauber zu stehlen, wird dieser komplett aufgesogen.") S( "A Stone from the Land of Power. You are not sure what it is exactly, but " "as the Powerstones are kept in crystal cabinets, they are surely valuable.", - "Kamień z Krainy Mocy. W sumie to nie wiesz, co to jest, ale trzymają te " - "kamienie w kryształowych gablotach, także musi być bardzo cenny.") + "Ein Stein aus dem Land der Macht. Du bist dir nicht ganz sicher WAS es it, " + "aber da er in einem Kristall-Kabinett war, ist er sicher wertvoll!") -Orb("Fire", "Ognia") +Orb("Fire", "des Feuers") // achievements: @@ -1251,40 +1234,40 @@ Orb("Fire", "Ognia") // lines forgotten previously -S("Your Aether power has expired! RUN!", "Twoja moc Eteru się wyczerpała! UCIEKAJ!") +S("Your Aether power has expired! RUN!", "Deine Aether-Kraft ist zuende! LAUF!") -S("%The1 tricks %the2.", "%1 pokona%ł1 %a2.") -S("You trick %the1.", "Pokona%łeś0 %a1.") +S("%The1 tricks %the2.", "%Der1 %1 überlistet %den2 %a2.") +S("You trick %the1.", "Du überlistest %den1 %a1.") S( "A Witch with a Flash spell. Very dangerous!\n\nLuckily, she never uses the spell if it " "would kill her friends. She could destroy an Evil Golem, though.", - "Czarownica z czarem Błysk. Bardzo niebezpieczna!\n\nNa szczęście, nie użyje swojego " - "czaru, jeśli by to zabiło jej przyjaciółki.") + "Eine Hexe mit einem Blitz-Zauber. Sehr gefährlich!\n\n" + "Glücklicherweise setzt sie den Zauber nicht ein, wenn dies ihre Freunde gefährden würde. Aber gegen Böse Golems.") -S("Your Aether powers are drained by %the1!", "Twoja moc Eteru została wyssana przez %a1!") -S("As you leave, your powers are drained!", "Opuszczasz Krainę Mocy... Twoja moc znikła!") -S("%The1 picks up %the2!", "%1 podniosła %a2!") // currently only Witches, so only female form +S("Your Aether powers are drained by %the1!", "%Der1 %1 saugt deine Aether-Kraft auf!") +S("As you leave, your powers are drained!", "Deine Kraft verblasst, als du gehst...") +S("%The1 picks up %the2!", "%Der1 %1 hebt %den2 %a2 auf!") // currently only Witches, so only female form S("You can right click any element to get more information about it.\n\n", - "Kliknij obiekt prawym przyciskiem myszy, by zobaczyć więcej informacji na jego temat.\n\n") + "Du kannst auf alles rechtsklicken, um Informationen darüber zu bekommen.\n\n") -S("TRANSLATIONWARNING", "") +S("TRANSLATIONWARNING", "VORSICHT: Die deutsche Übersetzung enthält keine Funktionen nach Version 7.2! (Arbeite dran <3)") -S("The Hyperbugs are fighting!", "Hiperinsekty ze sobą walczą!") +S("The Hyperbugs are fighting!", "Die Hyperkäfer kämpfen!") -S("","") N("",GEN_N,"","","","") +S("","") N("",GEN_N,"","","") -S("Cheat-changed the display.", "Zmieniam tryb wyświetlania.") -S("Dead floor, with some rubble.", "Martwa ziemia, jest tu trochę gruzu.") +S("Cheat-changed the display.", "Anzeige geändert (Cheater!).") +S("Dead floor, with some rubble.", "Toter Boden, mit etwas Geröll.") // Camelot -N("Camelot", GEN_O, "Camelot", "Camelot", "Camelot", "w Camelot") -N("wall of Camelot", GEN_F, "ściana Camelot", "ściany Camelot", "ścianę Camelot", "ścianą Camelot") -N("moat of Camelot", GEN_F, "fosa Camelot", "fosy Camelot", "fosę Camelot", "fosą Camelot") -N("Round Table", GEN_O, "Okrągły Stół", "Okrągłe Stoły", "Okrągły Stół", "Okrągłym Stołem") -N("Knight", GEN_M, "Rycerz", "Rycerze", "Rycerza", "Rycerzem") -N("Holy Grail", GEN_M, "Święty Graal", "Święte Graale", "Świętego Graala", "Świętym Graalem") +N("Camelot", GEN_N, "Camelot", "Camelot", "in Camelot") +N("wall of Camelot", GEN_F, "Wand von Camelot", "Wände von Camelot", "Wand von Camelot") +N("moat of Camelot", GEN_M, "Graben von Camelot", "Gräben von Camelot", "Graben von Camelot") +N("Round Table", GEN_F, "Runde Tafel", "Runde Tafeln", "Runde Tafel") +N("Knight", GEN_M, "Ritter", "Ritter", "Ritter") +N("Holy Grail", GEN_M, "Heiliger Gral", "Heilige Grale", "Heiligen Gral") S( "The Knights of the Round Table are the greatest warriors of these lands. " @@ -1296,44 +1279,43 @@ S( "The radius of the Round Table is usually 28, but after you find a Holy Grail " "successfully, each new castle (and each Round Table) you find will be bigger.", - "Rycerze Okrągłego Stołu to najwięksi wojownicy tych krain. Niestety, nie są " - "zbyt pomysłowi w nazywaniu, i każdy swój zamek nazywają Camelot. " - "Prawdopodobnie nadajesz się, by stać się jednym z nich, ale na pewno " - "dadzą Ci jakąś misję, byś pokaza%ł0 swoją wartość...\n\n" - "Każdy zamek ma jeden skarb (Święty Graal) w samym środku. Promień Okrągłego " - "Stołu to normalnie 28, ale z każdym znalezionym Śwętym Graalem każdy nowy " - "zamek (i jego Okrągły Stół) będzie większy.") + "Die Ritter der Runden Tafel sind die größten Krieger dieser Lande. " + "...sie sind nur nicht sehr originell, irgendwie heißen alle Schlösser Camelot... " + "Du bist wahrscheinlich ihrer würdig, allerdings musst du ihnen das sicher beweisen.\n\n" + "Jedes Schloss enthält einen einzigen Schatz - den Heiligen Gral. Dieser ist in der Mitte. " + "Der Radius einer Tafel ist normalerweise 28, allerdings wächst mit jedem Gral, den du findest, " + "das nächste Schloss (und seine Tafel).") S("It would be impolite to land on the table!", - "Byłoby niegrzecznie wylądować na stole!") -S("You jump over the table!", "Skaczesz przez stół!") + "Es wäre unhöflich, auf dem Tisch zu landen.") +S("You jump over the table!", "Du kannst nicht über die Tafel springen!") S("That was not a challenge. Find a larger castle!", - "To nie było wyzwanie. Znajdź większy zamek!") + "Das war keine Herausforderung. Finde ein größeres Schloss!") S("The Knights congratulate you on your success!", - "Rycerze gratulują Ci sukcesu!") + "Die Ritter gratulieren dir zu deinem Erfolg!") S("The Knights laugh at your failure!", - "Rycerze śmieją się z Twojej porażki!") -S("The Knights stare at you!", "Rycerze gapią się na Ciebie ze zdziwieniem!") + "Die Ritter amüsieren sich über deinen Fehlschlag!") +S("The Knights stare at you!", "Die Ritter starren dich an...") S("Come on, this is too easy... find a bigger castle!", - "Eee, to będzie za łatwe... znajdź większy zamek!") -S("The Knights wish you luck!", "Rycerze życzą powodzenia!") + "Komm schon, das ist ja ZU einfach... such ein größeres Schloss!") +S("The Knights wish you luck!", "Die Ritter wünschen dir Glück!") S("Congratulations! You have found the Holy Grail!", - "Gratulacje! Znalaz%łeś0 Świętego Graala!") + "Gratulation! Du hast den Heiligen Gral gefunden!") -S("\"I would like to congratulate you again!\"", "\"Pragnę jeszcze raz Ci pogratulować!\"") -S("\"Find the Holy Grail to become one of us!\"", "\"Znajdź Świętego Graala, by stać się jednym z nas!\"") -S("\"The Holy Grail is in the center of the Round Table.\"", "\"Święty Graal jest pośrodku Okrągłego Stołu.\"") -S("\"I enjoy watching the hyperbug battles.\"", "\"Lubię oglądać bitwy hiperinsektów.\"") -S("\"Have you visited a temple in R'Lyeh?\"", "\"By%łeś0 w świątyni w R'Lyeh?\"") -S("\"Nice castle, eh?\"", "\"Ładny zamek, co?\"") +S("\"I would like to congratulate you again!\"", "\"Ich möchte dir erneut gratulieren!\"") +S("\"Find the Holy Grail to become one of us!\"", "\"Finde den Gral, um einer von uns zu werden!\"") +S("\"The Holy Grail is in the center of the Round Table.\"", "\"Der Heilige Gral ist im Zentrum der Runden Tafel.\"") +S("\"I enjoy watching the hyperbug battles.\"", "\"Ich mag es, den Hyperkäfer-Schlachten zuzusehen.\"") +S("\"Have you visited a temple in R'Lyeh?\"", "\"Warst du schon in einem der Tempel in R'Lyeh?\"") +S("\"Nice castle, eh?\"", "\"Nettes Schloss, nicht?\"") // Temple -N("Temple of Cthulhu", GEN_F, "Świątynia Cthulhu", "Świątynie Cthulhu", "Świątynię Cthulhu", "w Świątyni Cthulhu") -N("big statue of Cthulhu", GEN_O, "pomnik Cthulhu", "pomniki Cthulhu", "pomnik Cthulhu", "pomnikiem Cthulhu") -N("Grimoire", GEN_F, "Księga", "Księgi", "Księgę", "Księgą") -N("Cult Leader", GEN_M, "Przywódca Kultu", "Przywódcy Kultu", "Przywódcę Kultu", "Przywódcą Kultu") +N("Temple of Cthulhu", GEN_M, "Cthulhus Tempel", "Cthulhus Tempel", "in Cthulhus Tempel") +N("big statue of Cthulhu", GEN_F, "große Cthulhu-Statue", "große Cthulhu-Statuen", "große Cthulhu-Statue") +N("Grimoire", GEN_N, "Grimoire", "Grimoires", "Grimoire") +N("Cult Leader", GEN_M, "Kult-Anführer", "Kult-Anführer", "Kult-Anführer") S("The temple of Cthulhu consists of many concentric circles of columns. " "You will surely encounter many Cultists there, who believe that a pilgrimage " @@ -1342,12 +1324,11 @@ S("The temple of Cthulhu consists of many concentric circles of columns. " "The circles in the temple of Cthulhu are actually horocycles. They are " "infinite, and there is an infinite number of them.", - "Świątynia Cthulhu składa się z wielu koncentrycznych kręgów kolumn. " - "Spotkasz tu wielu Kultystów, dla których pielgrzymka do wewnętrznych kręgów " - "to szansa na bycie bliżej Cthulhu, i Księgi zawierające wiele interesujących " - "sekretów.\n\n" - "Kręgi w Świątyni Cthulhu są właściwie horocyklami. Są nieskończone, i " - "jest ich nieskończenie wiele." + "Der Tempel von Cthulhu. Er besteht aus mehreren, konzentrischen Kreisen aus Säulen. " + "Du wirst sicherlich einige Okkultisten hier finden - diese glauben, eine Reise in die " + "inneren Kreise bringt sie näher zu Cthulhu selbst - und Grimoires - die sicher viele " + "sinteressante Geheimnisse verbergen.\n\n" + "Die Kreise hier sind eigentlich Horozyklen - unendlich groß, und unendlich viele davon." ) S("The Grimoires contain many secrets of the Great Old Ones. " @@ -1355,10 +1336,9 @@ S("The Grimoires contain many secrets of the Great Old Ones. " "You hope to read them when you return home, and to learn many things. " "The knowledge is valuable to you, but it is rather pointless to try to get " "several copies of the same Grimoire...", - "Te Księgi zawierają tajemnice Wielkich Przedwiecznych. " - "Każdy krąg wewnętrzny w Świątyni Cthulhu zawiera nowe Księgi, z nowymi sekretami. " - "Zamierzasz je przeczytać po powrocie do domu. Wiedza jest dla Ciebe wartościowa, " - "ale nie ma sensu, by brać kilka kopii tej samej Księgi..." + "Die Grimoires enthalten viele Geheimnisse der Großen Alten. " + "Jeder neue innere Kreis des Tempels von Cthulhu enthält neue Grimoires, mit mehr Geheimnissen. " + "Das Wissen ist dir sehr kostbar, aber es wäre natürlich sinnlos, mehrmals dasselbe Grimoire aufzuheben..." ) S("These statues of Cthulhu are too large to carry, and they don't look too " @@ -1366,23 +1346,22 @@ S("These statues of Cthulhu are too large to carry, and they don't look too " "their reasons. But you can go! When you move into the cell containing " "a statue, you push the statue to the cell you left.\n", - "Te pomniki Cthulhu są za duże, by je nosić, zresztą i tak nie wyglądają " - "na zbyt cenne. Potwory nigdy przez nie nie przechodzą... pewnie mają swoje " - "powody. Ale Ty możesz przejść! Kiedy wchodzisz na pole z pomnikiem, " - "automatycznie przesuwasz pomnik na pole, które opuści%łeś0." + "Diese Statuen von Cthulhu sind zu groß um sie zu tragen (und sehen sowieso nicht wertvoll aus). " + "Die meisten Monster gehen nie durch sie... die haben schon ihre Gründe. " + "Du aber schon! Wenn du in die Zelle gehst, in der eine steht, schiebst du sie an deinen Ursprungsort." ) S("These Cultists can push the statues, just like you.", - "Ci kultyści mogą przesuwać pomniki, tak samo jak Ty.") + "Diese Kultisten können die Statuen schieben, genau wie du.") S("You already have this Grimoire! Seek new tomes in the inner circles.", - "Już masz taką Księgę! Szukaj nowych tomów w wewnętrznych kręgach.") + "Du hast dieses Grimoire schon! Suche neue in den inneren Kreisen.") -S("You push %the1 behind you!", "Popchn%ąłeś0 %a1 za siebie.") +S("You push %the1 behind you!", "Die schiebst %den1 %1 hinter dich.") // More texts -S("Your total kills", "Łączne zabicia") +S("Your total kills", "Deine Gesamt-Kills") S( "In most lands, more treasures are generated with each enemy native to this land you kill. " @@ -1390,50 +1369,47 @@ S( "Friendly creatures and parts of monsters (such as the Ivy) do appear in the list, " "but are not counted in the total kill count.", - "W większości krain, zabijanie przeciwników pochodzących z danej krainy " - "powoduje, że generowane jest więcej skarbów. Ponadto, 100 zabić jest konieczne, " - "by móc znaleźć Cmentarz i Mrowisko.\n\n" - "Przyjazne stworzenia i części potworów (jak np. Bluszcz) występują na liście, " - "ale nie są liczone do łącznej liczby zabić.") + "In den meisten Ländern werden mehr Schätze generiert, je mehr Feinde du darin tötest. " + "Darüber hinaus benötigst du 100 Kills für den Friedhof und den Stock.\n\n" + "Freundliche Kreaturen und Monster-Teile (beispielsweise Efeu) werden zwar gezeigt, zählen aber nicht zur Gesamt-Punktzahl.") S("There must be some temples of Cthulhu in R'Lyeh...", - "Muszą być jakieś świątynie Cthulhu w R'Lyeh...") + "Es muss duch ein paar Tempel von Cthulhu in R'Lyeh geben...") S("You overheard Hedgehog Warriors talking about emeralds...", - "Podsłucha%łeś0 Jeże rozmawiające o szmaragdach...") + "Du überhörst Igelkrieger, die über Smaragde sprechen...") S("You overhear miners talking about a castle...", - "Podsłucha%łeś0 górników rozmawiających o zamku...") + "Du hörst Minenarbeiter... sie sprechen über ein Schloss...") -S("A castle in the Crossroads...", "O zamku na Skrzyżowaniu...") +S("A castle in the Crossroads...", "Ein Schloss in der Kreuzung...") /* S("You can find Temples of Cthulhu in R'Lyeh once you collect five Statues of Cthulhu.", - "Po znalezieniu 5 Statuetek Cthulhu możesz w R'Lyeh trafić na Świątynie Cthulhu.") + "Du kannst Tempel von Cthulhu in R'Lyeh finden, sobald du fünf seiner Statuen besitzt.") */ -S("You have to escape first!", "Musisz najpierw uciec!"); -S("There is not enough space!", "Nie ma miejsca!"); +S("You have to escape first!", "Du musst erst entkommen!"); +S("There is not enough space!", "Zu wenig Platz!"); -S("Customize character", "pokoloruj postać") -S("gender", "płeć") +S("Customize character", "Character anpassen") +S("gender", "Geschlecht") // -Orb("the Dragon", "Smoka") +Orb("the Dragon", "des Drachen") S("This Orb allows you to throw fire, just like the Fire Cultists.\n\n" "Each fire drains 5 charges. You are not allowed to throw fire into adjacent cells.", - "Ta sfera pozwala Ci rzucać ogniem, tak jak Ogniści Kultyści. \n\n" - "Każdy rzucony ogień wymaga 5 ładunków. Nie możesz rzucać ogniem do sąsidenich " - "komórek." + "Diese Perle erlaubt es dir, Feuer zu werfen (genau wie die Feuer-Okkultisten).\n\n" + "Jedes Feuer verbraucht 5 Ladungen. Du darfst kein Feuer auf angrenzende Zellen werfen." ) -S("You throw fire!", "Rzucasz ogniem!") +S("You throw fire!", "Du wirfst Feuer!") -Orb("Trickery", "Sztuczek") +Orb("Trickery", "des Truges") -N("Illusion", GEN_F, "Iluzja", "Iluzje", "Iluzję", "Iluzją") +N("Illusion", GEN_F, "Illusion", "Illusionen", "Illusion") S("This Orb allows you to create illusions of yourself. Illusions are targetted " "by most monsters, just like yourself, Thumpers, and your friends.\n\n" @@ -1441,40 +1417,477 @@ S("This Orb allows you to create illusions of yourself. Illusions are targetted "per turn. You can also click your illusion to take it away, restoring 4 charges.\n\n" "If you have both Orb of Teleport and Orb of Trickery, Illusion is cast " "first -- you can then teleport on your Illusion to switch places with it.", - "Ta sfera pozwala Ci tworzyć iluzje samego siebie. Większość potworów celuje w " - "iluzje, podobnie jak w Ciebie, Dudniki i Twoich przyjaciół.\n\n" - "Każda iluzja wymaga 5 ładunków do stworzenia, i jednego dodatkowego ładunku na " - "kolejkę. Możesz też kliknąć swoją iluzję by ją zabrać, co przywraca 4 ładunki.\n\n" - "Jeśli masz zarówno Sferę Teleportacji, jak i Sztuczek, Iluzja rzucana jest " - "jako pierwsza -- możesz następnie teleportować się na swoją iluzję, by się z nią " - "zamienić miejscami." + "Diese Perle erlaubt dir, Illusionen deiner selbst zu erschaffen. Diese werden " + "von den meisten Monstern verfolgt (wie du, Thumper, und deine Freunde).\n\n" + "Jede Illusion benötigt 5 Ladungen zum Erschaffen, plus eine Ladung pro Zug. " + "Du kannst deine Illusion anklicken um sie zu entfernen, wofür du 4 Ladungen bekommst.\n\n" + "Besitzt du eine Perle des Teleports und eine des Truges, wird Illusion bevorzugt -- " + "du kannst dich dann auf deine Illusion teleportieren, um die Plätze zu tauschen." ) S("Illusions are targetted " "by most monsters, just like yourself, Thumpers, and your friends.", - "Większość potworów celuje w " - "iluzje, podobnie jak w Ciebie, Dudniki i Twoich przyjaciół.") + "Illusionen werden von den meisten Monstern verfolgt " + "(wie du, Thumper, und deine Freunde).") -S("You create an Illusion!", "Tworzysz iluzję!") -S("You take the Illusion away.", "Zabierasz iluzję!") +S("You create an Illusion!", "Du erschaffst eine Illusion!") +S("You take the Illusion away.", "Du entfernst die Illusion.") -S("You cannot target that far away!", "Nie możesz celować tak daleko!") -S("You cannot target that close!", "Nie możesz celować tak blisko!") -S("Cannot teleport on a monster!", "Nie możesz teleportować się na potwora!") -S("Cannot teleport on an item!", "Nie możesz teleportować się na przedmiot!") -S("Cannot teleport here!", "Nie możesz teleportować się tutaj!") -S("Cannot cast illusion on an item!", "Nie możesz rzucić iluzji na przedmiot!") -S("Cannot cast illusion here!", "Nie możesz rzucić ilzuji tutaj!") -S("Cannot cast illusion on a monster!", "Nie możesz rzucić ilzuji na potwora!") -S("Cannot throw fire there!", "Nie możesz tego podpalić!") +S("You cannot target that far away!", "Zu weit weg!") +S("You cannot target that close!", "Zu nah!") +S("Cannot teleport on a monster!", "Kann nicht auf Monster teleportieren!") +S("Cannot teleport on an item!", "Kann nicht auf Gegenstände teleportieren!") +S("Cannot teleport here!", "Du kannst dich hierhin nicht teleportieren!") +S("Cannot cast illusion on an item!", "Kann Illusion nicht auf Gegenständen erschaffen!") +S("Cannot cast illusion here!", "Du kannst hier keine Illusion erschaffen!") +S("Cannot cast illusion on a monster!", "Kann Illusion nicht auf Monstern erschaffen!") +S("Cannot throw fire there!", "Du kannst dort kein Feuer hinwerfen!") // teleport -> target // You cannot target that close! + +S("or ESC to see how it ended", "oder ESC um zu sehen, wie alles endete") +S("high contrast", "Hoher Kontrast") +S("draw the heptagons darker", "Heptagone verdunkeln"); +S("targetting ranged Orbs Shift+click only", "Distanz-Perlen per Shift-Klick") +S("Shift+F, Shift+O, Shift+T, Shift+L, Shift+U, etc.", + "Shift+F, Shift+O, Shift+T, Shift+L, Shift+U, etc.") + S("also hold Alt during the game to toggle high contrast", + "Du kannst auch ALT im Spiel halten, um hohen Kontrast umzuschalten") + +// Crossroads II + +N("Crossroads II", GEN_N, "II. Kreuzung", "II. Kreuzungen", "auf der II. Kreuzung") + +S( + "An alternate layout of the Crossroads. It is more dense and more regular, " + "although you won't find the castle of Camelot here.", + + "Ein alternatives Layout der Kreuzung. Es ist beständiger und dichter, aber du findest Camelot hier nicht.") + +// Caribbean + +N("Caribbean", GEN_F, "Karibik", "Karibiken", "auf der Karibik") + +N("Pirate", GEN_M, "Pirat", "Piraten", "Pirat") +N("Shark", GEN_M, "Hai", "Haie", "Hai") +N("Parrot", GEN_F, "Papagei", "Papageien", "Papagei") +N("Pirate Treasure", GEN_M, "Piratenschatz", "Piratenschätze", "Piratenschatz") +N("Compass", GEN_M, "Kompass", "Kompasse", "Kompass") + +N("sea", GEN_M, "See", "Seen", "See") +N("boat", GEN_N, "Boot", "Boote", "Boot") +N("island", GEN_F, "Insel", "Inseln", "Insel") +N("tree", GEN_M, "Baum", "Bäume", "Baum") + +Orb("Time", "der Zeit") + +S("This dangerous sea contains nasty sharks and pirates. ", + "Dieser gefährliche See enthält fiese Haie und Piraten.") + +S("The islands of Caribbean are infinite and circular, and " + "the pirates probably have hidden their treasures somewhere far from the coast.", + "Die Inseln der Karibik sind unzählig und kreisförmig -- die Piraten haben " + "ihre Schätze sicher fernab der Küste versteckt.") + +S( + "Hyperbolic pirates do not need huge ships, since so many lands to conquest " + "are so close. These small boats are enough for them.\n\n" + "Boats allow you to go through water. If you are in a boat, you can move into " + "a water cell (and the boat will come with you).", + + "Hyperbolische Piraten brauchen keine riesigen Schiffe -- so viele Länder zum " + "Erobern sind ja ziemlich dicht zusammen. Diese kleinen Boote reichen ihnen.\n\n" + "Boote lassen dich durch Wasser bewegen. Bist du in einem, kannst du auf eine Wasser-" + "Zelle gehen (und das Boot kommt natürlich mit).") + +S( + "The forests of Caribbean are too dense to be traversed by humans, " + "and they are hard to burn. Many colorful parrots can be found there.", + "Die karibischen Wälder sind zu dicht um von Menschen durchquert zu werden, " + "und brennen nur schwerlich. Es gibt hier aber viele, farbenfrohe Papageien.") + +S("Ye wonder where did th' Pirates find all these riches...", + "Du fragst dich, woher die Piraten all diese Schätze haben...") + +S( + "The hyperbolic pirates have no use for treasure maps. However, they have found " + "out that a compass points to the center of the island. So they just go as " + "far towards the center as they can, and hide their treasure there.", + + "Die hyperbolischen Piraten haben für Schatzkarten keinen Gebrauch. Allerdings " + "fanden sie heraus, dass ein Kompass in die Mitte einer Insel zeigt -- " + "also gehen sie so weit dort hin, wie sie können, und verstecken dort ihre Schätze.") + +S("Just a nasty shark.", "Ist bloß ein fieser Hai.") + +S("Parrots feel safe in the forests of Caribbean, so they " + "never leave them. But they will help the Pirates by attacking the intruders.", + + "Papageien fühlen sich sicher in den karibischen Wäldern, daher verlassen sie diese nie. " + "Allerdings helfen sie den Piraten beim Angreifen der Eindringlinge.") + +S("Just a typical hyperbolic pirate.", "Ist bloß ein typischer, hyperbolischer Pirat. Mit Augenklappe und so.") + +S( + "Normally, the power of most Orbs slowly fades away, even when " + "you are not actively using them. This Orb prevents this.\n\n" + + "When you have the Orb of Time, Orbs which are not active won't lose their power. " + "Orbs are considered active if they have a continuous power which has actually " + "affected something in the last turn.\n\n" + + "Orbs of Shielding remain active after being activated (even if you are no longer " + "attacked), and Orbs of Time have a bigger cap inside their native Caribbean than " + "outside.", + + "Normalerweise schwindet die Kraft der meisten Perlen, sogar wenn du sie nicht einsetzt. " + "Die Perle der Zeit verhindert dies.\n\n" + + "Besitzt du eine, verlieren nicht-aktive Perlen keine Kraft. " + "Perlen zählen als aktiv, wenn sie eine andauernde Kraft haben, die letzten Zug " + "etwas beeinflusst hat.\n\n" + + "Perlen des Schutzes bleiben nach Aktivierung aktiv (auch wenn du nicht mehr angegriffen wirst), " + "und Perlen der Zeit halten in der Karibik länger als an anderen Orten.") + +// Achievements: + +// Parrot : Find and collect Pirate Treasure. +// Caribbean Shark : Collect 10 Pirate Treasures. +// Pirate : Collect 25 Pirate Treasures. +// Master of Caribbean : Collect 50 Pirate Treasures. + +// Red Rock Valley + +N("Red Rock Valley", GEN_N, "Rotfelsental", "Rotfelsentäler", "im Rotfelsental") + +N("Rock Snake", GEN_F, "Felsenschlange", "Felsenschlangen", "Felsenschlange") +N("Rock Snake Tail", GEN_M, "Felsenschlangenschweif", "Felsenschlangenschweifs", "Felsenschlangenschweif") +N("Red Troll", GEN_M, "Roter Troll", "Rote Trolle", "Roten Troll") +N("Red Gem", GEN_M, "Roter Stein", "Rote Steine", "Roten Stein") + +N("rock I", GEN_M, "Fels I", "Felsen I", "Fels I") +N("rock II", GEN_M, "Fels II", "Felsen II", "Fels II") +N("rock III", GEN_M, "Fels III", "Felsen III", "Fels III") + +Orb("Space", "des Raumes") + +S("Not enough power for telekinesis!", "Nicht genügend Macht für Telekinese!") + +S("This land contains high rock formations. Most of the valley is at level 0, " + "while items are found at level 3. It is impossible to gain two or more levels, " + "or to lose three levels, in a single move, (attacks are possible at any " + "difference, though). Kill Red Trolls and Rock Snakes to make a cell higher.", + + "Dieses Land enthält hohe Fels-Formationen. Der Großteil des Tals ist auf Ebene 0, " + "aber die meisten Gegenstände finden sich auf Ebene 3 (III). " + "Du kannst immer nur eine Ebene rauf (0 > I > II > III), oder bis zu zwei runter. " + "Angriffe sind auf jeder Höhe möglich. Töte Rote Trolle und Felsenschlangen, um eine " + "Zelle zu erhöhen.") + +S("A kind of Troll native to the Red Rock Valley.", + "Eine spezielle Troll-Gattung, die im Rotfelsental lebt.") + +S( + "Rock snakes are similar to Sandworms, but they move each turn. However, they " + "only move on the hexagonal cells. They are also somewhat longer than the Sandworms.", + + "Felsenschlangen sind Sandwürmern ähnlich, allerdings bewegen sie sich jeden Zug. " + "Dafür meiden sie allerdings heptagonale Zellen. Sie sind auch länger als Sandwürmer.") + +S("A gem from the Red Rock Valley.", "Ein Edelstein aus dem Rotfelsental.") + +S( + "This Orb is able to bring faraway items to your location, even if there are " + "monsters or barriers on the way. The cost of " + "bringing an item (in charges) equals the square of its distance to you. Contrary " + "to some other Orbs, usage is not allowed if you have not enough power left.", + + "Diese Perle kann entfernte Gegenstände zu dir bringen, auch wenn Monster oder Barrieren im Weg sind. " + "Die Ladungs-Kosten dafür ist die Distanz des Gegenstands zu dir zum Quadrat. " + "Anders als ein paar andere Perlen kannst du diese nicht benutzen, wenn sie nicht genug Ladungen hat.") + +// Climber : Find and collect a Red Gem. +// Red Troll : Collect 10 Red Gems. +// Rock Snake : Collect 25 Red Gems. +// Master of Red Rock : Collect 50 Red Gems. + +// missing sentences + +S("%The1 drowns!", "%Der1 %1 ertrinkt!"); +S("%The1 falls!", "%Der1 %1 fällt!"); + +// these were missing from the translation for some reason + +S("Hell has these lakes everywhere... They are shaped like evil stars, and filled with burning sulphur.", + "Diese Seen sind überall in der Hölle... Sie sehen aus wie böse Sterne, und sind voller flammendem Schwefel.") + +// Hardcore Mode + +S("hardcore mode", "HARDCORE-MODUS"); + +S("One wrong move and it is game over!", "Eine falsche Bewegung kostet dich den Kopf!"); +S("Not so hardcore?", "Doch nicht so hardcore?"); + +// Shoot'em up Mode + +S("shoot'em up mode", "Baller-Modus"); +S("Welcome to the Shoot'em Up mode!", "Willkommen im Baller-Modus!"); +S("F/;/Space/Enter/KP5 = fire, WASD/IJKL/Numpad = move", "F/[;]/[LEER]/[ENTER]/[Numpad 5] = schießen, WASD/IJKL/[Numpad] = bewegen"); + +N("Rogue", GEN_M, "Schurke", "Schurken", "Schurken") +N("Knife", GEN_N, "Messer", "Messer", "Messer") +N("Flail", GEN_M, "Morgenstern", "Morgensterne", "Morgenstern") +N("Fireball", GEN_M, "Feuerball", "Feuerbälle", "Feuerball") +N("Tongue", GEN_F, "Zunge", "Zungen", "Zunge") + +S("In the Shoot'em Up mode, you are armed with thrown Knives.", + "Im Baller-Modus bist du mit Wurfmessern bewaffnet.") +S("A simple, but effective, missile, used by rogues.", + "Eine einfache, aber effektive, Wurfwaffe. Schurken verwenden sie.") +S("This attack is likely to hit the attacker.", + "Dieser Angriff trifft wahrscheinlich den Angreifer.") +S("This magical missile burns whatever it hits.", "Dieses magische Geschoss verbrennt alles, was sie trifft.") +S("Some monsters have long tongues, which allow them to attack enemies in nearby cells.", + "Manche Monster haben lange Zungen, mit denen sie Feinde in nahen Zellen angreifen können.") + +// modes for the local highscores + +S(", m - mode: normal", ", m - Modus: Normal") +S(", m - mode: hardcore only", ", m - Modus: Hardcore") +S(", m - mode: shoot'em up", "m - Modus: Ballern") + +// update description for Steam: + +// (Shoot'em Up mode and two more lands than in the free version, and more are planned!) + +// missing lines: + +S("You would get hurt!", "Du würdest dir wehtun!") +S("PARTIAL", "TEILWEISE") + +S("Cannot drop %the1 here!", "Du kannst %den1 %1 hier nicht fallenlassen!"); + +// Euclidean scores +S(" (E:%1)", " (E:%1)"); + +S("You cannot attack Rock Snakes directly!", "Du kannst Felsenschlangen nicht direkt angreifen!"); + +S("\"I am lost...\"", "\"Ich bin verloren...\""); + +S("You are killed by %the1!", "%Der1 %1 tötet dich!") + +// new menu for Version 7.1 + +S("(v) menu", "Menü - V") +S("return to the game", "zurück zum Spiel") +S("or 'v' to see the main menu", "oder V um das Menü einzublenden") + +S("HyperRogue %1", "HyperRogue %1") +S("basic configuration", "Einstellungen") +S("advanced configuration", "(Erweitert)") +S("local highscores", "Highscores (Lokal)") +S("help", "Hilfe") +S("restart game", "Neustart") +S("special game modes", "Spielmodi") +S("save the game", "Speichern") +S("quit the game", "Beenden") +S("review your quest", "Quest anzeigen") +S("review the scene", "Die Szene anzeigen") +S("game over screen", "Game-Over-Bildschirm") +S("continue game", "Weiter") +S("play the game!", "Spielen!") + +// fixed descriptions for Shmup achievements + +S("You have used less knives than ever before. Congratulations!", + "Du hast weniger Messer als zuvor benutzt. Gratulation!") + +S("You have improved both your real time and knife count. Congratulations!", + "Du hast sowohl weniger Zeit als auch Messer als zuvor benutzt. Gratulation!") + +S("%1 knives (%2)", "%1 Messer (%2)") + +// temporary +S("No description yet." ,"Noch keine Beschreibung...") + +// special case when no Spice is visible +S("The sandworm explodes!", "Der Sandwurm explodiert!") + +// Ocean + +// achievements: +// Reached Ocean: Find and collect an Amber. +// Albatross: Collect 10 Ambers. +// Amber Albatross: Collect 25 Ambers. +// Master of the Tides: Collect 50 Ambers. + +N("Ocean", GEN_M, "Ozean", "Ozeane", "im Ozean") + +S( + "You can collect some valuable Ambers on the coast, but beware the tides!\n\n" + "You can also take one of the boats and venture into the Ocean, " + "to find other coasts, dangerous whirlpools, and islands inhabited by Pirates.", + + "Du kannst Bernsteine auf den Küsten sammeln, aber achte auf die Gezeiten!\n\n" + "Du kannst ebenso eines der Boote nehmen und in den Ozean reisen " + "um andere Küsten, gefährliche Strudel, und piratenbesetzte Inseln zu finden.") + +N("Albatross", GEN_M, "Albatross", "Albatrosse", "Albatross") + +S( + "Those large seabirds attack you for some reason. At least they are not " + "as fast as Eagles...", + "Diese großen Seevögel greifen dich aus irgendeinem Grund an. " + "Wenigstens sind sie langsamer als Adler...") + +N("stranded boat", GEN_N, "gestrandetes Boot", "gestrandete Boote", "gestrandete Boot") + +S( + "This boat cannot go through the sand. But if you sit inside and " + "wait for the tide, you will be able to use it to travel through the Ocean.", + + "Dieses Boot kann nicht durch den Sand schwimmen. Wartest du allerdings bis zur Flut, " + "kannst du damit durch den Ozean reisen." + ) + +N("Amber", GEN_M, "Bernstein", "Bernsteine", "Bernstein") + +S( + "When the tide is away, beautiful ambers can be found on the hyperbolic beaches. " + "Perhaps there used to be a forest here?" , + "Bei Ebbe können wunderschöne Bernsteine auf den hyperbolischen Stränden gefunden werden. Vielleicht war hier früher ein Wald...?") + +Orb("Air", "der Luft") + +S("This Orb allows you to blow your enemies away.\n\n" + "Click a monster to blow it one cell away. It cannot be used against mimics, ghosts, sharks and other monsters restricted to a specific terrain, and multi-tile monsters.", + "Diese Perle erlaubt es dir, deine Feinde wegzupusten.\n\n" + "Klicke auf ein Monster, um es eine Zelle wegzupusten. Die Perle ist wirkungslos gegenüber Mimiken, Geistern, Haien, und anderen Monstern, die nur auf bestimmten Terrain leben können. Monster, die größer als eine Zelle sind, sind auch immun." + ) + + +N("Sea Border", GEN_F, "Seegrenze", "Seegrenzen", "Seegrenze") + +S("Border between seas.", "Eine Grenze zwischen Seen.") + +// Whirlpool + +// achievements: +// Escaped Whirlpool: Collect a Pearl, and escape the Whirlpool. +// Vortex Shark: Collect 10 Pearls. +// Vortex Pirate: Collect 25 Pearls. +// Master of the Whirlpool: Collect 50 Pearls. + +N("Whirlpool", GEN_M, "Strudel", "Strudel", "im Strudel") + +S( + "Many lost boats are spinning in this whirlpool. Some of them contain treasures " + "and Pirates.\n\n" + "Unmanned boats will go one cell clockwise in each turn. Sharks and manned boats " + "are only allowed to go with the current, that is, towards the center, or clockwise.", + + "Viele verlorene Boote wirbeln in diesem Strudel... manche enthalten Schätze oder Piraten.\n\n" + "Unbemannte Boote bewegen sich jeden Zug eine Zelle im Uhrzeigersinn. " + "Haie und bemannte Boote dürfen nur mit der Strömung schwimmen (das heißt, zur Mitte oder im Uhrzeigersinn)." + ) + +N("Pearl", GEN_F, "Perle", "Perlen", "Perle") + +S( + "You do not know exactly why, but there are valuable pearls on many boats " + "in the whirlpool.", + "Du weißt nicht genau warum, aber es gibt schöne Perlen auf vielen Booten im Strudel." + ) + +Orb("Water", "des Wassers") + +S( "This Orb allows your boat to go against the current, " + "and also to go into the land, creating water on the way.", + "Diese Perle erlaubt es dir, gegen die Strömung zu schwimmen. " + "Du kannst damit auch durch Land schwimmen (wobei du Wasser kreierst).") + +S("You cannot go against the current!", "Du kannst nicht gegen die Strömung schwimmen!") + +// Minefield + +// achievements: +// Reached Minefield: Collect a Bomberbird Egg. +// Minesweeper: Collect 10 Bomberbird Eggs. +// Bomberbird: Collect 25 Bomberbird Eggs. +// Master of the Minefield: Collect 50 Bomberbird Eggs. + +N("Minefield", GEN_N, "Minenfeld", "Minenfelder", "im Minenfeld") +N("minefield", GEN_F, "Mine?", "Minen?", "Mine?") +N("cell without mine", GEN_F, "minenlose Zelle", "minenlose Zellen", "minenlose Zelle") + +S( + "This minefield has been created by the Bomberbirds to protect their valuable eggs. " + "Mines explode when they are stepped on, creating fire all around them " + "(this fire never expires in the Minefield). If you don't step on a mine, you " + "know the number of mines in cells around you. These numbers are marked with " + "color codes on the cells you have visited.", + "Dieses Minenfeld wurde von den Bombenvögeln erschaffen, um ihre wertvollen Eier zu schützen. " + "Minen explodieren, wenn sie betreten werden, was Feuer um sie herum erzeugt (dieses erlischt im Minenfeld nicht). " + "Wenn du nicht auf eine trittst, weißt du, wie viele Minen um dich herum sind. " + "Diese Zahlen werden farblich markiert auf Zellen, die du besucht hast." + ) + +N("Bomberbird", GEN_M, "Bombenvogel", "Bombenvögel", "Bombenvogel") + +S( + "Dark red birds who have created the minefield.\n\n" + "They create a mine on the spot where they are killed, provided " + "that the terrain is suitable. Also note that mines are triggered " + "by dead birds falling on them.", + + "Dunkelrote Vögel, die das Minenfeld erschufen.\n\n" + "Sie erzeugen eine Mine dort, wo sie sterben (vorausgesetzt, das Terrain passt). " + "Tote, fallende Vögel lösen Minen auch aus!") + +N("Tame Bomberbird", GEN_M, "Zahmer Bombenvogel", "Zahme Bombenvögel", "Zahmen Bombenvogel") + +S( + "This bomberbird will follow you at some distance, and attack your enemies. " + "You can kill it to place a mine.", + + "Dieser Bombenvogel folgt dir auf Distanz, und attackiert deine Feinde. " + "Du kannst ihn töten, um eine Mine zu legen.") + +N("Bomberbird Egg", GEN_N, "Bombenvogel-Ei", "Bombenvogel-Eier", "Bombenvogel-Ei") + +S( + "Bomberbird eggs are big and tasty, and thus valuable. " + "They can hatch when left alone for some time (but this will never happen " + "if you are watching).", + + "Bombenvogel-Eier sind groß und schmackhaft - daher wertvoll. " + "Sie können nach einiger Zeit schlüpfen (aber machen dies nie, wenn du zusiehst).") + + +Orb("Friendship", "der Freundschaft") + +S("This Orb summons a friendly Bomberbird.", + "Diese Perle ruft einen freundlich gesinnten Bombenvogel herbei.") + +S("Still confused? Read the FAQ on the HyperRogue website!\n\n", + "Noch verwirrt? Lies das FAQ auf der HyperRogue-Webseite.\n\n") + +S("Nowhere to blow %the1!", "Kein Platz um %den1 %a1 wegzupusten!") +S("%The1 is immune to wind!", "%Der1 %1 ist gegen immun gegen Wind!") +S("You blow %the1 away!", "Du bläst %den1 %a1 weg!") + +S("WARNING: you are entering a minefield!", "ACHTUNG: Du betrittst ein Minenfeld!") +S("No mines next to you.", "Keine Minen um dich.") +S("A mine is next to you!", "1 Mine um dich!") +S("Two mines next to you!", "2 Minen um dich!") +S("Three mines next to you!", "3 Minen um dich!") +S("Four mines next to you!", "4 Minen um dich!") +S("Five mines next to you!", "5 Minen um dich!") +S("Six mines next to you!", "6 Minen um dich!") +S("Seven mines next to you!", "7 Minen um dich!") + +S("You have to run away from the water!", "Du musst vor dem Wasser fliehen!") #undef Orb -S("or ESC to see how it ended", "lub ESC by zobaczyć, jak się skończyło") -S("high contrast", "wysoki kontrast") -S("draw the heptagons darker", "siedmiokąty ciemniejsze"); -S("targetting ranged Orbs with Shift+click only", "celowanie zdalne tylko Shift+klik") -S("Shift+F, Shift+O, Shift+T, Shift+L, Shift+U, etc.", - "Shift+F, Shift+O, Shift+T, Shift+L, Shift+U, itd.") diff --git a/language-pl.cpp b/language-pl.cpp index dfd11410..6f0b0208 100644 --- a/language-pl.cpp +++ b/language-pl.cpp @@ -117,21 +117,21 @@ N("chasm", GEN_N, "przepaść", "przepaści", "przepaść", "przepaścią") N("big tree", GEN_N, "duże drzewo", "duże drzewa", "duże drzewo", "dużym drzewem") N("tree", GEN_N, "drzewo", "drzewo", "drzewo", "drzewem") // lands -N("Great Wall", GEN_N, "Wielka Ściana", "Wielkie Ściany", "Wielką Ścianę", "na Wielkiej Ścianie") -N("Crossroads", GEN_N, "Skrzyżowanie", "Skrzyżowania", "Skrzyżowanie", "na Skrzyżowaniu") -N("Desert", GEN_F, "Pustynia", "Pustynie", "Pustynię", "na Pustyni") -N("Icy Land", GEN_F, "Lodowa Kraina", "Lodowe Krainy", "Lodową Krainę", "w Lodowej Krainie") -N("Living Cave", GEN_F, "Żywa Jaskinia", "Żywe Jaskinie", "Żywą Jaskinię", "w Żywej Jaskini") -N("Jungle", GEN_F, "Dżungla", "Dżungle", "Dżunglę", "w Dżungli") -N("Alchemist Lab", GEN_N, "Laboratorium", "Laboratoria", "Laboratorium", "w Laboratorium") -N("Mirror Land", GEN_F, "Kraina Luster", "Krainy Luster", "Krainę Luster", "w Krainie Luster") -N("Graveyard", GEN_O, "Cmentarz", "Cmentarze", "Cmentarz", "na Cmentarzu") +N("Great Wall", GEN_N, "Wielka Ściana", "Wielka Ściana", "Wielką Ścianę", "na Wielkiej Ścianie") +N("Crossroads", GEN_N, "Skrzyżowanie", "Skrzyżowanie", "Skrzyżowanie", "na Skrzyżowaniu") +N("Desert", GEN_F, "Pustynia", "Pustynia", "Pustynię", "na Pustyni") +N("Icy Land", GEN_F, "Lodowa Kraina", "Lodowa Kraina", "Lodową Krainę", "w Lodowej Krainie") +N("Living Cave", GEN_F, "Żywa Jaskinia", "Żywa Jaskinia", "Żywą Jaskinię", "w Żywej Jaskini") +N("Jungle", GEN_F, "Dżungla", "Dżungla", "Dżunglę", "w Dżungli") +N("Alchemist Lab", GEN_N, "Laboratorium", "Laboratorium", "Laboratorium", "w Laboratorium") +N("Mirror Land", GEN_F, "Kraina Luster", "Kraina Luster", "Krainę Luster", "w Krainie Luster") +N("Graveyard", GEN_O, "Cmentarz", "Cmentarz", "Cmentarz", "na Cmentarzu") N("R'Lyeh", GEN_N, "R'Lyeh", "R'Lyeh", "R'Lyeh", "w R'Lyeh") -N("Hell", GEN_N, "Piekło", "Piekła", "Piekło", "w Piekle") +N("Hell", GEN_N, "Piekło", "Piekło", "Piekło", "w Piekle") N("Cocytus", GEN_M, "Kocyt", "Kocyt", "Kocytu", "w Kocycie") -N("Land of Eternal Motion", GEN_N, "Kraina Wiecznego Ruchu", "Krainy Wiecznego Ruchu", "Krainę Wiecznego Ruchu", "w Krainie Wiecznego Ruchu") -N("Dry Forest", GEN_M, "Puszcza", "Puszcze", "Puszczę", "w Puszczy") -N("Game Board", GEN_F, "Plansza", "Plansze", "Planszę", "na Planszy") +N("Land of Eternal Motion", GEN_N, "Kraina Wiecznego Ruchu", "Kraina Wiecznego Ruchu", "Krainę Wiecznego Ruchu", "w Krainie Wiecznego Ruchu") +N("Dry Forest", GEN_M, "Puszcza", "Puszcza", "Puszczę", "w Puszczy") +N("Game Board", GEN_F, "Plansza", "Plansza", "Planszę", "na Planszy") // Game messages @@ -212,10 +212,10 @@ S("You have found the Key! Now unlock this Orb of Yendor!", "Znalaz%łeś0 Klucz S("This orb is dead...", "Ta sfera jest martwa...") S("Another Dead Orb.", "Jeszcze jedna Martwa Sfera.") S("You have found %the1!", "Znalaz%łeś0 %a1!") -S("You feel that %the2 become%s2 more dangerous.", "Masz wrażenie, że %2 staje się bardziej niebezpieczn%ya2.") +S("You feel that %the2 become%s2 more dangerous.", "Masz wrażenie, że %P2 staje się bardziej niebezpieczn%ya2.") S("With each %1 you collect...", "Z każd%ymą1 %abl1, które znajdujesz...") S("Are there any magical orbs in %the1?...", "Czy %abl1 są jakieś magiczne sfery?") -S("You feel that %the1 slowly become%s1 dangerous...", "Masz wrażenie, że %1 powoli staje się niebezpieczn%ya1...") +S("You feel that %the1 slowly become%s1 dangerous...", "Masz wrażenie, że %P1 powoli staje się niebezpieczn%ya1...") S("Better find some other place.", "Lepiej znajdź inne miejsce.") S("You have a vision of the future, fighting demons in Hell...", "Masz wizję przyszłości, w której walczysz z demonami w Piekle...") S("With this Elixir, your life should be long and prosperous...", "Ten Eliksir pozwoli Ci na długie i szczęśliwe życie...") @@ -233,7 +233,7 @@ S("To access Hell, collect 10 treasures each of 9 kinds...", "By dostać się do S("Abandon all hope, the gates of Hell are opened!", "Porzuć wszelką nadzieję, bramy Piekła są otwarte!") S("And the Orbs of Yendor await!", "I sfery Yendoru czekają!") S("You switch places with %the1.", "Zamieniasz się miejscami z %abl1.") -S("You rejoin %the1.", "Połączy%łeś1 się z %abl1.") +S("You rejoin %the1.", "Połączy%łeś0 się z %abl1.") S("The mirror shatters!", "Lustro pęka!") S("The cloud turns into a bunch of images!", "Chmura zamienia się w obrazy!") S("The slime reacts with %the1!", "Maź reaguje z %abl1!") @@ -856,8 +856,10 @@ S( "and other land types bring magical orbs.\n\n" "A special treasure, Hyperstone, can be found on the Crossroads, but only " "after you have found 10 of every other treasure.", - "Ta kraina jest szybkim przejściem do pozostałych krain. Bardzo łatwo dostać się " - "stąd do pozostałych krain. Również potwory z tych krain łatwo tutaj wejdą!\n\n" + + "Ta kraina jest szybkim przejściem do pozostałych krain.\n\n" + "Bardzo łatwo stąd dostać się do większości miejsc, ale można też tu spotkać " + "potwory z różnych stron!\n\n" "Możesz znaleźć magiczne przedmioty na Skrzyżowaniu, jeśli zdoby%łeś0 wystarczająco " "wiele skarbów w ich rodzinnych krainach. Są to sfery, magiczne lustra i chmury.\n\n" "Specyficzne skarby Skrzyżowań, Hiperkamienie, można znaleźć na Skrzyżowaniu, ale tylko " @@ -900,7 +902,7 @@ S("This frozen lake is a hellish version of the Icy Land. Now, your body heat me S("A land where you cannot stop, because every piece of floor is extremely unstable. Only monsters who " "can run forever are able to survive there, and only phoenix feathers are so light that they do not disturb " "the floor.\n", - "Kraina, w której nie możesz przestać się ruszać, bo każdy fragment podłogi jest bardzo niestabilna. " + "Kraina, w której nie możesz przestać się ruszać, bo grunt jest wszędzie bardzo niestabilny. " "Jedynie stworzenia będące w stanie wiecznie się ruszać mogą tu przeżyć, i jedynie pióra feniksa " "są na tyle lekkie, by nie zaburzyć podłogi.") @@ -973,7 +975,7 @@ S("Collect 60 $$$ to access even more lands", "Znajdź 60 $$$ by iść do kolejn // Emerald Mine -N("Emerald Mine", GEN_F, "Kopalnia Szmaragdów", "Kopalnie Szmaragdów", "Kopalnię Szmaragdów", "w Kopalni Szmaragdów") +N("Emerald Mine", GEN_F, "Kopalnia Szmaragdów", "Kopalnia Szmaragdów", "Kopalnię Szmaragdów", "w Kopalni Szmaragdów") N("Pikeman", GEN_M, "Pikinier", "Pikinierzy", "Pikiniera", "Pikinierem") N("Flail Guard", GEN_M, "Strażnik z cepem", "Strażnicy z cepami", "Strażnika z cepem", "Strażnikiem z cepem") N("Miner", GEN_M, "Górnik", "Górnicy", "Górnika", "Górnikiem") @@ -1029,12 +1031,12 @@ S("This orb allows you to instantly kill a non-adjacent enemy by clicking it. " "Ta sfera pozwala natychmiastowo zabić niesąsiadującego przeciwnika (klikając go). " "Każde użycie zmniejsza poziom naładowania o 30.") -S("%The1 is immune to mental blasts!", "%1 jest odporn%y1 na atak psychiczny!") -S("You kill %the1 with a mental blast!", "Zabi%łeś1 %a2 mocą psychiczną!") +S("%The1 is immune to mental blasts!", "%1 jest odporn%ya1 na atak psychiczny!") +S("You kill %the1 with a mental blast!", "Zabi%łeś0 %a1 mocą psychiczną!") // Vineyard -N("Vineyard", GEN_F, "Winnica", "Winnice", "Winnicę", "w Winnicy") +N("Vineyard", GEN_F, "Winnica", "Winnica", "Winnicę", "w Winnicy") N("Vine Beast", GEN_M, "Winny Stwór", "Winne Stwory", "Winnego Stwora", "Winnym Stworem") N("Vine Spirit", GEN_M, "Winny Duszek", "Winne Duszki", "Winnego Duszka", "Winnym Duszkiem") N("vine", GEN_F, "winorośl", "winorośle", "winorośl", "winoroślą") @@ -1083,7 +1085,7 @@ Orb("Aether", "Eteru") // Dead Caves -N("Dead Cave", GEN_F, "Martwa Jaskinia", "Martwe Jaskinie", "Martwą Jaskinię", "w Martwej Jaskini") +N("Dead Cave", GEN_F, "Martwa Jaskinia", "Martwa Jaskinia", "Martwą Jaskinię", "w Martwej Jaskini") N("Dark Troll", GEN_M, "Mroczny Troll", "Mroczne Trolle", "Mrocznego Trolla", "Mrocznym Trollem") N("Earth Elemental", GEN_M, "Żywiołak", "Żywiołaki", "Żywiołaka", "Żywiołakiem") N("dead wall", GEN_F, "martwa ściana", "martwe ściany", "martwą ścianę", "martwą ścianą") @@ -1113,7 +1115,7 @@ S( "Somehow, this cave has not received the spark of Life yet.", "Dziwnym trafem, ta jaskinia jeszcze nie zdobyła iskry Życia.") // Hive -N("Hive", GEN_N, "Mrowisko", "Mrowiska", "Mrowisko", "w Mrowisku") +N("Hive", GEN_N, "Mrowisko", "Mrowisko", "Mrowisko", "w Mrowisku") N("Red Hyperbug", GEN_M, "Czerwony Hiperinsekt", "Czerwone Hiperinsekty", "Czerwonego Hiperinsekta", "Czerwonym Hiperinsektem") N("Green Hyperbug", GEN_M, "Zielony Hiperinsekt", "Zielone Hiperinsekty", "Zielonego Hiperinsekta", "Zielonym Hiperinsektem") N("Blue Hyperbug", GEN_M, "Niebieski Hiperinsekt", "Niebieskie Hiperinsekty", "Niebieskiego Hiperinsekta", "Niebieskim Hiperinsektem") @@ -1154,7 +1156,7 @@ S("This orb lets you go through living walls. It also has powers in some of the // Land of Power -N("Land of Power", GEN_F, "Kraina Mocy", "Krainy Mocy", "Krainą Mocy", "w Krainie Mocy") +N("Land of Power", GEN_F, "Kraina Mocy", "Kraina Mocy", "Krainą Mocy", "w Krainie Mocy") N("Witch Apprentice", GEN_F, "Uczennica", "Uczennice", "Uczennicę", "Uczennicą") N("Speed Witch", GEN_F, "Czarownica Szybka", "Czarownice Szybkie", "Czarownicę Szybką", "Czarownicą Szybką") N("Flash Witch", GEN_F, "Czarownica Błysku", "Czarownice Błysku", "Czarownicę Błysku", "Czarownicą Błysku") @@ -1197,7 +1199,7 @@ S( "The Land of Power is filled with everburning fire, magical Orbs, and guarde "Witches are allowed to use all the powers of the " "basic orbs against intruders. These powers never expire, but a Witch " "can use only one power at a time (not counting Orbs of Life).\n\n" - "Witches and Golems don't pursue you into other Lands. Also, most Orb powers" + "Witches and Golems don't pursue you into other Lands. Also, most Orb powers " "are drained when you leave the Land of Power.", "Kraina Mocy jest wypełniona wiecznie płonącym ogniem, magicznymi Sferami, " "i strzeżona przez Czarownice i golemy. Podstawowe Sfery walają się wszędzie, a " @@ -1327,7 +1329,7 @@ S("\"Nice castle, eh?\"", "\"Ładny zamek, co?\"") // Temple -N("Temple of Cthulhu", GEN_F, "Świątynia Cthulhu", "Świątynie Cthulhu", "Świątynię Cthulhu", "w Świątyni Cthulhu") +N("Temple of Cthulhu", GEN_F, "Świątynia Cthulhu", "Świątynia Cthulhu", "Świątynię Cthulhu", "w Świątyni Cthulhu") N("big statue of Cthulhu", GEN_O, "pomnik Cthulhu", "pomniki Cthulhu", "pomnik Cthulhu", "pomnikiem Cthulhu") N("Grimoire", GEN_F, "Księga", "Księgi", "Księgę", "Księgą") N("Cult Leader", GEN_M, "Przywódca Kultu", "Przywódcy Kultu", "Przywódcę Kultu", "Przywódcą Kultu") @@ -1467,7 +1469,6 @@ S("Cannot throw fire there!", "Nie możesz tego podpalić!") // teleport -> target // You cannot target that close! -#undef Orb S("or ESC to see how it ended", "lub ESC by zobaczyć, jak się skończyło") S("high contrast", "wysoki kontrast") @@ -1478,3 +1479,1250 @@ S("Shift+F, Shift+O, Shift+T, Shift+L, Shift+U, etc.", "Shift+F, Shift+O, Shift+T, Shift+L, Shift+U, itd.") S("also hold Alt during the game to toggle high contrast", "Alt podczas gry przełącza wysoki kontrast") + +// Crossroads II + +N("Crossroads II", GEN_N, "Skrzyżowanie II", "Skrzyżowania II", "Skrzyżowanie II", "na Skrzyżowaniu II") + +S( + "An alternate layout of the Crossroads. It is more dense and more regular, " + "although you won't find the castle of Camelot here.", + + "Alternatywny układ Skrzyżowania. Jest gęstszy i bardziej regularny, " + "choć nie znajdziesz tutaj zamku Camelot.") + +// Caribbean + +// note: in Polish, +// 'Karaiby' is plural in Polish, should probably fix the grammar for this + +N("Caribbean", GEN_N, "Karaiby", "Morze Karaibskie", "Karaibów", "na Karaibach") + +N("Pirate", GEN_M, "Pirat", "Piraci", "Pirata", "Piratem") +N("Shark", GEN_M, "Rekin", "Rekiny", "Rekina", "Rekinem") +N("Parrot", GEN_F, "Papuga", "Papugi", "Papugę", "Papugą") +N("Pirate Treasure", GEN_M, "Skarb Piratów", "Skarby Piratów", "Skarb Piratów", "Skarbem Piratów") +N("Compass", GEN_M, "Kompas", "Kompasy", "Kompas", "Kompasem") + +N("sea", GEN_F, "morze", "morza", "morze", "morzem") +N("boat", GEN_F, "łódka", "łódki", "łódkę", "łódką") +N("island", GEN_F, "wyspa", "wyspy", "wyspę", "wyspą") +N("tree", GEN_N, "drzewo", "drzewa", "drzewo", "drzewem") + +Orb("Time", "Czasu") + +S("This dangerous sea contains nasty sharks and pirates. ", + "Niebezpieczne morze, pełne rekinów i piratów.") + +S("The islands of Caribbean are infinite and circular, and " + "the pirates probably have hidden their treasures somewhere far from the coast.", + "Wyspy na Karaibach są okrągłe nieskończone... Skarby piratów są pewnie " + "schowane gdzieś daleko od brzegu.") + +S( + "Hyperbolic pirates do not need huge ships, since so many lands to conquest " + "are so close. These small boats are enough for them.\n\n" + "Boats allow you to go through water. If you are in a boat, you can move into " + "a water cell (and the boat will come with you).", + + "Hiperboliczni piraci nie potrzebują dużych statków, skoro tyle lądów do " + "zdobycia jest tak blisko. Wystarczą im małe łódki.\n\n" + "Łódki pozwalają poruszać się przez wodę. Jeśli jesteś na łódce, możesz " + "przejść na pole z wodą (a łódka przesunie się razem z Tobą).") + +S( + "The forests of Caribbean are too dense to be traversed by humans, " + "and they are hard to burn. Many colorful parrots can be found there.", + "Lasy na Karaibach są zbyt gęste, by mógł przez nie przejść człowiek, " + "i trudno jest je spalić. Mieszka w nich dużo kolorowych papug.") + +S("Ye wonder where did th' Pirates find all these riches...", + "Zastanawiasz się, gdzie Piraci znaleźli te bogactwa...") + +S( + "The hyperbolic pirates have no use for treasure maps. However, they have found " + "out that a compass points to the center of the island. So they just go as " + "far towards the center as they can, and hide their treasure there.", + + "Mapy są bezużyteczne dla hiperbolicznych piratów, ale zauważyli oni, że " + "kompas zawsze wskazuje w kierunku środka wyspy. Zatem piraci po prostu " + "idą tak daleko w stronę środka, jak mogą, i tam chowają swoje skarby.") + +S("Just a nasty shark.", "Zwykły groźny rekin.") + +S("Parrots feel safe in the forests of Caribbean, so they " + "never leave them. But they will help the Pirates by attacking the intruders.", + + "Papugi czują się bezpiecznie w lasach Karaibów, i ich nie opuszczają, ale " + "chętnie pomogą Piratom walczyć z najeźdźcami.") + +S("Just a typical hyperbolic pirate.", "Typowy hiperboliczny pirat.") + +S( + "Normally, the power of most Orbs slowly fades away, even when " + "you are not actively using them. This Orb prevents this.\n\n" + + "When you have the Orb of Time, Orbs which are not active won't lose their power. " + "Orbs are considered active if they have a continuous power which has actually " + "affected something in the last turn.\n\n" + + "Orbs of Shielding remain active after being activated (even if you are no longer " + "attacked), and Orbs of Time have a bigger cap inside their native Caribbean than " + "outside.", + + "Zazwyczaj moc Sfer powoli wygasa, nawet gdy ich nie używasz aktywnie. Ta Sfera " + "temu zapobiega.\n\n" + + "Jeśli masz Sferę Czasu, nieaktywne sfery nie będą traciły mocy. Sfery są " + "uważane za aktywne, jeśli mają ciągły efekt, który rzeczywiście na coś " + "wpłynął w ostatniej turze.\n\n" + + "Sfery Tarczy pozostają aktywne po aktywacji (nawet jeżeli nikt więcej nie " + "atakuje), i Sfery Czasu mają większy limit na Karaibach niż poza nimi.") + +// Achievements: + +// Parrot : Find and collect Pirate Treasure. +// Caribbean Shark : Collect 10 Pirate Treasures. +// Pirate : Collect 25 Pirate Treasures. +// Master of Caribbean : Collect 50 Pirate Treasures. + +// Red Rock Valley + +N("Red Rock Valley", GEN_F, "Dolina Czerwonej Skały", "Dolina Czerwonej Skały", "Dolinę Czerwonej Skały", "w Dolinie Czerwonej Skały") + +N("Rock Snake", GEN_M, "Skalny Wąż", "Skalne Węże", "Skalnego Węża", "Skalnym Wężem") +N("Rock Snake Tail", GEN_O, "Ogon Węża", "Ogony Węża", "Ogon Węża", "Ogonem Węża") +N("Red Troll", GEN_M, "Czerwony Troll", "Czerwone Trolle", "Czerwonego Trolla", "Czerwonym Trollem") +N("Red Gem", GEN_O, "Czerwony Kamień", "Czerwone Kamienie", "Czerwony Kamień", "Czerwonym Kamieniem") + +N("rock I", GEN_F, "skała I", "skały I", "skałę I", "skałą I") +N("rock II", GEN_F, "skała II", "skały II", "skałę II", "skałą II") +N("rock III", GEN_F, "skała III", "skały III", "skałę III", "skałą III") + +Orb("Space", "Przestrzeni") + +S("Not enough power for telekinesis!", "Za mało mocy do telekinezy!") + +S("This land contains high rock formations. Most of the valley is at level 0, " + "while items are found at level 3. It is impossible to gain two or more levels, " + "or to lose three levels, in a single move, (attacks are possible at any " + "difference, though). Kill Red Trolls and Rock Snakes to make a cell higher.", + + "W tej krainie są wysokie formacje skalne. Większość doliny jest na poziomie 0, " + "a przedmioty można znaleźć na poziomie 3. Niemożliwe jest wzniesienie się na " + "dwa lub więcej poziomów, lub obniżenie się o trzy poziomy, w jednym ruchu " + "(ale atakować można przy każdej różnicy poziomów). Zabij Czerwonego Trolla " + "albo Skalnego Węża, by podnieść poziom pola.") + +S("A kind of Troll native to the Red Rock Valley.", + "Ten rodzaj Trolla mieszka w Dolinie Czerwonej Skały.") + +S( + "Rock snakes are similar to Sandworms, but they move each turn. However, they " + "only move on the hexagonal cells. They are also somewhat longer than the Sandworms.", + + "Kamienne węże są podobne do Pustynnych Czerwi, ale wykonują ruch w każdej kolejce. " + "Mogą jednak poruszać się tylko po sześciokątach. Są trochę dłuższe niż Pustynne " + "Czerwie.") + +S("A gem from the Red Rock Valley.", "Kamień szlachetny z Doliny Czerwonej Skały.") + +S( + "This Orb is able to bring faraway items to your location, even if there are " + "monsters or barriers on the way. The cost of " + "bringing an item (in charges) equals the square of its distance to you. Contrary " + "to some other Orbs, usage is not allowed if you have not enough power left.", + + "Ta Sfera może ściągać do Ciebie odległe przedmioty, nawet, jak po drodze są " + "potwory lub inne przeszkody. Koszt ściągnięcia przedmiotu (w ładunkach) równy jest " + "kwadratowi odległości. W przeciwieństwie do niektórych innych Sfer, nie możesz " + "użyć Sfery Przestrzeni, jeśli nie masz wystarczająco dużo mocy.") + +// Climber : Find and collect a Red Gem. +// Red Troll : Collect 10 Red Gems. +// Rock Snake : Collect 25 Red Gems. +// Master of Red Rock : Collect 50 Red Gems. + +// missing sentences + +S("%The1 drowns!", "%1 się utopi%ł1!"); +S("%The1 falls!", "%1 spad%ł1!"); + +// these were missing from the translation for some reason + +S("Hell has these lakes everywhere... They are shaped like evil stars, and filled with burning sulphur.", + "Piekło jest pełne tych jezior pełnych płonącej siarki, w kształcie złych gwiazd...") + +// Hardcore Mode + +S("hardcore mode", "tryb hardcore"); + +S("One wrong move and it is game over!", "Jeden fałszywy ruch i koniec gry!"); +S("Not so hardcore?", "Hardkor to nie to?"); + +// Shoot'em up Mode + +S("shoot'em up mode", "tryb strzelanki"); +S("Welcome to the Shoot'em Up mode!", "Witaj w trybie strzelanki!"); +S("F/;/Space/Enter/KP5 = fire, WASD/IJKL/Numpad = move", "F/;/Space/Enter/KP5 = strzał, WASD/IJKL/Numpad = ruch"); + +N("Rogue", GEN_M, "Cwaniak", "Cwaniaki", "Cwaniaka", "Cwaniakiem") +N("Knife", GEN_O, "Nóż", "Noże", "Nóż", "Nożem") +N("Flail", GEN_O, "Cep", "Cepy", "Cep", "Cepem") +N("Fireball", GEN_F, "Ognista Kula", "Ogniste Kule", "Ognistą Kulę", "Ognistą Kulą") +N("Tongue", GEN_O, "Język", "Języki", "Język", "Językiem") + +S("In the Shoot'em Up mode, you are armed with thrown Knives.", + "W trybie strzelanki jesteś uzbrojony w noże do rzucania.") +S("A simple, but effective, missile, used by rogues.", + "Prosta choć efektywna broń rzucana, używana przez poszukiwaczy skarbów.") +S("This attack is likely to hit the attacker.", + "Ten atak pewnie trafi w atakującego.") +S("This magical missile burns whatever it hits.", "Ten magiczny pocisk pali to, w co trafi.") +S("Some monsters have long tongues, which allow them to attack enemies in nearby cells.", + "Niektóre potwory mają długie języki, dzięki którym mogą atakować sąsiednie pola.") + +// modes for the local highscores + +S(", m - mode: normal", ", m - tryb normalny") +S(", m - mode: hardcore only", ", m - tryb hardcore") +S(", m - mode: shoot'em up", "m - tryb strzelanki") + +// update description for Steam: + +// (Shoot'em Up mode and two more lands than in the free version, and more are planned!) + +// missing lines: + +S("You would get hurt!", "To by bolało!") +S("PARTIAL", "CZĘŚCIOWO") + +S("Cannot drop %the1 here!", "Nie możesz tu położyć Martwej Sfery!"); + +// Euclidean scores +S(" (E:%1)", " (E:%1)"); + +S("You cannot attack Rock Snakes directly!", "Nie możesz atakować Skalnych Węży bezpośrednio!"); + +S("\"I am lost...\"", "\"Zgubiłem się...\""); + +S("You are killed by %the1!", "Zabi%ł1 Ciebie %1!") + +// new menu for Version 7.1 + +S("(v) menu", "(v) menu") +S("return to the game", "wróć do gry") +S("or 'v' to see the main menu", "lub 'v' by zobaczyć menu") + +S("HyperRogue %1", "HyperRogue %1") +S("basic configuration", "podstawowa konfiguracja") +S("advanced configuration", "zaawansowana konfiguracja") +S("local highscores", "lokalne wyniki") +S("help", "help") +S("restart game", "gra od nowa") +S("special game modes", "specjalne tryby gry") +S("save the game", "zapisz i zakończ") +S("quit the game", "koniec gry") +S("review your quest", "przegląd misji") +S("review the scene", "przegląd sceny") +S("game over screen", "ekran końca gry") +S("continue game", "kontynuuj grę") +S("play the game!", "graj!") + +// fixed descriptions for Shmup achievements + +S("You have used less knives than ever before. Congratulations!", + "Zużyłeś mniej noży, niż kiedykolwiek wcześniej. Gratulacje!") + +S("You have improved both your real time and knife count. Congratulations!", + "Poprawi%łeś0 swój najlepszy czas rzeczywisty i liczbę noży. Gratulacje!") + +S("%1 knives (%2)", "noży: %1 (%2)") + +// temporary +S("No description yet." ,"Brak opisu.") + +// special case when no Spice is visible +S("The sandworm explodes!", "Czerw eksplodował!") + +// Ocean + +// achievements: +// Reached Ocean: Find and collect an Amber. +// Albatross: Collect 10 Ambers. +// Amber Albatross: Collect 25 Ambers. +// Master of the Tides: Collect 50 Ambers. + +N("Ocean", GEN_O, "Ocean", "Oceany", "Ocean", "na Oceanie") + +S( + "You can collect some valuable Ambers on the coast, but beware the tides!\n\n" + "You can also take one of the boats and venture into the Ocean, " + "to find other coasts, dangerous whirlpools, and islands inhabited by Pirates.", + + "Możesz zbierać cenne bursztyny na plaży, ale uważaj na odpływy!\n\n" + "Możesz też wziąć łódkę i popłynąć nią przez Ocean, by znaleźć inne brzegi, " + "niebezpieczne wiry, i wyspy zamieszkane przez Piratów.") + +N("Albatross", GEN_O, "Albatros", "Albatrosy", "Albatrosa", "Albatrosem") + +S( + "Those large seabirds attack you for some reason. At least they are not " + "as fast as Eagles...", + "Te wielkie morskie ptaki atakują Ciebie z jakiegoś powodu. Przynajmniej nie są " + "tak szybkie, jak Orły...") + +N("stranded boat", GEN_F, "łódka na mieliźnie", "łódki na mieliźnie", "łódkę na mieliźnie", "w łódce na mieliźnie") + +S( + "This boat cannot go through the sand. But if you sit inside and " + "wait for the tide, you will be able to use it to travel through the Ocean.", + + "Ta łódka nie może pływać przez piasek. Ale jeśli w niej usiądziesz " + "i poczekasz na przypływ, to będzie mogła płynąć przez Ocean." + ) + +N("Amber", GEN_O, "Bursztyn", "Bursztyny", "Bursztyn", "Bursztynem") + +S( + "When the tide is away, beautiful ambers can be found on the hyperbolic beaches. " + "Perhaps there used to be a forest here?" , + "W czasie odpływu na hiperbolicznej plaży można znaleźć piękne bursztyny.") + +Orb("Air", "Powietrza") + +S("This Orb allows you to blow your enemies away.\n\n" + "Click a monster to blow it one cell away. It cannot be used against mimics, ghosts, sharks and other monsters restricted to a specific terrain, and multi-tile monsters.", + "Ta Sfera pozwala Ci zdmuchnąć Twoich przeciwników.\n\n" + "Kliknij potwora, by go zdmuchnąć o jedno pole. Nie można używać przeciwko mimikom, duchom, i potworom zajmującym wiele pól." + ) + + +N("Sea Border", GEN_O, "Granica morska", "Granice morskie", "Granicy morskiej", "na Granicy morskiej") + +S("Border between seas.", "Granica między morzami.") + +// Whirlpool + +// achievements: +// Escaped Whirlpool: Collect a Pearl, and escape the Whirlpool. +// Vortex Shark: Collect 10 Pearls. +// Vortex Pirate: Collect 25 Pearls. +// Master of the Whirlpool: Collect 50 Pearls. + +N("Whirlpool", GEN_O, "Wir", "Wiry", "Wir", "w Wirze") + +S( + "Many lost boats are spinning in this whirlpool. Some of them contain treasures " + "and Pirates.\n\n" + "Unmanned boats will go one cell clockwise in each turn. Sharks and manned boats " + "are only allowed to go with the current, that is, towards the center, or clockwise.", + + "Dużo statków zagubiło się w tym wirze. Na niektórych z nich są skarby i Piraci.\n\n" + "Statki bez załogi poruszają się o 1 pole w każdej kolejce, zgodnie z ruchem wskazówek " + "zegara. Rekiny i statki z załogą mogą poruszać się tylko z prądem, czyli w kierunku " + "środka wiru, albo zgodnie z ruchem wskazówek zegara." + ) + +N("Pearl", GEN_F, "Perła", "Perły", "Perłę", "Perłą") + +S( + "You do not know exactly why, but there are valuable pearls on many boats " + "in the whirlpool.", + "Właściwie nie wiesz, dlaczego, ale na wielu statkach w Wirze można znaleźć " + "drogocenne perły." + ) + +Orb("Water", "Wody") + +S( "This Orb allows your boat to go against the current, " + "and also to go into the land, creating water on the way.", + "Ta Sfera pozwala Twojemu statkowi płynąć pod prąd, " + "a także płynąć przez ląd, tworząc wodę po drodze.") + +S("You cannot go against the current!", "Nie możesz płynąć pod prąd!") + +// Minefield + +// achievements: +// Reached Minefield: Collect a Bomberbird Egg. +// Minesweeper: Collect 10 Bomberbird Eggs. +// Bomberbird: Collect 25 Bomberbird Eggs. +// Master of the Minefield: Collect 50 Bomberbird Eggs. + +N("Minefield", GEN_N, "Pole Minowe", "Pola Minowe", "Pole Minowe", "na Polu Minowym") +N("minefield", GEN_N, "pole minowe", "pola minowe", "pole minowe", "polem minowym") +N("cell without mine", GEN_N, "pole bez miny", "pola bez min", "pole bez min", "polem bez min") + +S( + "This minefield has been created by the Bomberbirds to protect their valuable eggs. " + "Mines explode when they are stepped on, creating fire all around them " + "(this fire never expires in the Minefield). If you don't step on a mine, you " + "know the number of mines in cells around you. These numbers are marked with " + "color codes on the cells you have visited.", + "To pole minowe zostało stworzone przez ptaki, Bombardiery, w celu ochrony ich jaj. " + "Miny eksplodują, gdy ktoś na nich stanie, tworząc ogień wokół (ten ogień nigdy " + "nie na Polu Minowym). Jeśli uda Ci się nie stanąć na minę, to poznajesz liczbę " + "min na polach wokół siebie. Te liczby są oznaczone kolorowymi kropkami na " + "odwiedzonych polach." + ) + +N("Bomberbird", GEN_O, "Bombardier", "Bombardiery", "Bombardiera", "Bombardierem") + +S( + "Dark red birds who have created the minefield.\n\n" + "They create a mine on the spot where they are killed, provided " + "that the terrain is suitable. Also note that mines are triggered " + "by dead birds falling on them.", + + "Ciemnoczerwone ptaki, które stworzyły pole minowe.\n\n" + "Na polu, na które spadły, powstaje mina, o ile teren jest odpowiedni. " + "Pamiętaj, że mina wybucha, gdy spadnie na nią martwy ptak.") + +N("Tame Bomberbird", GEN_O, "Oswojony Bombardier", "Oswojone Bombardiery", "Oswojonego Bombardiera", "Oswojonym Bombardierem") + +S( + "This bomberbird will follow you at some distance, and attack your enemies. " + "You can kill it to place a mine.", + + "Ten bombardier będzie latał za Tobą, i atakował Twoich wrogów. Możesz też " + "go zabić, by podłożyć minę.") + +N("Bomberbird Egg", GEN_N, "Jajo Bombardiera", "Jaja Bombardiera", "Jajo Bombardiera", "Jajem Bombardiera") + +S( + "Bomberbird eggs are big and tasty, and thus valuable. " + "They can hatch when left alone for some time (but this will never happen " + "if you are watching).", + + "Jaja Bombardierów są wartościowe, bo są duże i smaczne. " + "Mogą się wykluć, gdy dasz im czas (ale nie stanie się to, jeżeli patrzysz)." + ) + + +Orb("Friendship", "Przyjaźni") + +S("This Orb summons a friendly Bomberbird.", + "Ta sfera przywołuje przyjaznego Bombardiera.") + +S("Still confused? Read the FAQ on the HyperRogue website!\n\n", + "Coś jest niejasne? Przeczytaj FAQ na stronie HyperRogue! (po angielsku)\n\n") + +S("Nowhere to blow %the1!", "Nie ma gdzie zdmuchnąć %a1!") +S("%The1 is immune to wind!", "%1 jest odporn%ya1 na wiatr!") +S("You blow %the1 away!", "Zdmuchn%ąłeś0 %a1!") + +S("WARNING: you are entering a minefield!", "UWAGA: wchodzisz na pole minowe!") +S("No mines next to you.", "Nie ma min obok Ciebie.") +S("A mine is next to you!", "Jedna mina koło ciebie!") +S("Two mines next to you!", "Dwie miny koło Ciebie!") +S("Three mines next to you!", "Trzy miny koło Ciebie!") +S("Four mines next to you!", "Cztery miny koło Ciebie!") +S("Five mines next to you!", "Pięć min koło Ciebie!") +S("Six mines next to you!", "Sześć min koło Ciebie!") +S("Seven mines next to you!", "Siedem min koło Ciebie!") + +S("You have to run away from the water!", "Musisz uciec z wody!") + +// Version 7.2 + +N("Palace", GEN_O, "Pałac", "Pałace", "Pałac", "w Pałacu") +N("palace wall", GEN_F, "mur Pałacu", "mury Pałacu", "mur Pałacu", "murem Pałacu") + +S("Apparently a princess is kept locked somewhere, but you won't ever find her in this hyperbolic palace. ", + "Gdzieś tu jest uwięziona księżniczka, ale w tym hiperbolicznym pałacu nigdy jej nie znajdziesz. ") + +S("Apparently a prince is kept locked somewhere, but you won't ever find him in this hyperbolic palace. ", + "Gdzieś tu jest uwięziony książę, ale w tym hiperbolicznym pałacu nigdy go nie znajdziesz. ") + +S("So better just to concentrate on collecting treasure. " + "Beware the traps, and the guards, who are hard to kill!", + + "Także lepiej się skoncentrować na szukaniu skarbów. " + "Uwaga na pułapki, i trudnych do pokonania strażników!" + ) + +N("trapdoor", GEN_N, "zapadnia", "zapadnie", "zapadnię", "zapadnią") +S("This floor will fall after someone goes there. Go quickly!", + "Ta podłoga się zapadnie, jak ktoś będzie przechodził. Prechodź szybko!") + +N("closed gate", GEN_F, "zamknięta brama", "zamknięte bramy", "zamkniętą bramę", "zamkniętą bramą") +N("open gate", GEN_F, "otwarta brama", "otwarte bramy", "otwartą bramę", "otwartą bramą") +N("closing plate", GEN_F, "zamykająca płyta", "zamykające płyty", "zamykającą płytę", "zamykającą płytą") +N("opening plate", GEN_F, "otwierająca płyta", "otwierające płyty", "otwierającą płytę", "otwierającą płytą") + +S("Green pressure plates open all gates in radius 3 around them. " + "Similarly, red pressure plates close all gates in this radius.", + + "Zielone płyty otwierają wszystkie bramy w promieniu 3 wokół nich. " + "Podobnie, czerwone płyty zamykają wszystkie bramy w tym promieniu.") + +N("Hypersian Rug", GEN_O, "Hiperski Dywan", "Hiperskie Dywany", "Hiperski Dywan", "Hiperskim Dywanem") +S("Nice, a hyperbolic rug! It will not fit very well on your flat Euclidean floor, but who cares?", + "Jaki ładny hiperboliczny dywan! Nie będzie dobrze przylegał do Twojej płaskiej, euklidesowej podłogi, ale co z tego?") + +Orb("the Frog", "Żaby") +S("This Orb lets you jump to a place which is two cell away from you, in a single turn. " + "You can jump over water, chasms and fire, but not over walls.", + "Ta Sfera pozwala na skok do miejsca odległego od Ciebie o dwa pola, w jednej kolejce. " + "Możesz przeskoczyć wodę, przepaść i ogień, ale nie ścianę.") +S("Cannot jump through %the1!", "Nie możesz skakać przez %a1!") +S("You jump!", "Skaczesz!") + +S("\n\nNote: when pushing %the1 off a heptagonal cell, you can control the pushing direction " + "by clicking left or right half of the heptagon.", + "\n\nUwaga: kiedy spychasz %a1 z siedmiokąta, możesz sterować kierunkiem pchnięcia " + "klikając lewą lub prawą połowę siedmiokąta." + ) + +S(" With the keyboard, you can rotate the view for a similar effect (Page Up/Down).", + " Na klawiaturze możesz obrócić widok, by uzyskać podobny efekt (Page Up/Down).") + +N("Palace Guard", GEN_M, "Strażnik Pałacu", "Strażnicy Pałacu", "Strażnika Pałacu", "Strażnikiem Pałacu") + +S("You have to hit Palace Guards several times to kill them. After each hit, they " + "are pushed away and stunned for some time.", + "Musisz uderzyć Strażnika kilka razy, by go zabić. Po każdym trafieniu strażnik " + "jest odpychany i ogłuszony przez pewien czas.") + +N("Fat Guard", GEN_M, "Gruby Strażnik", "Grubi Strażnicy", "Grubego Strażnika", "Grubym Strażnikiem") + +S("Fat guards are too heavy to be pushed away by your hits.", + "Grubi Strażnicy są zbyt ciężcy, by dało się ich odepchnąć atakiem.") + +N("Skeleton", GEN_M, "Kościotrup", "Kościotrupy", "Kościotrupa", "Kościotrupem") +S("Skeletons work similar to Palace Guards, but they won't die no matter how many " + "times you hit them. Well, you have to be more creative...\n\n" + "Skeletons attacked outside of their native land, Palace, are stunned for a longer time.", + "Kościotrupy działają podobnie do Strażników Pałacu, ale nie zabijesz ich, " + "ilekolwiek byś ich atakowa%ł0. Wymyśl coś bardziej twórczego...\n\n" + "Kościotrup zaatakowany poza Pałacem będzie ogłuszony przez dłuższy czas." + ) + +N("Vizier", GEN_M, "Wezyr", "Wezyrowie", "Wezyra", "Wezyrem") +S("Viziers are neither pushed away nor stunned. However, you attack them automatically when " + "escaping from them.", + "Wezyrowie ani nie są ogłuszani, ani odpychani, ale automatycznie ich atakujesz, gdy " + "od nich uciekasz.") + +S("You stun %the1.", "Ogłuszy%łeś0 %a1.") +S("The gate is closing right on you! RUN!", "Brama leci na Ciebie! UCIEKAJ!") +S("%The1 is crushed!", "%1 zosta%ł1 przygniecion%ya1!") +S("You hit %the1.", "Trafi%łeś0 %a1.") +S("Hit him by walking away from him.", "Odejdź od niego, by go trafić.") +S("Hmm, he has been training in the Emerald Mine. Interesting...", "Ciekawe... trenował w Kopalni Szmaragdów.") + +// Reached the Palace: Find and collect a Hypersian Rug. +// Palace Guard: Collect 10 Hypersian Rugs. +// Vizier: Colect 25 Hypersian Rugs. +// Prince: Colect 50 Hypersian Rugs. + +// Living Fjord + +N("Living Fjord", GEN_O, "Żywy Fiord", "Żywe Fiordy", "Żywy Fiord", "w Żywym Fiordzie") + +S("A coastal area, from where you can get both to the inland worlds and to the Ocean. " + "Each turn, each cell will become water or earth, based on the majority of cells around it. " + "Contrary to the Living Caves, this process is not affected by most items and monsters, " + "but elementals, dead Trolls, and cells outside of the Living Fjord have " + "a very powerful effect.", + "Nadbrzeżny rejon, z którego możesz dostać się zarówno do krain wewnątrzlądowych, " + "jak i na Ocean. W każdej kolejce, każde pole zmienia się w wodę lub ziemię, " + "w zależności od większości pól wokół. W przeciwieństwie do Żywej Jaskini, na ten proces " + "nie wpływa większość przedmiotów i stworzeń, ale żywiolaki, martwe Trolle, i pola " + "poza granicą Żywego Fiordu mają bardzo silny efekt." + ) + +N("Fjord Troll", GEN_M, "Fjordtroll", "Fjordtrolle", "Fjordtrolla", "Fjordtrollem") +S("Fjord Trolls leave a wall when they die, causing the living fjord to rise around it. " + "Contrary to Rock Trolls, items around are not destroyed.", + "Fjordtrolle zostawiają ścianę po zabiciu, co powoduje, że żywy fiord w okolicy się podnosi. " + "W przeciwieństwie do Skalnych Trolli, Fjordtrolle nie niszczą przedmiotów wokół." + ) + +N("Viking", GEN_M, "Wiking", "Wikingowie", "Wikinga", "Wikingiem") +S("Mighty warriors from the Fjord, who can use boats.", + "Potężni wojownicy z Fiordu, używający łódek.") + +N("Water Elemental", GEN_M, "Wodny Żywiołak", "Wodne Żywiołaki", "Wodnego Żywiołaka", "Wodnym Żywiołakiem") +S("Wherever this powerful being goes, the living fjord " + "sinks below water, non-magical boats are destroyed, and fires are extinguished.\n\n" + "As a special case, you can attack the Water Elemental from the water, without drowning immediately.", + "Gdziekolwiek przejdzie ta potężna istota, żywy fiord tonie, niemagiczne łódki są niszczone, a " + "ogień gaśnie.\n\n" + "Jako szczególny przypadek, możesz atakować Wodnego Żywiołaka z wody, nie topiąc się.") + + +N("Garnet", GEN_O, "Granat", "Granaty", "Granat", "Granatem") +S("Vikings believe that garnets improve their strength.", + "Wikingowie wierzą, że granaty dają im siłę.") + +Orb("the Fish", "Ryby") +S("This Orb lets you dive into the water. While diving, you are able to see and collect underwater treasures, " + "while being invisible to monsters yourself. You are afraid of jumping into the water straight from a boat, so usually you won't do it.", + "Ta Sfera pozwala Ci nurkować. Podczas nurkowania możesz widzieć i zbierać podwodne " + "skarby, a potwory Ciebie nie widzą. Boisz się wyskakiwać do wody z łódki, także raczej tego nie zrobisz.") + +S("%The1 is washed away!", "%2 zmy%ł2 %a1!") +// %1 zosta%ł1 zmyt%ya1!") +S("%The1 is extinguished!", "%2 ugasi%ł2 %a1!") + +// Reached the Living Fjord: Find and collect a Garnet. +// Viking: Collect 10 Garnets. +// Water Elemental: Colect 25 Garnets. +// Master of the Fjord: Colect 50 Garnets. + +// implemented, not appears in the game yet + +Orb("Discord", "Niezgody") + +S("Causes most monsters to attack other monsters, not only you and your friends.", + "Powoduje, że większość potworów będzie też atakowała inne potwory, nie tylko Ciebie " + "i Twoich przyjaciół.") + +// Shmup Configuration + +S("forward", "do przodu") +S("backward", "do tyłu") +S("turn left", "skręć w lewo") +S("turn right", "skręć w prawo") +S("move up", "idź do góry") +S("move right", "idź w prawo") +S("move down", "idź do dołu") +S("move left", "idź w lewo") +S("throw a knife", "rzut nożem") +S("face the pointer", "celuj we wskaźnik") +S("throw at the pointer", "rzut we wskaźnik") +S("drop Dead Orb", "połóż Martwą Sferę") +S("center the map on me", "centruj mapę na mnie") +S("activate Orb power", "aktywuj moc Sfery") + +S("pan up", "przewiń w górę") +S("pan right", "przewiń w prawo") +S("pan down", "przewiń w dół") +S("pan left", "przewiń w lewo") +S("rotate left", "obróć w lewo") +S("rotate right", "obróć w prawo") +S("home", "centruj na graczy") + +S("do nothing", "nic") +S("rotate view", "obróć widok") +S("panning X", "przewiń X") +S("panning Y", "przewiń Y") +S("player 1 X", "gracz 1 X") +S("player 1 Y", "gracz 1 Y") +S("player 1 go", "gracz 1 idź") +S("player 1 spin", "gracz 1 obrót") +S("player 2 X", "gracz 2 X") +S("player 2 Y", "gracz 2 Y") +S("player 2 go", "gracz 2 idź") +S("player 2 spin", "gracz 2 obrót") + +S("Joystick %1, axis %2", "Joystick %1, oś %2") +S("one player", "jeden gracz") +S("two players", "dwóch graczy") +S("configure player 1", "skonfiguruj gracza 1") +S("configure player 2", "skonfiguruj gracza 2") +S("configure panning", "skonfiguruj przewijanie") +S("configure joystick axes", "skonfiguruj osie joysticka") +S("continue playing", "kontynuuj grę") +S("start playing in the shmup mode", "zacznij grę w trybie strzelanki") +S("return to the turn-based mode", "powrót do trybu turowego") +S("save the configuration", "zapis konfiguracji") +S("press a key to unassign", "naciśnij klawisz do odwiązania") +S("press a key for '%1'", "naciśnij klawisz dla '%1'") +S("unassign a key", "odwiąż klawisz") + +// extra pattern modes + +S("explore the Emerald Pattern", "Eksploracja Szmaragdowego Wzoru") + +// extra flavor/Knight lines + +S("Kill a Vizier in the Palace to access Emerald Mine", "Zabij Wezyra w Pałacu, by iść do Kopalni Szmaragdów") +S("Collect 5 Emeralds to access Camelot", "Zbierz 5 Szmaragdów, by dostać się do Camelot") +S("Some lands unlock at specific treasures or kills", "Niektóre krainy otwierają się przy konkretnych skarbach") + +S("You will be fighting red rock snakes, too...", "Będziesz też walczyć z czerwonymi skalnymi wężami...") + +S("\"The Red Rock Valley is dangerous, but beautiful.\"", + "\"Dolina Czerwonej Skały jest piękna, choć niebezpieczna.\"") +S("\"Train in the Desert first!\"", "\"Potrenuj najpierw na Pustynni!\"") +S("\"I like collecting ambers at the beach.\"", "\"Lubię zbierać bursztyny na plaży.\"") +S("\"Our Table seats %1 Knights!\"", "\"Przy naszym stole mieści się %1 Rycerzy!\"") +S("\"There are %1 floor tiles inside our Table!\"", "\"Nasz stół otacza %1 pól podłogi!\"") +S("\"By now, you should have your own formula, you know?\"", "\"Wiesz co, m%ógł0byś już mieć swój własny wzór!\"") +S("\"Have you tried to take a boat and go into the Ocean? Try it!\"", "\"Próbowa%łeś0 wziąć łódkę i płynąć na Ocean?\"") + +//====================// +// NEW IN VERSION 7.3 // +//====================// + +// new name for 'Ivy D' + +N("Dead Ivy", GEN_M, "Martwy Bluszcz", "Martwe Bluszcze", "Martwy Bluszcz", "Martwym Bluszczem") + +// new messages for living/nonliving monsters + +S("%The1 bites %the2!", "%1 ugryz%ł1 %a2!") +S("%The1 attacks %the2!", "%1 atakuje %a2!") +S("You destroy %the1 with a mental blast!", "Zniszczy%łeś0 %a1 mocą psychiczną!") +S("The ivy kills %the1!", "Bluszcz zabił %a1!") +S("You destroy %the1.", "Zniszczy%łeś0 %a1.") +S("%The1 kills %the2!", "%1 zabi%ł1 %a2!") +S("%The1 sinks!", "%1 uton%ął1!"); + +S("Cannot jump on %the1!", "Nemůžeš skočit na %1!") + +// renamed Fifty to Palace +S("explore the Palace Pattern (4 colors)", "Eksploracja Wzoru Pałac (4 kolory)") +S("explore the Palace Pattern (8 colors)", "Eksploracja Wzoru Pałac (8 kolorów)") + +// Map Editor +//============ + +S("map editor", "edytor map") +S("You activate your terraforming powers!", "Uaktywni%łeś0 swoje moce edycji!") +S("Press F5 to clear the board.", "Wciśnij F5, by wyczyścić planszę.") +S("Press F5 to restart the game normally.", "Wciśnij F5, by zacząć normalną grę.") +S("High quality shots not available on this platform", "Zrzuty HQ niedostępne na tej platformie") +S("Saved the high quality shot to %1", "Zapisano zrzut HQ do %1") +S("Map saved to %1", "Mapa zapisana do %1") +S("Map loaded from %1", "Mapa wczytana z %1") +S("copying", "kopiuję") +S("boundary", "brzeg") +S("clear monster", "zabierz potwora") +S("use at your own risk!", "używasz na własne ryzyko!") + +// Note: in English, these have been arranged from longest to shortest. +// This gives a somewhat nice effect on the top left corner of the screen. +// You may want to aim for the same effect when translating + +S("0-9 = radius (%1)", "0-9 = promień (%1)") +S("b = boundary", "i = przedmioty") +S("m = monsters", "m = potwory") +S("w = walls", "w = ściany") +S("i = items", "l = krainy") +S("l = lands", "c = kopia") +S("c = copy", "b = brzeg") + +// And this is from shortest to longest (bottom left corner) +S("F1 = help", "F1 = pomoc") +S("F2 = save", "F2 = zapisz") +S("F3 = load", "F3 = wczytaj") +S("F5 = restart", "F5 = restart") +S("F6 = HQ shot", "F6 = zrzut HQ") +S("F7 = player on/off", "F7 = gracz wł/wył") +S("ESC = return to the game", "ESC = powrót do gry") + +S( + "This mode allows you to edit the map.\n\n" + "NOTE: Use at your own risk. Combinations which never " + "appear in the real game may work in an undefined way " + "(do not work, look strangely, give strange messages, or crash the game).\n\n" + "To get the most of this editor, " + "some knowledge of inner workings of HyperRogue is required. " + "Each cell has four main fields: land type, wall type, monster type, item type. " + "The same wall type (especially \"none\", \"sea\", or \"bonfire\") may look or " + "work a bit differently, based on the land it is in. Sometimes an object may " + "appear twice on the list due to subtle differences (for example, Demons could " + "move next turn or not).\n\n" + "Press w, i, l, or m to choose which aspect of cells to change, " + "then just click on the cells and they will change. Press 'c' while " + "hovering over a cell to copy that cell, this copies all information about it. " + "When copying large areas or placing multi-tile monsters, it might be important where " + "on the cell you are clicking.\n\n" + "You can also press 0-9 to apply your changes to a greater radius. " + "This also affects the copy/paste feature, allowing to copy a larger area.\n\n" + "Press F2 to save the current map (and F3 to load it). If you try this after " + "a long game of HyperRogue (without using Orbs of Safety), the filesize will " + "be very large! " + "Note however that large structures, such as " + "Great Walls, large circles and horocycles, are destroyed by this.\n\n" + "Press 'b' to mark cells as boundaries. Such cells, and cells beyond " + "them, are not copied by the copy/paste feature, nor saved by the " + "save feature.\n\n", + + + "Ten tryb pozwala edytować mapę.\n\n" + "UWAGA: używasz na własne ryzyko! Kombinacje, które nigdy nie pojawiają się " + "w prawdziwej grze, mogą działać w sposód nieokreślone (nie działać, wyglądać " + "dziwnie, produkować dziwne teksty, albo wywalać grę).\n\n" + "By wynieść najwięcej z tego edytora, przydatna jest pewna wiedza o działaniu " + "HyperRogue. Każde pole ma cztery atrybuty: typ lądu, typ ściany, typ potwora, " + "typ przedmiotu. Ten sam typ ściany (szczególnie \"nic\", \"morze\", albo \"ognisko\")" + " może wyglądać albo działać różnie, w zależności od lądu, na którym się " + "znajduje. Czasami obiekt może występować dwa razy na liście ze względu na " + "subtelne różnice (na przykład, Demons mogą się ruszać w następnej turze albo nie).\n\n" + "Wciśnij w, i, l, m by wybrać, który atrybut zmienić, następnie klikaj pola " + "i będą się zmieniać. Naciśnij 'c', gdy myszka jest nad polem, by kopiować to " + "pole -- to kopiuje całą informację o tym polu. Kiedy kopiujesz albo stawiasz " + "potwory wielopolowe, może mieć znaczenie punkt pola, w którym klikasz.\n\n" + "Możesz też nacisnąć 0-9 by zastosować zmianę w większym promieniu. " + "To wpływa również na kopiowanie/wklejanie, pozwalając na skopiowanie " + "większego obszaru.\n\n" + "Wciśnij F2, by zapisać obecną mapę (i F3, by naładować). Jak spróbujesz " + "to zrobić po długiej grze w HyperRogue (nie używającej Sfer Bezpieczeństwa), " + "rozmiar pliku będzie bardzo duży! Uwaga: duże struktury, jak Wielkie Ściany " + "i horocykle, są przez to niszczone.\n\n" + "Naciśnij 'b' by zaznaczyć pole jako brzeg. Takie pola, i pola za nimi, " + "nie są kopiowane funkcją copy/paste, ani też nie są zapisywane funkcją save.\n\n" + ) + +// Princess Quest +//================ + +// Saved the Princess - "Wybawca" - "Uratuj Księżniczkę." +// Princess Challenge - "Misja Księżniczka" - "Zwycięstwo w misji Księżniczka." +// Martial Artist - "Sztuki walki" - "Pozwól nieuzbrojonej Księżniczce wygrać walkę" + +S( + "A mouse squeaks at you. It seems that it wants you to go somewhere. " + "That's interesting, what could you find here?\n\n" + "Note: in the part of the Palace that you are exploring during this " + "quest, the distribution of monsters, pressure plates, and items has been " + "changed somewhat, to make it a bit more suitable for less " + "experienced players. The number of monsters does not depend on the " + "number of Hypersian Rugs you have collected, and there are more " + "opening plates.\n\n" + "However, even with the normal distribution, it appears that it should be " + "always possible to reach your goal. If you want this challenge, " + "select it from the special game modes menu.", + + "Myszka piszczy na Ciebie. Wydaje się, że chce Ciebie gdzieś " + "zaprowadzić. Ciekawe, co tam może być?\n\n" + "W części Pałacu, którą zwiedzasz podczas tej misji, " + "rozkład potworów, płyt, i przedmiotów został trochę zmieniony, " + "by misja była bardziej odpowiednia dla mniej doświadczonych " + "graczy. W szczególności, liczba potworów nie zależy od liczby zebranych " + "Hiperskich Dywanów, i jest więcej płyt otwierających.\n\n" + "Jednak nawet przy normalnym rozkładzie wydaje się, że " + "zawsze powinno być możliwe dotarcie do celu. Jeśli chcesz " + "takiego wyzwania, wybierz je z menu specjalnych trybów gry.") + +S("\"When I visited the Palace, a mouse wanted me to go somewhere.\"", + "\"Kiedy byłem w Pałacu, mysz chciała, bym gdzieś poszedł.\"") + +S("\"I wonder what was there...\"", "\"Zastanawiam się, co tam było...\"") + +N("Mouse", GEN_F, "Myszka", "Myszki", "Myszkę", "Myszką") + +S("You hear a distant squeak!", "Słyszysz odległy pisk!") +S("%The1 squeaks in a confused way.", "Zmieszan%ya1 %1 pisn%ął1.") +S("%The1 squeaks gratefully!", "%1 pisn%ął1 w podziękowaniu!"); +S("%The1 squeaks hopelessly.", "%1 pisn%ął1 bez nadziei."); +S("%The1 squeaks in despair.", "%1 pisn%ął1 rozpaczliwie."); +S("%The1 squeaks sadly.", "%1 pisn%ął1 smutno."); +S("%The1 squeaks with hope!", "%1 pisn%ął1 z nadzieją!"); +S("%The1 squeaks happily!", "%1 pisn%ął1 szczęśliwie!"); +S("%The1 squeaks excitedly!", "%1 się ekscytuje!"); + +N("giant rug", GEN_O, "wielki dywan", "wielkie dywany", "wielki dywan", "wielkim dywanem") + +S("This is the biggest Hypersian Rug you have ever seen! " + "Unfortunately, it is too large to take it as a trophy.", + "To jest największy hiperski dywan, jaki kiedykolwiek widzia%łeś0! " + "Niestety, jest za duży, by wziąć go jako zdobycz.") + +N("Prince", GEN_M, "Książę", "Książęta", "Księcia", "Księciem") +N("Princess", GEN_F, "Księżniczka", "Księżniczki", "Księżniczkę", "Księżniczką") + +S("%1 takes %his1 revenge on %the2!", "%1 się mści!") +S("\"That should teach you to take me seriously!\"", + "\"Traktuj mnie poważnie! Niech to będzie dla Ciebie nauczką!\"") + +S("%The1 kisses you, and begs you to bring %him1 away from here.", + "%1 Ciebie pocałowa%ł1, i poprosi%ł1, byś %go1 gdzieś zabra%ł0.") + +S("\"I want my revenge. Stun a guard and leave him for me!\"", + "Chcę zemsty. Ogłusz strażnika i mi go zostaw!\"") + +S("\"That felt great. Thanks!\"", "\"Wspaniałe uczucie. Dzięki!\"") + +S("\"Bring me out of here please!\"", "Proszę, zabierz mnie stąd!\"") + +S("%The1 kisses you, and thanks you for saving %him1.", + "%1 Ciebie pocałowa%ł1, i podziękowa%ł1 za uratowanie %go1.") + +S("\"I have been trained to fight with a Hypersian scimitar, you know?\"", + "Trenowa%łem1 walkę hiperskim szamszirem, wiesz?\"") + +S("\"I would love to come to your world with you!\"", + "Chcia%ł1bym wrócić z Tobą do Twojego świata!\"") + +S("\"Straight lines stay close to each other forever, this is so romantic!\"", + "\"Linie proste, co mogą zawsze być blisko siebie... Jakie to romantyczne!\"") + +S("\"Maps... Just like the world, but smaller... how is that even possible?!\"", + "\"Mapy... jak świat, tylko mniejsze... jak to w ogóle możliwe?!\"") + +Orb("Love", "Miłości") +S("Love takes time, but it heals all wounds, and transcends time and space.\n\n" + "The Orb of Love is worth 30$$$, if you end the game with it.\n", + + "Miłość potrzebuje czasu, ale leczy wszelkie rany, i czas i przestrzeń nie są " + "dla niej przeszkodami.\n\n" + "Sfera Miłości jest warta 30$$$, jeśli skończysz z nią grę.\n") + +// Princess Challenge: + +S("%1 Challenge", "Misja %1") +S("Save %the1 first to unlock this challenge!", "Uratuj %a1, by mieć dostęp do tej misji!") +S("Welcome to %the1 Challenge!", "Uratuj %a1!") +S("The more Hypersian Rugs you collect, the harder it is.", "Im więcej zbierzesz Hiperskich Dywanów, tym misja trudniejsza.") +S("Follow the Mouse and escape with %the1!", "Idź za Myszką i ucieknij z %abl1!") +S("Hardness frozen at %1.", "Trudność zamrożona: %1."); +S("Congratulations! Your score is %1.", "Gratulacje! Twój wynik to %1.") + +S("u = undo", "u = cofnij") +S("f = flip %1", "f = odbicie %1") + +S("Failed to save map to %1", "Nie udało się zapisać do %1") +S("Failed to load map from %1", "Nie udało się wczytać %1") +S("save whom", "kogo ratujemy") +S("other", "inne") // other keys in the main menu + +// VERSION 7.4 + +// missing texts, refactored things, and rule changes +//==================================================== + +S("%The1 activates her Flash spell!", "%1 rzuci%ł1 swój czar Błysk!") + +N("Fire", GEN_O, "Ogień", "Ognie", "Ogień", "Ogniem") +S("This cell is on fire. Most beings and items cannot survive.", + "To pole się pali. Większość stworzeń i przedmiotów tu nie przeżyje.") + +N("Eternal Fire", GEN_O, "Wieczny Ogień", "Wieczne Ognie", "Wieczny Ogień", "Wiecznym Ogniem") +S("This fire never burns out.", "Ten ogień pali się wiecznie.") + +S("Some rubble.", "Gruzy.") + +S("The Orb loses its power as it leaves the Land of Power!", + "Sfera traci swą moc, gdy opuszcza Krainę Mocy!") + +S("%The1 fills the hole!", "%1 zatka%ł1 dziurę!") + +N("Tentacle+Ghost", GEN_F, "Macka+Duch", "Macki+Duchy", "Mackę+Ducha", "Macką+Duchem") + +// Land Overview +//=============== + +S("world overview", "przegląd krain") +S("or 'o' to see the world overview", "lub 'o', by obejrzeć przegląd krain") + +S("forbidden to find in %the1", "zakazana %abl1") +S("too dangerous to use in %the1", "zbyt niebezpieczna %abl1") +S("useless in %the1", "bezużyteczna %abl1") +S("only native Orbs allowed in %the1", "tylko rodzime sfery %abl1") +S("this Orb is never unlocked globally (only hubs)", "ta Sfera występuje tylko w centrach") +S("collect 25 %2 to unlock it in %the1", "znajdź 25x %2 by udostępnić %abl1") +S("collect 3 %2 to unlock it in %the1", "znajdź 3x %2 by udostępnić %abl1") +S("native in %the1 (collect 10 %2)", "rodzima %abl1 (10x %2)") +S("native in %the1 (collect 1 %2)", "rodzima %abl1 (1x %2)") +S("secondary in %the1 (collect 10 %3, or 25 %2)", "podrzędna %abl1 (10x %3, lub 25x %2)") +S("the native Orb of %the1", "rodzima sfera %abl1") +S("this Orb appears on floors and is used by witches", "ta Sfera pojawia się na ziemi i jest używana przez czarownice") +S("a prized Orb, it appears only in cabinets", "cenna Sfera, tylko w gablotach") +S("this Orb never appears in %the1", "ta Sfera nie pojawia się %abl1") +S("Hub Land: orbs appear here if unlocked in their native land", "Centrum: sfery pojawiają się tu przy 10 skarbach") +S("kill a monster, or collect 25 %2", "zabij potwora, lub znajdź 25x %2") + +S("Always available.\n", "Kraina zawsze dostępna.\n") +S("Treasure required: %1 $$$.\n", "Wymagane skarby: %1 $$$.\n") +S("Accessible only from %the1.\n", "Kraina dostępna tylko poprzez %a1.\n") +S("Accessible only from %the1 (until finished).\n", "Kraina dostępna tylko poprzez %a1 (przed ukończeniem).\n") + +S("Accessible only from %the1 or %the2.\n", "Kraina dostępna tylko poprzez %a1 i %a2.\n") + +S("Kills required: %1.\n", "Wymagani pokonani przeciwnicy: %1.\n") +S("Finished lands required: %1 (collect 10 treasure)\n", + "Wymagane ukończone krainy: %1 (zdobądź 10 skarbów)\n") + +S("Treasure required: %1 x %2.\n", "Wymagane skarby: %1 x %2.\n") + +S("Alternatively: kill a %1.\n", "Alternatywnie: zabij %a1.\n") + +S("Kills required: any Elemental (Living Fjord/Dead Caves).\n", + "Wymagane zabicia: dowolny Żywiołak (Żywy Fjord/Martwa Jaskinia).") + +S("Variants of %the1 are always available in the Random Pattern Mode.", + "Warianty krainy %1 są zawsze dostępne w trybie losowych wzorków.") + +S("Variants of %the1 are available in the Random Pattern Mode after " + "getting a highscore of at least 10 %2.", + "Warianty krainy %1 są dostępne w trybie losowych wzorków po zdobyciu " + "10x %2.") + +S(" kills: %1", " zabicia: %1") +S(" $$$: %1", " $$$: %1") +S(" Hyperstone: %1/%2", " Hiperkamienie: %1/%2") +S(" Hell: %1/9", " Piekło: %1/9") + +// improved editor + +S("vector graphics editor -- press F1 for help", "edytor grafiki -- wciśnij F1, by zobaczyć pomoc") +S("pics to save/load:", "obrazki do zapisu/wczytania:") +S("level to save/load:", "mapa do zapisu/wczytania:") + +S("F4 = extension", "F4 = rozszerzenie") +S("Enter = back", "Enter = powrót") +S("SPACE = map/graphics", "SPACE = mapa/grafika") + +S("Emerald Pattern", "Szmaragdowy Wzór") +S("Palace Pattern", "Pałacowy Wzór") +S("Zebra Pattern", "Wzór Zebra") +S("rotational symmetry", "symetria obrotowa") +S("symmetry 0-1", "symetria 0-1") +S("symmetry 0-2", "symetria 0-2") +S("symmetry 0-3", "symetria 0-3") + +S("display pattern codes (full)", "pokaż kody wzorku (pełne)") +S("display pattern codes (simplified)", "pokaż kody wzorku (uproszczone)") +S("display only hexagons", "pokaż tylko sześciokąty") +S("display only heptagons", "pokaż tylko siedmiokąty") +S("predesigned patterns", "zaprojektowane wzorki") + +S("Gameboard", "Plansza") +S("random colors", "losowe kolory") +S("emerald pattern", "szmaragdowy wzór") +S("four elements", "cztery żywioły") +S("eight domains", "osiem domen") +S("zebra pattern", "wzór zebry") +S("three stripes", "trzy paski") +S("random black-and-white", "losowy czarno-biały wzorek") +S("p = paint", "p = kolory") +S("r = regular", "r = wzorki") + +S( + "In this mode you can draw your own player characters, " + "floors, monsters, and items. Press 'e' while hovering over " + "an object to edit it. Start drawing shapes with 'n', and " + "add extra vertices with 'a'. Press 0-9 to draw symmetric " + "pictures easily. More complex pictures can " + "be created by using several layers ('l'). See the edges of " + "the screen for more keys.", + + "W tym trubie możesz narysować swoje postacie, podłogi, potwory, " + "i przedmioty. Naciśnij 'e', gdy przesuwasz mysz ponad obiektem, " + "by go edytować. Zaczynaj nowe kształty od 'n', dodawaj wierzchołki 'a'. " + "Naciśnij 0-9 by łatwo rysować symetryczne obrazy. Bardziej " + "złożone obrazy mogą być tworzone przy użyciu warstw ('l'). " + "Pozostałe klawisze są wymienione na krawędziach ekranu.") + +S( + "Press 'r' to choose a regular pattern. When a pattern is on, " + "editing a cell automatically edits all cells which are " + "equivalent according to this pattern. You can choose from " + "several patterns, and choose which symmetries matter " + "for equivalence. Also, you can press Space to switch between " + "the map and graphics editor quickly -- note that editing floors " + "with the graphics editor also adheres to the pattern.", + + "Wciśnij 'r', by wybrać regularny wzorek. Gdy wzorek jest włączony, " + "edytowanie pola automatycznie edytuje także wszystkie pola, " + "które są mu równoważne ze względu na ten wzorek. Możesz wybrać jeden " + "z kilku wzorków, i wybrać symetrie uwzględniane przy obliczaniu równoważności. " + "Możesz też nacisnąć spację, by szybko się przenosić pomiędfzy edytorem map " + "i edytorem grafiki -- edytowanie podłóg w edytorze grafiki również " + "następuje zgodnie ze wzorkiem.") + +S("monster" ,"potwór") +S("item", "przedmiot") +S("floor", "podłoga") +S("hexagonal", "sześciokąt") +S("heptagonal", "siedmiokąt") +S("floor/pattern", "podłoga/wzorek") + +S("l = layers: %1", "l = warstwy: %1") +S("1-9 = rotations: %1", "1-9 = obroty: %1") +S("0 = symmetry", "0 = symetria") +S("0 = asymmetry", "0 = asymetria") +S("%1 vertices", "wierzchołki: %1") +S("a = add v", "a = dodaj v") +S("m = move v", "m = przenieś v") +S("d = delete v", "d = skasuj v") +S("c = readd v", "c = ponownie v") +S("b = reorder", "b = kolejność") +S("t = shift", "t = przesuń") +S("y = spin", "y = obróć") + +S("'n' to start", "n = start") +S("z = zoom in", "z = zbliżenie") +S("o = zoom out", "o = oddalenie") +S("g = grid", "g = siatka") +S("e = edit this", "e = edytuj to") + +S("x: %1", "x: %1") +S("y: %1", "y: %1") +S("z: %1", "z: %1") +S("r: %1", "r: %1") +S("ϕ: %1°", "ϕ: %1°") + +S("A fake Land with colored floors.", + "Fałszywa Kraina z kolorowymi podłogami.") + +S("random pattern mode", "tryb losowych wzorów") + +// Ivory Tower +//============= + +N("Ivory Tower", GEN_F, "Wieża z Kości Słoniowej", "Wieże z Kości Słoniowej", "Wieżą z Kości Słoniowej", "na Wieży z Kości Słoniowej") + +S( + "Powerful wizards claimed this part of the world, to perform their magical " + "experiments in peace and solitude. They have changed the direction of gravity, " + "to make it even harder for intruders to reach them.\n\n" + "Gravity works as follows: cells are unstable if they are empty, and there is " + "no cell immediately below them which contains a wall. It is impossible to move " + "from one unstable cell to another, except if moving down.", + + "Część świata zajęta przez potężnych czarodziejów, w celu prowadzenia magicznych " + "eksperymentów w spokoju i samotności. Zmienili oni kierunek grawitacji, " + "by intruzom było jeszcze trudniej się do nich dostać.\n\n" + "Grawitacja działa w sposób następujący: pole jest niestabilne, jeśli jest puste, i " + "żadne pole bezpośrednio pod nim nie zawiera ściany. Nie można przejść z jednego " + "niestabilnego pola na inne, chyba że w dół." + ) + +N("Servant", GEN_M, "Sługa", "Słudzy", "Sługę", "Sługą") +S("A simple servant of the master of the Ivory Tower.", + "Prosty sługa mistrza Wieży z Kości Słoniowej.") + +N("Gargoyle", GEN_M, "Rzygacz", "Rzygacze", "Rzygacza", "Rzygaczem") +N("stone gargoyle", GEN_M, "kamienny rzygacz", "kamienne rzygacze", "kamiennego rzygacza", "kamiennym rzygaczem") +N("stone gargoyle floor", GEN_F, "podłoga z rzygacza", "podłogi z rzygacza", "podłogę z rzygacza", "podłogą z rzygacza") +N("stone gargoyle bridge", GEN_O, "most z rzygacza", "mosty z rzygacza", "most z rzygacza", "mostem z rzygacza") + +S( + "A being made of stone, who likes high buildings. It becomes normal stone when " + "killed, but only if next to something stable -- otherwise it falls.", + "Stworzenie wykonane z kamienia, lubi wysokie budynki. Zamienia się w normalny " + "kamień, gdy go zabijesz, ale tylko, gdy stanie się to obok czegoś stabilnego -- " + "w przeciwnym razie spada.") + +N("Ivory Figurine", GEN_F, "Figurka", "Figurki", "Figurkę", "Figurką") + +S("A beautiful figurine, made of ivory. Figurines close to the base of the Tower " + "tend do disappear after you have collected many of them.", + "Piękna figurka z kości słoniowej. Figurki blisko podstawy Wieży znikają, gdy " + "zbierzesz dużo figurek.") + +N("Platform", GEN_F, "Platforma", "Platformy", "Platformę", "Platformą") +S("You can stand here.", "Możesz na niej stanąć.") + +N("ladder", GEN_F, "drabina", "drabiny", "drabinę", "drabiną") +S("You can use this ladder to climb the Tower.", + "Użyj tej drabiny, by wspiąć się na Wieżę.") + +Orb("Matter", "Materii") + +S("This Orb allows to temporarily create impassable matter, either to block paths or " + "to build bridges across chasms and waters.", + "Ta sfera pozwala tymczasowo stworzyć nieprzekraczalną barierę. Można to wykorzystać " + "do blokowania tras lub do budowy mostów nad przepaściami i wodami.") + +N("temporary wall", GEN_F, "tymczasowa ściana", "tymczasowe ściany", "tymczasową ścianę", "tymczasową ścianą") +N("temporary floor", GEN_F, "tymczasowa podłoga", "tymczasowe podłogi", "tymczasową podłogę", "tymczasową podłogą") +N("temporary bridge", GEN_O, "tymczasowy most", "tymczasowe mosty", "tymczasowy most", "tymczasowym mostem") + +S("This structure will disappear after some time.", "Ta konstrukcja zniknie za jakiś czas.") + +S("Nothing to stand on here!", "Nie ma tu na czym stać!") +S("Gravity does not allow this!", "Grawitacja nie pozwala!") + +// Elemental Planes +//================== + +N("Elemental Planes", GEN_F, "Strefa Żywiołów", "Strefy Żywiołów", "Strefę Żywiołów", "w Strefie Żywiołów") +N("Plane of Fire", GEN_F, "Strefa Ognia", "Strefy Ognia", "Strefę Ognia", "w Strefie Ognia") +N("Plane of Earth", GEN_F, "Strefa Ziemi", "Strefy Ziemi", "Strefę Ziemi", "w Strefie Ziemi") +N("Plane of Air", GEN_F, "Strefa Powietrza", "Strefy Powietrza", "Strefę Powietrza", "w Strefie Powietrza") +N("Plane of Water", GEN_F, "Strefa Wody", "Strefy Wody", "Strefę Wody", "w Strefie Wody") + +S("The Elemental Planes are divided into four subzones: Planes of Fire, Water, Air, and Earth. " + "You need to collect a Shard from each Plane to construct an Elemental Gem. " + "It is dangerous to collect too many Shards of the same type without constructing a Gem.", + + "Strefa Żywiołów dzielą się na cztery podstrefy: Strefa Ognia, Wody, Powietrza, i Ziemi. " + "Musisz znaleźć Okruch każdego żywiołu, by skonstruować Kamień Żywiołów. " + "Jest niebezpiecznie zbierać wiele Okruchów tego samego żywiołu bez konstruowania Kamienia." + ) + +N("Fire Elemental", GEN_M, "Ognisty Żywiołak", "Ogniste Żywiołaki", "Ognistego Żywiołaka", "Ognistym Żywiołakiem") + +S("This monster leaves a trail of fire behind.", + "Ten żywiołak zostawia za sobą ścianę ognia.") + +N("Air Elemental", GEN_M, "Powietrzny Żywiołak", "Powietrzne Żywiołaki", "Powietrznego Żywiołaka", "Powietrznym Żywiołakiem") + +S("An Air Elemental looks like a live tornado. Once you are three (or less) cells from it, " + "it is impossible to move closer, due to strong winds. You can stand and wait, though. " + "This also affects most monsters.", + + "Powietrzny Żywiołak wygląda jak żywa trąba powietrzna. Gdy znajdziesz się trzy lub " + "mniej pól od niego, nie możesz się zbliżyć bardziej, ze względu na silny powiew. " + "Możesz jednak stać w miejscu i czekać. Powietrzny Żywiołak wpływa także na potwory.") + +N("Fire Shard", GEN_O, "Okruch Ognia", "Okruchy Ognia", "Okruch Ognia", "Okruchem Ognia") +N("Air Shard", GEN_O, "Okruch Powietrza", "Okruchy Powietrza", "Okruch Powietrza", "Okruchem Powietrza") +N("Water Shard", GEN_O, "Okruch Wody", "Okruchy Wody", "Okruch Wody", "Okruchem Wody") +N("Earth Shard", GEN_O, "Okruch Ziemi", "Okruchy Ziemi", "Okruch Ziemi", "Okruchem Ziemi") +N("Elemental Gem", GEN_O, "Kamień Żywiołów", "Kamienie Żywiołów", "Kamień Żywiołów", "Kamieniem Żywiołów") + +Orb("Summoning", "Przywołania") + +S( + "This orb allows you to summon monsters. Usually, they are either Elementals or " + "native creatures. While the monsters do not like being summoned, and will " + "attack you once they recover from summoning sickness, such summoning " + "often has its uses.", + "Ta sfera pozwala Ci przywoływać potwory. Zwykle są to Żywiołaki albo stworzenia " + "pochodzące z danej krainy. Stwory nie lubią być przywoływane, i będą atakować " + "po wyjściu ze zmieszania wywołanego przywołaniem. Ale jednak takie przywoływanie " + "ma pewne zastosowania." + ) + +N("limestone wall", GEN_F, "wapienna ściana", "wapienne ściany", "wapienną ścianę", "wapienną ścianą") + +S("Simply a wall. Mostly.", "Po prostu ściana. W zasadzie.") + +// Zebra +//======= + +N("Zebra", GEN_F, "Zebra", "Zebry", "Zebrą", "w Zebrze") +S("Everything in this Land has black and white stripes.", + "Wszystko w tej Krainie ma czarne i białe paski.") + +N("Striped Dog", GEN_M, "Pasiasty Pies", "Pasiate Psy", "Pasiastego Psa", "Pasiastym Psem") +S("A predator native to the Zebra.", "Drapieżnik żyjący w krainie Zebry.") + +N("Onyx", GEN_O, "Onyks", "Onyksy", "Onyks", "Onyksem") +S("A black gem with white stripes. It is beautiful.", "Piękny, drogocenny czarny kamień z białymi paskami.") + +// Crossroads III +//================ + +N("Crossroads III", GEN_N, "Skrzyżowanie III", "Skrzyżowania III", "Skrzyżowanie III", "na Skrzyżowaniu III") + +S("An alternate layout of the Crossroads. Great Walls cross here at right angles.", + "Alternatywny układ Skrzyżowania. Wielkie Ściany przecinają się tu pod kątami prostymi.") + +S("Cannot create temporary matter on a monster!", "Nie można tworzyć tymczasowej materii na potworze!"); +S("Cannot create temporary matter on an item!", "Nie można tworzyć tymczasowej materii na przedmiocie!"); +S("Cannot create temporary matter here!", "Nie można tu stworzyć tymczasowej materii!"); +S("Cannot summon on a monster!", "Nie można przywołać na potworze!"); +S("No summoning possible here!", "Przywołanie niemożliwe!"); +S("You summon %the1!", "Przywoła%łeś0 %a1!") + +S("F4 = file", "F4 = plik") + +S("The Air Elemental blows you away!", "Powietrzny Żywiołak Ciebie zdmuchnie!") + +// appended to cave troll description +S(" Additionally, all items around the killed Troll will be destroyed.", + " Dodatkowo, wszystkie przedmioty wokół zabitego Trolla ulegają zniszczeniu.") + +#undef Orb + diff --git a/language-ru.cpp b/language-ru.cpp index d3911481..e3f34c00 100644 --- a/language-ru.cpp +++ b/language-ru.cpp @@ -1173,7 +1173,7 @@ S( "The Land of Power is filled with everburning fire, magical Orbs, and guarde "Witches are allowed to use all the powers of the " "basic orbs against intruders. These powers never expire, but a Witch " "can use only one power at a time (not counting Orbs of Life).\n\n" - "Witches and Golems don't pursue you into other Lands. Also, most Orb powers" + "Witches and Golems don't pursue you into other Lands. Also, most Orb powers " "are drained when you leave the Land of Power.", "Земля силы полна вечно горящими огнями и магическими сферами и защищена " "ведьмами и големами. Все обычные сферы есть здесь, " @@ -1241,8 +1241,6 @@ S("%The1 picks up %the2!", "%1 поднял%E1 %a2!") // currently only Witches, S("You can right click any element to get more information about it.\n\n", "Кликните правой кнопкой мыши, чтобы узнать больше.\n\n") -S("TRANSLATIONWARNING", "") - S("The Hyperbugs are fighting!", "Гипержуки сражаются!") S("","") N("",GEN_N,"","","","") @@ -1456,5 +1454,1290 @@ S("Shift+F, Shift+O, Shift+T, Shift+L, Shift+U, etc.", S("also hold Alt during the game to toggle high contrast", "также Alt во время игры переключает высокий контраст") +// Crossroads II + +N("Crossroads II", GEN_N, "Перекрёсток II", "Перекрёстки II", "Перекрёсток II", "на Перекрёстке II") + +S( + "An alternate layout of the Crossroads. It is more dense and more regular, " + "although you won't find the castle of Camelot here.", + + "Другая схема перекрёстка. Она плотнее и регулярнее обычной, " + "но замок Камелот Вы здесь не найдёте." +) + +// Caribbean + +// 'Karaiby' is plural in Polish, should probably fix the grammar for this + +N("Caribbean", GEN_M, "Карибы", "Карибы", "Карибы", "на Карибах") + +N("Pirate", GEN_M, "Пират", "Пираты", "Пирата", "Пиратом") +N("Shark", GEN_F, "Акула", "Акулы", "Акулу", "Акулой") +N("Parrot", GEN_M, "Попугай", "Попугаи", "Попугая", "Попугаем") +N("Pirate Treasure", GEN_N, "Сокровище пиратов", "Сокровища пиратов", "Сокровище пиратов", "Сокровищем пиратов") +N("Compass", GEN_O, "Компас", "Компасы", "Компас", "Компасом") + +N("sea", GEN_O, "море", "моря", "море", "морем") +N("boat", GEN_F, "лодка", "лодки", "лодку", "лодкой") +N("island", GEN_O, "остров", "острова", "остров", "островом") +N("tree", GEN_N, "дерево", "деревья", "дерево", "деревом") + +Orb("Time", "Времени") + +S("This dangerous sea contains nasty sharks and pirates. ", + "Опасное море, полное акул и пиратов.") + +S("The islands of Caribbean are infinite and circular, and " + "the pirates probably have hidden their treasures somewhere far from the coast.", + "Карибские острова бесконечные и круглые. Возможно, пираты " + "прячут свои сокровища где-то вдали от берега.") + +S( + "Hyperbolic pirates do not need huge ships, since so many lands to conquest " + "are so close. These small boats are enough for them.\n\n" + "Boats allow you to go through water. If you are in a boat, you can move into " + "a water cell (and the boat will come with you).", + + "Гиперболическим пиратам не нужны большие корабли, ведь много земель " + "для завоевания так близки. Достаточно этих маленьких лодок.\n\n" + "Лодки позволяют двигаться по воде. Если Вы в лодке, Вы можете " + "перейти на клетку с водой (и лодка переместится туда же).") + +S( + "The forests of Caribbean are too dense to be traversed by humans, " + "and they are hard to burn. Many colorful parrots can be found there.", + "Карибские леса слишком плотны, чтобы сквозь них мог пройти человек, " + "и их трудно поджечь. Много разноуветных попугаев живёт здесь.") + +S("Ye wonder where did th' Pirates find all these riches...", + "Интересно, где Пираты нашли эти богатства...") + +S( + "The hyperbolic pirates have no use for treasure maps. However, they have found " + "out that a compass points to the center of the island. So they just go as " + "far towards the center as they can, and hide their treasure there.", + + "Карты бесполезны для гиперболических пиратов, но они знают, что " + "компас всегда показывает в центр острова. Так что они просто идут " + "как можно дальше к центру острова и прячут там сокровища.") + +S("Just a nasty shark.", "Просто противная акула.") + +S("Parrots feel safe in the forests of Caribbean, so they " + "never leave them. But they will help the Pirates by attacking the intruders.", + + "Попугаи чувствуют себя в безопасности в Карибских лесах и " + "никогда их не покидают. Но они помогают пиратам, нападая на чужаков.") + +S("Just a typical hyperbolic pirate.", "Обычный гиперболический пират.") + +S( + "Normally, the power of most Orbs slowly fades away, even when " + "you are not actively using them. This Orb prevents this.\n\n" + + "When you have the Orb of Time, Orbs which are not active won't lose their power. " + "Orbs are considered active if they have a continuous power which has actually " + "affected something in the last turn.\n\n" + + "Orbs of Shielding remain active after being activated (even if you are no longer " + "attacked), and Orbs of Time have a bigger cap inside their native Caribbean than " + "outside.", + + "Обычно сила сфер угасает, даже если Вы не используете их. Сфера Времени " + "препятствует этому.\n\n" + + "Если у Вас есть сфера Времени, неактивные сферы не теряют свою силу. Сфера " + "считается активной, если она имеет постоянный эффект, проявившийся на " + "последнем ходе.\n\n" + + "Сфера Щита считается активной всегда (даже если Вы никого не атаковали). " + "Сфера Времени имеет на Карибах больший эффект, чем в других местах.") + +// Achievements: + +// Parrot : Find and collect Pirate Treasure. +// Caribbean Shark : Collect 10 Pirate Treasures. +// Pirate : Collect 25 Pirate Treasures. +// Master of Caribbean : Collect 50 Pirate Treasures. + +// Red Rock Valley + +N("Red Rock Valley", GEN_F, "Долина Красных Скал", "Долины Красных Скал", "Далину Красных Скал", "в Долине Красных Скал") + +N("Rock Snake", GEN_F, "Каменная змея", "Каменные змеи", "Каменную змею", "Каменной змеёй") +N("Rock Snake Tail", GEN_O, "Хвост змеи", "Хвосты змей", "Хвост змеи", "Хвостом змеи") +N("Red Troll", GEN_M, "Красный тролль", "Красные тролли", "Красного тролля", "Красным троллем") +N("Red Gem", GEN_O, "Красный камень", "Красные камни", "Красный камень", "Красным камнем") + +N("rock I", GEN_F, "скалы I", "скалы I", "скалу I", "скалой I") +N("rock II", GEN_F, "скалы II", "скалы II", "скалу II", "скалой II") +N("rock III", GEN_F, "скалы III", "скалы III", "скалу III", "скалой III") + +Orb("Space", "Пространства") + +S("Not enough power for telekinesis!", "Мало силы для телекинеза!") + +S("This land contains high rock formations. Most of the valley is at level 0, " + "while items are found at level 3. It is impossible to gain two or more levels, " + "or to lose three levels, in a single move, (attacks are possible at any " + "difference, though). Kill Red Trolls and Rock Snakes to make a cell higher.", + + "Эта земля содержт участки высоких скал. Большая часть долины находится на уровне 0, " + "а все предметы лежат на уровне 3. Невозможно подняться на 2 или больше уровня " + "или опуститься на 3 уровня за один ход, хотя атаковать можно всегда. " + "Убейте Красного тролля или Каменную змею, чтобы сделать клетку выше.") + +S("A kind of Troll native to the Red Rock Valley.", + "Этот вид троллей обитает в Долине Красных Скал.") + +S( + "Rock snakes are similar to Sandworms, but they move each turn. However, they " + "only move on the hexagonal cells. They are also somewhat longer than the Sandworms.", + + "Каменные змеи похожи на Пустынных червей, но движутся каждый ход. Однако они " + "могут перемещаться только по шестиугольникам. Также они несколько длиннее червей.") + +S("A gem from the Red Rock Valley.", "Камень из Долины Красных Скал.") + +S( + "This Orb is able to bring faraway items to your location, even if there are " + "monsters or barriers on the way. The cost of " + "bringing an item (in charges) equals the square of its distance to you. Contrary " + "to some other Orbs, usage is not allowed if you have not enough power left.", + + "Эта сфера может принести Вам предметы издалека, даже если на пути есть монстры " + "или препятствия. Стоимость использования равна квадрату расстояния " + "до предмета. В отличие от некоторых других сфер, она не может быть использована, " + "если ей силы не хватает.") + +// Climber : Find and collect a Red Gem. +// Red Troll : Collect 10 Red Gems. +// Rock Snake : Collect 25 Red Gems. +// Master of Red Rock : Collect 50 Red Gems. + +// missing sentences + +S("%The1 drowns!", "%1 утонул%E1!"); +S("%The1 falls!", "%1 упал%E1!"); + +// these were missing from the translation for some reason + +S("Hell has these lakes everywhere... They are shaped like evil stars, and filled with burning sulphur.", + "В Аду эти озёра повсюду. Они похожи на звёзды и наполнны кипящей серой.") + +// Hardcore Mode + +S("hardcore mode", "режим hardcore"); + +S("One wrong move and it is game over!", "Один неверный шаг, и игра закончится!"); +S("Not so hardcore?", "не так хардкорно?"); + +// Shoot'em up Mode + +S("shoot'em up mode", "режим стрельбы"); +S("Welcome to the Shoot'em Up mode!", "Добро пожаловать в режим стрельбы!"); +S("F/;/Space/Enter/KP5 = fire, WASD/IJKL/Numpad = move", "F/;/Space/Enter/KP5 = стрелять, WASD/IJKL/Numpad = ходить"); + +N("Rogue", GEN_M, "Разбойник", "Разбойники", "Разбойника", "Разбойником") +N("Knife", GEN_O, "Нож", "Ножи", "Нож", "Ножом") +N("Flail", GEN_O, "Цеп", "Цепы", "Цеп", "Цепом") +N("Fireball", GEN_O, "Огненный Шар", "Огненные Шары", "Огненный Шар", "Огненным Шаром") +N("Tongue", GEN_O, "Язык", "Языки", "Язык", "Языком") + +S("In the Shoot'em Up mode, you are armed with thrown Knives.", + "В режиме стрельбы Вы вооружены метательными ножами.") +S("A simple, but effective, missile, used by rogues.", + "Простой, но эффективный снаряд, используемый разбойниками.") +S("This attack is likely to hit the attacker.", + "Эта атака, вероятно, попадёт в атакующего.") +S("This magical missile burns whatever it hits.", "Этот магический снаряд поджигает всё, во что попадает.") +S("Some monsters have long tongues, which allow them to attack enemies in nearby cells.", + "Некоторые существа имеют длинные языки, которые позволяют им атаковать врагов на соседних клетках.") + +// modes for the local highscores + +S(", m - mode: normal", ", m - нормальный режим") +S(", m - mode: hardcore only", ", m - режим hardcore") +S(", m - mode: shoot'em up", "m - режим стрельбы") + +// update description for Steam: + +S("You are killed by %the1!", "Вас убил %1!") + +// (Shoot'em Up mode and two more lands than in the free version, and more are planned!) + +S("You would get hurt!", "Это было больно!") +S("PARTIAL", "ЧАСТИЧНО") +S("Cannot drop %the1 here!", "Сюда нельзя положить мёртвую сферу!") +S("You cannot attack Rock Snakes directly!", "Вы не можете атаковать Каменную змею!"); +S(" (E:%1)", " (E:%1)"); + +S("\"I am lost...\"", "\"Я потерялся...\""); + +// achievements from Version 7.0 which have not yet been translated + +// Hardcore : Get the Orb of Yendor in the Hardcore mode. +// Хардкор: Соберите сферу Йендора в режиме Хардкор +// Knife Master : Get the Orb of Yendor in the Shoot'em Up mode. +// Мастер ножей: Соберите сферу Йендора в режиме стрельбы. + +// new menu for Version 7.1 + +S("(v) menu", "(v) меню") +S("return to the game", "вернуться в игру") +S("or 'v' to see the main menu", "или 'v', чтобы открыть главное меню") + +S("HyperRogue %1", "HyperRogue %1") +S("basic configuration", "базовые настройки") +S("advanced configuration", "продвинутые настройки") +S("local highscores", "локальные рекорды") +S("help", "помощь") +S("restart game", "играть заново") +S("special game modes", "специальные режимы") +S("save the game", "сохранить игру") +S("quit the game", "выйти из игры") +S("review your quest", "смотреть квест") +S("review the scene", "смотреть сцену") +S("game over screen", "экран конца игры") +S("continue game", "продолжить игру") +S("play the game!", "играть!") + +// fixed descriptions for Shmup achievements + +S("You have used less knives than ever before. Congratulations!", + "Вы использовали меньше ножей, чем раньше. Поздравляем!") + +S("You have improved both your real time and knife count. Congratulations!", + "Вы улучшили результаты по реальному времени и количеству ножей. Поздравляем!") + +S("%1 knives (%2)", "ножи: %1 (%2)") + +// temporary +S("No description yet." ,"Нет описания.") + +// special case when no Spice is visible +S("The sandworm explodes!", "Червь взорвался!") + +// Ocean + +// achievements: +// Reached Ocean: Find and collect an Amber. +// Открыть Океан: Найдите а соберите Янтарь. +// Albatross: Collect 10 Ambers. +// Альбатрос: Соберите 10 янтарей. +// Amber Albatross: Collect 25 Ambers. +// Янтарный альбатрос: соберите 25 янтарей. +// Master of the Tides: Collect 50 Ambers. +// Мастер приливов: Соберите 50 янтарей. + +N("Ocean", GEN_O, "Океан", "Океаны", "Океан", "в Океане") + +S( + "You can collect some valuable Ambers on the coast, but beware the tides!\n\n" + "You can also take one of the boats and venture into the Ocean, " + "to find other coasts, dangerous whirlpools, and islands inhabited by Pirates.", + + "Вы модете найти ценный Янтарь не берегу, но остерегайтесь приливов!\n\n" + "Вы модете найти лодку и отправиться в Океан, чтобы найти другие берега, " + "опасные Водовороты и острова, полные пиратов.") + +N("Albatross", GEN_M, "Альбатрос", "Альбатросы", "Альбатроса", "Альбатросом") + +S( + "Those large seabirds attack you for some reason. At least they are not " + "as fast as Eagles...", + "Эти большие морские птицв почему-то атакуют Вас. Они хотя бы не такие " + "быстрые, как Орлы...") + +N("stranded boat", GEN_F, "лодка на мели", "лодки на мели", "лодку на мели", "в лодке на мели") + + +S( + "This boat cannot go through the sand. But if you sit inside and " + "wait for the tide, you will be able to use it to travel through the Ocean.", + + "Эта лодка не может пройти сквозь песок. Но если вы сядете внутрь " + "и дождётесь прилива, Вы сможете ей воспользоваться." + ) + +N("Ocean", GEN_O, "Океан", "Океаны", "Океан", "в Океане") + +N("Amber", GEN_O, "Янтарь", "Янтари", "Янтарь", "Янтарём") + +S( + "When the tide is away, beautiful ambers can be found on the hyperbolic beaches. " + "Perhaps there used to be a forest here?", + + "Во время отлива на гиперболических берегах можно найти прекрасный Янтарь. " + "Може, здесь когда-то был лес?" + ) + +Orb("Air", "Воздуха") + +S("This Orb allows you to blow your enemies away.\n\n" + "Click a monster to blow it one cell away. It cannot be used against mimics, ghosts, sharks and other monsters restricted to a specific terrain, and multi-tile monsters.", + "Эта сфера позволяет Вам сдуват врагов вдаль.\n\n" + "Нажми на монстра, чтобы сдуть его на 1 клетку. Невозможно сдуть мимиков, духов, акул и других монстров, живущих на определённой территории, и монстров из нескольких частей." + ) + +N("Sea Border", GEN_O, "Граница моря", "Границы моря", "Границу моря", "на Границе моря") + +S("Border between seas.", "Граница между морями.") + +// Whirlpool + +// achievements: +// Escaped Whirlpool: Collect a Pearl, and escape the Whirlpool. +// Покинуть Водоворот: Соберите Жемчужину и выберитесь из Водоворота. +// Vortex Shark: Collect 10 Pearls. +// Акула вихря: Соберите 10 жемчужин. +// Vortex Pirate: Collect 25 Pearls. +// Пират Вихря: Соберите 25 жемчужин. +// Master of the Whirlpool: Collect 50 Pearls. +// Мастер Водоворота: Соберите 50 жемчужин. + +N("Whirlpool", GEN_O, "Водоворот", "Водовороты", "Водоворот", "в Водовороте") + +S( + "Many lost boats are spinning in this whirlpool. Some of them contain treasures " + "and Pirates.\n\n" + "Unmanned boats will go one cell clockwise in each turn. Sharks and manned boats " + "are only allowed to go with the current, that is, towards the center, or clockwise.", + + "Много лодок погибло в этом водовороте. В некоторых из них были ценности и Пираты.\n\n" + "Пустые лодки движутся на одну клетку по часовой стрелке каждые ход. Акулы и лодки с людьми " + "движутся по течению, то есть к центру или по часовой стрелке." + ) + +N("Pearl", GEN_F, "Жемчужина", "Жемчужины", "Жемчужину", "Жемчужиной") + +S( + "You do not know exactly why, but there are valuable pearls on many boats " + "in the whirlpool.", + "Неизвестно, почему, но этих жемчужин довольно много в лодках в этом водовороте." + ) + +Orb("Water", "Воды") + +S( "This Orb allows your boat to go against the current, " + "and also to go into the land, creating water on the way.", + "Эта сфера позволяет тебе плыть против течения, " + "а также двигаться по суше, создавая воду по пути.") + +S("You cannot go against the current!", "Нельзя плыть против течения!") + +// Minefield + +// achievements: +// Reached Minefield: Collect a Bomberbird Egg. +// Открыть Минное поле: Соберите Яйцо бомбардира. +// Minesweeper: Collect 10 Bomberbird Eggs. +// Сапёр: Соберите 10 Яиц бомбардира. +// Bomberbird: Collect 25 Bomberbird Eggs. +// Бомбардир: Соберите 25 Яиц бомбадира. +// Master of the Minefield: Collect 50 Bomberbird Eggs. +// Мастер Минного поля: Соберите 50 Яиц бомбардира. + +N("Minefield", GEN_N, "Минное поле", "Минные поля", "Минное поле", "на Минном поле") +N("minefield", GEN_N, "минное поле", "минные поля", "минное поле", "на минном поле") +N("cell without mine", GEN_N, "поле без мин", "поля без мин", "поле без мин", "полем без мин") + +S( + "This minefield has been created by the Bomberbirds to protect their valuable eggs. " + "Mines explode when they are stepped on, creating fire all around them " + "(this fire never expires in the Minefield). If you don't step on a mine, you " + "know the number of mines in cells around you. These numbers are marked with " + "color codes on the cells you have visited.", + "Минное поле было создано птицами Бомбардирами, чтобы охранять их ценные яйца. " + "Мина взрывается, когда Вы наступаете на неё, и создаёт огонь вокруг Вас (огонь " + "здесь горит вечно). Если Вы не наступили на мину, то Вы знаете, сеолько мин рядом с Вами. " + "Эти числа кодируются цветами клеток, на которых Вы были." + ) + +N("Bomberbird", GEN_M, "Бомбардир", "Бомбардиры", "Бомбардира", "Бомбардиром") + +S( + "Dark red birds who have created the minefield.\n\n" + "They create a mine on the spot where they are killed, provided " + "that the terrain is suitable. Also note that mines are triggered " + "by dead birds falling on them.", + + "Тёмно-чёрные птицы, создавшие Минное поле.\n\n" + "Когда птица умирает, на клетке, где она была, остаётся мина. " + "Помни, что мёртвые птицы могут активировать мины.") + +N("Tame Bomberbird", GEN_M, "Ручной бомбардир", "Ручные бомбардиры", "Ручного бомбардира", "Ручным бомбардиром") + +S( + "This bomberbird will follow you at some distance, and attack your enemies. " + "You can kill it to place a mine.", + + "Этот бомбардир будет следовать за Вами и атаковать Ваших врагов. " + "Можете его убить, чтобы оставить мину.") + +N("Bomberbird Egg", GEN_N, "Яйцо бомбардира", "Яйца бомбардира", "Яйцо бомбардира", "Яйцом бомбардира") + +S( + "Bomberbird eggs are big and tasty, and thus valuable. " + "They can hatch when left alone for some time (but this will never happen " + "if you are watching).", + + "Яйца бомбардиров большие и вкусные, и потому ценные. " + "Если оставть их в покое, может вылупиться бомбардир (но этого " + "не случится, пока Вы на них смотрите)." + ) + +Orb("Friendship", "Дружбы") + +S("This Orb summons a friendly Bomberbird.", + "Эта сфера вызывает ручного Бомбардира.") + +S("Nowhere to blow %the1!", "Некуда сдуть %a1!") +S("%The1 is immune to wind!", "%1 защищён от ветра!") +S("You blow %the1 away!", "Вы сдули %a1!") + +S("WARNING: you are entering a minefield!", "ВНИМАНИЕ: вы вошли на минное поле!") +S("No mines next to you.", "Нет мин рядом с Вами.") +S("A mine is next to you!", "Одна мина рядом с Вами!") +S("Two mines next to you!", "Две мины рядом с Вами!") +S("Three mines next to you!", "Три мины рядом с Вами!") +S("Four mines next to you!", "Четыре мины рядом с Вами!") +S("Five mines next to you!", "Пяти мин рядом с Вами!") +S("Six mines next to you!", "Шесть мин рядом с Вами!") +S("Seven mines next to you!", "Семь мин рядом с Вами!") + +S("Still confused? Read the FAQ on the HyperRogue website!\n\n", + "Что-т неясно? Прочитайте FAQ на сайте HyperRogue! (по-английски)\n\n") + +S("You have to run away from the water!", "Убегайте из воды!") + + +N("Palace", GEN_O, "Дворец", "Дворцы", "Дворец", "в Дворце") +N("palace wall", GEN_F, "стена дворца", "стены дворца", "стену дворца", "стеной дворца") + +S("Apparently a princess is kept locked somewhere, but you won't ever find her in this hyperbolic palace. ", + "Видимо, принцесса где-то заперта, но в гиперболическом дворце Вы её не найдёте. ") + +S("Apparently a prince is kept locked somewhere, but you won't ever find him in this hyperbolic palace. ", + "Видимо, принц где-то заперт, но в гиперболическом дворце Вы его не найдёте. ") + +S("So better just to concentrate on collecting treasure. " + "Beware the traps, and the guards, who are hard to kill!", + + "Лучше сконцентрироваться на сборе сокровищ. " + "Остерегайтесь ловушек и стражников, которых сложно убить!" + ) + +N("trapdoor", GEN_F, "ловушка", "ловушки", "ловушку", "ловушкой") +S("This floor will fall after someone goes there. Go quickly!", + "Пол провалится, как только на него наступят. Бегите!") + +N("closed gate", GEN_O, "закрытый проход", "закрытые проходы", "закрытый проход", "закрытым проходом") +N("open gate", GEN_O, "открытый проход", "открытые проходы", "открытый проход", "открытым проходом") +N("closing plate", GEN_F, "закрывающая плита", "закрывающие плиты", "закрывающую плиту", "закрывающей плитой") +N("opening plate", GEN_F, "открывающая плита", "открывающие плиты", "открывающую плиту", "открывающей плитой") + +S("Green pressure plates open all gates in radius 3 around them. " + "Similarly, red pressure plates close all gates in this radius.", + + "Зелёная плита открывает все проходы в радиусе 3 клеток. " + "Аналогично, красная плита закрывает проходы в том же радиусе.") + +N("Hypersian Rug", GEN_O, "Гиперсидский ковёр", "Гиперсидские ковры", "Гиперсидский ковёр", "Гиперсидским ковром") +S("Nice, a hyperbolic rug! It will not fit very well on your flat Euclidean floor, but who cares?", + "Прекрасный гиперболический ковёр! На плоский пол его не положишь, ну и пусть.") + +Orb("the Frog", "Жабы") +S("This Orb lets you jump to a place which is two cell away from you, in a single turn. " + "You can jump over water, chasms and fire, but not over walls.", + "Эта сфера позволяет прыгать на 2 клетки за один ход. " + "Вы можете прыгать через воду, огонь или пропасть, но не через стены.") +S("Cannot jump through %the1!", "Нельзя прыгать через %a1!") +S("You jump!", "Вы прыгнули!") + +S("\n\nNote: when pushing %the1 off a heptagonal cell, you can control the pushing direction " + "by clicking left or right half of the heptagon.", + "\n\nВажно: когда Вы толкаете %a1 с семиугольника, Вы можете выбирать направление движения, " + "нажимая на соответствующую половину семиугольника." + ) + +S(" With the keyboard, you can rotate the view for a similar effect (Page Up/Down).", + " На клавиатуре пользуйтесь поворотом поля для того же эффекта (Page Up/Down).") + +N("Palace Guard", GEN_M, "Дворцовый стражник", "Дворцовые стражники", "Дворцового стражника", "Дворцовым стражником") + +S("You have to hit Palace Guards several times to kill them. After each hit, they " + "are pushed away and stunned for some time.", + "Чтобы убить Дворцового стражника, его нужно ударить несколько раз. После каждого удара " + "он отлетает на одну клетку назад и застывает на некоторое время.") + +N("Fat Guard", GEN_M, "Тучный стражник", "Тучные стражники", "Тучного стражника", "Тучным стражником") + +S("Fat guards are too heavy to be pushed away by your hits.", + "Тучный стражник слишком тяжёл, чтобы отлетать от Ваших ударов.") + +N("Skeleton", GEN_M, "Скелет", "Скелеты", "Скелета", "Скелетом") +S("Skeletons work similar to Palace Guards, but they won't die no matter how many " + "times you hit them. Well, you have to be more creative...\n\n" + "Skeletons attacked outside of their native land, Palace, are stunned for a longer time.", + "Скелет реагирует на удары как Дворцовый стражник, но сколько раз бы Вы его не ударили, " + "он не умрёт. Хитрее надо быть...\n\n" + "Если скелет атакован вне его родной земли, Дворца, он застывает на более долгое время." + ) + +N("Vizier", GEN_M, "Визирь", "Визири", "Визиря", "Визирем") +S("Viziers are neither pushed away nor stunned. However, you attack them automatically when " + "escaping from them.", + "Визиря нельзя ни оглушить, ни оттолкнуть. Вы атакуете его каждый раз, когда " + "убегаете от него.") + +S("You stun %the1.", "Вы оглушили %a1.") +S("The gate is closing right on you! RUN!", "Проход закрывается! БЕГИТЕ!") +S("%The1 is crushed!", "%1 разрушается") +S("You hit %the1.", "Вы ударили %a1.") +S("Hit him by walking away from him.", "Ударьте его, убежав от него.") +S("Hmm, he has been training in the Emerald Mine. Interesting...", "Он тренировался в Изумрудной шахте. Хм, интересно...") + +// Reached the Palace: Find and collect a Hypersian Rug. +// Открыть Дворец: Найдите и соберите Гиперсидский ковёр. +// Palace Guard: Collect 10 Hypersian Rugs. +// Дворцовый страж: Соберите 10 Гиперсидских ковров. +// Vizier: Collect 25 Hypersian Rugs. +// Визирь: Соберите 25 Гиперсидских ковров +// Prince: Collect 50 Hypersian Rugs. +// Принц: Соберите 50 Гиперсидских ковров. + +// Living Fjord + +N("Living Fjord", GEN_O, "Живой фьорд", "Живые фьорды", "Живой фьорд", "в Живом фьорде") + +S("A coastal area, from where you can get both to the inland worlds and to the Ocean. " + "Each turn, each cell will become water or earth, based on the majority of cells around it. " + "Contrary to the Living Caves, this process is not affected by most items and monsters, " + "but elementals, dead Trolls, and cells outside of the Living Fjord have " + "a very powerful effect.", + "Прибрежный регион, из которого можно попасть как в наземные области, так и в Океан. " + "Каждый ход каждая клетка становится сушей или водой, основываясь на том, каких соседей больше. " + "В отличие от Живой пещеры этот процесс не зависит от объектов и монстров, за " + "исключением Элементалей, мёртвых Троллей и клеток вне Живого фьорда - " + "все они имеют очень сильный эффект." + ) + +N("Fjord Troll", GEN_M, "Тролль фьорда", "Тролли фьорда", "Тролля фьорда", "Троллем фьорда") +S("Fjord Trolls leave a wall when they die, causing the living fjord to rise around it. " + "Contrary to Rock Trolls, items around are not destroyed.", + "Тролли фьорда превращаются в стену при смерти, вызывая рост живых фьордов вокруг. " + "В отличие от горных троллей они не уничтожают предметы." + ) + +N("Viking", GEN_M, "Викинг", "Викинги", "Викинга", "Викингом") +S("Mighty warriors from the Fjord, who can use boats.", + "Могучие воины из Фьорда, способные использовать лодки.") + +N("Water Elemental", GEN_M, "Водный элементаль", "Водные элементали", "Водного элементаля", "Водным элементалем") +S("Wherever this powerful being goes, the living fjord " + "sinks below water, non-magical boats are destroyed, and fires are extinguished.\n\n" + "As a special case, you can attack the Water Elemental from the water, without drowning immediately.", + "Где бы ни шло это могущественное существо, фьорды расступаются перед ним, " + "обычные лодки уничтожаются, огонь гаснет.\n\n" + "Однако, если Вы атакуете его, находяст в воде, Вас не затянет сразу в воду.") + + +N("Garnet", GEN_O, "Гранат", "Гранаты", "Гранат", "Гранатом") +S("Vikings believe that garnets improve their strength.", + "Викинги верятЮ что гранаты дают им силу.") + +Orb("the Fish", "Рыбы") +S("This Orb lets you dive into the water. While diving, you are able to see and collect underwater treasures, " + "while being invisible to monsters yourself. You are afraid of jumping into the water straight from a boat, so usually you won't do it.", + "Эта сфера позволяет нырять. Когда Вы ныряете, Вы видите и можете собирать подводные ценности, " + "а враги Вас не видят. Но Вы боитесь прягать из лодки прямо в воду.") + +S("%The1 is washed away!", "%a1 смыло водой!") +S("%The1 is extinguished!", "%1 гаснет!") + +// Reached the Living Fjord: Find and collect a Garnet. +// Открыть Живой фьорд: Найдите и соберите Гранат. +// Viking: Collect 10 Garnets. +// Викинг: Соберите 10 гранатов. +// Water Elemental: Collect 25 Garnets. +// Водный элементаль: Соберите 25 гранатов. +// Master of the Fjord: Collect 50 Garnets. +// Мастер фьорда: Соберите 50 гранатов. + +// implemented, not appears in the game yet + +Orb("Discord", "Раздора") + +S("Causes most monsters to attack other monsters, not only you and your friends.", + "Монстры начинают атаковать других монстров, а не только Вас и ваших союзников.") + +// Shmup Configuration + +S("forward", "вперёд") +S("backward", "назад") +S("turn left", "повернуть налево") +S("turn right", "повернуть направо") +S("move up", "идти наверх") +S("move right", "идти направо") +S("move down", "идти вниз") +S("move left", "идти налево") +S("throw a knife", "кинуть нож") +S("face the pointer", "лицом к цели") +S("throw at the pointer", "кинуть нож в цель") +S("drop Dead Orb", "бросить мёртвую сферу") +S("center the map on me", "центрировать карту по мне") +S("activate Orb power", "активировать сферу") + +S("pan up", "крутить вверх") +S("pan right", "крутить вправо") +S("pan down", "крутить вниз") +S("pan left", "крутить влево") +S("rotate left", "повернуть влево") +S("rotate right", "повернуть вправо") +S("home", "центр на игроках") + +S("do nothing", "ничего") +S("rotate view", "повернуть вид") +S("panning X", "крутить X") +S("panning Y", "крутить Y") +S("player 1 X", "игрок 1 X") +S("player 1 Y", "игрок 1 Y") +S("player 1 go", "игрок 1 идёт") +S("player 1 spin", "игрок 1 вертит") +S("player 2 X", "игрок 2 X") +S("player 2 Y", "игрок 2 Y") +S("player 2 go", "игрок 2 идёт") +S("player 2 spin", "игрок 2 вертит") + +S("Joystick %1, axis %2", "Джойстик %1, ось %2") +S("one player", "один игрок") +S("two players", "два игрока") +S("configure player 1", "настройки игрока 1") +S("configure player 2", "настройки игрока 2") +S("configure panning", "настройки прокрутки") +S("configure joystick axes", "настройка джойстика") +S("continue playing", "продолжить игру") +S("start playing in the shmup mode", "начать игру в режиме стрельбы") +S("return to the turn-based mode", "вернуться в пошаговый режим") +S("save the configuration", "сохранить настройки") +S("press a key to unassign", "нажмите, чтобы отменить назначение") +S("press a key for '%1'", "нажмите клавишу для '%1'") +S("unassign a key", "отменить") + +// extra pattern modes + +S("explore the Emerald Pattern", "Изучить Изумрудный узор") +// S("explore the Fifty Pattern (4 colors)", "Изучить узор 50 (4 цвета)") +// S("explore the Fifty Pattern (8 colors)", "Изучить узор 50 (8 цветов)") + +// extra flavor/Knight lines + +S("Kill a Vizier in the Palace to access Emerald Mine", "Убей Визиря во дворце, чтобы открыть Изумрудную шахту.") +S("Collect 5 Emeralds to access Camelot", "Собери 5 изумрудов, чтобы открыть Камелот.") +S("Some lands unlock at specific treasures or kills", "Для открытия некоторых земель нужно определённые сокровища или убитые враги.") + +S("You will be fighting red rock snakes, too...", "Вы тоже будете биться с красными змеями...") + +S("\"The Red Rock Valley is dangerous, but beautiful.\"", + "\"Долина красных камней опасна, но прекрасна.\"") +S("\"Train in the Desert first!\"", "\"Потренируйтесь сначала в Пустыне!\"") +S("\"I like collecting ambers at the beach.\"", "\"Люблю собирать янтарь на берегу.\"") +S("\"Our Table seats %1 Knights!\"", "\"За нашим столом сидит %1 рыцарей!\"") +S("\"There are %1 floor tiles inside our Table!\"", "\"Внутри стола %1 клеток!\"") +S("\"By now, you should have your own formula, you know?\"", "\"Сейчас у Вас должна быть своя формула!\"") +S("\"Have you tried to take a boat and go into the Ocean? Try it!\"", "\"Вы пробовали взять лодку и уплыть в Океан?\"") + +//====================// +// NEW IN VERSION 7.3 // +//====================// + +// new name for 'Ivy D' + +N("Dead Ivy", GEN_O, "Мёртвый плющ", "Мёртвые плющи", "Мёртвый плющ", "Мёртвым плющом") + +// new messages for living/nonliving monsters + +S("%The1 bites %the2!", "%1 ударил%E1 %a2!") +S("%The1 attacks %the2!", "%1 атаковал%E1 %a2!") +S("You destroy %the1 with a mental blast!", "Вы уничтожили %a1 силой мысли!") +S("The ivy kills %the1!", "Плющ убил %a1!") +S("You destroy %the1.", "Вы уничтожили %a1.") +S("%The1 kills %the2!", "%1 убил%E1 %a2!") +S("%The1 sinks!", "%1 утонул%E1!"); + +S("Cannot jump on %the1!", "Нельзя прыгнуть на %1!") + +// renamed Fifty to Palace +S("explore the Palace Pattern (4 colors)", "Изучить узор Дворца (4 цветов)") +S("explore the Palace Pattern (8 colors)", "Изучить узор Дворца (8 цветов)") + +// Map Editor +//============ + +S("map editor", "редактор карт") +S("You activate your terraforming powers!", "Вы активировали силу редактирования!") +S("Press F5 to clear the board.", "Нажмите F5, чтобы очистить доску.") +S("Press F5 to restart the game normally.", "Нажмите F5, чтобы начать нормальную игру.") +S("High quality shots not available on this platform", "Скрины высокого качества недоступны на этой платформе") +S("Saved the high quality shot to %1", "Скрин высокого качества сохранён в %1") +S("Map saved to %1", "Карта сохранена в %1") +S("Map loaded from %1", "Карта загружена из %1") +S("copying", "копирование") +S("boundary", "граница") +S("clear monster", "удалить монстра") +S("use at your own risk!", "используйте это на свой риск!") + +// Note: in English, these have been arranged from longest to shortest. +// This gives a somewhat nice effect on the top left corner of the screen. +// You may want to aim for the same effect when translating + +S("0-9 = radius (%1)", "0-9 = радиус (%1)") +S("b = boundary", "i = предметы") +S("m = monsters", "b = граница") +S("w = walls", "m = монстры") +S("i = items", "l = земли") +S("l = lands", "c = копия") +S("c = copy", "w = стены") + +// And this is from shortest to longest (bottom left corner) +S("F1 = help", "F1 = помощь") +S("F2 = save", "F2 = записать") +S("F3 = load", "F3 = загрузить") +S("F5 = restart", "F5 = перезапуск") +S("F6 = HQ shot", "F6 = скриншот HQ") +S("F7 = player on/off", "F7 = игрок вкл/выкл") +S("ESC = return to the game", "ESC = вернуться в игру") + +S( + "This mode allows you to edit the map.\n\n" + "NOTE: Use at your own risk. Combinations which never " + "appear in the real game may work in an undefined way " + "(do not work, look strangely, give strange messages, or crash the game).\n\n" + "To get the most of this editor, " + "some knowledge of inner workings of HyperRogue is required. " + "Each cell has four main fields: land type, wall type, monster type, item type. " + "The same wall type (especially \"none\", \"sea\", or \"bonfire\") may look or " + "work a bit differently, based on the land it is in. Sometimes an object may " + "appear twice on the list due to subtle differences (for example, Demons could " + "move next turn or not).\n\n" + "Press w, i, l, or m to choose which aspect of cells to change, " + "then just click on the cells and they will change. Press 'c' while " + "hovering over a cell to copy that cell, this copies all information about it. " + "When copying large areas or placing multi-tile monsters, it might be important where " + "on the cell you are clicking.\n\n" + "You can also press 0-9 to apply your changes to a greater radius. " + "This also affects the copy/paste feature, allowing to copy a larger area.\n\n" + "Press F2 to save the current map (and F3 to load it). If you try this after " + "a long game of HyperRogue (without using Orbs of Safety), the filesize will " + "be very large! " + "Note however that large structures, such as " + "Great Walls, large circles and horocycles, are destroyed by this.\n\n" + "Press 'b' to mark cells as boundaries. Such cells, and cells beyond " + "them, are not copied by the copy/paste feature, nor saved by the " + "save feature.\n\n", + + "В этом режиме можно редактировать карту.\n\n" + "ВНИМАНИЕ: используйте его на свой риск! Комбинации, которые не могут возникнуть " + "в настоящей игре, могут иметь неопределённое поведение (не работать, выглядеть " + "странно, выдавать странные сообщения, вызывать вылет игры).\n\n" + "Чтобы пользоваться редактором, нужно немного представлять, как устроена игра " + "HyperRogue. Каждая клетка содержит четыре основных элемента: тип земли, тип стены, тип монстра" + "тип предмета. некоторые типы стен (особенно \"ничего\", \"море\" и \"костёр\")" + " могут выглядеть или работать немного по-разному в зависимости от земли, в которой они " + "находятся. Иногда объект может находиться в списке в двух экземплярах в зависимости от разных вещей " + "(например, будет ли Демон двигаться на следующий ход).\n\n" + "Нажмите w, i, l, m чтобы выбрать, какой атрибут клетки будете менять, нажмите на клетку, " + "и она изменится. Нажмите 'c', когда мышка находится над клетко , чтобы копировать " + "клетку -- копируется вся информация о ней. Если Вы копируете или размещаете " + "монстров из нескольких клеток, может иметь значение часть клетки, на которую Вы нажмёте.\n\n" + "Нажмите 0-9, чтобы применить изменения с большим радиусом. " + "Это также влияет на копирование/вставку, копируя большую область.\n\n" + "Нажмите F2, чтобы сохранить текущую карту (и F3, чтобы загрузить). Если вы попробуете " + "сделат это после долгой игры в HyperRogue (без сфер Безопасности), " + "размер файла может быть очень велик! Большие структуры, такие как Великие стены " + "и ороциклы, будут уничтожены.\n\n" + "Нажмите 'b', чтобы обозначить клетку как границу. Такие клетки, как и клетки за ними, " + "не будут копироваться, вставляться и сохраняться.\n\n" + ) + +// Princess Quest +//================ + +// Saved the Princess - "Wybawca" - "Uratuj Księżniczkę." +// Princess Challenge - "Misja Księżniczka" - "Zwycięstwo w misji Księżniczka." +// Martial Artist - "Sztuki walki" - "Pozwól nieuzbrojonej Księżniczce wygrać walkę" + +S( + "A mouse squeaks at you. It seems that it wants you to go somewhere. " + "That's interesting, what could you find here?\n\n" + "Note: in the part of the Palace that you are exploring during this " + "quest, the distribution of monsters, pressure plates, and items has been " + "changed somewhat, to make it a bit more suitable for less " + "experienced players. The number of monsters does not depend on the " + "number of Hypersian Rugs you have collected, and there are more " + "opening plates.\n\n" + "However, even with the normal distribution, it appears that it should be " + "always possible to reach your goal. If you want this challenge, " + "select it from the special game modes menu.", + + "Мышка пищит на Вас. Как будто она хочет, чтобы Вы пошли куда-то. " + "Интересно, что же там может быть?\n\n" + "В той части Дворца, которая будет доступна в Квесте, " + "распределение монстров, плит и предметов немного изменено, " + "чтобы подходить для не очень опытных игроков. " + "Количество монстров не зависит от количества собранных сокровищ, " + "и открывающих плит здесь больше.\n\n" + "Но и при нормальном распределении Квест можно пройти. " + "Если Вы хотите это сделать, выберите специальный режим в меню." +) + +S("\"When I visited the Palace, a mouse wanted me to go somewhere.\"", + "\"Когда я был во Дворце, мышь пыталась меня позвать куда-то.\"") + +S("\"I wonder what was there...\"", "\"Интересно, что там было...\"") + +N("Mouse", GEN_F, "Мышка", "Мышки", "Мышку", "Мышкой") + +S("You hear a distant squeak!", "Вы слышите писк!") +S("%The1 squeaks in a confused way.", "%1 пищит, запутавшись.") +S("%The1 squeaks gratefully!", "%1 пищит с благодарностью!"); +S("%The1 squeaks hopelessly.", "%1 пищит без надежды."); +S("%The1 squeaks in despair.", "%1 пищит в отчаянии."); +S("%The1 squeaks sadly.", "%1 пищит грустно."); +S("%The1 squeaks with hope!", "%1 пищит с надеждой!"); +S("%The1 squeaks happily!", "%1 пищит радостно!"); +S("%The1 squeaks excitedly!", "%1 пищит азартно!"); + +N("giant rug", GEN_O, "огромный ковёр", "огромные ковры", "огромный ковёр", "огромным ковром") + +S("This is the biggest Hypersian Rug you have ever seen! " + "Unfortunately, it is too large to take it as a trophy.", + "Это самый большой гиперсидский ковёр, который Вы когда-либо видели! " + "К сожалению, он слишком большой, чтобы забрать его.") + +N("Prince", GEN_M, "Принц", "Принцы", "Принца", "Принцем") +N("Princess", GEN_F, "Принцесса", "Принцессы", "Принцессу", "Принцессой") + +S("%1 takes %his1 revenge on %the2!", "%1 будет мстить!") +S("\"That should teach you to take me seriously!\"", + "\"Относись ко мне серьёзно! Будет тебе наука!\"") + +S("%The1 kisses you, and begs you to bring %him1 away from here.", + "%1 поцеловал%E1 тебя, и попросил%E1 увести отсюда.") + +S("\"I want my revenge. Stun a guard and leave him for me!\"", + "Я хочу мстить! Оглуши стража и оставь его мне!\"") + +S("\"That felt great. Thanks!\"", "\"Это было прекрасно. Спасибо!\"") + +S("\"Bring me out of here please!\"", "Прошу, уведи меня отсюда!\"") + +S("%The1 kisses you, and thanks you for saving %him1.", + "%1 поцеловал%E1 тебя и поблагодарил%E1 за спасение.") + +S("\"I have been trained to fight with a Hypersian scimitar, you know?\"", + "Я тренировал%c1 с гиперсидским ятаганом, ты в курсе?\"") + +S("\"I would love to come to your world with you!\"", + "Я хотел%E1 бы отправиться в Ваш мир вместе с Вами!\"") + +S("\"Straight lines stay close to each other forever, this is so romantic!\"", + "\"Прямые линии остаются близко друг к другу... Как романтично!\"") + +S("\"Maps... Just like the world, but smaller... how is that even possible?!\"", + "\"Карты... как мир, только меньше... как это возможно?!\"") + +Orb("Love", "Любви") +S("Love takes time, but it heals all wounds, and transcends time and space.\n\n" + "The Orb of Love is worth 30$$$, if you end the game with it.\n", + + "Любовь требует времени, но лечит все раны, и проходит сквозь " + "время и пространство.\n\n" + "Сфера любви стоит 30$$$, если закончить игру с ней.\n") + +// Princess Challenge: + +S("%1 Challenge", "Миссия %1") +S("Save %the1 first to unlock this challenge!", "Спаси %a1, прежде чем разблокировать миссию!") +S("Welcome to %the1 Challenge!", "Спаси %a1!") +S("The more Hypersian Rugs you collect, the harder it is.", "Чем больше Вы нашли гиперсидских ковров, тем это сложнее.") +S("Follow the Mouse and escape with %the1!", "Следуq за Мышкой и выйди с %abl1!") +S("Hardness frozen at %1.", "Сложность заморожена на %1."); +S("Congratulations! Your score is %1.", "Поздравляем! Ваш результат: %1.") + +S("u = undo", "u = отмена") +S("f = flip %1", "f = перевернуть %1") +S("Failed to save map to %1", "Не удалось созранить карту в %1") +S("Failed to load map from %1", "Не удалось загрузить карту из %1") +S("save whom", "кого сохранить") +S("other", "другое") // other keys in the main menu + +// VERSION 7.4 + +// missing texts, refactored things, and rule changes +//==================================================== + +S("%The1 activates her Flash spell!", "%1 активировал%E1 заклинание вспышки!") + +N("Fire", GEN_O, "Огонь", "Огни", "Огонь", "Огнём") +S("This cell is on fire. Most beings and items cannot survive.", + "Эта клетка в огне. Большинство существ и предметов не могут выжить.") + +N("Eternal Fire", GEN_O, "Вечный огонь", "Вечные огни", "Вечный огонь", "Вечным огнём") +S("This fire never burns out.", "Этот огонь никогда не гаснет.") + +S("Some rubble.", "Щебень.") + +S("The Orb loses its power as it leaves the Land of Power!", + "Сфера потеряла свою силу, когда покинула Землю силы!") + +S("%The1 fills the hole!", "%1 упал%E1 в дыру!") + +N("Tentacle+Ghost", GEN_N, "Щупальце+Дух", "Щупальца+Духи", "Щупальце+Духа", "Щупальцем+Духом") + +// Land Overview +//=============== + +S("world overview", "обзор мира") +S("or 'o' to see the world overview", "или 'o', чтобы посмотреть обзор") + +S("forbidden to find in %the1", "запрещена %abl1") +S("too dangerous to use in %the1", "слишком опасна %abl1") +S("useless in %the1", "бесполезна %abl1") +S("only native Orbs allowed in %the1", "только родные сферы доступны %abl1") +S("this Orb is never unlocked globally (only hubs)", "эта сфера открывается только ы Центрах") +S("collect 25 %2 to unlock it in %the1", "collect 25x %2, чтобы открыть её %abl1") +S("collect 3 %2 to unlock it in %the1","collect 3x %2, чтобы открыть её %abl1") +S("native in %the1 (collect 10 %2)", "родная %abl1 (10x %2)") +S("native in %the1 (collect 1 %2)", "родная %abl1 (1x %2)") +S("secondary in %the1 (collect 10 %3, or 25 %2)", "дополнительная %abl1 (10x %3, или 25x %2)") +S("the native Orb of %the1", "родная сфера %abl1") +S("this Orb appears on floors and is used by witches", "эта сфера появляется на земле и используется ведьмами") +S("a prized Orb, it appears only in cabinets", "ценная сфера, только в кабинетах") +S("this Orb never appears in %the1", "эта сфера никогда не появляется %abl1") +S("Hub Land: orbs appear here if unlocked in their native land", "Центр: сфера появвляется здесь, когда она разблокировна в своей родной земле") +S("kill a monster, or collect 25 %2", "убей монстра, или собери 25x %2") + +S("Always available.\n", "Земля всегда доступна.\n") +S("Treasure required: %1 $$$.\n", "Сокровищ нужно: %1 $$$.\n") +S("Accessible only from %the1.\n", "Доступно только из %a1.\n") +S("Accessible only from %the1 (until finished).\n", "Доступно только из %a1 (пока не окончена).\n") + +S("Accessible only from %the1 or %the2.\n", "Доступно только из %a1 и %a2.\n") + +S("Kills required: %1.\n", "УБийств нужно: %1 $$$.\n") +S("Finished lands required: %1 (collect 10 treasure)\n", + "Земель окончено: %1 (собрано 10 сокровищ)\n") + +S("Treasure required: %1 x %2.\n", "Сокровищ собрано: %1 x %2.\n") + +S("Alternatively: kill a %1.\n", "Альтернатива: убить %a1.\n") + +S("Kills required: any Elemental (Living Fjord/Dead Caves).\n", + "Требуется убить любого элементаля (Живой фьорд/Мёртвая пещера).") + +S("Variants of %the1 are always available in the Random Pattern Mode.", + "Варианты земли %1 всегда доступны в режиме случайного узора.") + +S("Variants of %the1 are available in the Random Pattern Mode after " + "getting a highscore of at least 10 %2.", + "Варианты земли %1 доступны в редиме случайного узора при рекорде не менее 10x " + "%2.") + +S(" kills: %1", " убийств: %1") +S(" $$$: %1", " $$$: %1") +S(" Hyperstone: %1/%2", " Гиперкамней: %1/%2") +S(" Hell: %1/9", " Ад: %1/9") + +// improved editor + +S("vector graphics editor -- press F1 for help", "графический редактор -- нажмите F1, чтобы получить помощь") +S("pics to save/load:", "картинки для загрузки/сохранения:") +S("level to save/load:", "карты для загрузки/сохранения:") + +S("F4 = extension", "F4 = расширение") +S("Enter = back", "Enter = назад") +S("SPACE = map/graphics", "SPACE = карта/графика") + +S("Emerald Pattern", "Изумрудный узор") +S("Palace Pattern", "Дворцовый узор") +S("Zebra Pattern", "узор Зебра") +S("rotational symmetry", "вращательная симметрия") +S("symmetry 0-1", "симметрия 0-1") +S("symmetry 0-2", "симметрия 0-2") +S("symmetry 0-3", "симметрия 0-3") + +S("display pattern codes (full)", "показать коды узоров (полные)") +S("display pattern codes (simplified)", "показать коды узоров (упрощённые)") +S("display only hexagons", "показать только шестиугольники") +S("display only heptagons", "показать только семиугольники") +S("predesigned patterns", "спроектированные узоры") + +S("Gameboard", "Игровая доска") +S("random colors", "случайные цвета") +S("emerald pattern", "изумрудный узор") +S("four elements", "четыре элемента") +S("eight domains", "восемь областей") +S("zebra pattern", "ущор зебры") +S("three stripes", "три полосы") +S("random black-and-white", "случайный чёрно-белый") +S("p = paint", "p = раскраска") +S("r = regular", "r = узор") + +S( + "In this mode you can draw your own player characters, " + "floors, monsters, and items. Press 'e' while hovering over " + "an object to edit it. Start drawing shapes with 'n', and " + "add extra vertices with 'a'. Press 0-9 to draw symmetric " + "pictures easily. More complex pictures can " + "be created by using several layers ('l'). See the edges of " + "the screen for more keys.", + + "В этом режиме можно нарисовать своего персонажа, пол, монстров, " + "предметы. Нажмите 'e', держа мышь над объектом, " + "чтобы его изменить. Добавляйте формы с 'n', вершины с 'a'. " + "Нажмите 0-9 чтобы сделать симметричный узор. Более " + "сложные фигуры могут состоять из нескольких слоёв ('l'). " + "Остальные клавиши смотри в углах экрана.") + +S( + "Press 'r' to choose a regular pattern. When a pattern is on, " + "editing a cell automatically edits all cells which are " + "equivalent according to this pattern. You can choose from " + "several patterns, and choose which symmetries matter " + "for equivalence. Also, you can press Space to switch between " + "the map and graphics editor quickly -- note that editing floors " + "with the graphics editor also adheres to the pattern.", + + "Нажмите 'r', чтобы выбрать регулярный узор. Когда узор выбран, " + "изменение клетки автоматически изменяет все эквивалентные, " + "ей в этом узоре. Вы можете выбрать один из нескольких узоров " + "и определить, какие симметрии важны для эквивалентности. " + "Нажмите пробел, чтобы переключиться между картой и графическим " + "редактором -- изменение пола влияет на узор.") + +S("monster" ,"монстр") +S("item", "предмет") +S("floor", "пол") +S("hexagonal", "шестиугольник") +S("heptagonal", "семиугольник") +S("floor/pattern", "пол/узор") + +S("l = layers: %1", "l = слой: %1") +S("1-9 = rotations: %1", "1-9 = поворот: %1") +S("0 = symmetry", "0 = симметрия") +S("0 = asymmetry", "0 = асимметрия") +S("%1 vertices", "вершины: %1") +S("a = add v", "a = добавить v") +S("m = move v", "m = передвинуть v") +S("d = delete v", "d = удалить v") +S("c = readd v", "c = обновить v") +S("b = reorder", "b = порядок") +S("t = shift", "t = сдвиг") +S("y = spin", "y = поворот") + +S("'n' to start", "n = начать") +S("z = zoom in", "z = приблизить") +S("o = zoom out", "o = отдалить") +S("g = grid", "g = сетка") +S("e = edit this", "e = изменить") + +S("x: %1", "x: %1") +S("y: %1", "y: %1") +S("z: %1", "z: %1") +S("r: %1", "r: %1") +S("ϕ: %1°", "ϕ: %1°") + +S("A fake Land with colored floors.", + "Фиктивная земля с разноцветным полом.") + +S("random pattern mode", "режим случайных узоров") + +// Ivory Tower +//============= + +N("Ivory Tower", GEN_F, "Башня из слоновой кости", "Башни из слоновой кости", "Башню из слоновой кости", "в Башне из слоновой кости") + +S( + "Powerful wizards claimed this part of the world, to perform their magical " + "experiments in peace and solitude. They have changed the direction of gravity, " + "to make it even harder for intruders to reach them.\n\n" + "Gravity works as follows: cells are unstable if they are empty, and there is " + "no cell immediately below them which contains a wall. It is impossible to move " + "from one unstable cell to another, except if moving down.", + + "Мощные колдуны создавали эту землю, чтобы проводить магические " + "эксперименты в покое и уединении. Они изменили направление силы тяжести, " + "чтобы сделать попадание сюда труднее.\n\n" + "Гравитация работает так: клетка нестабильна, если она пуста, и " + "поле под ним не содердит стены. Нельзя перейти с одного нестабильного поля " + "на другое, иначе как вниз." + ) + +N("Servant", GEN_M, "Слуга", "Слуги", "Слугу", "Слугой") +S("A simple servant of the master of the Ivory Tower.", + "Обычный слуга Хозяина башни из слоновой кости.") + +N("Gargoyle", GEN_F, "Горгулья", "Горгульи", "Горгулью", "Горгульей") +N("stone gargoyle", GEN_F, "каменная горгулья", "каменные горгульи", "каменную горгулью", "каменной горгульей") +N("stone gargoyle floor", GEN_O, "пол с горгульей", "полы с горгульями", "пол с горгульей", "полом с горгульей") +N("stone gargoyle bridge", GEN_O, "мост с горгульей", "мосты с горгульями", "мост с горгульей", "мостом с горгульями") + +S( + "A being made of stone, who likes high buildings. It becomes normal stone when " + "killed, but only if next to something stable -- otherwise it falls.", + "Существо из камня, выглядящее как высокое здание. Становится камнем, когда " + "умирает, если рядом есть что-то стабильное -- " + "иначе падает.") + +N("Ivory Figurine", GEN_F, "Фигурка", "Фигурки", "Фигурку", "Фигуркой") + +S("A beautiful figurine, made of ivory. Figurines close to the base of the Tower " + "tend do disappear after you have collected many of them.", + "Чудесная фигурка из слоновой кости. Фигурки рядом с основанием " + "башни пропадают, когда Вы соберёте много их.") + +N("Platform", GEN_F, "Платформа", "Платформы", "Платформу", "Платформой") +S("You can stand here.", "Можно встать сюда.") + +N("ladder", GEN_F, "лестница", "лестницы", "лестницу", "лестницей") +S("You can use this ladder to climb the Tower.", + "Используйти лестницу, чтобы забраться на Башню.") + +Orb("Matter", "Вещества") + +S("This Orb allows to temporarily create impassable matter, either to block paths or " + "to build bridges across chasms and waters.", + "Эта сфера позволяет временно создавать непроходимое вещество, чтобы блокировать " + "пути или строить мосты через пропасть или воду.") + +N("temporary wall", GEN_F, "временная стена", "временные стены", "временную стену", "временной стеной") +N("temporary floor", GEN_O, "временный пол", "временные полы", "временный пол", "временным полом") +N("temporary bridge", GEN_O, "временный мост", "временные мосты", "временный мост", "временным мостом") + +S("This structure will disappear after some time.", "Эта конструкция пропадёт через некоторое время.") + +S("Nothing to stand on here!", "Не на чем стоять!") +S("Gravity does not allow this!", "Гравитация не позволяет!") + +// Elemental Planes +//================== + +N("Elemental Planes", GEN_F, "Плоскость Стихий", "Плоскости Стихий", "Плоскость Стихий", "в Плоскости Стихий") +N("Plane of Fire", GEN_F, "Плоскость Огня", "Плоскости Огня", "Плоскость Огня", "в Плоскости Огня") +N("Plane of Earth", GEN_F, "Плоскость Земли", "Плоскости Земли", "Плоскость Земли", "в Плоскости Земли") +N("Plane of Air", GEN_F, "Плоскость Воздуха", "Плоскости Воздуха", "Плоскость Воздуха", "в Плоскости Воздуха") +N("Plane of Water", GEN_F, "Плоскость Воды", "Плоскости Воды", "Плоскость Воды", "в Плоскости Воды") + +S("The Elemental Planes are divided into four subzones: Planes of Fire, Water, Air, and Earth. " + "You need to collect a Shard from each Plane to construct an Elemental Gem. " + "It is dangerous to collect too many Shards of the same type without constructing a Gem.", + + "Есть четыре Плоскости Стихий: Плоскость Огня, Воды, Воздуха и Земли. " + "Вам нужно собрать по Осколку из каждой, чтобы собрать камень стихий. " + "Собирать много осколков, не собирая Камень, довольно опасно." + ) + +N("Fire Elemental", GEN_M, "Огненный Элементаль", "Огненные Элементали", "Огненного Элементаля", "Огненным Элементалем") + +S("This monster leaves a trail of fire behind.", + "Этот Элементаль оставляет за собой след Огня.") + +N("Air Elemental", GEN_M, "Воздушный Элементаль", "Воздушные Элементали", "Воздушного Элементаля", "Воздушным Элементалем") + +S("An Air Elemental looks like a live tornado. Once you are three (or less) cells from it, " + "it is impossible to move closer, due to strong winds. You can stand and wait, though. " + "This also affects most monsters.", + + "Воздушные элементаль похож на живое торнадо. Если Вы находитесь от него на расстоянии 3 или менее " + "Вы не можете подойти ближе из-за сильного ветра. Но можно стоять и ждать. Это действует на всех монстров.") + +N("Fire Shard", GEN_O, "Осколок Огня", "Осколки Огня", "Осколок Огня", "Осколком Огня") +N("Air Shard", GEN_O, "Осколок Воздуха", "Осколки Воздуха", "Осколок Воздуха", "Осколком Воздуха") +N("Water Shard", GEN_O, "Осколок Воды", "Осколки Воды", "Осколок Воды", "Осколком Воды") +N("Earth Shard", GEN_O, "Осколок Земли", "Осколки Земли", "Осколок Земли", "Осколком Земли") +N("Elemental Gem", GEN_O, "Камень стихий", "Камни стихий", "Камень стихий", "Камнем стихий") + +Orb("Summoning", "Призыва") + +S( + "This orb allows you to summon monsters. Usually, they are either Elementals or " + "native creatures. While the monsters do not like being summoned, and will " + "attack you once they recover from summoning sickness, such summoning " + "often has its uses.", + "Эта сфера позволяет призывать монстров. Обычно это Элементали или родные " + "для земли существа. Существа не нравится быть вызванным, и как только " + "оно оправится от вызова, будет Вас атаковать." + ) + +N("limestone wall", GEN_F, "известняковая стена", "известняковые стены", "известняковую стену", "известняковой стеной") + +S("Simply a wall. Mostly.", "Обычная стена. В основном.") + +// Zebra +//======= + +N("Zebra", GEN_F, "Зебра", "Зебры", "Зебру", "в Зебре") +S("Everything in this Land has black and white stripes.", + "Всё в этой Земли имеет белые и чёрные полосы.") + +N("Striped Dog", GEN_M, "Полосатый пёс", "Полосатые псы", "Полосатого пса", "Полосатым псом") +S("A predator native to the Zebra.", "Типичный хищник этой земли.") + +N("Onyx", GEN_O, "Оникс", "Ониксы", "Оникс", "Ониксом") +S("A black gem with white stripes. It is beautiful.", "Драгоценный чёрный камень с белыми полосками.") + +// Crossroads III +//================ + +N("Crossroads III", GEN_O, "Перекрёсток III", "Перекрёстки III", "Перекрёсток III", "на Перекрёстке III") + +S("An alternate layout of the Crossroads. Great Walls cross here at right angles.", + "Альтернативный вариант Перекрёстка. Великие стены пересекаются под прямым углом.") + +// Steam achievements: + +/* + "NEW_ACHIEVEMENT_5_12_NAME" "Открыть Башню слоновой кости" + "NEW_ACHIEVEMENT_5_12_DESC" "Найдите и соберите Фигурку из слоновой кости." + "NEW_ACHIEVEMENT_5_13_NAME" "Слуга" + "NEW_ACHIEVEMENT_5_13_DESC" "Соберите 10 Фигурок." + "NEW_ACHIEVEMENT_5_14_NAME" "Горгулья" + "NEW_ACHIEVEMENT_5_14_DESC" "Соберите 25 Фигурок." + "NEW_ACHIEVEMENT_5_15_NAME" "Мастер Башни" + "NEW_ACHIEVEMENT_5_15_DESC" "Соберите 50 Фигурок." + "NEW_ACHIEVEMENT_5_16_NAME" "Открыть Зебру" + "NEW_ACHIEVEMENT_5_16_DESC" "Найдите и соберите Оникс." + "NEW_ACHIEVEMENT_5_17_NAME" "Полосатый пёс" + "NEW_ACHIEVEMENT_5_17_DESC" "Соберите 10 Ониксов." + "NEW_ACHIEVEMENT_5_18_NAME" "Пятнистый пёс" + "NEW_ACHIEVEMENT_5_18_DESC" "Соберите 25 Ониксов." + "NEW_ACHIEVEMENT_5_19_NAME" "Клетчатый пёс" + "NEW_ACHIEVEMENT_5_19_DESC" "Соберите 50 Ониксов." + "NEW_ACHIEVEMENT_5_20_NAME" "Элементалист" + "NEW_ACHIEVEMENT_5_20_DESC" "Создайте Камень стихий." + "NEW_ACHIEVEMENT_5_21_NAME" "Младший элементаль" + "NEW_ACHIEVEMENT_5_21_DESC" "Создайте 10 Камней стихий." + "NEW_ACHIEVEMENT_5_22_NAME" "Старший элементаль" + "NEW_ACHIEVEMENT_5_22_DESC" "Создайте 25 Камней стихий." + "NEW_ACHIEVEMENT_5_23_NAME" "Мастер Стихий" + "NEW_ACHIEVEMENT_5_23_DESC" "Создайте 50 Камней стихий." +*/ + +S("Cannot create temporary matter on a monster!", "Нельзя создать временную материю на монстре!") +S("Cannot create temporary matter on an item!", "Нельзя создать временную материю на предмете!") +S("Cannot create temporary matter here!", "Нельзя создать временную материю здесь!") +S("Cannot summon on a monster!", "Нельзя призвать монстра на занятую клетку!") +S("No summoning possible here!", "Призыв невозможен!") +S("You summon %the1!", "Вы призвали %a1!") + +S("F4 = file", "F4 = файл") #undef Orb + +// "Skeletons attacked outside of their native land, Palace, are stunned for a longer time.", + +S("TRANSLATIONWARNING", "") +// S("TRANSLATIONWARNING", "Warning: new features from 7.4 are not yet translated to Russian") diff --git a/language-tr.cpp b/language-tr.cpp index 105802db..624eca22 100644 --- a/language-tr.cpp +++ b/language-tr.cpp @@ -181,7 +181,8 @@ S("You wonder where all these monsters go, after their death...", "Bütün bu ca S("You feel that the souls of slain enemies pull you to the Graveyard...", "Katlettiğin düşmanların ruhlarının seni mezarlığa çektiğini hissediyorsun...") S("Wrong color!", "Yanlış renk!") //this one is a bit problematic -S("You cannot move through %the1!", "%abl1n geçemezsin!") +S("You cannot move through %the1!", "%1 hücresinden geçemezsin!") +// S("You cannot move through %the1!", "%abl1n geçemezsin!") S("%The1 would kill you there!", "%1 orada seni hemencecik öldürür!") S("Wow! %1! This trip should be worth it!", "Vay canına! %1! Bu seyahati yaptığına değecek!") S("For now, collect as much treasure as possible...", "Şimdilik mümkün olduğunca fazla hazine topla...") @@ -1101,7 +1102,7 @@ S( "The Land of Power is filled with everburning fire, magical Orbs, and guarde "Witches are allowed to use all the powers of the " "basic orbs against intruders. These powers never expire, but a Witch " "can use only one power at a time (not counting Orbs of Life).\n\n" - "Witches and Golems don't pursue you into other Lands. Also, most Orb powers" + "Witches and Golems don't pursue you into other Lands. Also, most Orb powers " "are drained when you leave the Land of Power.", "Güç Diyarı sönmeyen ateşle, büyülü Kürelerle dolu ve cadılar ve golemler ile korunuyor. Her yerde temel Küreler var ve daha değerliler de kristal kabinlerde korunuyor. \n\n" "Cadılar bu kürelerin gücünü olası işgalcilere karşı kullanabilirler. Bu güçlerin süresi bitmez ama Yaşam Küresi hariç cadılar aynı anda sadece birini kullanabilir. \n\n" @@ -1292,10 +1293,6 @@ S("You overhear miners talking about a castle...", S("A castle in the Crossroads...", "Arayollarda bir Kale...") -// S("TRANSLATIONWARNING", "Uyarı: Türkçe çeviri henüz Sürüm 6.2' daki yeni özellikleri kapsamıyor.") - -S("TRANSLATIONWARNING", "") - S("You have to escape first!", "Önce kaçman gerekiyor!"); S("There is not enough space!", "Yeterince yer yok!"); @@ -1335,8 +1332,6 @@ S("You create an Illusion!", "Bir İlüzyon ürettin!") S("You take the Illusion away.", "İllüzyonu yok ettin.") -#undef Orb - S("Cannot teleport on a monster!", "Bir canavarın üzerine ışınlanamazsın!") S("Cannot teleport on an item!", "Bir eşyanın üzerine ışınlanamazsın!") S("Cannot teleport here!", "Buraya ışınlanamazsın!") @@ -1364,3 +1359,1288 @@ S("also hold Alt during the game to toggle high contrast", "ayrıca oyun sırasında Alt'a basılı tutarak yüksek kontrastı açıp kapatabilirsin.") +// Crossroads II + +N("Crossroads II", GEN_N, "Arayollar 2", "Arayollar 2'ler", "Arayollar 2'yi", "Arayollar 2'de") + +S( + "An alternate layout of the Crossroads. It is more dense and more regular, " + "although you won't find the castle of Camelot here.", + + "Arayolların alternatif bir versiyonu. Daha yoğun ve daha düzenli, ama Kamelot'un kalesini burada bulamazsın.") + +// Caribbean + +// 'Karaiby' is plural in Polish, should probably fix the grammar for this + +N("Caribbean", GEN_M, "Karayipler", "Karayip", "Karayipleri", "Karayiplerde") + +N("Pirate", GEN_M, "Korsan", "Korsanlar", "Korsanı", "Korsanla") +N("Shark", GEN_M, "Köpekbalığı", "Köpekbalıkları", "Köpekbalığını", "Köpekbalığıyla") +N("Parrot", GEN_F, "Papağan", "Papağanlar", "Papağanı", "Papağanla") +N("Pirate Treasure", GEN_M, "Korsan Hazinesi", "Korsan Hazineleri", "Korsan Hazinesini", "Korsan Hazinesiyle") +N("Compass", GEN_M, "Pusula", "Pusulalar", "Pusulayı", "Pusulayla") + +N("sea", GEN_F, "deniz", "denizler", "denizi", "denizle") +N("boat", GEN_F, "kayık", "kayıklar", "kayığı", "kayıkla") +N("island", GEN_F, "ada", "adalar", "adayı", "adayla") +N("tree", GEN_N, "ağaç", "ağaçlar", "ağacı", "ağaçla") + +Orb("Time", "Zaman") + +S("This dangerous sea contains nasty sharks and pirates. ", + "Bu tehlikeli deniz vahşi köpekbalıkları ve korsanlar barındırıyor.") + +S("The islands of Caribbean are infinite and circular, and " + "the pirates probably have hidden their treasures somewhere far from the coast.", + "Karayip Adaları sonsuz ve dairesel. Korsanlar hazinelerini büyük ihtimalle kıyılardan uzak yerlere saklıyordur.") + +S( + "Hyperbolic pirates do not need huge ships, since so many lands to conquest " + "are so close. These small boats are enough for them.\n\n" + "Boats allow you to go through water. If you are in a boat, you can move into " + "a water cell (and the boat will come with you).", + + "Hiperbolik korsanlar yakınlarda fethedilecek bir sürü toprak olduğundan devasa gemilere ihtiyaç duymuyor. " + "Bu küçük kayıklar onlar için yeterli.\n\n" + "Kayıklar suda ilerleyebilmeni sağlıyor. Eğer bir kayık içindeysen, bir su hücresine ilerleyebilirsin. (Ve kayık da seninle birlikte gelir). ") + +S( + "The forests of Caribbean are too dense to be traversed by humans, " + "and they are hard to burn. Many colorful parrots can be found there.", + "Karayip Ormanları insanlar tarafından gezilmek için fazla yoğun, ve yanmaya da dirençli. " + "Buralarda bir sürü, renkli papağana rastlayabilirsin.") + +S("Ye wonder where did th' Pirates find all these riches...", + "Korsanların bu kadar serveti nereden bulduğunu merak ediyorsun...") + +S( + "The hyperbolic pirates have no use for treasure maps. However, they have found " + "out that a compass points to the center of the island. So they just go as " + "far towards the center as they can, and hide their treasure there.", + + "Hazine haritalarının hiperbolik korsanlar için bir değeri yok. " + "Ancak, adanın ortasını gösteren bir pusula keşfettiler. " + "Böylece, ortaya doğru olabildiğince ilerler ve hazinelerini orada saklarlar.") + +S("Just a nasty shark.", "Sadece vahşi bir köpekbalığı.") + +S("Parrots feel safe in the forests of Caribbean, so they " + "never leave them. But they will help the Pirates by attacking the intruders.", + + "Papağanlar Karayip Ormanlarında güvende hissederler, bu yüzden buraları hiç terketmezler. İçeriye girenlere saldırarak korsanlara da yardım etmiş olurlar. ") + +S("Just a typical hyperbolic pirate.", "Sadece bildiğiniz bir hiperbolik korsan.") + +S( + "Normally, the power of most Orbs slowly fades away, even when " + "you are not actively using them. This Orb prevents this.\n\n" + + "When you have the Orb of Time, Orbs which are not active won't lose their power. " + "Orbs are considered active if they have a continuous power which has actually " + "affected something in the last turn.\n\n" + + "Orbs of Shielding remain active after being activated (even if you are no longer " + "attacked), and Orbs of Time have a bigger cap inside their native Caribbean than " + "outside.", + + "Normalde Kürelerin güçleri ,onları aktif olarak kullanmadığında bile, yavaşça azalır. Bu Küre bunu engeller.\n\n" + + "Zaman Küresine sahip olduğunda aktif olmayan küreler güçlerini kaybetmez. Sürekli gücü olan küreler eğer son turda bir şey etkiledilerse aktif sayılır.\n\n" + + "Kalkan Küresi aktifleştirdikten sonra da (saldıraya uğramasan bile) aktif kalır. " + "Ayrıca Zaman Küresinin sınırı onların bulunduğu Karayiplerde daha fazladır.") + +// Achievements: + +// Parrot : Find and collect Pirate Treasure. +// Caribbean Shark : Collect 10 Pirate Treasures. +// Pirate : Collect 25 Pirate Treasures. +// Master of Caribbean : Collect 50 Pirate Treasures. + +// Papağan : Bir Korsan Hazinesi bul ve topla. +// Karayip Köpekbalığı : 10 Korsan Hazinesi topla. +// Korsan : 25 Korsan Hazinesi topla. +// Karayip Korsanı : 50 Korsan Hazinesi topla. + +// Red Rock Valley + +N("Red Rock Valley", GEN_F, "Kızılkaya Vadisi", "Kızılkaya Vadileri", "Kızılkaya Vadisini", "Kızılkaya Vadisinde") + +N("Rock Snake", GEN_M, "Kaya Yılanı", "Kaya Yılanları", "Kaya Yılanını", "Kaya Yılanıyla") +N("Rock Snake Tail", GEN_O, "Kaya Yılanı Kuyruğu", "Kaya Yılanı Kuyrukları", "Kaya Yılan Kuyruğunu", "Kaya Yılan Kuyruğuyla") +N("Red Troll", GEN_M, "Kızıl Trol", "Kızıl Troller", "Kızıl Trolü", "Kızıl Trolle") +N("Red Gem", GEN_M, "Kızıl Mücevher", "Kızıl Mücevherler", "Kızıl Mücevheri", "Kızıl Mücevherle") + +N("rock I", GEN_F, "kaya I", "kayalar I", "kayayı I", "kayayla I") +N("rock II", GEN_F, "kaya II", "kayalar II", "kayayı II", "kayayla II") +N("rock III", GEN_F, "kaya III", "kayalar III", "kayayı III", "kayayla III") + +Orb("Space", "Boşluk") + +S("Not enough power for telekinesis!", "Telekinezi için yeterince güç yok!") + +S("This land contains high rock formations. Most of the valley is at level 0, " + "while items are found at level 3. It is impossible to gain two or more levels, " + "or to lose three levels, in a single move, (attacks are possible at any " + "difference, though). Kill Red Trolls and Rock Snakes to make a cell higher.", + + "Bu diyar kaya oluşumları barındırır. Vadinin çoğu yükseklik 0'dadır, eşyalar ise yükseklik 3'te bulunabilir. " + "Tek hamlede iki veya daha fazla yükseklik kazanamaz yahut üç veya daha fazla yükseklik kazanamazsın. (ama yükseklikler arası saldırılar mümkün). Kızıl Trolleri ve Kaya Yılanlarını öldürerek bir hücreyi yükseltebilirsin. ") + +S("A kind of Troll native to the Red Rock Valley.", + "Kızılkaya Vadisinde yaşayan bir trol.") + +S( + "Rock snakes are similar to Sandworms, but they move each turn. However, they " + "only move on the hexagonal cells. They are also somewhat longer than the Sandworms.", + + "Kaya yılanları her tur hareket etmesi hariç Kumkurtlarına benzer. Ayrıca, sadece altıgen hücrelerde hareket ederler. Kumkurtlarından bir nebze daha genişlerdir. ") + +S("A gem from the Red Rock Valley.", "Kızılkaya Vadisinden bir kızıl mücevher.") + +S( + "This Orb is able to bring faraway items to your location, even if there are " + "monsters or barriers on the way. The cost of " + "bringing an item (in charges) equals the square of its distance to you. Contrary " + "to some other Orbs, usage is not allowed if you have not enough power left.", + + "Bu küre uzaktaki eşyaları , arada canavar yahut engeller olup olmadığı farketmeksizin, senin olduğun hücreye getirir. Bu işlem eşyanın uzaklığı kadar güç tüketir. Bazı Kürelerin aksine, güç yoksa bu küreyi kullanamazsın.") + +// Climber : Find and collect a Red Gem. +// Red Troll : Collect 10 Red Gems. +// Rock Snake : Collect 25 Red Gems. +// Master of Red Rock : Collect 50 Red Gems. + +// Tırmanan : Bir Kırmızı Mücevher bul ve topla. +// Kızıl Trol : 10 Kırmızı Mücevher topla. +// Kaya Yılanı : 25 Kırmızı Mücevher topla. +// Kızılkaya Efendisi : 50 Kırmızı Mücevher topla. + +// missing sentences + +S("%The1 drowns!", "%1 boğuldu!"); +S("%The1 falls!", "%1 düştü!"); + +// these were missing from the translation for some reason + +S("Hell has these lakes everywhere... They are shaped like evil stars, and filled with burning sulphur.", + "Cehennemde her yerde bunun gibi göller var. Şeytani star şeklinde ve yanan sülfürle dolu...") + +// Hardcore Mode + +S("hardcore mode", "Aşmış mod"); + +S("One wrong move and it is game over!", "Tek bir yanlış hamle ve oyun biter!"); +S("Not so hardcore?", "O kadar da aşmış değil?"); + +// Shoot'em up Mode + +S("shoot'em up mode", "tryb strzelanki"); +S("Welcome to the Shoot'em Up mode!", "Witaj w trybie strzelanki!"); +S("F/;/Space/Enter/KP5 = fire, WASD/IJKL/Numpad = move", "F/;/Space/Enter/KP5 = strzał, WASD/IJKL/Numpad = ruch"); + +N("Rogue", GEN_M, "Seyyah", "Seyyahlar", "Seyyahı", "Seyyahla") +N("Knife", GEN_M, "Bıçak", "Bıçaklar", "Bıçağı", "Bıçakla") +N("Flail", GEN_M, "Topuz", "Topuzlar", "Topuzu", "Topuzla") +N("Fireball", GEN_F, "Ateş Topu", "Ateş Topları", "Ateş Topunu", "Ateş Topuyla") +N("Tongue", GEN_O, "Dil", "Diller", "Dili", "Dille") + +S("In the Shoot'em Up mode, you are armed with thrown Knives.", + "SHMUP modunda silahın fırlatılabilen bıçaklar.") +S("A simple, but effective, missile, used by rogues.", + "Seyyahlar tarafından kullanılan basit ama etkili bir silah.") +S("This attack is likely to hit the attacker.", + "Bu saldırı büyük ihtimalle saldırganı vuracaktır.") +S("This magical missile burns whatever it hits.", "Bu büyülü saldırı değdiği şeyi yakar.") +S("Some monsters have long tongues, which allow them to attack enemies in nearby cells.", + "Bazı canavarlar uzun dillere sahip, böylece yakındaki hücrelere saldırabiliyorlar.") + +// modes for the local highscores + +S(", m - mode: normal", ", m - normal mod") +S(", m - mode: hardcore only", ", m - aşmış mod") +S(", m - mode: shoot'em up", "m - SHMUP modu") + +// update description for Steam: + +// (SHMUP modu ve bedava versiyonda olmayan iki yeni diyar, ve daha fazlası eklenecek!) + +S("You would get hurt!", "Orada hasar alırsın!") +S("PARTIAL", "KISMÎ") + +S("Cannot drop %the1 here!", "Ölü Küreyi buraya bırakamazsın!"); + +// Euclidean scores +S(" (E:%1)", " (Ö:%1)"); + +S("You cannot attack Rock Snakes directly!", "Kaya Yılanlarına doğrudan saldıramazsın!"); + +S("\"I am lost...\"", "Kayboldum..."); + +S("You are killed by %the1!", "%1 tarafından öldürüldün!") + + +// achievements from Version 7.0 which have not yet been translated + +//AN IDEA FOR A NEW GAME MOD: a mini game where you can choose which land you are starting in, and world generates only that land. +//No achievement is possible, it is only good for training, or trying new lands. +//Every different land in that level is unlocked by visiting the mentioned land once. + +// Hardcore : Get the Orb of Yendor in the Hardcore mode. +// Knife Master : Get the Orb of Yendor in the Shoot'em Up mode. + +// achievements from Version 7.0 which have not yet been translated + +// Hardcore : Aşmış modda Yendor'un küresini ele geçir. +// Bıçakçı : SHMUP modunda Yendor'un Küresini ele geçir. +// new menu for Version 7.1 + +//correction for Great Wall. I mistakenly translated it as Wall of China, since back then I did not know the context. Below is a better translation. +N("Great Wall", GEN_M, "Büyük Duvar", "Büyük Duvarları", "Büyük Duvarı", "Büyük Duvarda") + +S("(v) menu", "(v) menü") +S("return to the game", "oyuna dön") +S("or 'v' to see the main menu", "veya ana menüyü görmek için 'v'ye bas.") + +S("HyperRogue %1", "HyperRogue %1") +S("basic configuration", "temel ayarlar") +S("advanced configuration", "gelişmiş ayarlar") +S("local highscores", "yerel yüksek skorlar") +S("help", "yardım") +S("restart game", "oyunu yeniden başlat") +S("special game modes", "özel oyun modları") +S("save the game", "oyunu kaydet") +S("quit the game", "oyundan çık") +S("review your quest", "görevine gözat") +S("review the scene", "durumu gör") +S("game over screen", "oyun bitiş ekranı") +S("continue game", "oyuna devam et") +S("play the game!", "oyna!") + +// fixed descriptions for Shmup achievements + +S("You have used less knives than ever before. Congratulations!", + "Her zamankinden daha az bıçak kullandın. Tebrikler!") + +S("You have improved both your real time and knife count. Congratulations!", + "Hem toplam zamanını hem de bıçak sayını geliştirdin. Tebrikler!") + +S("%1 knives (%2)", "bıçaklar: %1 (%2)") + +// temporary +S("No description yet." ,"Henüz bir açıklama yok.") + +// special case when no Spice is visible +S("The sandworm explodes!", "Kumkurdu patladı!") + +// Ocean + +// achievements: +// Reached Ocean: Find and collect an Amber. +// Albatross: Collect 10 Ambers. +// Amber Albatross: Collect 25 Ambers. +// Master of the Tides: Collect 50 Ambers. +// achievements: +// Okyanus'a Ulaş: Bir Kehribar topla. +// Albatros: 10 Kehribar topla. +// Kehribar Albatros: 25 Kehribar topla. +// Dalgaların Efendisi: 50 Kehribar topla. + +N("Ocean", GEN_O, "Okyanus", "Okyanuslar", "Okyanusu", "Okyanusla") + +S( + "You can collect some valuable Ambers on the coast, but beware the tides!\n\n" + "You can also take one of the boats and venture into the Ocean, " + "to find other coasts, dangerous whirlpools, and islands inhabited by Pirates.", + + "Kıyıdan çok değerli kehribarlar toplayabilirsin, ama dalgalara dikkat et!\n\n" + "Kayıklardan birini alıp , başka kıyılar, tehlikeli tayfunlar ve" + "korsanların egemenliğindeki adalar bulmak için okyanusa açılabilirsin.") + +N("Albatross", GEN_O, "Albatros", "Albatroslar", "Albatrosu", "Albatrosla") + +S( + "Those large seabirds attack you for some reason. At least they are not " + "as fast as Eagles...", + "Bu iri denizkuşları sana nedense saldırıyor. En azından kartallar kadar hızlı değiller.") + +N("stranded boat", GEN_F, "terkedilmiş bot", "terkedilmiş botlar", "terkedilmiş botu", "terkedilmiş botla") + +S( + "This boat cannot go through the sand. But if you sit inside and " + "wait for the tide, you will be able to use it to travel through the Ocean.", + + "Bu bot kumda hareket edemez. Ama içine oturur ve dalgayı beklersen bunu OKyanus'ta seyahat etmek için kullanabilirsin." + ) + +N("Ocean", GEN_O, "Okyanus", "Okyanuslar", "Okyanusu", "Okyanusla") + +N("Amber", GEN_O, "Kehribar", "Kehribarlar", "Kehribarı", "Kehribarla") + +S( + "When the tide is away, beautiful ambers can be found on the hyperbolic beaches. " + "Perhaps there used to be a forest here?", + "Dalga uzaktayken şahane kehribarlar hiperbolik kumsallarda bulunabilir. " + "Belki önceleri burada bir orman vardı?" + ) + +Orb("Air", "Hava") + +S("This Orb allows you to blow your enemies away.\n\n" + "Click a monster to blow it one cell away. It cannot be used against mimics, ghosts, sharks and other monsters restricted to a specific terrain, and multi-tile monsters.", + "Bu Küre düşmanları rüzgârla uzağa ittirmene yarar.\n\n" + "Bir canavara tıklayarak onu rüzgârla bir hücre ittirebilirsin. Bu özellik, taklitçilere, hayaletlere, köpekbalıklarına, çok hücreli canavarlara ve belli bir araziye özgü canavarlara karşı kullanılamaz." + ) + +N("Sea Border", GEN_O, "Deniz Sınırı", "Deniz Sınırları", "Deniz Sınırını", "Deniz Sınırında") + +S("Border between seas.", "Denizler arasındaki sınır.") + +// Whirlpool + +// achievements: +// Escaped Whirlpool: Collect a Pearl, and escape the Whirlpool. +// Vortex Shark: Collect 10 Pearls. +// Vortex Pirate: Collect 25 Pearls. +// Master of the Whirlpool: Collect 50 Pearls. + +// Tayfundan Kaç: Bir İnci Topla ve Tayfundan Kaç. +// Kasırga Köpekbalığı: 10 inci Topla. +// Kasırga Korsanı: 25 İnci Topla. +// Tayfunun Efendisi: 50 İnci Topla. + +N("Whirlpool", GEN_O, "Tayfun", "Tayfunlar", "Tayfunu", "Tayfunda") + +S( + "Many lost boats are spinning in this whirlpool. Some of them contain treasures " + "and Pirates.\n\n" + "Unmanned boats will go one cell clockwise in each turn. Sharks and manned boats " + "are only allowed to go with the current, that is, towards the center, or clockwise.", + + "Bu tayfunda pek çok kayıp kayık geziniyor. Bır kısmında hazineler yahut korsanlar var.\n\n" + "İnsansız kayıklar her tur saat yönünde bir hücre hareket eder. Köpekbalıkları ve içinde insan olan kayıklar sadece akıntıyla -yani merkeze doğru- ya da saat yönünde hareket edebilir." + ) + +N("Pearl", GEN_F, "İnci","İnciler","İnciyi","İncide") + +S( + "You do not know exactly why, but there are valuable pearls on many boats " + "in the whirlpool.", + "Nedeni bilinmez ama, pek tayfunun içindeki pek çok botta değerli inciler var." + ) + +Orb("Water", "Su") + +S( "This Orb allows your boat to go against the current, " + "and also to go into the land, creating water on the way.", + "Bu Küre akıntıya karşı hareket edebilmene imkân verir. Ayrıca bu küreyle karaya doğru hareket edip yolunda su çıkararak ilerleyebilirsin.") + +S("You cannot go against the current!", "Akıntıya karşı hareket edemezsin!") + +// Minefield + +// achievements: +// Reached Minefield: Collect a Bomberbird Egg. +// Minesweeper: Collect 10 Bomberbird Eggs. +// Bomberbird: Collect 25 Bomberbird Eggs. +// Master of the Minefield: Collect 50 Bomberbird Eggs. + +// achievements: +// Mayıntarlasına Ulaş: Bir Bombacıkuş Yumurtası topla. +// Mayın Tarayıcı: 10 Bombacıkuş Yumurtası topla. +// Bombacıkuş: 25 Bombacıkuş Yumurtası topla. +// Mayıntarlası Efendisi: 50 Bombacıkuş Yumurtası topla. + +N("Minefield", GEN_N, "Mayıntarlası", "Mayıntarlaları", "Mayıntarlasını", "Mayıntarlasında") +N("minefield", GEN_N, "mayıntarlası", "mayıntarlaları", "mayıntarlasını", "mayıntarlasıyla") +N("cell without mine", GEN_N, "mayınsız hücre", "mayınsız hücreler", "mayınsız hücreyi", "mayınsız hücreyle") + +S( + "This minefield has been created by the Bomberbirds to protect their valuable eggs. " + "Mines explode when they are stepped on, creating fire all around them " + "(this fire never expires in the Minefield). If you don't step on a mine, you " + "know the number of mines in cells around you. These numbers are marked with " + "color codes on the cells you have visited.", + "Bu mayıntarlası Bombacıkuşlar tarafından değerli yumurtalarını korumak için düzenlenmiş." +"Mayınlar üzerine basınca etrafında ateş çıkararak patlıyor" +"(Mayıntarlasında bu ateş zamanla sönmez). Eğer bir mayına basmazsan, etrafındaki mayın sayısını bilebilirsin." +"Bu sayılar daha önce ziyaret ettiğin hücrelerde farklı renk kodlarıyla işaretlidir." + ) + +N("Bomberbird", GEN_O, "Bombacıkuş", "Bombacıkuşlar", "Bombacıkuşunu", "Bombacıkuşuyla") + +S( + "Dark red birds who have created the minefield.\n\n" + "They create a mine on the spot where they are killed, provided " + "that the terrain is suitable. Also note that mines are triggered " + "by dead birds falling on them.", + + "Mayıntarlasını düzenleyen kızıl, siyah kuşlar.\n\n" + "Öldüklerinde öldükleri hücrede, eğer hücre tipi uygunsa bir mayın çıkarırlar. " + "Ayrıca dikkat, mayınlar, üzerine düşen ölü kuşlarla da tetiklenebilir.") + +N("Tame Bomberbird", GEN_O, "Sakin Bombacıkuş", "Sakin Bombacıkuşlar", "Sakin Bombacıkuşunu", "Sakin Bombacıkuşuyla") + +S( + "This bomberbird will follow you at some distance, and attack your enemies. " + "You can kill it to place a mine.", + + "Bu bombacıkuş seni belli bir mesafeden takip eder ve düşmanlarına saldırır. Onu öldürerek bir mayın döşeyebilirsin.") + + +N("Bomberbird Egg", GEN_N, "Bombacıkuş Yumurtası", "Bombacıkuş Yumurtaları", "Bombacıkuş Yumurtasını", "Bombacıkuş Yumurtasıyla") + +S( + "Bomberbird eggs are big and tasty, and thus valuable. " + "They can hatch when left alone for some time (but this will never happen " + "if you are watching).", + + "Bombacıkuş yumurtaları büyük ve lezzetlidir, bu sebeple değerlidir. Eğer yalnız bırakılırlarsa çatlayabilirler. (Ama bu sen izlerken olmaz.)" + ) + +Orb("Friendship", "Dostluk") + +S("This Orb summons a friendly Bomberbird.", + "Bu Küre barışçıl bir Bombacıkuş çıkarır.") + +S("Nowhere to blow %the1!", "%a1! ittirecek bir yer yok!") +S("%The1 is immune to wind!", "%1 rüzgârdan etkilenmiyor!") +S("You blow %the1 away!", "%a1! rüzgârla ittirdin!") + +S("WARNING: you are entering a minefield!", "UYARI: bir mayıntarlasına giriyorsun!") +S("No mines next to you.", "Yakınında hiç mayın yok.") +S("A mine is next to you!", "Yakınında bir mayın var!") +S("Two mines next to you!", "Yakınında iki mayın var!") +S("Three mines next to you!", "Yakınında üç mayın var!") +S("Four mines next to you!", "Yakınında dört mayın var!") +S("Five mines next to you!", "Yakınında beş mayın var!") +S("Six mines next to you!", "Yakınında altı mayın var!") +S("Seven mines next to you!", "Yakınında yedi mayın var!") + +S("Still confused? Read the FAQ on the HyperRogue website!\n\n", + "Hâlâ karışık mı geliyor? HyperRogue vebsitesinden SSS'i okuyun! \n\n") + +S("You have to run away from the water!", "Sudan kaçmak zorundasın!") + +//N("Icewolf", GEN_M, "Buzkurdu", "Buzkurtları", "Buzkurdunu", "Buzkurduyla") +N("Palace", GEN_O, "Saray", "Saraylar", "Sarayı", "Sarayda") +N("palace wall", GEN_F, "Saray Duvarı", "Saray Duvarları", "Saray Duvarını", "Saray Duvarı") + +S("Apparently a princess is kept locked somewhere, but you won't ever find her in this hyperbolic palace. ", + "Görünen o ki, bir prenses bir yerlerde saklı tutuluyor, ama bu hiperbolik sarayda onu bulman mümkün değil. ") + +S("Apparently a prince is kept locked somewhere, but you won't ever find him in this hyperbolic palace. ", + "Görünen o ki, bir şehzade bir yerlerde saklı tutuluyor, ama bu hiperbolik sarayda onu bulman mümkün değil. ") + +S("So better just to concentrate on collecting treasure. " + "Beware the traps, and the guards, who are hard to kill!", + + "Yani sadece hazineleri toplamaya odaklansan iyi olur. " + "Tuzaklara dikkat! Öldürmesi pek zor olan muhafızlara da dikkat et!" + ) + +N("trapdoor", GEN_N, "tuzak kapısı", "tuzak kapıları", "tuzak kapısını", "tuzak kapısıyla") +S("This floor will fall after someone goes there. Go quickly!", + "Bu zemin birisi oradan geçtikten sonra çöker! Çabuk uzaklaş!") + +N("closed gate", GEN_F, "kapalı kapı", "kapalı kapılar", "kapalı kapıyı", "kapalı kapıyla") +N("open gate", GEN_F, "açık kapı", "açık kapılar", "açık kapıyı", "açık kapıyla") +N("closing plate", GEN_F, "kapanan levha", "kapanan levhalar", "kapanan levhayı", "kapanan levhayla") +N("opening plate", GEN_F, "açılan levha", "açılan levhalar", "açılan levhayı", "açılan levhayla") + +S("Green pressure plates open all gates in radius 3 around them. " + "Similarly, red pressure plates close all gates in this radius.", + + "Yeşil baskı levhaları 3 uzaklıktaki bütün kapıları açar. " + "Aynı şekilde, kırmızı baskı levhaları bu komşuluktaki kapıları kapatır.") + +N("Hypersian Rug", GEN_O, "Aşkınlı Kilim", "Aşkınlı Kilimler", "Aşkınlı Kilimi", "Aşkınlı Kilimle") +S("Nice, a hyperbolic rug! It will not fit very well on your flat Euclidean floor, but who cares?", + "Harika! Bir hiperbolik kilim! Evindeki öklidyen zemine pek yakışmayacak, ama kimin umrunda!") + +Orb("the Frog", "Kurbağa") +S("This Orb lets you jump to a place which is two cell away from you, in a single turn. " + "You can jump over water, chasms and fire, but not over walls.", + "Bu Küre tek tur içinde senden iki hücre uzağa zıplamanı sağlar.") +S("Cannot jump through %the1!", "%1 hücresinden zıplayamazsın!") +S("You jump!", "Zıpladın!") + +S("\n\nNote: when pushing %the1 off a heptagonal cell, you can control the pushing direction " + "by clicking left or right half of the heptagon.", + "\n\nNot: %a1 bir yedigensel hücreden iterken, itmenin yönünü yedigenin sol ve sağ yarısına tıklayarak belirleyebilirsin." + ) + +S(" With the keyboard, you can rotate the view for a similar effect (Page Up/Down).", + " Klavyeyle görüntüyü döndürerek benzer bir etki yakalayabilirsin. (Page Up/Down).") + +N("Palace Guard", GEN_M, "Saray Muhafızı", "Saray Muhafızları", "Saray Muhafızını", "Saray Muhafızıyla") + +S("You have to hit Palace Guards several times to kill them. After each hit, they " + "are pushed away and stunned for some time.", + "Saray Muhafızlarının ölmesi için onlara bir kaç kere vurmalısın. Her vuruştan sonra geri itilirler ve birkaç turluk sersemlerler.") + +N("Fat Guard", GEN_M, "Şişman Muhafız", "Şişman Muhafızlar", "Şişman Muhafızı", "Şişman Muhafızla") + +S("Fat guards are too heavy to be pushed away by your hits.", + "Şişman Muhafızlar vuruşlarınla geriye itilmek için fazla ağır.") + +N("Skeleton", GEN_M, "Kościotrup", "Kościotrupy", "Kościotrupa", "Kościotrupem") +S("Skeletons work similar to Palace Guards, but they won't die no matter how many " + "times you hit them. Well, you have to be more creative...\n\n" + "Skeletons attacked outside of their native land, Palace, are stunned for a longer time.", + "İskeletler Saray Muhafızlarına benzerdir, ama kaç sefer vurulurlarsa vurulsunlar ölmezler. " + "Onları öldürmek için daha yaratıcı olmanız gerekiyor... \n\n Sarayın dışında darbe alan iskeletler daha uzun süre için sersemlerler." + ) + +N("Vizier", GEN_M, "Vezir", "Vezirler", "Veziri", "Vezirler") +S("Viziers are neither pushed away nor stunned. However, you attack them automatically when " + "escaping from them.", + "Vezirler sersemlemez ve geriye itilmez, onlardan kaçarken otomatik olarak onlara saldırmış olursun.") + +S("You stun %the1.", "%a1 sersemlettin.") +S("The gate is closing right on you! RUN!", "Kapı üzerine kapanıyor! KAÇ!") +S("%The1 is crushed!", "%1 ezildi!") +S("You hit %the1.", "%1 düşmanına vurdun.") +S("Hit him by walking away from him.", "Ona ondan uzaklaşarak vur.") +S("Hmm, he has been training in the Emerald Mine. Interesting...", "Çok garip... Zümrüt Madeninde alıştırma yapıyormuş.") + +// Reached the Palace: Find and collect a Hypersian Rug. +// Palace Guard: Collect 10 Hypersian Rugs. +// Vizier: Colect 25 Hypersian Rugs. +// Prince: Colect 50 Hypersian Rugs. + +// Saraya Ulaş: Bir Aşkınlı Kilim bul ve topla. +// Saray Muhafızı: 10 Aşkınlı Kilim topla. +// Vezir: 25 Aşkınlı Kilim topla. +// Şehzade: 50 Aşkınlı Kilim topla. + +// Living Fjord + +N("Living Fjord", GEN_O, "Yaşayan Fiyort", "Yaşayan Fiyortlar", "Yaşayan Fiyortu", "Yaşayan Fiyortta") + +S("A coastal area, from where you can get both to the inland worlds and to the Ocean. " + "Each turn, each cell will become water or earth, based on the majority of cells around it. " + "Contrary to the Living Caves, this process is not affected by most items and monsters, " + "but elementals, dead Trolls, and cells outside of the Living Fjord have " + "a very powerful effect.", + "Sahil şeridinde bir bölge, buradan hem iç diyarlara hem de Okyanus'a geçebilirsin. " + "Her tur, her hücre etrafındaki hücrelerin çoğunluğuna göre su veya toprak olacak. " + "Yaşayan Mağaraların aksine, bu süreç eşyalar veya canavarlardan etkilenmez. " + "Ancak Özütler, Ölü Troller ve Yaşayan Fiyortların dışındaki hücrelerin etkisi çok güçlüdür." + ) + +N("Fjord Troll", GEN_M, "Fiyort Trolü", "Fiyort Trolleri", "Fiyort Trolünü", "Fiyort Trolüyle") +S("Fjord Trolls leave a wall when they die, causing the living fjord to rise around it. " + "Contrary to Rock Trolls, items around are not destroyed.", + "Fiyort Trolleri öldüklerinde geriye bir duvar bırakıp cesetlerinin etrafına yaşayan fiyortun yükselmesine sebep olurlar. " + "Kaya Trollerinin aksine etraflarındaki eşyalar yok olmaz." + ) + +N("Viking", GEN_M, "Viking", "Vikingler", "Vikingi", "Vikingle") +S("Mighty warriors from the Fjord, who can use boats.", + "Fiyortun kayık kullanabilen kudretli savaşçıları.") + +N("Water Elemental", GEN_M, "Su Özütü", "Su Özütleri", "Su Özütünü", "Su Özütüyle") +S("Wherever this powerful being goes, the living fjord " + "sinks below water, non-magical boats are destroyed, and fires are extinguished.\n\n" + "As a special case, you can attack the Water Elemental from the water, without drowning immediately.", + "Bu güçlü yaratığın geçtiği her yerde Yaşayan Fiyort su altına gömülür, sihirli olmayan kayıklar yok olur ve ateşler söner. \n\n " + "İstisna bir durum olarak Su Özütüne suyun içerisinden hemen boğulmadan vurursan onu öldürebilirsin. ") + +N("Garnet", GEN_O, "Nartaşı", "Nartaşları", "Nartaşını", "Nartaşıyla") + +S("Vikings believe that garnets improve their strength.", + "Vikingler nartaşlarının güçlerini artırdığını düşünür.") + +Orb("the Fish", "Balık") +S("This Orb lets you dive into the water. While diving, you are able to see and collect underwater treasures, " + "while being invisible to monsters yourself. You are afraid of jumping into the water straight from a boat, so usually you won't do it.", + "Bu Küre suya dalabilmeni sağlar. Suyun altındayken suyun altını görebilir ve sualtı hazinelerini toplayabilirsin. Bunu yaparken canavarlar seni göremez." + "Korkun sebebiyle bir kayıktan suya genelde doğrudan atlayamıyorsun.") + +S("%The1 is washed away!", "%1 suya karışıp gitti!") +S("%The1 is extinguished!", "%1 söndü!") + +// Reached the Living Fjord: Find and collect a Garnet. +// Viking: Collect 10 Garnets. +// Water Elemental: Colect 25 Garnets. +// Master of the Fjord: Colect 50 Garnets. + +// Yaşayan Fiyortlara Ulaş: Bir Nartaşı bul ve topla. +// Viking: 10 Nartaşı topla. +// Su Özütü: 25 Nartaşı topla. +// Fiyort Efendisi: 50 Nartaşı topla. + +// implemented, not appears in the game yet + +Orb("Discord", "İhtilaf") + +S("Causes most monsters to attack other monsters, not only you and your friends.", + "Çoğu canavarın sen ve dostların yanında diğer canavarlara da saldırmasına sebep olur.") + +// Shmup Configuration + +S("forward", "ileri") +S("backward", "geri") +S("turn left", "sola dön") +S("turn right", "sağa dön") +S("move up", "yukarı git") +S("move right", "sağa git") +S("move down", "aşağı git") +S("move left", "sola git") +S("throw a knife", "bıçak at") +S("face the pointer", "mausa bak") +S("throw at the pointer", "mausa doğru at") +S("drop Dead Orb", "Ölü Küreyi bırak") +S("center the map on me", "centruj mapę na mnie") +S("activate Orb power", "Küre gücünü aktif et") + +S("pan up", "yukarı kaydır") +S("pan right", "sağa kaydır") +S("pan down", "aşağı kaydır") +S("pan left", "sola kaydır") +S("rotate left", "sola döndür") +S("rotate right", "sağa döndür") +S("home", "ortaya geri dön") + +S("do nothing", "hiçbir şey yapma") +S("rotate view", "görüntüyü çevir") +S("panning X", "yatay kaydır") +S("panning Y", "dikey kaydır") +S("player 1 X", "oyuncu 1, yatay") +S("player 1 Y", "oyuncu 1, dikey") +S("player 1 go", "oyuncu 1, git") +S("player 1 spin", "oyuncu 1, dön") +S("player 2 X", "oyuncu 2, yatay") +S("player 2 Y", "oyuncu 2, dikey") +S("player 2 go", "oyuncu 2, git") +S("player 2 spin", "oyuncu 2, dön") + +S("Joystick %1, axis %2", "Joystick %1, eksen %2") +S("one player", "tek kişilik") +S("two players", "iki kişilik") +S("configure player 1", "1. oyuncuyu ayarla") +S("configure player 2", "2. oyuncuyu ayarla") +S("configure panning", "kaydırmayı ayarla") +S("configure joystick axes", "joystick eksenlerini ayarla") +S("continue playing", "oyuna devam et") +S("start playing in the shmup mode", "SEMUP modunda oyun başlat") +S("return to the turn-based mode", "tur bazlı moda dön") +S("save the configuration", "ayarları kaydet") +S("press a key to unassign", "atamayı iptal için bir tuşa bas ") +S("press a key for '%1'", "'%1' için bir tuşa bas") +S("unassign a key", "bir tuş atamasını iptal et") + +// extra pattern modes + +S("explore the Emerald Pattern", "Zümrüt Dokusunu keşfet") +// S("explore the Fifty Pattern (4 colors)", "50 Dokuyu keşfet (4 renk)") +// S("explore the Fifty Pattern (8 colors)", "50 Dokuyu keşfet (8 renk)") + +// extra flavor/Knight lines + +S("Kill a Vizier in the Palace to access Emerald Mine", "Zümrüt Madenine ulaşmak için Saray'da bir Vezir öldür.") +S("Collect 5 Emeralds to access Camelot", "Kamelot'a ulaşmak için 5 Zümrüt topla.") +S("Some lands unlock at specific treasures or kills", "Bazı diyarlara ulaşabilmek için belirli öldürmeler ve hazineler gerekebilir.") + +S("You will be fighting red rock snakes, too...", "Kızıl yılanlarla da savaşacaksın...") + +S("\"The Red Rock Valley is dangerous, but beautiful.\"", + "\"KızılKaya Vadisi tehlikeli ama manzara çok güzel.\"") +S("\"Train in the Desert first!\"", "\"Önce Çöl'de kendini yetiştir!\"") +S("\"I like collecting ambers at the beach.\"", "\"Sahilde Kehribarlar toplamayı seviyorum.\"") +S("\"Our Table seats %1 Knights!\"", "\"Masamızda %1 Şövalye oturuyor!\"") +S("\"There are %1 floor tiles inside our Table!\"", "\"Masamızın içinde %1 zemin hücresi var!\"") +S("\"By now, you should have your own formula, you know?\"", "\"Şimdiye kadar kendi formülünü bulmalıydın değil mi?\"") +S("\"Have you tried to take a boat and go into the Ocean? Try it!\"", "\"Bir kayığa binip Okyanus'a açılmayı denedin mi? Denemelisin!\"") + +//====================// +// NEW IN VERSION 7.3 // +//====================// +//CORRECTION: + +N("closing plate", GEN_F, "kapatma levhası", "kapatma levhaları", "kapatma levhasını", "kapatma levhasıyla") +N("opening plate", GEN_F, "açma levhası", "açma levhaları", "açma levhasını", "açma levhasıyla") + +// new name for 'Ivy D' + +N("Dead Ivy", GEN_M, "Ölü Sarmaşık", "Ölü Sarmaşıklar", "Ölü Sarmaşığı", "Ölü Sarmaşıkla") + +// new messages for living/nonliving monsters + +S("%The1 bites %the2!", "%1 %a2 ısırdı!") +S("%The1 attacks %the2!", "%1 %2 tarafına saldırdı!") +S("You destroy %the1 with a mental blast!", "%a1 bir zihin patlamasıyla yok ettin!") +S("The ivy kills %the1!", "Sarmaşık %a1 öldürdü!") +S("You destroy %the1.", "%a1 yok ettin.") +S("%The1 kills %the2!", "%1 %a2 öldürdü!") +S("%The1 sinks!", "%1 battı!"); + +S("Cannot jump on %the1!", "%1 hücresine atlayamazsın!") + +// renamed Fifty to Palace +S("explore the Palace Pattern (4 colors)", "Saray Dokusunu Keşfet (4 renk)") +S("explore the Palace Pattern (8 colors)", "Saray Dokusunu Keşfet (8 renk)") + +// Map Editor +//============ + +S("map editor", "harita editörü") +S("You activate your terraforming powers!", "Yerdüzenleyici güçlerini harekete geçirdin!") +S("Press F5 to clear the board.", "Tahtayı temizlemek için F5'e bas") +S("Press F5 to restart the game normally.", "Oyunu normal başlatmak için F5'e bas") +S("High quality shots not available on this platform", "Yüksek kalite resimler bu platformda mevcut değil") +S("Saved the high quality shot to %1", "HQ resim %1 konumuna kaydedildi") +S("Map saved to %1", "Harita %1 konumuna kaydedildi") +S("Map loaded from %1", "Harita %1 konumundan yüklendi") +S("copying", "kopyalıyor") +S("boundary", "sınır") +S("clear monster", "canavarı temizle") +S("use at your own risk!", "sorumluluk sende!") + +// Note: in English, these have been arranged from longest to shortest. +// This gives a somewhat nice effect on the top left corner of the screen. +// You may want to aim for the same effect when translating + +S("0-9 = radius (%1)", "0-9 = promień (%1)") +S("b = boundary", "i = sınır") +S("m = monsters", "m = canavar") +S("w = walls", "w = duvar") +S("i = items", "l = eşya") +S("l = lands", "c = diyar") +S("c = copy", "b = kopya") + +// And this is from shortest to longest (bottom left corner) +S("F1 = help", "F1 = yardım") +S("F2 = save", "F2 = kaydet") +S("F3 = load", "F3 = yükle") +S("F5 = restart", "F5 = yeniden başlat") +S("F6 = HQ shot", "F6 = HQ resim çek") +S("F7 = player on/off", "F7 = oyuncu açık/kapalı") +S("ESC = return to the game", "ESC = oyuna geri dön") + +S( + "This mode allows you to edit the map.\n\n" + "NOTE: Use at your own risk. Combinations which never " + "appear in the real game may work in an undefined way " + "(do not work, look strangely, give strange messages, or crash the game).\n\n" + "To get the most of this editor, " + "some knowledge of inner workings of HyperRogue is required. " + "Each cell has four main fields: land type, wall type, monster type, item type. " + "The same wall type (especially \"none\", \"sea\", or \"bonfire\") may look or " + "work a bit differently, based on the land it is in. Sometimes an object may " + "appear twice on the list due to subtle differences (for example, Demons could " + "move next turn or not).\n\n" + "Press w, i, l, or m to choose which aspect of cells to change, " + "then just click on the cells and they will change. Press 'c' while " + "hovering over a cell to copy that cell, this copies all information about it. " + "When copying large areas or placing multi-tile monsters, it might be important where " + "on the cell you are clicking.\n\n" + "You can also press 0-9 to apply your changes to a greater radius. " + "This also affects the copy/paste feature, allowing to copy a larger area.\n\n" + "Press F2 to save the current map (and F3 to load it). If you try this after " + "a long game of HyperRogue (without using Orbs of Safety), the filesize will " + "be very large! " + "Note however that large structures, such as " + "Great Walls, large circles and horocycles, are destroyed by this.\n\n" + "Press 'b' to mark cells as boundaries. Such cells, and cells beyond " + "them, are not copied by the copy/paste feature, nor saved by the " + "save feature.\n\n", + + "Bu mod haritayı düzenlemeni sağlar..\n\n" + "NOT: sorumluluk sende! Gerçek oyunda hiç karşına çıkmayacak kombinasyonlar " + "bilinmeyen bir şekilde çalışabilir. (çalışmayabilir, garip gözükebilir, oyunu çökertebilir.).\n\n" + "Editörü layığıyla kullanabilmek için HyperRogue'un iç dinamiklerine dair bilgi sahibi olman beklenir. " + "Her hücre dört temel alana sahip: diyar tipi, duvar tipi, canavar tipi, eşya tipi." + "Aynı duvar tipi (özellikle \"hiç\", \"deniz\", ve \"kampateşi\")" + " içinde bulunduğu diyara göre farklı gözükebilir ve farklı işlev edinebilir. " + "Bazen bir eşya özel durumundan ötürü listede iki kez gözükebilir." + "(Meselâ şeytanın bir sonraki tur hareket edip edemeyeceği durumu).\n\n" + "Hücrelerin hangi özelliğini değiştirmek istedğinizi w, i, l ve m'ye basarak seç. " + "İşaretçinin olduğu hücreyi başka yere kopyalamak için c'ye bas. Bu, hücreye dair bilgiyi de kopyalar. " + "Çok hücreli canavarları kopyalarken hücrenin neresine bastığın sonucu değiştirebilir.\n\n " + "Değişikliklerini daha büyük bir çapta uygulamak için 0-9'a basabilirsin.. " + "Bu aynı zamanda, kopyala/yapıştır özelliğinin de çapını genişletir.\n\n" + "Mevcut haritayı kaydetmek için F2'ye bas (yüklemek için de F3'e bas). Eğer bunu Güvenlik Küresi kullanmadığınız bir oyunda denersen, " + "dosya boyutu çok büyük olacaktır! Dikkat: Büyük yapılar, meselâ horosikıllar, büyük duvarlar, geniş çemberler bu özelliği kullanınca yok olurlar. \n\n" + "Hücreleri sınır olarak belirlemek için b'ye basın. Bu hücreler ve bu hücrelerin ötesindeki hücreler, kopyala/yapıştır ve kaydetme özelliğine dahil edilmezler. \n\n" + ) + +// Princess Quest +//================ + +// Saved the Princess - "Prensesi Kurtar" - "Prensesi kurtar." +// Princess Challenge - "Prenses Görevi- "Prenses Görevini tamamla." +// Martial Artist - "Dövüş Sporu" - "Silahsız bir Prensesin bir dövüşü kazanmasına yardım et." + +S( + "A mouse squeaks at you. It seems that it wants you to go somewhere. " + "That's interesting, what could you find here?\n\n" + "Note: in the part of the Palace that you are exploring during this " + "quest, the distribution of monsters, pressure plates, and items has been " + "changed somewhat, to make it a bit more suitable for less " + "experienced players. The number of monsters does not depend on the " + "number of Hypersian Rugs you have collected, and there are more " + "opening plates.\n\n" + "However, even with the normal distribution, it appears that it should be " + "always possible to reach your goal. If you want this challenge, " + "select it from the special game modes menu.", + + "Bir fare sana ciyakladı. Galiba senin bir yere gitmeni istiyor." + "Gerçekten ilginç, burada ne bulabilirsin ki?\n\n" + "W części Pałacu, którą zwiedzasz podczas tej misji, " + "Not: Sarayın bu görev için hazırlanmış kısmında, canavarların dağılımı, baskı levhaları, ve eşyalar daha az deneyimli oyuncular düşünülerek bir nebze değiştirildi." + "Canavar sayısı topladığın Aşkınlı Kilim sayısına bağlı değil ve burada daha çok açma levhası var. \n\n" + "Yine de, normal dağılımla bile, bu görev her zaman tamamlanabilir. Eğer o görevi istiyorsan, özel oyun modları menüsünden onu seçebilirsin.") + +S("\"When I visited the Palace, a mouse wanted me to go somewhere.\"", + "\"Sarayı ziyaret ettiğimde, bir fare benden bir yere gitmemi istedi.\"") + +S("\"I wonder what was there...\"", "\"Orada ne olduğunu merak ediyorum...\"") + +N("Mouse", GEN_F, "Fare", "Fareler", "Fareyi", "Fareyle") + +S("You hear a distant squeak!", "Uzaktan gelen bir ciyaklama duydun!") +S("%The1 squeaks in a confused way.", "%1 şaşkın bir şekilde ciyaklıyor.") +S("%The1 squeaks gratefully!", "%1 minnetle ciyaklıyor."); +S("%The1 squeaks hopelessly.", "%1 umutsuzca ciyaklıyor."); +S("%The1 squeaks in despair.", "%1 karamsarlıkla ciyaklıyor."); +S("%The1 squeaks sadly.", "%1 üzüntüyle ciyaklıyor."); +S("%The1 squeaks with hope!", "%1 umutla ciyaklıyor!"); +S("%The1 squeaks happily!", "%1 neşeyle ciyaklıyor!"); +S("%The1 squeaks excitedly!", "%1 heyecanla ciyaklıyor!"); + +N("giant rug", GEN_O, "devasa kilim", "devasa kilimler", "devasa kilimi", "devasa kilimle") + +S("This is the biggest Hypersian Rug you have ever seen! " + "Unfortunately, it is too large to take it as a trophy.", + "Bu, gördüğün en büyük Aşkınlı Kilim! " + "Maalesef yanında götüremeyeceğin kadar büyük.") + +N("Prince", GEN_M, "Şehzade", "Şehzadeyi", "Şehzadeler", "Şehzadeyle") +N("Princess", GEN_F, "Prenses", "Prensesi", "Prensesler", "Prensesle") + +S("%1 takes %his1 revenge on %the2!", "%1 intikamını alıyor!") +S("\"That should teach you to take me seriously!\"", + "\"Bu sana beni ciddiye alman gerektiğini öğretir!\"") + +S("%The1 kisses you, and begs you to bring %him1 away from here.", + "%1 seni öpüyor ve sana %go1 buradan uzaklaştırman için yalvarıyor.") + +S("\"I want my revenge. Stun a guard and leave him for me!\"", + "İntikam istiyorum! Bir muhafızı sersemlet ve onu bana bırak!\"") + +S("\"That felt great. Thanks!\"", "\"Çok iyi hissettim! Sağol!\"") + +S("\"Bring me out of here please!\"", "Beni buradan çıkar lütfen!\"") + +S("%The1 kisses you, and thanks you for saving %him1.", + "%1 seni öptü ve %go1 kurtardığın için sana teşekkür etti.") + +S("\"I have been trained to fight with a Hypersian scimitar, you know?\"", + "Hiç Aşkınlı Palasıyla savaşmak üzere eğitilmemiştim biliyor musun?\"") + +S("\"I would love to come to your world with you!\"", + "Senle beraber dünyana gelmeyi çok isterdim!\"") + +S("\"Straight lines stay close to each other forever, this is so romantic!\"", + "\"Doğrular birbirlerine hep yakın, bu çok romantik!\"") + +S("\"Maps... Just like the world, but smaller... how is that even possible?!\"", + "\"Haritalar... Gerçek dünya gibi, ama daha küçük... bu nasıl mümkün olabilir?!\"") + +Orb("Love", "Aşk") +S("Love takes time, but it heals all wounds, and transcends time and space.\n\n" + "The Orb of Love is worth 30$$$, if you end the game with it.\n", + + "Aşk zaman alır, ama her yarayı iyileştirir ve zaman ve mekâna galip gelir.\n\n" + "Aşk Küresi oyunu onunla bitirebilirsen 30$$$ eder.\n") + +// Princess Challenge: + +S("%1 Challenge", "%1 Görevi") +S("Save %the1 first to unlock this challenge!", "Bu görevi açmak için önce %a1 kurtar!") +S("Welcome to %the1 Challenge!", "%1 görevine hoşgeldin!") +S("The more Hypersian Rugs you collect, the harder it is.", "Ne kadar Aşkınlı Kilim toplarsan o kadar zor.") +S("Follow the Mouse and escape with %the1!", "Fareyi takip et ve %abl1 kaç!") +S("Hardness frozen at %1.", "Trudność zamrożona: %1."); +S("Congratulations! Your score is %1.", "Tebrikler! Puanın: %1.") + +S("u = undo", "u = geri al") +S("Failed to save map to %1", "Harita %1 konumuna kaydedilemedi.") +S("Failed to load map from %1", "Harita %1 konumundan yüklenemedi") +S("other", "diğer") // other keys in the main menu +S("f = flip %1", "f = çevir %1") +S("save whom", "kim kurtarılacak") + +// VERSION 7.4 + +// missing texts, refactored things, and rule changes +//==================================================== + +S("%The1 activates her Flash spell!", "%1 Işık büyüsünü aktifleştirdi!") + +N("Fire", GEN_O, "Ateş", "Ateşler", "Ateşi", "Ateşle") +S("This cell is on fire. Most beings and items cannot survive.", + "Bu hücre yanıyor. Üzerindeki çoğu eşya ve canlı ölecek.") + +N("Eternal Fire", GEN_O, "Sonsuz Ateş", "Sonsuz Ateşler", "Sonsuz Ateşi", "Sonsuz Ateşle") +S("This fire never burns out.", "Bu ateş hiç sönmüyor.") + +S("Some rubble.", "Döküntüler.") + +S("The Orb loses its power as it leaves the Land of Power!", + "Küre Güç Diyarından ayrılırken gücünü kaybediyor!") + +S("%The1 fills the hole!", "%1 deliği dolduruyor!") + +N("Tentacle+Ghost", GEN_F, "Dokungaç&Hayalet", "Dokungaç&Hayaletler", "Dokungaç&Hayaleti", "Dokungaç&Hayaletle") + +// Land Overview +//=============== + +S("world overview", "dünya önizlemesi") +S("or 'o' to see the world overview", "veya dünya önizlemesini görmek için 'o'ya basın.") + +S("forbidden to find in %the1", "%abl1 bulmak yasak.") +S("too dangerous to use in %the1", "zbyt niebezpieczna %abl1") +S("useless in %the1", "%abl1 işe yaramaz") +S("only native Orbs allowed in %the1", "%abl1 sadece oraya özgü Küreler kullanılabilir.") +S("this Orb is never unlocked globally (only hubs)", "bu Küre hiç tüm dünya için aktif edilmedi (sadece yerelde)") +S("collect 25 %2 to unlock it in %the1", "%abl1 onu aktif etmek için 25 tane %2 topla.") +S("collect 3 %2 to unlock it in %the1", "%abl1 onu aktif etmek için 3 tane %2 topla.") +S("native in %the1 (collect 10 %2)", "%abl1 bulunuyor (10 tane %2)") +S("native in %the1 (collect 1 %2)", "%abl1 bulunuyor (1 tane %2)") +S("secondary in %the1 (collect 10 %3, or 25 %2)", "%abl1 ikincil olarak bulunuyor (10 tane %3, veya 25 tane %2)") +S("the native Orb of %the1", "%abl1 doğal olarak bulunan Küre") +S("this Orb appears on floors and is used by witches", "Bu Küre zeminlerde bulunur ve cadılarca kullanılır.") +S("a prized Orb, it appears only in cabinets", "çok kıymetli bir Küre, sadece vitrinde bulunur.") +S("this Orb never appears in %the1", "Bu Küre %abl1 hiç bulunmaz") +S("Hub Land: orbs appear here if unlocked in their native land", "Merkez: Ana diyarında aktifleştirilen küreler burada gözükür.") +S("kill a monster, or collect 25 %2", "bir canavar öldür, ya da 25 tane %2 topla.") + +S("Always available.\n", "Her zaman mevcut.\n") +S("Treasure required: %1 $$$.\n", "Hazine gerekiyor: %1 $$$.\n") +S("Accessible only from %the1.\n", "Sadece %a1 erişilebilir.\n") +S("Accessible only from %the1 (until finished).\n", "Sadece %a1 erişilebilir. %a1 (bitirilene kadar).\n") + +S("Accessible only from %the1 or %the2.\n", "Sadece %a1 veya %a2 erişilebilir.\n") + +S("Kills required: %1.\n", "Gereken leşler: %1 $$$.\n") +S("Finished lands required: %1 (collect 10 treasure)\n", + "Gereken bitirilmiş diyarlar: %1 (10 hazine toplananlar)\n") + +S("Treasure required: %1 x %2.\n", "Gereken hazine: %1 tane %2.\n") + +S("Alternatively: kill a %1.\n", "Ya da: Bir %1 öldür.\n") + +S("Kills required: any Elemental (Living Fjord/Dead Caves).\n", + "Gereken leşler: Herhangi bir Özüt (Yaşayan Fiyort/Ölü Mağaralar).") + +S("Variants of %the1 are always available in the Random Pattern Mode.", + "%1 çeşitlemeleri Rastgele Doku Modunda her zaman mevcuttur.") + +S("Variants of %the1 are available in the Random Pattern Mode after " + "getting a highscore of at least 10 %2.", + "%1 çeşitlemeleri Rastgele Doku Modunda en az on tane %2 skoru elde ederek açılır. ") + +S(" kills: %1", " leşler: %1") +S(" $$$: %1", " $$$: %1") +S(" Hyperstone: %1/%2", " Aşkıntaş: %1/%2") +S(" Hell: %1/9", " Cehennem: %1/9") + +// improved editor + +S("vector graphics editor -- press F1 for help", "vektör grafik editörü -- yardım için F1'e bas.") +S("pics to save/load:", "kaydedilecek/yüklenecek resimler") +S("level to save/load:", "kaydedilecek/yüklenecek bölüm") + +S("F4 = extension", "F4 = genişletme") +S("Enter = back", "Enter = geri") +S("SPACE = map/graphics", "SPACE = harita/grafikler") + +S("Emerald Pattern", "Zümrüt Dokusu") +S("Palace Pattern", "Saray Dokusu") +S("Zebra Pattern", "Zebra Dokusu") +S("rotational symmetry", "döngüsel simetri") +S("symmetry 0-1", "simetri 0-1") +S("symmetry 0-2", "simetri 0-2") +S("symmetry 0-3", "simetri 0-3") + +S("display pattern codes (full)", "doku kodlarını göster (tam)") +S("display pattern codes (simplified)", "doku kodlarını göster (basitleştirilmiş)") +S("display only hexagons", "sadece altıgenleri göster") +S("display only heptagons", "sadece yedigenleri göster") +S("predesigned patterns", "hazır dokular") + +S("Gameboard", "Oyun Tahtası") +S("random colors", "rastgele renkler") +S("emerald pattern", "zümrüt dokusu") +S("four elements", "dört element") +S("eight domains", "sekiz alan") +S("zebra pattern", "zebra dokusu") +S("three stripes", "üç şerit") +S("random black-and-white", "rastgle siyah-beyaz") +S("p = paint", "p = boya") +S("r = regular", "r = düzenli") + +S( + "In this mode you can draw your own player characters, " + "floors, monsters, and items. Press 'e' while hovering over " + "an object to edit it. Start drawing shapes with 'n', and " + "add extra vertices with 'a'. Press 0-9 to draw symmetric " + "pictures easily. More complex pictures can " + "be created by using several layers ('l'). See the edges of " + "the screen for more keys.", + + "Bu modda kendi karakterlerini, zeminlerini, canavarlarını ve eşyalarını çizebilirsin. İşaretçiyi bir nesneye götür ve onu düzenlemek için 'e'ye bas. " + "'n' ile şekiller çizmeye başlayabilir, 'a' ile yeni köşeler ekleyebilirsin. 0-9'a basarak simetrik resimleri daha kolay çizebilirsin. " + "Daha karmaşık resimler için birden fazla atman gerekebilir ('l'). Ekranın kıyılarına bakara daha fazla tuşu öğrenebilirsin." + ) + +S( + "Press 'r' to choose a regular pattern. When a pattern is on, " + "editing a cell automatically edits all cells which are " + "equivalent according to this pattern. You can choose from " + "several patterns, and choose which symmetries matter " + "for equivalence. Also, you can press Space to switch between " + "the map and graphics editor quickly -- note that editing floors " + "with the graphics editor also adheres to the pattern.", + + "'r'ye basarak düzenli bir doku seçebilirsin. Bir doku aktifken, bir hücreyi değiştirmek o hücreye bu dokuda eşdeğer bütün hücreleri de değiştirir." + " Birden çok doku seçebilirsin ve hangi simetrilerin eşdeğer olduğunu seçebilirsin. Ayrıca, Space'e basarak harita ve grafik editörü arasında hızlıca gidip gelebilirsin -- " + "zeminin grafik editörüyle değiştirilmesinin dokuyu da değiştireceğini unutma.") + +S("monster" ,"canavar") +S("item", "eşya") +S("floor", "zemin") +S("hexagonal", "altıgensel") +S("heptagonal", "yedigensel") +S("floor/pattern", "zemin/doku") + +S("l = layers: %1", "l = katmanlar: %1") +S("1-9 = rotations: %1", "1-9 = döndürmeler %1") +S("0 = symmetry", "0 = simetri") +S("0 = asymmetry", "0 = asimetri") +S("%1 vertices", "köşeler: %1") +S("a = add v", "a = ekle v") +S("m = move v", "m = taşı v") +S("d = delete v", "d = sil v") +S("c = readd v", "c = yeniden ekle v") +S("b = reorder", "b = yeniden sırala") +S("t = shift", "t = kaydır") +S("y = spin", "y = döndür") + +S("'n' to start", "n = başlat") +S("z = zoom in", "z = yaklaş") +S("o = zoom out", "o = uzaklaş") +S("g = grid", "g = şablon") +S("e = edit this", "e = bunu düzenle") + +S("x: %1", "x: %1") +S("y: %1", "y: %1") +S("z: %1", "z: %1") +S("r: %1", "r: %1") +S("ϕ: %1°", "ϕ: %1°") + +S("A fake Land with colored floors.", + "Renkli zeminli bir sahte diyar.") + +S("random pattern mode", "rastgele doku modu") + +// Ivory Tower +//============= + +N("Ivory Tower", GEN_F, "Fildişi Kule", "Fildişi Kuleler", "Fildişi Kuleyi", "Fildişi Kulede") + +S( + "Powerful wizards claimed this part of the world, to perform their magical " + "experiments in peace and solitude. They have changed the direction of gravity, " + "to make it even harder for intruders to reach them.\n\n" + "Gravity works as follows: cells are unstable if they are empty, and there is " + "no cell immediately below them which contains a wall. It is impossible to move " + "from one unstable cell to another, except if moving down.", + + "Güçlü büyücüler, dünyanın bu kısmını, büyüsel deneylerini sessiz sakin uygulayabilecekleri yer olarak seçtiler. Davetsiz misafirlerin, onlara ulaşabilmesini daha zor kılmak için yerçekiminin yönünü değiştirdiler.\n\n" + "Yerçekimi şu şekilde çalışır: Hücreler eğer boşlar ise dengesiz haldedirler ve hücrelerin hemen altında bulunan bir duvar yoktur. Bir dengesiz hücreden diğerine ilerlemek imkansızdır, aşağı doğru ilerlemek hariç.\n\n" + + ) + +N("Servant", GEN_M, "Hizmetkâr", "Hizmetkârlar", "Hizmetkârı", "Hizmetkârla") +S("A simple servant of the master of the Ivory Tower.", + "Fildişi Kuledeki basit bir hizmetkâr.") + +N("Gargoyle", GEN_M, "Çörten", "Çörtenler", "Çörteni", "Çörtenle") +N("stone gargoyle", GEN_M, "taş çörten", "taş çörtenler", "taş çörteni", "taş çörtenle") +N("stone gargoyle floor", GEN_F, "taş çörten zemini", "taş çörten zeminleri", "taş çörten zeminini", "taş çörten zeminiyle") +N("stone gargoyle bridge", GEN_O, "taş çörten köprüsü", "taş çörten köprüleri", "taş çörten köprüsünü", "taş çörten köprüsüyle") + +S( + "A being made of stone, who likes high buildings. It becomes normal stone when " + "killed, but only if next to something stable -- otherwise it falls.", + "Yüksek binaları seven taştan yapılmış bir yaratık. Öldürüldüğünde eğer durağan bir şeyin yanındaysa normal taş haline gelir, yoksa düşer.") + +N("Ivory Figurine", GEN_F, "Fildişi Biblo", "Fildişi Biblolar", "Fildişi Bibloyu", "Fildişi Bibloyla") + +S("A beautiful figurine, made of ivory. Figurines close to the base of the Tower " + "tend do disappear after you have collected many of them.", + "Fildişinden yapılmış güzel bir biblo. Bunlardan çok sayıda topladığında, kulenin temeline yakın biblolar yok olmaya başlar.") + +N("Platform", GEN_F, "Platform", "Platformlar", "Platformu", "Platformla") +S("You can stand here.", "Burada durabilirsin.") + +N("ladder", GEN_F, "merdiven", "merdivenler", "merdiveni", "merdivenle") +S("You can use this ladder to climb the Tower.", + "Kuleye çıkmak için bu merdiveni kullanabilirsin.") + +Orb("Matter", "Madde") + +S("This Orb allows to temporarily create impassable matter, either to block paths or " + "to build bridges across chasms and waters.", + "Bu Küre, yolları tıkamak veya boşluklar ve su üzerine köprü kurmak için geçilemez madde oluşturmaya yarar. ") + +N("temporary wall", GEN_F, "geçici duvar", "geçici duvarlar", "geçici duvarı", "geçici duvarla") +N("temporary floor", GEN_F, "geçici zemin", "geçici zeminler", "geçici zemini", "geçici zeminle") +N("temporary bridge", GEN_O, "geçici köprü", "geçici köprüler", "geçici köprüyü", "geçici köprüyle") + +S("This structure will disappear after some time.", "Bu yapı bir süre sonra yok olacak.") + +S("Nothing to stand on here!", "Burada duracağın bir şey yok!") +S("Gravity does not allow this!", "Yerçekimi buna izin vermiyor!") + +// Elemental Planes +//================== + +N("Elemental Planes", GEN_F, "Unsur Düzlemleri", "Unsur Düzlemleri", "Unsur Düzlemlerini", "Unsur Düzlemlerinde") +N("Plane of Fire", GEN_F, "Ateş Düzlemi", "Ateş Düzlemleri", "Ateş Düzlemini", "Ateş Düzleminde") +N("Plane of Earth", GEN_F, "Toprak Düzlemi", "Toprak Düzlemleri", "Toprak Düzlemini", "Toprak Düzleminde") +N("Plane of Air", GEN_F, "Ateş Düzlemi", "Ateş Düzlemleri", "Hava Düzlemini", "Hava Düzleminde") +N("Plane of Water", GEN_F, "Su Düzlemi", "Su Düzlemleri", "Su Düzlemini", "Su Düzleminde") + +S("The Elemental Planes are divided into four subzones: Planes of Fire, Water, Air, and Earth. " + "You need to collect a Shard from each Plane to construct an Elemental Gem. " + "It is dangerous to collect too many Shards of the same type without constructing a Gem.", + + "Unsur Düzlemleri dört altalana ayrılır: Ateş, Su, Hava ve Toprak Düzlemleri. Bir Unsurtaşı yapmak için her dört düzlemden birer parça toplaman gerekiyor. " +"Bir Unsurtaşı yapmadan aynı cins parçadan çok sayıda toplamak tehlikelidir." + ) + +N("Fire Elemental", GEN_M, "Ateş Unsuru", "Ateş Unsurları", "Ateş Unsurunu", "Ateş Unsuruyla") + +S("This monster leaves a trail of fire behind.", + "Bu canavar arkasında ateşten bir iz bırakıyor.") + +N("Air Elemental", GEN_M, "Hava Unsuru", "Hava Unsurları", "Hava Unsurunu", "Hava Unsuruyla") + +S("An Air Elemental looks like a live tornado. Once you are three (or less) cells from it, " + "it is impossible to move closer, due to strong winds. You can stand and wait, though. " + "This also affects most monsters.", + + "Hava Unsuru canlı bir hortuma benziyor. Eğer ondan üç ya da daha az uzaklıktaysan, güçlü rüzgârlardan ötürü daha fazla yakınlaşman mümkün değildir. Geçip gitmesini bekleyebilirsin elbette. Bu çoğu canavarı da etkiler. ") + +N("Fire Shard", GEN_M, "Ateş Parçası", "Ateş Parçaları", "Ateş Parçasını", "Ateş Parçasıyla") +N("Air Shard", GEN_M, "Hava Parçası", "Hava Parçaları", "Hava Parçasını", "Hava Parçasıyla") +N("Water Shard", GEN_M, "Su Parçası", "Su Parçaları", "Su Parçasını", "Su Parçasıyla") +N("Earth Shard", GEN_M, "Toprak Parçası", "Toprak Parçaları", "Toprak Parçasını", "Toprak Parçasıyla") +N("Elemental Gem", GEN_M, "Unsurtaşı", "Unsurtaşları", "Unsurtaşını", "Unsurtaşıyla") + +Orb("Summoning", "Çağırma") + +S( + "This orb allows you to summon monsters. Usually, they are either Elementals or " + "native creatures. While the monsters do not like being summoned, and will " + "attack you once they recover from summoning sickness, such summoning " + "often has its uses.", + "Bu küre canavar çağırabilmeni sağlar. Genelde Özütler veya yerel canavarlar çağrılır." +"Canavarlar çağrılmaktan hoşlanmasalar ve çağrılma hastalıkları biter bitmez sana saldıracak olsalar da, yine de çağırmanın işe yaradığı yerler olabilir." + ) + +N("limestone wall", GEN_F, "kireçtaşı duvar", "kireçtaşı duvarlar", "kireçtaşı duvarı", "kireçtaşı duvarla") + +S("Simply a wall. Mostly.", "Yalnızca bir duvar. Büyük ihtimalle.") + +// Zebra +//======= + +N("Zebra", GEN_F, "Zebra", "Zebralar", "Zebrayı", "Zebrada") +S("Everything in this Land has black and white stripes.", + "Bu diyardaki her şey siyah ve beyaz şeritlere sahip.") + +N("Striped Dog", GEN_M, "Şeritli Köpek", "Şeritli Köpekler", "Şeritli Köpeği", "Şeritli Köpekle") +S("A predator native to the Zebra.", "Zebra'da yaşayan bir vahşi hayvan.") + +N("Onyx", GEN_O, "Akik", "Akikler", "Akiği", "Akikle") +S("A black gem with white stripes. It is beautiful.", "Beyaz şeritli siyah bir mücevher. Çok güzel.") + +// Crossroads III +//================ + +N("Crossroads III", GEN_N, "Arayollar III", "Arayollar III", "Arayolları III", "Arayollarda III") + +S("An alternate layout of the Crossroads. Great Walls cross here at right angles.", + "Arayollar için bir alternatif düzen. Büyük Duvarlar burada dik açı yaparak kesişir.") + +// Steam achievements: + +/* + "NEW_ACHIEVEMENT_5_12_NAME" "Fildişi Kule'ye ulaş" + "NEW_ACHIEVEMENT_5_12_DESC" "Bir Fildişi Biblo bul ve topla." + "NEW_ACHIEVEMENT_5_13_NAME" "Hizmetkâr" + "NEW_ACHIEVEMENT_5_13_DESC" "10 Fildişi Biblo topla." + "NEW_ACHIEVEMENT_5_14_NAME" "Çörten" + "NEW_ACHIEVEMENT_5_14_DESC" "25 Fildişi Biblo topla." + "NEW_ACHIEVEMENT_5_15_NAME" "Kule Efendisi" + "NEW_ACHIEVEMENT_5_15_DESC" "50 Fildişi Biblo topla." + "NEW_ACHIEVEMENT_5_16_NAME" "Zebra'ya Ulaş" + "NEW_ACHIEVEMENT_5_16_DESC" "Bir Akik bul ve topla." + "NEW_ACHIEVEMENT_5_17_NAME" "Çizgili Köpek" + "NEW_ACHIEVEMENT_5_17_DESC" "10 Akik Topla." + "NEW_ACHIEVEMENT_5_18_NAME" "Benekli Köpek" + "NEW_ACHIEVEMENT_5_18_DESC" "25 Akik Topla." + "NEW_ACHIEVEMENT_5_19_NAME" "Damalı Köpek" + "NEW_ACHIEVEMENT_5_19_DESC" "50 Akik Topla." + "NEW_ACHIEVEMENT_5_20_NAME" "Unsurcu" + "NEW_ACHIEVEMENT_5_20_DESC" "Bir Unsurtaşı oluştur." + "NEW_ACHIEVEMENT_5_21_NAME" "İkincil Unsur" + "NEW_ACHIEVEMENT_5_21_DESC" "10 Unsurtaşı oluştur." + "NEW_ACHIEVEMENT_5_22_NAME" "Esas Unsur" + "NEW_ACHIEVEMENT_5_22_DESC" "25 Unsurtaşı oluştur." + "NEW_ACHIEVEMENT_5_23_NAME" "Elementlerin Efendisi" + "NEW_ACHIEVEMENT_5_23_DESC" "50 Unsurtaşı oluştur." +*/ + +S("Cannot create temporary matter on a monster!", "Geçici maddenin üzerinde bir canavar çıkaramazsın!"); +S("Cannot create temporary matter on an item!", "Bir eşyanın üzerinde geçici madde oluşturamazsın!"); +S("Cannot create temporary matter here!", "Burada geçici madde oluşturamazsın!"); +S("Cannot summon on a monster!", "Bir canavarın üstüne çağıramazsın!"); +S("No summoning possible here!", "Çağırmak burada mümkün değil!"); +S("You summon %the1!", "%a1 çağırdın!") + +S("F4 = file", "F4 = dosya") + +//CORRECTION FOR ELEMENTALS + +N("Earth Elemental", GEN_M, "Toprak Unsuru", "Toprak Unsurları", "Toprak Unsurunu", "Toprak Unsuruyla") +N("Water Elemental", GEN_M, "Su Unsuru", "Su Unsurları", "Su Unsurunu", "Su Unsuruyla") +S("Wherever this powerful being goes, the living fjord " + "sinks below water, non-magical boats are destroyed, and fires are extinguished.\n\n" + "As a special case, you can attack the Water Elemental from the water, without drowning immediately.", + "Bu güçlü yaratığın geçtiği her yerde Yaşayan Fiyort su altına gömülür, sihirli olmayan kayıklar yok olur ve ateşler söner. \n\n " + "İstisna bir durum olarak Su Unsuruna suyun içerisinden anında boğulmadan vurursan onu öldürebilirsin. ") +S("A coastal area, from where you can get both to the inland worlds and to the Ocean. " + "Each turn, each cell will become water or earth, based on the majority of cells around it. " + "Contrary to the Living Caves, this process is not affected by most items and monsters, " + "but elementals, dead Trolls, and cells outside of the Living Fjord have " + "a very powerful effect.", + "Sahil şeridinde bir bölge, buradan hem iç diyarlara hem de Okyanus'a geçebilirsin. " + "Her tur, her hücre etrafındaki hücrelerin çoğunluğuna göre su veya toprak olacak. " + "Yaşayan Mağaraların aksine, bu süreç eşyalar veya canavarlardan etkilenmez. " + "Ancak Yaşayan Fiyortların dışındaki hücreler, Unsurlar ve Ölü Trollerin etkisi çok güçlüdür." + ) + +#undef Orb + +// S("TRANSLATIONWARNING", "Uyarı: Türkçe çeviri henüz Sürüm 7.4' daki yeni özellikleri kapsamıyor.") +S("TRANSLATIONWARNING", "") + diff --git a/language.cpp b/language.cpp index 2ebf8d44..6cb34519 100644 --- a/language.cpp +++ b/language.cpp @@ -1,6 +1,6 @@ // #define CHECKTRANS -#define NUMLAN 5 +#define NUMLAN 6 #define GEN_M 0 #define GEN_F 1 @@ -17,10 +17,17 @@ struct stringpar { stringpar(eItem i) { v= iinf[i].name; } }; +const char *dnameof(eMonster m) { return minf[m].name; } +const char *dnameof(eLand l) { return linf[l].name; } +const char *dnameof(eWall w) { return winf[w].name; } +const char *dnameof(eItem i) { return iinf[i].name; } + void rep(string& pattern, string what, string to) { - size_t at = pattern.find(what); - if(at != string::npos) - pattern = pattern.replace(at, what.size(), to); + while(true) { + size_t at = pattern.find(what); + if(at == string::npos) break; + pattern = pattern.replace(at, what.size(), to); + } } typedef unsigned hashcode; @@ -84,13 +91,18 @@ string choose4(int g, string a, string b, string c, string d) { } int playergender(); +int princessgender(); int lang(); +#include +set warnshown; + void basicrep(string& x) { const sentence *s = findInHashTable(x, all_sentences); - if(!s) { + if(!s && !warnshown.count(x)) { printf("WARNING: no translations for '%s'\n", x.c_str()); + warnshown.insert(x); } int l = lang(); @@ -114,25 +126,6 @@ void basicrep(string& x) { void parrep(string& x, string w, stringpar p) { int l = lang(); const fullnoun *N = findInHashTable(p.v, all_nouns); - if(l == 0) { - // proper names (R'Lyeh) - if(N && (N->english_grammar_flags & 1)) { - rep(x,"%"+w,p.v); - rep(x,"%the"+w, p.v); - rep(x,"%The"+w, p.v); - } - else { - rep(x,"%"+w,p.v); - rep(x,"%the"+w, "the " + p.v); - rep(x,"%The"+w, "The " + p.v); - } - // plural names (Crossroads) - if(N && (N->english_grammar_flags & 2)) - rep(x,"%s"+w, ""); - else - rep(x,"%s"+w, "s"); - return; - } if(l == 1) { if(N) { rep(x, "%"+w, N->n[0].nom); @@ -140,11 +133,13 @@ void parrep(string& x, string w, stringpar p) { rep(x, "%a"+w, N->n[0].acc); rep(x, "%abl"+w, N->n[0].abl); rep(x, "%ł"+w, choose3(N->n[0].genus, "ł", "ła", "ło")); + rep(x, "%łem"+w, choose3(N->n[0].genus, "łem", "łam", "łom")); rep(x, "%ął"+w, choose3(N->n[0].genus, "ął", "ęła", "ęło")); rep(x, "%ya"+w, choose3(N->n[0].genus, "y", "a", "e")); rep(x, "%yą"+w, choose4(N->n[0].genus, "ego", "ą", "e", "y")); rep(x, "%oa"+w, choose3(N->n[0].genus, "", "a", "o")); rep(x, "%ymą"+w, choose3(N->n[0].genus, "ym", "ą", "ym")); + rep(x, "%go"+w, choose3(N->n[0].genus, "go", "ją", "je")); } else { rep(x,"%"+w, p.v); @@ -154,7 +149,7 @@ void parrep(string& x, string w, stringpar p) { rep(x, "%ł"+w, choose3(0, "ł", "ła", "ło")); } } - if(lang() == 2) { + if(l == 2) { if(N) { rep(x, "%"+w, N->n[1].nom); rep(x, "%P"+w, N->n[1].nomp); @@ -168,7 +163,7 @@ void parrep(string& x, string w, stringpar p) { rep(x, "%abl"+w, p.v); } } - if(lang() == 3) { + if(l == 3) { if(N) { rep(x, "%"+w, N->n[2].nom); rep(x, "%P"+w, N->n[2].nomp); @@ -179,6 +174,8 @@ void parrep(string& x, string w, stringpar p) { rep(x, "%el"+w, choose3(N->n[2].genus, "el", "la", "lo")); rep(x, "%ůj"+w, choose4(N->n[2].genus, "ého", "ou", "é", "ůj")); rep(x, "%ým"+w, choose3(N->n[2].genus, "ým", "ou", "ým")); + rep(x, "%ho"+w, choose3(N->n[2].genus, "ho", "ji", "ho")); + if(p.v == "Mirror Image") rep(x, "%s"+w, "se"); if(p.v == "Mirage") @@ -191,7 +188,7 @@ void parrep(string& x, string w, stringpar p) { rep(x, "%abl"+w, p.v); } } - if(lang() == 4) { + if(l == 4) { if(N) { rep(x, "%"+w, N->n[3].nom); rep(x, "%P"+w, N->n[3].nomp); @@ -199,6 +196,7 @@ void parrep(string& x, string w, stringpar p) { rep(x, "%abl"+w, N->n[3].abl); rep(x, "%E"+w, choose3(N->n[3].genus, "", "а", "о")); rep(x, "%A"+w, choose3(N->n[3].genus, "ый", "ая", "ое")); + rep(x, "%c"+w, choose3(N->n[3].genus, "ся", "ась", "")); } else { rep(x,"%"+w,p.v); @@ -207,6 +205,46 @@ void parrep(string& x, string w, stringpar p) { rep(x, "%abl"+w, p.v); } } + if(l == 5) { + if(N) { + rep(x, "%"+w, N->n[4].nom); + rep(x, "%P"+w, N->n[4].nomp); + rep(x, "%a"+w, N->n[4].acc); + rep(x, "%abl"+w, N->n[4].abl); + rep(x, "%Der"+w, choose3(N->n[4].genus, "Der", "Die", "Das")); + rep(x, "%der"+w, choose3(N->n[4].genus, "der", "die", "das")); + rep(x, "%den"+w, choose3(N->n[4].genus, "den", "die", "das")); + } + else { + rep(x,"%"+w,p.v); + rep(x, "%P"+w, p.v); + rep(x, "%a"+w, p.v); + rep(x, "%abl"+w, p.v); + rep(x, "%Der"+w, "The"); + rep(x, "%der"+w, "the"); + rep(x, "%den"+w, "the"); + } + } + if(true) { + // proper names (R'Lyeh) + rep(x,"%"+w,p.v); + if(N && (N->english_grammar_flags & 1)) { + rep(x,"%the"+w, p.v); + rep(x,"%The"+w, p.v); + } + else { + rep(x,"%the"+w, "the " + p.v); + rep(x,"%The"+w, "The " + p.v); + rep(x,"%him"+w, princessgender() ? "her" : "him"); + rep(x,"%his"+w, princessgender() ? "her" : "his"); + } + // plural names (Crossroads) + if(N && (N->english_grammar_flags & 2)) + rep(x,"%s"+w, ""); + else + rep(x,"%s"+w, "s"); + } + return; } void postrep(string& s) { @@ -230,6 +268,23 @@ string XLAT(string x, stringpar p1, stringpar p2) { postrep(x); return x; } +string XLAT(string x, stringpar p1, stringpar p2, stringpar p3) { + basicrep(x); + parrep(x,"1",p1.v); + parrep(x,"2",p2.v); + parrep(x,"3",p2.v); + postrep(x); + return x; + } +string XLAT(string x, stringpar p1, stringpar p2, stringpar p3, stringpar p4) { + basicrep(x); + parrep(x,"1",p1.v); + parrep(x,"2",p2.v); + parrep(x,"3",p2.v); + parrep(x,"4",p2.v); + postrep(x); + return x; + } string XLATN(string x) { if(lang()) { diff --git a/mapeditor.cpp b/mapeditor.cpp new file mode 100644 index 00000000..9fa07ec1 --- /dev/null +++ b/mapeditor.cpp @@ -0,0 +1,1570 @@ +#include +#include + +#ifdef WINDOWS +#include "direntx.h" +#include "direntx.c" +#else +#include +#endif + +namespace mapeditor { + cell *modelcell[200]; + + void clearModelCells() { + for(int i=0; i<200; i++) modelcell[i] = NULL; + } + + void applyModelcell(cell *c) { + if(mapeditor::whichPattern == 'H') return; + int i = realpattern(c); + cell *c2 = modelcell[i]; + if(c2) { + c->wall = c2->wall; + c->land = c2->land; + c->monst = c2->monst; + c->item = c2->item; + c->landparam = c2->landparam; + c->wparam = c2->wparam; + c->mondir = c2->mondir; + if(c2->mondir != NODIR) + c->mondir = (c2->mondir - patterndir(c2) + patterndir(c) + 7*6*5) % c->type; + } + } + } + +namespace mapstream { + std::map cellids; + vector cellbyid; + vector relspin; + + FILE *f; + + void addToQueue(cell* c) { + if(cellids.count(c)) return; + int numcells = size(cellbyid); + cellbyid.push_back(c); + cellids[c] = numcells; + } + + void saveChar(char c) { fwrite(&c, 1, 1, f); } + template void save(T& c) { fwrite(&c, sizeof(T), 1, f); } + + char loadChar() { char c; int i=fread(&c, 1, 1, f); if(i!=1) return 0; else return c; } + template int load(T& c) { return fread(&c, sizeof(T), 1, f); } + int32_t loadInt() { int i; if(load(i) < 1) return -1; else return i; } + + void savePoint(const hyperpoint& h) { + for(int i=0; i<3; i++) { double x = h[i]; save(x); } + } + + hyperpoint loadPoint() { + hyperpoint h; + for(int i=0; i<3; i++) { double x; load(x); h[i] = x; } + return h; + } + + bool saveMap(const char *fname) { + f = fopen(fname, "wb"); + if(!f) return false; + int32_t i = VERNUM; save(i); + save(mapeditor::whichPattern); + addToQueue(cwt.c->master->c7); + for(int i=0; itype; j++) if(c->mov[j] && cellids.count(c->mov[j]) && + cellids[c->mov[j]] < i) { + int32_t i = cellids[c->mov[j]]; + save(i); + saveChar(c->spn[j]); + saveChar(j); + break; + } + } + saveChar(c->land); + saveChar(c->mondir); + saveChar(c->monst); + saveChar(c->wall); + // saveChar(c->barleft); + // saveChar(c->barright); + saveChar(c->item); + saveChar(c->mpdist); + // saveChar(c->bardir); + save(c->wparam); save(c->landparam); + saveChar(c->stuntime); saveChar(c->hitpoints); + for(int j=0; jtype; j++) { + cell *c2 = c->mov[j]; + if(c2 && c2->land != laNone) addToQueue(c2); + } + } + int32_t n = -1; save(n); + int32_t id = cellids.count(cwt.c) ? cellids[cwt.c] : -1; + save(id); + + for(int i=0; id[l].list)) { + usershapelayer& ds(us->d[l]); + save(i); save(j); save(l); save(ds.sym); save(ds.rots); save(ds.color); + n = size(ds.list); save(n); + savePoint(ds.shift); + savePoint(ds.spin); + for(int i=0; i= 0 && dir < t) + return (dir + rspin) % t; + else + return dir; + } + + bool loadMap(const char *fname) { + f = fopen(fname, "rb"); + if(!f) return false; + int vernum = loadInt(); + printf("vernum = %d\n", vernum); + if(vernum >= 7400) load(mapeditor::whichPattern); + + clearMemory(); + initcells(); + cleargraphmemory(); + if(shmup::on) shmup::init(); + + while(true) { + cell *c; + int rspin; + + if(size(cellbyid) == 0) { + c = origin.c7; + rspin = 0; + } + else { + int32_t parent = loadInt(); + + if(parent<0 || parent >= size(cellbyid)) break; + int dir = loadChar(); + cell *c2 = cellbyid[parent]; + dir = fixspin(dir, relspin[parent], c2->type); + c = createMov(c2, dir); + // printf("%p:%d,%d -> %p\n", c2, dir, c); + + // spinval becomes xspinval + rspin = (c2->spn[dir] - loadChar() + 42) % c->type; + } + + cellbyid.push_back(c); + relspin.push_back(rspin); + c->land = (eLand) loadChar(); + c->mondir = fixspin(rspin, loadChar(), c->type); + c->monst = (eMonster) loadChar(); + c->wall = (eWall) loadChar(); + // c->barleft = (eLand) loadChar(); + // c->barright = (eLand) loadChar(); + c->item = (eItem) loadChar(); + c->mpdist = loadChar(); + c->bardir = NOBARRIERS; + // fixspin(rspin, loadChar(), c->type); + if(vernum < 7400) { + load(c->aitmp); + c->wparam = c->aitmp; + } + else load(c->wparam); + load(c->landparam); + // backward compatibility + if(vernum < 7400 && !isIcyLand(c->land)) c->landparam = HEAT(c); + c->stuntime = loadChar(); + c->hitpoints = loadChar(); + + if(mapeditor::whichPattern) + mapeditor::modelcell[mapeditor::realpattern(c)] = c; + } + + int32_t whereami = loadInt(); + if(whereami >= 0 && whereami < size(cellbyid)) + cwt.c = cellbyid[whereami]; + else cwt.c = origin.c7; + + for(int i=0; ibardir != NODIR && c->bardir != NOBARRIERS) + buildBarrier(c); + } + + for(int d=BARLEV-1; d>=0; d--) + for(int i=0; impdist <= d) + for(int j=0; jtype; j++) { + cell *c2 = createMov(c, j); + setdist(c2, d+1, c); + } + } + + cellbyid.clear(); + relspin.clear(); + + if(shmup::on) shmup::init(); + + timerstart = time(NULL); turncount = 0; + sagephase = 0; hardcoreAt = 0; + timerstopped = false; + savecount = 0; savetime = 0; + cheater = 1; + + if(vernum >= 7400) while(true) { + int i = loadInt(); + if(i == -1) break; + int j = loadInt(), l = loadInt(); + if(i<0 || i >= USERSHAPEGROUPS) break; + if(j<0 || j >= USERSHAPEIDS) break; + if(l<0 || l >= USERLAYERS) break; + + initShape(i, j); + usershapelayer& ds(usershapes[i][j]->d[l]); + + load(ds.sym); load(ds.rots); load(ds.color); + ds.list.clear(); + int siz = loadInt(); + + ds.shift = loadPoint(); + ds.spin = loadPoint(); + + for(int i=0; i > v; + + struct undo_info { + cell *c; + eWall w; + eItem i; + eMonster m; + eLand l; + char wparam; + int32_t lparam; + char dir; + }; + + vector undo; + + bool checkEq(undo_info& u) { + return u.w == u.c->wall && u.i == u.c->item && u.m == u.c->monst && u.l == u.c->land && + u.dir == u.c->mondir && u.lparam == u.c->landparam && u.wparam == u.c->wparam; + } + + void saveUndo(cell *c) { + undo_info u; + u.c=c; u.w = c->wall; u.i = c->item; u.m = c->monst; u.l = c->land; u.dir = c->mondir; + u.wparam = c->wparam; u.lparam = c->landparam; + undo.push_back(u); + } + + undo_info& lastUndo() { return undo[size(undo)-1]; } + + void undoLock() { + if(!size(undo) || lastUndo().c) { + undo_info i; i.c = NULL; undo.push_back(i); + } + } + + void applyUndo() { + while(size(undo) && !lastUndo().c) undo.pop_back(); + while(size(undo)) { + undo_info& i(lastUndo()); + if(!i.c) break; + i.c->wall = i.w; + i.c->item = i.i; + i.c->monst = i.m; + i.c->land = i.l; + i.c->mondir = i.dir; + i.c->wparam = i.wparam; + i.c->landparam = i.lparam; + undo.pop_back(); + } + } + + void checkUndo() { + if(checkEq(undo[size(undo)-1])) undo.pop_back(); + } + + string actkeys = "-" + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789!@#$%^&*()_+=[{]}\\|;:'\",<.>/?`~"; + + int itc(int k) { + if(k == 0) return 0; + if(k == 1) return 0x40; + if(k == 2) return 0x80; + if(k == 3) return 0xFF; + return 0x20; + } + + int colorhistory[10] = { + 0x202020, 0x800000, 0x008000, 0x000080, + 0x404040, 0xC0C0C0, 0x804000, 0xC0C000, + 0x408040, 0xFFD500 + }, lch; + + bool choosefile = false; + bool editext = false; + + #define CDIR 0xC0C0C0 + #define CFILE 0xFFFFFF + + bool filecmp(const pair &f1, const pair &f2) { + if(f1.first == "../") return true; + if(f2.first == "../") return false; + if(f1.second != f2.second) + return f1.second == CDIR; + return f1.first < f2.first; + } + + void drawFileDialog() { + displayfr(vid.xres/2, 30 + vid.fsize, 2, vid.fsize, + XLAT(cmode == emDraw ? "pics to save/load:" : "level to save/load:"), 0xFFFFFF, 8); + + string cfile = cmode == emDraw ? picfile : levelfile; + displayfr(vid.xres/2, 34 + vid.fsize * 2, 2, vid.fsize, + cfile, editext ? 0xFF00FF : 0xFFFF00, 8); + + displayButton(vid.xres*1/5, 38+vid.fsize * 3, + "F2 = save", 2000+SDLK_F2, 8); + displayButton(vid.xres*2/5, 38+vid.fsize * 3, + "F3 = load", 2000+SDLK_F3, 8); + displayButton(vid.xres*3/5, 38+vid.fsize * 3, + "F4 = extension", 2000+SDLK_F4, 8); + displayButton(vid.xres*4/5, 38+vid.fsize * 3, + "Enter = back", 2000+SDLK_RETURN, 8); + + v.clear(); + + DIR *d; + struct dirent *dir; + + string where = "."; + for(int i=0; id_name; + if(s != ".." && s[0] == '.') ; + else if(size(s) > 4 && s.substr(size(s)-4) == (cmode == emDraw ? ".pic" : ".lev")) + v.push_back(make_pair(s, CFILE)); + else if(dir->d_type & DT_DIR) + v.push_back(make_pair(s+"/", CDIR)); + } + closedir(d); + } + sort(v.begin(), v.end(), filecmp); + + int q = v.size(); + int percolumn = (vid.yres-38) / (vid.fsize+5) - 4; + int columns = 1 + (q-1) / percolumn; + + for(int i=0; i= '0' && uni <= '0'+15) + i=0, j=uni-'0'; + if(uni >= 'a' && uni <= 'a'+15) + i=1, j=uni-'a'; + if(uni >= 'A' && uni <= 'A'+15) + i=2, j=uni-'A'; + + if(i<3) { + color &= ~ (0xFF << (8*i)); + color |= (17*j) << (8*i); + } + else if(uni == ' ') { + bool inHistory = false; + for(int i=0; i<10; i++) if(colorhistory[i] == paintwhat) + inHistory = true; + if(!inHistory) { colorhistory[lch] = paintwhat; lch++; lch %= 10; } + return 1; + } + else if(uni >= 'q' && uni <= 'z') { + color = colorhistory[uni - 'q']; + return 1; + } + else if(uni) return 2; + return 0; + } + + void displayFunctionKeys() { + int fs = vid.fsize + 5; + displayButton(8, vid.yres-8-fs*10, XLAT("F1 = help"), SDLK_F1, 0); + displayButton(8, vid.yres-8-fs*9, XLAT("F2 = save"), SDLK_F2, 0); + displayButton(8, vid.yres-8-fs*8, XLAT("F3 = load"), SDLK_F3, 0); + displayButton(8, vid.yres-8-fs*7, XLAT("F4 = file"), SDLK_F3, 0); + displayButton(8, vid.yres-8-fs*6, XLAT("F5 = restart"), SDLK_F5, 0); + displayButton(8, vid.yres-8-fs*5, XLAT("F6 = HQ shot"), SDLK_F6, 0); + displayButton(8, vid.yres-8-fs*4, XLAT("F7 = player on/off"), SDLK_F7, 0); + displayButton(8, vid.yres-8-fs*3, XLAT("SPACE = map/graphics"), ' ', 0); + displayButton(8, vid.yres-8-fs*2, XLAT("ESC = return to the game"), SDLK_ESCAPE, 0); + } + + void showMapEditor() { + + if(choosefile) { drawFileDialog(); return; } + + if(subscreen == 2) { + displayStat(2, XLAT("Emerald Pattern"), ONOFF(whichPattern == 'f'), 'f'); + displayStat(3, XLAT("Palace Pattern"), ONOFF(whichPattern == 'p'), 'p'); + displayStat(4, XLAT("Zebra Pattern"), ONOFF(whichPattern == 'z'), 'z'); + + if(whichPattern == 'f') symRotation = true; + displayStat(6, XLAT("rotational symmetry"), ONOFF(symRotation), '0'); + displayStat(7, XLAT("symmetry 0-1"), ONOFF(sym01), '1'); + displayStat(8, XLAT("symmetry 0-2"), ONOFF(sym02), '2'); + displayStat(9, XLAT("symmetry 0-3"), ONOFF(sym03), '3'); + + displayStat(11, XLAT("display pattern codes (full)"), ONOFF(displaycodes), 'd'); + displayStat(12, XLAT("display pattern codes (simplified)"), ONOFF(displaycodes), 's'); + + displayStat(14, XLAT("display only hexagons"), ONOFF(whichShape == '6'), '6'); + displayStat(15, XLAT("display only heptagons"), ONOFF(whichShape == '7'), '7'); + + displayStat(17, XLAT("predesigned patterns"), "", 'r'); + } + else if(subscreen == 3) { + displayStat(2, XLAT("Gameboard"), "", 'g'); + displayStat(3, XLAT("random colors"), "", 'r'); + + displayStat(5, XLAT("emerald pattern"), "emerald", 'e'); + + displayStat(7, XLAT("four elements"), "palace", 'b'); + displayStat(8, XLAT("eight domains"), "palace", 'a'); + + displayStat(10, XLAT("zebra pattern"), "zebra", 'z'); + displayStat(11, XLAT("three stripes"), "zebra", 'x'); + + displayStat(13, XLAT("random black-and-white"), "current", 'w'); + } + else if(subscreen == 1 && painttype == 6) + drawColorDialog(paintwhat); + else if(subscreen == 1) { + v.clear(); + if(painttype == 4) painttype = 0; + switch(painttype) { + case 0: + for(int i=0; i=2) return 0; + if(anyshiftclick) return -1; + return 1; + } + + void spillCopy(cell *c1, int d1, cell *c2, int d2, int r) { + saveUndo(c1); + int cf = copyflip ? -1 : 1; + if(c2->land == laNone) return; + c1->wall = c2->wall; + c1->item = c2->item; + c1->land = c2->land; + c1->monst = c2->monst; + c1->landparam = c2->landparam; + c1->wparam = c2->wparam; + // c1->tmp = c2->tmp; + if(c2->mondir == NODIR) c1->mondir = NODIR; + else c1->mondir = (cf * (c2->mondir - d2) + d1 + 42) % c1->type; + checkUndo(); + + if(r) for(int i=0; itype; i++) { + if(c1 != mouseover && (i == 0 || i == 1 || i == c1->type-1)) continue; + createMov(c1, i); + int i0 = (42+cf*i+d1) % c1->type; + int i1 = (i + d2) % c2->type; + spillCopy(c1->mov[i0], c1->spn[i0], c2->mov[i1], c2->spn[i1], r-1); + } + } + + int subpatternEmerald(int i) { + if((sym01?1:0)+(sym02?1:0)+(sym03?1:0) >= 2) i &= ~3; + if(sym01 && (i&1)) i ^= 1; + if(sym02 && (i&2)) i ^= 2; + if(sym03 && (i&2)) i ^= 3; + return i; + } + + int subpatternZebra(int i) { + i = subpatternEmerald(i); + if(symRotation) { + if(i >= 8 && i < 12) i -= 4; + if(i >= 12 && i < 16) i -= 8; + if(i >= 20 && i < 24) i -= 4; + if(i >= 24 && i < 28) i -= 8; + if(i >= 32 && i < 36) i -= 4; + if(i >= 36 && i < 40) i -= 8; + } + return i; + } + + int subpatternPalace(int i) { + i = subpatternEmerald(i); + if(symRotation && i >= 3) i -= ((i/4-1) % 7) * 4; + return i; + } + + int subpattern(cell *c) { + switch(whichPattern) { + case 'z': + return subpatternZebra(zebra40(c)); // 4 to 43 + case 'f': + return subpatternEmerald(emeraldval(c)); // 44 to 99 + case 'p': { + int i = fiftyval049(c); + i *= 4; + if(polara50(c)) i|=1; + if(polarb50(c)) i|=2; + return subpatternPalace(i); + } + case 'H': + return realpattern(c); + } + return c->type-6; // 0 to 1 + } + + int realpattern(cell *c) { + switch(whichPattern) { + case 'z': + return zebra40(c); // 4 to 43 + case 'f': + return emeraldval(c); // 44 to 99 + case 'p': { + int i = fiftyval049(c); + i *= 4; + if(polara50(c)) i|=1; + if(polarb50(c)) i|=2; + return i; + } + case 'H': + return towerval(c); + } + return c->type-6; // 0 to 2 + } + + int cellShapeGroup() { + if(whichPattern == 'f') return 4; + if(whichPattern == 'p') return 5; + if(whichPattern == 'z') return 6; + if(whichPattern == 'H') return 7; + return 3; + } + + int drawcellShapeGroup() { + if(drawcell == cwt.c) return 0; + if(drawcell->monst) return 1; + if(drawcell->item) return 2; + return cellShapeGroup(); + } + + int drawcellShapeID() { + if(drawcell == cwt.c) return vid.female; + if(drawcell->monst) return drawcell->monst; + if(drawcell->item) return drawcell->item; + return subpattern(drawcell); + } + + int subpatternShape(int i) { + if(whichPattern == 'z') return subpatternZebra(i); + if(whichPattern == 'f') return subpatternEmerald(i); + if(whichPattern == 'p') return subpatternPalace(i); + return i; + } + + bool editingShape(int group, int id) { + if(group != mapeditor::drawcellShapeGroup()) return false; + if(group < 3) return id == drawcellShapeID(); + return subpatternShape(id) == subpattern(drawcell); + } + + bool reflectPatternAt(cell *c) { + return whichPattern == 'p' && polarb50(c); + } + + int patterndir(cell *c, char w) { + switch(w) { + case 'z': { + int t = zebra40(c); + + int t4 = t>>2, tcdir; + + if(t4 == 10) tcdir = 0; + else if(t4 >= 4 && t4 < 7) tcdir = 40 + (t&3); + else if(t4 >= 1 && t4 < 4) tcdir = t+12; + else if(t4 >= 7 && t4 < 10) tcdir = t-24; + + for(int i=0; itype; i++) if(c->mov[i] && zebra40(c->mov[i]) == tcdir) + return i; + } + + case 'f': { + int t = emeraldval(c); + int tcdir, tbest = (t&3); + for(int i=0; itype; i++) { + cell *c2 = c->mov[i]; + if(c2) { + int t2 = emeraldval(c2); + if((t&3) == (t2&3) && t2 > tbest) + tbest = t2, tcdir = i; + } + } + return tcdir; + } + + case 'p': { + int tcdir = -1, tbest = -1; + int pa = polara50(c); + int pb = polarb50(c); + for(int i=0; itype; i++) { + cell *c2 = c->mov[i]; + if(c2 && polara50(c2) == pa && polarb50(c2) == pb) { + int t2 = fiftyval049(c2); + if(t2 > tbest) tbest = t2, tcdir = i; + } + } + return tcdir; + } + + case 'H': { + cell *c2 = chosenDown(c, 1, 1); + if(!c2) return 0; + return neighborId(c, c2); + } + } + return 0; + } + + void spill(cell *c, int r, int cdir) { + + if(painttype == 4 && radius) { + if(mouseover->type != copywhat->type) return; + if(cdir<0) cdir=0; + if(mouseover->type == 6 && ((cdir^copydir)&1)) { + cdir++; cdir %= 6; + } + spillCopy(mouseover, cdir, copywhat, copydir, radius); + } + + saveUndo(c); + switch(painttype) { + case 0: + c->monst = eMonster(paintwhat); + c->hitpoints = 3; + c->stuntime = 0; + c->mondir = cdir; + + if((isWorm(c) || isIvy(c)) && c->mov[cdir] && + !isWorm(c->mov[cdir]) && !isIvy(c->mov[cdir])) + c->mondir = NODIR; + break; + case 1: + c->item = eItem(paintwhat); + break; + case 2: { + eLand last = c->land; + c->land = eLand(paintwhat); + if(isIcyLand(c) && isIcyLand(last)) + HEAT(c) += spillinc() / 100.; + else if(last == laDryForest && c->land == laDryForest) + c->landparam += spillinc(); + else if(last == laOcean && c->land == laOcean) + c->landparam += spillinc(); + else if(last == laHive && c->land == laHive) + c->landparam += spillinc(); + else + c->landparam = 0; + break; + } + case 3: { + eWall last = c->wall; + c->wall = eWall(paintwhat); + + if(last != c->wall) { + if(hasTimeout(c)) + c->wparam = 10; + else if(c->wall == waWaxWall) + c->landparam = rand() & 0xFFFFFF; + } + else if(hasTimeout(c)) + c->wparam += spillinc(); + break; + } + case 5: + c->land = laNone; + c->wall = waNone; + c->item = itNone; + c->monst = moNone; + c->landparam = 0; + // c->tmp = -1; + break; + case 6: + c->land = laCanvas; + c->wall = waNone; + c->landparam = paintwhat; + break; + case 4: + c->wall = copywhat->wall; + c->item = copywhat->item; + c->land = copywhat->land; + c->monst = copywhat->monst; + c->landparam = copywhat->landparam; + c->wparam = copywhat->wparam; + if(copywhat->mondir == NODIR) c->mondir = NODIR; + else if(c->mondir == c->type-1) c->mondir = 0; + else c->mondir++; + break; + } + checkUndo(); + if(r) for(int i=0; itype; i++) spill(createMov(c, i), r-1, c->spn[i]); + } + + void allInPattern(cell *c, int r, int cdir) { + + if(!whichPattern) { + spill(c, r, cdir); + return; + } + + vector v; + v.push_back(c); + sval++; + c->aitmp = sval; + + cdir = cdir - patterndir(c); + int sp = subpattern(c); + + int at = 0; + while(at < size(v)) { + cell *c2 = v[at]; + at++; + + if(subpattern(c2) == sp) { + spill(c2, r, fixdir(cdir + patterndir(c2), c)); + modelcell[realpattern(c2)] = c2; + } + for(int i=0; itype; i++) { + cell *c3 = c2->mov[i]; + if(c3 && c3->aitmp != sval) + c3->aitmp = sval, v.push_back(c3); + } + } + } + + bool handleKeyFile(int uni, int& sym) { + string& s(cmode == emDraw ? picfile : levelfile); + int i = size(s) - (editext?0:4); + if(uni > 2000) sym = uni - 2000; + if(sym == SDLK_RETURN || sym == SDLK_ESCAPE) { + choosefile = false; + return true; + } + else if(sym == SDLK_F2 || sym == SDLK_F3) { + choosefile = false; + return false; + } + else if(sym == SDLK_F4) { + editext = !editext; + } + else if(sym == SDLK_BACKSPACE && i) { + s.erase(i-1, 1); + } + else if(uni >= 32 && uni < 127) { + s.insert(i, s0 + char(uni)); + } + else if(uni >= 1000 && uni <= 1000+size(v)) { + string where = "", what = s, whereparent = "../"; + for(int i=0; i= 2 && s.substr(i-2,3) == "../") + whereparent = s.substr(0, i+1) + "../"; + else + whereparent = where; + where = s.substr(0, i+1), what = s.substr(i+1); + } + int i = uni - 1000; + if(v[i].first == "../") { + s = whereparent + what; + } + else if(v[i].second == CDIR) + s = where + v[i].first + what; + else + s = where + v[i].first; + } + return true; + } + + void handleKey(int uni, int sym) { + if(choosefile && handleKeyFile(uni, sym)) ; + else if(subscreen == 1 && painttype == 6) { + paintwhat_str = "paint"; + int v = handleKeyColor(uni, paintwhat); + if(v == 1) subscreen = 0; + if(v == 2) cmode = emNormal; + } + else if(subscreen == 1) { + for(int z=0; z= 'a' && uni <= 'z') { + whichCanvas = uni; + subcanvas = rand(); + firstland = laCanvas; randomPatternsMode = false; + restartGame(); subscreen = 0; + } + else if(uni != 0) subscreen = 0; + } + else if(subscreen == 2) { + if(uni == 'f' || uni == 'p' || uni == 'z' || uni == 'H') { + if(whichPattern == uni) whichPattern = 0; + else whichPattern = uni; + clearModelCells(); + } + + else if(uni == '0') symRotation = !symRotation; + else if(uni == '1') sym01 = !sym01; + else if(uni == '2') sym02 = !sym02; + else if(uni == '3') sym03 = !sym03; + else if(uni == '6' || uni == '7') { + if(whichShape == uni) whichShape = 0; + else whichShape = uni; + } + else if(uni == '3') sym03 = !sym03; + else if(uni == 'd') displaycodes = displaycodes == 1 ? 0 : 1; + else if(uni == 's') displaycodes = displaycodes == 2 ? 0 : 2; + + else if(uni == 'r') + subscreen = 3; + + else if(uni != 0) subscreen = 0; + } + else { + // left-clicks are coded with '-', and right-clicks are coded with sym F1 + if(uni == '-') undoLock(); + if(mousepressed && mouseover && sym != SDLK_F1) + allInPattern(mouseover, radius, neighborId(mouseover, mouseover2)); + + if(mouseover) for(int i=0; itype; i++) createMov(mouseover, i); + if(uni == 'u') applyUndo(); + else if(uni == 'v' || sym == SDLK_F10 || sym == SDLK_ESCAPE) cmode = emNormal; + else if(uni >= '0' && uni <= '9') radius = uni - '0'; + else if(uni == 'm') subscreen = 1, painttype = 0; + else if(uni == 'i') subscreen = 1, painttype = 1; + else if(uni == 'l') subscreen = 1, painttype = 2; + else if(uni == 'w') subscreen = 1, painttype = 3; + else if(uni == 'r') subscreen = 2; + else if(uni == 't' && mouseover) { + cwt.c = mouseover; playermoved = true; + cwt.spin = neighborId(mouseover, mouseover2); + } + else if(uni == 'b') painttype = 5, paintwhat_str = XLAT("boundary"); + else if(uni == 'p') + subscreen = 1, paintwhat = (painttype ==6 ? paintwhat : 0x808080), painttype = 6; + else if(sym == SDLK_F2) { + if(mapstream::saveMap(levelfile.c_str())) + addMessage(XLAT("Map saved to %1", levelfile)); + else + addMessage(XLAT("Failed to save map to %1", levelfile)); + } + else if(sym == SDLK_F5) { + restartGame(); + } + else if(sym == SDLK_F3) { + if(mapstream::loadMap(levelfile.c_str())) + addMessage(XLAT("Map loaded from %1", levelfile)); + else + addMessage(XLAT("Failed to load map from %1", levelfile)); + } + else if(sym == SDLK_F4) + choosefile = true; + else if(sym == SDLK_F6) { + saveHighQualityShot(); + } + else if(sym == SDLK_F7) { + drawplayer = !drawplayer; + } + else if(uni == 'c') { + if(mouseover && mouseover2) + copydir = neighborId(mouseover, mouseover2); + if(copydir<0) copydir = 0; + copyflip = (uni == 'f'); + copywhat = mouseover, painttype = 4; + paintwhat_str = XLAT("copying"); + } + else if(uni == 'f') { + copyflip = !copyflip; + } + else if(uni == 'h' || sym == SDLK_F1) { + lastmode = cmode; + cmode = emHelp; + help = mehelptext(); + } + else if(uni == ' ') { + cmode = emDraw; + drawcell = mouseover ? mouseover : cwt.c; + } + } + } + +// VECTOR GRAPHICS EDITOR + + const char* drawhelp = + "In this mode you can draw your own player characters, " + "floors, monsters, and items. Press 'e' while hovering over " + "an object to edit it. Start drawing shapes with 'n', and " + "add extra vertices with 'a'. Press 0-9 to draw symmetric " + "pictures easily. More complex pictures can " + "be created by using several layers ('l'). See the edges of " + "the screen for more keys."; + + string drawhelptext() { + return XLAT(mapeditor::drawhelp); + } + + int dslayer; + bool coloring; + int colortouse = 0xC0C0C0; + + transmatrix drawtrans; + + void loadShape(int sg, int id, hpcshape& sh, int d, int layer) { + initShape(sg, id); + usershapelayer *dsCur = &usershapes[sg][id]->d[layer]; + dsCur->list.clear(); + dsCur->sym = d==2; + for(int i=sh.s; i < sh.s + (sh.e-sh.s)/d; i++) + dsCur->list.push_back(hpc[i]); + } + + void drawGhosts(cell *c, const transmatrix& V, int ct) { +/* if(cmode == emDraw && cwt.c->type == 6 && ct == 6) for(int a=0; arots; a++) { + + transmatrix V2 = V * spin(M_PI + 2*M_PI*a/dsCur->rots); + + if(outofmap(mouseh)) break; + + hyperpoint P2 = V2 * inverse(cwtV) * mouseh; + + int xc, yc, sc; + getcoord(P2, xc, yc, sc); + displaychr(xc, yc, sc, 10, 'x', 0xFF); + + if(crad > 0 && c->cpdist <= 3) { + lalpha = 0x80; + transmatrix movtocc = V2 * inverse(cwtV) * rgpushxto0(ccenter); + for(int d=0; d<84; d++) + drawline(movtocc * ddi(d+1, crad) * C0, movtocc * ddi(d, crad) * C0, 0xC00000); + lalpha = 0xFF; + } + } */ + } + + hyperpoint ccenter = C0; + hyperpoint coldcenter = C0; + + void drawGrid() { + if(cmode == emDraw) { + lalpha = 0x20; + for(int d=0; d<84; d++) { + transmatrix d2 = drawtrans * rgpushxto0(ccenter); + if(d % (84/drawcell->type) == 0) + lalpha = 0x40; + else + lalpha = 0x20; + drawline(d2 * C0, d2 * spin(M_PI*d/42)* xpush(1) * C0, 0xC0C0C0); + for(int u=2; u<=20; u++) { + if(u % 5 == 0) lalpha = 0x40; + else lalpha = 0x20; + drawline( + d2 * spin(M_PI*d/42)* xpush(u/20.) * C0, + d2 * spin(M_PI*(d+1)/42)* xpush(u/20.) * C0, + 0xC0C0C0); + } + } + drawline(drawtrans*ccenter, drawtrans*coldcenter, 0xC0C0C0); + + lalpha = 0xFF; + } + } + + void showDrawEditor() { + + if(coloring) { + drawColorDialog(colortouse); + return; + } + + if(choosefile) { drawFileDialog(); return; } + + int sg = drawcellShapeGroup(); + + string line1, line2; + + switch(sg) { + case 0: + line1 = XLAT("character"); + line2 = XLAT(vid.female ? "female" : "male"); + break; + + case 1: + line1 = XLAT("monster"); + line2 = XLAT1(minf[drawcell->monst].name); + break; + + case 2: + line1 = XLAT("item"); + line2 = XLAT1(iinf[drawcell->item].name); + break; + + case 3: + line1 = XLAT("floor"); + line2 = XLAT(drawcell->type == 6 ? "hexagonal" : "heptagonal"); + break; + + default: + line1 = XLAT("floor/pattern"); + line2 = "#" + its(subpattern(cwt.c)); + break; + } + + usershape *us =usershapes[drawcellShapeGroup()][drawcellShapeID()]; + + int fs = vid.fsize + 5; + + // displayButton(8, 8+fs*9, XLAT("l = lands"), 'l', 0); + displayfr(8, 8+fs, 2, vid.fsize, line1, 0xC0C0C0, 0); + displayfr(8, 8+fs*2, 2, vid.fsize, line2, 0xC0C0C0, 0); + displayButton(8, 8+fs*3, XLAT("l = layers: %1", its(dslayer)), 'l', 0); + if(us) { + usershapelayer& ds(us->d[dslayer]); + displayButton(8, 8+fs*4, XLAT("1-9 = rotations: %1", its(ds.rots)), '1' + (ds.rots % 9), 0); + displayButton(8, 8+fs*5, XLAT(ds.sym ? "0 = symmetry" : "0 = asymmetry"), '0', 0); + + displayfr(8, 8+fs*7, 2, vid.fsize, XLAT("%1 vertices", its(size(ds.list))), 0xC0C0C0, 0); + displayfr(8, 8+fs*8, 2, vid.fsize, XLAT("a = add v"), 0xC0C0C0, 0); + displayfr(8, 8+fs*9, 2, vid.fsize, XLAT("m = move v"), 0xC0C0C0, 0); + displayfr(8, 8+fs*10, 2, vid.fsize, XLAT("d = delete v"), 0xC0C0C0, 0); + displayfr(8, 8+fs*11, 2, vid.fsize, XLAT("c = readd v"), 0xC0C0C0, 0); + displayfr(8, 8+fs*12, 2, vid.fsize, XLAT("b = reorder"), 0xC0C0C0, 0); + + displayfr(8, 8+fs*14, 2, vid.fsize, XLAT("t = shift"), 0xC0C0C0, 0); + displayfr(8, 8+fs*15, 2, vid.fsize, XLAT("y = spin"), 0xC0C0C0, 0); + displayButton(8, 8+fs*16, XLAT("p = paint"), 'p', 0); + + } + else { + displayfr(8, 8+fs*5, 2, vid.fsize, XLAT("'n' to start"), 0xC0C0C0, 0); + } + + displayfr(vid.xres-8, 8+fs*4, 2, vid.fsize, XLAT("g = grid"), 0xC0C0C0, 16); + displayButton(vid.xres-8, 8+fs*3, XLAT("z = zoom in"), 'z', 16); + displayButton(vid.xres-8, 8+fs*2, XLAT("o = zoom out"), 'o', 16); + displayfr(vid.xres-8, 8+fs, 2, vid.fsize, XLAT("e = edit this"), 0xC0C0C0, 16); + + if(!outofmap(mouseh)) { + hyperpoint mh = inverse(drawtrans * rgpushxto0(ccenter)) * mouseh; + displayfr(vid.xres-8, vid.yres-8-fs*6, 2, vid.fsize, XLAT("x: %1", fts4(mh[0])), 0xC0C0C0, 16); + displayfr(vid.xres-8, vid.yres-8-fs*5, 2, vid.fsize, XLAT("y: %1", fts4(mh[1])), 0xC0C0C0, 16); + displayfr(vid.xres-8, vid.yres-8-fs*4, 2, vid.fsize, XLAT("z: %1", fts4(mh[2])), 0xC0C0C0, 16); + + displayfr(vid.xres-8, vid.yres-8-fs*2, 2, vid.fsize, XLAT("r: %1", fts4(inverse_sinh(sqrt(mh[0]*mh[0]+mh[1]*mh[1])))), 0xC0C0C0, 16); + displayfr(vid.xres-8, vid.yres-8-fs, 2, vid.fsize, XLAT("ϕ: %1°", fts4(-atan2(mh[1], mh[0]) * 360 / 2 / M_PI)), 0xC0C0C0, 16); + } + + displayFunctionKeys(); + } + + void applyToShape(int sg, int id, int uni, hyperpoint mh) { + bool haveshape = usershapes[sg][id]; + if(!haveshape) { + if(uni == 'n' || uni == 'u') + initShape(sg, id); + else return; + } + + usershapelayer *dsCur = &usershapes[sg][id]->d[dslayer]; + if(uni == 'n') { + dsCur->list.clear(); + dsCur->list.push_back(mh); + saveImages(); + } + + if(uni == 'a' && haveshape) { + dsCur->list.push_back(mh); + saveImages(); + } + + if(uni == 'D') { + delete usershapes[sg][id]; + usershapes[sg][id] = NULL; + } + + if(uni == 'm' || uni == 'd' || uni == 'c' || uni == 'b') { + int i = 0; + if(size(dsCur->list) < 1) return; + for(int j=1; jlist); j++) + if(intval(mh, dsCur->list[j]) < intval(mh, dsCur->list[i])) + i = j; + if(uni == 'm') + dsCur->list[i] = mh; + if(uni == 'd') + dsCur->list.erase(dsCur->list.begin() + i); + if(uni == 'c') + dsCur->list.push_back(dsCur->list[i]); + if(uni == 'b') { + while(i) { + dsCur->list.push_back(dsCur->list[0]); + dsCur->list.erase(dsCur->list.begin()); + i--; + } + } + saveImages(); + } + + if(uni == 'L') { + if(!vid.female) loadShape(sg, id, shPBody, 2, 0); + else loadShape(sg, id, shFemaleBody, 2, 0); + + loadShape(sg, id, shPSword, 1, 1); + + if(vid.female) + loadShape(sg, id, shFemaleDress, 2, 2); + + if(vid.female) + loadShape(sg, id, shFemaleHair, 2, 3); + else + loadShape(sg, id, shPHead, 2, 3); + + loadShape(sg, id, shPFace, 2, 4); + + // loadShape(sg, id, shWolf, 2, dslayer); + + saveImages(); + } + + if(uni >= '1' && uni <= '9') { + dsCur->rots = uni - '0'; + if(dsCur->rots == 9) dsCur->rots = 21; + saveImages(); + } + if(uni == '0') { + dsCur->sym = !dsCur->sym; + saveImages(); + } + + if(uni == 't') { + dsCur->shift = mh; + saveImages(); + } + if(uni == 'y') { + dsCur->spin = mh; + saveImages(); + } + +#define COLORKEY (-10000) + if(uni == COLORKEY) dsCur->color = colortouse; + } + + void writeHyperpoint(FILE *f, hyperpoint h) { + for(int i=0; i<3; i++) fprintf(f, "%lf ", double(h[i])); + fprintf(f, "\n"); + } + + hyperpoint readHyperpoint(FILE *f) { + hyperpoint h; + for(int i=0; i<3; i++) { + double d; + fscanf(f, "%lf", &d); + h[i] = d; + } + return h; + } + + string drawHelpLine() { + return XLAT("vector graphics editor"); + } + + void drawHandleKey(int uni, int sym, double shiftmul) { + + if(choosefile && handleKeyFile(uni, sym)) return; + + if(coloring) { + int v = handleKeyColor(uni, colortouse); + if(v == 2) { coloring = false; return; } + else if(v == 1) { coloring = false; uni = COLORKEY; } + else return; + } + + dslayer &= 7; + hyperpoint mh = inverse(drawtrans) * mouseh; + + int sg = drawcellShapeGroup(); + + for(int i=0; id[l].list)) { + usershapelayer& ds(us->d[l]); + printf("// %d %d %d [%06X]\n", i, j, l, ds.color); + for(int i=ds.sh.s; i < ds.sh.e; i++) { + printf(" hpcpush(hpxyz(%f,%f,%f));\n", double(hpc[i][0]), double(hpc[i][1]), double(hpc[i][2])); + } + printf("\n"); + } + } + } + + if(uni == 'z') vid.scale *= 2; + if(uni == 'o') vid.scale /= 2; + + if(uni == ' ' && cheater) cmode = emMapEditor; + + if(uni == 'p') coloring = true; + + if(sym == SDLK_F4) choosefile = true; + + if(sym == SDLK_F2) { + FILE *f = fopen(picfile.c_str(), "wt"); + if(!f) { + addMessage(XLAT("Failed to save pictures to %1", picfile)); + return; + } + fprintf(f, "HyperRogue saved picture\n"); + fprintf(f, "%x\n", VERNUM_HEX); + for(int i=0; id[l].list)) { + usershapelayer& ds(us->d[l]); + fprintf(f, "\n%d %d %d %d %d %6x %d\n", + i, j, l, ds.sym, ds.rots, ds.color, int(size(ds.list))); + writeHyperpoint(f, ds.shift); + writeHyperpoint(f, ds.spin); + fprintf(f,"\n"); + for(int i=0; i 1000) break; + initShape(i, j); + usershapelayer& ds(usershapes[i][j]->d[l]); + ds.shift = readHyperpoint(f); + ds.spin = readHyperpoint(f); + ds.list.clear(); + for(int i=0; i> 2; + if(whichCanvas == 'r') + return rand() & 0xFFFFFF; + if(whichCanvas == 'e') { + static unsigned int fcol[4] = { 0x404040, 0x800000, 0x008000, 0x000080 }; + int fv = emeraldval(c); + return fcol[fv&3]; + } + if(whichCanvas == 'a') { + static unsigned int fcol8[8] = { + 0x800000, + 0x503000, + 0x206000, + 0x007010, + 0x004040, + 0x001070, + 0x200060, + 0x500030 + }; + + if(c->wall == waNone) { + int col = fcol8[land50(c)]; + if(polara50(c)) col += 0x181818; + return col; + } + } + if(whichCanvas == 'b') { + static unsigned int fcol[4] = { 0x404040, 0x800000, 0x008000, 0x000080 }; + return fcol[polara50(c) + 2 * polarb50(c)]; + } + if(whichCanvas == 'z') { + static unsigned int fcol[4] = { 0xC0C0C0, 0xE0E0E0, 0x404040, 0x606060 }; + int fv = zebra40(c); + return fcol[fv&3]; + } + if(whichCanvas == 'x') { + static unsigned int fcol[4] = { 0xC0C0C0, 0x800000, 0x008000, 0x000080 }; + return fcol[zebra3(c)]; + } + if(whichCanvas == 'w') { + static unsigned int fcol[2] = { 0x303030, 0xC0C0C0 }; + return fcol[randpattern(c, subcanvas) ? 1 : 0]; + } + return linf[laCanvas].color >> 2; + } + } diff --git a/mtrand.cpp b/mtrand.cpp new file mode 100644 index 00000000..72ad04f6 --- /dev/null +++ b/mtrand.cpp @@ -0,0 +1,53 @@ + + +// mtrand.cpp, see include file mtrand.h for information + +#include "mtrand.h" +// non-inline function definitions and static member definitions cannot +// reside in header file because of the risk of multiple declarations + +// initialization of static private members +unsigned long MTRand_int32::state[n] = {0x0UL}; +int MTRand_int32::p = 0; +bool MTRand_int32::init = false; + +void MTRand_int32::gen_state() { // generate new state vector + for (int i = 0; i < (n - m); ++i) + state[i] = state[i + m] ^ twiddle(state[i], state[i + 1]); + for (int i = n - m; i < (n - 1); ++i) + state[i] = state[i + m - n] ^ twiddle(state[i], state[i + 1]); + state[n - 1] = state[m - 1] ^ twiddle(state[n - 1], state[0]); + p = 0; // reset position +} + +void MTRand_int32::seed(unsigned long s) { // init by 32 bit seed + state[0] = s & 0xFFFFFFFFUL; // for > 32 bit machines + for (int i = 1; i < n; ++i) { + state[i] = 1812433253UL * (state[i - 1] ^ (state[i - 1] >> 30)) + i; +// see Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier +// in the previous versions, MSBs of the seed affect only MSBs of the array state +// 2002/01/09 modified by Makoto Matsumoto + state[i] &= 0xFFFFFFFFUL; // for > 32 bit machines + } + p = n; // force gen_state() to be called for next random number +} + +void MTRand_int32::seed(const unsigned long* array, int size) { // init by array + seed(19650218UL); + int i = 1, j = 0; + for (int k = ((n > size) ? n : size); k; --k) { + state[i] = (state[i] ^ ((state[i - 1] ^ (state[i - 1] >> 30)) * 1664525UL)) + + array[j] + j; // non linear + state[i] &= 0xFFFFFFFFUL; // for > 32 bit machines + ++j; j %= size; + if ((++i) == n) { state[0] = state[n - 1]; i = 1; } + } + for (int k = n - 1; k; --k) { + state[i] = (state[i] ^ ((state[i - 1] ^ (state[i - 1] >> 30)) * 1566083941UL)) - i; + state[i] &= 0xFFFFFFFFUL; // for > 32 bit machines + if ((++i) == n) { state[0] = state[n - 1]; i = 1; } + } + state[0] = 0x80000000UL; // MSB is 1; assuring non-zero initial array + p = n; // force gen_state() to be called for next random number +} + diff --git a/mtrand.h b/mtrand.h new file mode 100644 index 00000000..9ef94bcf --- /dev/null +++ b/mtrand.h @@ -0,0 +1,158 @@ + + +// mtrand.h +// C++ include file for MT19937, with initialization improved 2002/1/26. +// Coded by Takuji Nishimura and Makoto Matsumoto. +// Ported to C++ by Jasper Bedaux 2003/1/1 (see http://www.bedaux.net/mtrand/). +// The generators returning floating point numbers are based on +// a version by Isaku Wada, 2002/01/09 +// +// Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. The names of its contributors may not be used to endorse or promote +// products derived from this software without specific prior written +// permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Any feedback is very welcome. +// http://www.math.keio.ac.jp/matumoto/emt.html +// email: matumoto@math.keio.ac.jp +// +// Feedback about the C++ port should be sent to Jasper Bedaux, +// see http://www.bedaux.net/mtrand/ for e-mail address and info. + +#ifndef MTRAND_H +#define MTRAND_H + +class MTRand_int32 { // Mersenne Twister random number generator +public: +// default constructor: uses default seed only if this is the first instance + MTRand_int32() { if (!init) seed(5489UL); init = true; } +// constructor with 32 bit int as seed + MTRand_int32(unsigned long s) { seed(s); init = true; } +// constructor with array of size 32 bit ints as seed + MTRand_int32(const unsigned long* array, int size) { seed(array, size); init = true; } +// the two seed functions + void seed(unsigned long); // seed with 32 bit integer + void seed(const unsigned long*, int size); // seed with array +// overload operator() to make this a generator (functor) + unsigned long operator()() { return rand_int32(); } +// 2007-02-11: made the destructor virtual; thanks "double more" for pointing this out + virtual ~MTRand_int32() {} // destructor +protected: // used by derived classes, otherwise not accessible; use the ()-operator + unsigned long rand_int32(); // generate 32 bit random integer +private: + static const int n = 624, m = 397; // compile time constants +// the variables below are static (no duplicates can exist) + static unsigned long state[n]; // state vector array + static int p; // position in state array + static bool init; // true if init function is called +// private functions used to generate the pseudo random numbers + unsigned long twiddle(unsigned long, unsigned long); // used by gen_state() + void gen_state(); // generate new state +// make copy constructor and assignment operator unavailable, they don't make sense + MTRand_int32(const MTRand_int32&); // copy constructor not defined + void operator=(const MTRand_int32&); // assignment operator not defined +}; + +// inline for speed, must therefore reside in header file +inline unsigned long MTRand_int32::twiddle(unsigned long u, unsigned long v) { + return (((u & 0x80000000UL) | (v & 0x7FFFFFFFUL)) >> 1) + ^ ((v & 1UL) * 0x9908B0DFUL); +// 2013-07-22: line above modified for performance according to http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/Ierymenko.html +// thanks Vitaliy FEOKTISTOV for pointing this out +} + +inline unsigned long MTRand_int32::rand_int32() { // generate 32 bit random int + if (p == n) gen_state(); // new state vector needed +// gen_state() is split off to be non-inline, because it is only called once +// in every 624 calls and otherwise irand() would become too big to get inlined + unsigned long x = state[p++]; + x ^= (x >> 11); + x ^= (x << 7) & 0x9D2C5680UL; + x ^= (x << 15) & 0xEFC60000UL; + return x ^ (x >> 18); +} + +// generates double floating point numbers in the half-open interval [0, 1) +class MTRand : public MTRand_int32 { +public: + MTRand() : MTRand_int32() {} + MTRand(unsigned long seed) : MTRand_int32(seed) {} + MTRand(const unsigned long* seed, int size) : MTRand_int32(seed, size) {} + ~MTRand() {} + double operator()() { + return static_cast(rand_int32()) * (1. / 4294967296.); } // divided by 2^32 +private: + MTRand(const MTRand&); // copy constructor not defined + void operator=(const MTRand&); // assignment operator not defined +}; + +// generates double floating point numbers in the closed interval [0, 1] +class MTRand_closed : public MTRand_int32 { +public: + MTRand_closed() : MTRand_int32() {} + MTRand_closed(unsigned long seed) : MTRand_int32(seed) {} + MTRand_closed(const unsigned long* seed, int size) : MTRand_int32(seed, size) {} + ~MTRand_closed() {} + double operator()() { + return static_cast(rand_int32()) * (1. / 4294967295.); } // divided by 2^32 - 1 +private: + MTRand_closed(const MTRand_closed&); // copy constructor not defined + void operator=(const MTRand_closed&); // assignment operator not defined +}; + +// generates double floating point numbers in the open interval (0, 1) +class MTRand_open : public MTRand_int32 { +public: + MTRand_open() : MTRand_int32() {} + MTRand_open(unsigned long seed) : MTRand_int32(seed) {} + MTRand_open(const unsigned long* seed, int size) : MTRand_int32(seed, size) {} + ~MTRand_open() {} + double operator()() { + return (static_cast(rand_int32()) + .5) * (1. / 4294967296.); } // divided by 2^32 +private: + MTRand_open(const MTRand_open&); // copy constructor not defined + void operator=(const MTRand_open&); // assignment operator not defined +}; + +// generates 53 bit resolution doubles in the half-open interval [0, 1) +class MTRand53 : public MTRand_int32 { +public: + MTRand53() : MTRand_int32() {} + MTRand53(unsigned long seed) : MTRand_int32(seed) {} + MTRand53(const unsigned long* seed, int size) : MTRand_int32(seed, size) {} + ~MTRand53() {} + double operator()() { + return (static_cast(rand_int32() >> 5) * 67108864. + + static_cast(rand_int32() >> 6)) * (1. / 9007199254740992.); } +private: + MTRand53(const MTRand53&); // copy constructor not defined + void operator=(const MTRand53&); // assignment operator not defined +}; + +#endif // MTRAND_H + diff --git a/patterngen.cpp b/patterngen.cpp new file mode 100644 index 00000000..c13206fb --- /dev/null +++ b/patterngen.cpp @@ -0,0 +1,455 @@ +void spill50(cell *c, eWall w, int r) { + c->wall = w; + if(r) for(int i=0; itype; i++) spill50(createMov(c, i), w, r-1); + } + +int style = 3; + +struct state50 { + bool polarity1; + bool polarity2; + int color, color2, wc2; + }; + +void progress(cell *c, state50 s); + +#include + +map map50; + +void initPatternFifty(cell *c) { + state50 s; + s.polarity1 = 0; + s.polarity2 = 0; + s.color = 0; + s.color2 = 1; + s.wc2 = 0; + map50[c] = s; + } + +int par; + +int haverule[1<<24][8]; + +void saveCode(heptagon *H1, int d, heptagon *H2) { + +/* + if(!H1 || !H2) return; + if(H1->move[d] != H2) exit(1); + + int h1 = H1->fiftyval; + int h2 = H2->fiftyval; + + if(!h1 || !h2) return; + + if(haverule[h1][d] && haverule[h1][d] != h2) { + printf("rule conflict: %06x, %d, %06x/%06x\n", + h1, d, h2, haverule[h1][d]); + // exit(1); + } + + if(!haverule[h1][d]) { + haverule[h1][d] = h2; + + printf("RULE50(0x%06x, %d, 0x%06x)\n", h1, d, h2); + } */ + + fflush(stdout); + } + +void saveCode(cell *c) { + +/* heptagon *hept = c->master; + + if(hept != &origin) + saveCode(hept->move[0], hept->spin[0], hept); */ + + bool allcodes = c->master->fiftyval >= 0; + + for(int i=0; i<7; i++) + if(c->master->move[i] && c->master->move[i]->fiftyval >= 0) ; + else allcodes = false; + + if(allcodes) { + printf("RULE50(0x%03x", c->master->fiftyval); + int rulebase = 0; + for(int i=0; i<7; i++) + if(c->master->move[i]->fiftyval < c->master->move[rulebase]->fiftyval) + rulebase = i; + for(int i=0; i<7; i++) printf(", 0x%03x", c->master->move[(rulebase+i)%7]->fiftyval); + printf(")\n"); + } + + // hept->fiftyused = true; + } + +void encode(cell *c, state50 s, int mod, int spn) { +/*int i = 0; + i *= 16; i += s.color; + i *= 16; i += s.color2; + i *= 16; i += s.polarity1; + i *= 16; i += s.polarity2; + i *= 16; i += mod; + i *= 16; i += spn; + if(c->master->fiftyval) { printf("multiply 50val\n"); exit(1); } + c->master->fiftyval = i; c->master->fiftyused = false; */ + + c->master->fiftyval = + s.color + s.polarity1 * 8 + s.polarity2 * 16 + mod * 32; + // s.color * 16 + (s.polarity1 ? 128 : 0) + (s.polarity2 ? 256 :0) + mod; + + saveCode(c); + for(int i=0; i<7; i++) + saveCode(createStep(c->master, i)->c7); + + /* for(int i=0; i<7; i++) if(c->master->move[i]) { + saveCode(c->master, i, c->master->move[i]); + saveCode(c->master->move[i], c->master->spin[i], c->master); + } */ + } + +eWall colorwalls[4] = {waCIsland, waCIsland2, waMineOpen, waDeadfloor }; + +void patternFiftyAt(cell *c) { + if(!map50.count(c)) return; + + state50 s = map50[c]; + + // c->wall = waCIsland; + + // if(c->heat > ii) return; + + // printf("pfifty %p\n", c); + + if(style == 1 && s.polarity2) { + spill50(c, waCamelot, 3); + spill50(c, waNone, 2); + + for(int i=0; itype; i++) { + cellwalker cw(c, i); + cwstep(cw); // cw.c->item = itSilver; + cwspin(cw, 4); // 6 + cwstep(cw); // cw.c->item = itSilver; + cwspin(cw, 3); // 6 + cwstep(cw); cw.c->wall = waFloorA; cwstep(cw); + cwspin(cw, 1); + cwstep(cw); cw.c->wall = waFloorA; cwstep(cw); + } + } + + /*switch(ii) { + case 0: + spill50(c, waNone, 3); + break; + + case 1: + spill50(c, waNone, 3); + break; + + case 2: + spill50(c, waNone, 3); + break; + + case 3: + spill50(c, waNone, 3); + break; + } */ + + if(style == 2) { + spill50(c, waCavefloor, 2); + spill50(c, waFloorA, 1); + } + + if(style == 3) { + spill50(c, colorwalls[s.color], 3); + // c->item = itGold; +// if(s.polarity2) return; + } + + encode(c, s, 0, 0); + + int sgn = s.polarity2 ? 1 : -1; + int sgn1 = s.polarity1 ? 1 : -1; + + int col2 = s.color2, sw = s.wc2; + + while(col2 != 7-s.color) { + sw += (s.polarity1?1:-1); sw %= 7; + while(true) { col2++; col2 &= 7; if(col2 != s.color) break; } + } + + for(int i=0; itype; i++) { + cellwalker cw(c, sw); + cwspin(cw, sgn1 * i); + cwstep(cw); + cwspin(cw, sgn*4); + cwstep(cw); + if(cw.spin < 0 || cw.spin >= 7 || cw.c->type != 7) exit(1); + encode(cw.c, s, 1+i, cw.spin); + } + + for(int i=0; itype; i++) { + cellwalker cw(c, sw); + cwspin(cw, sgn1 * i); + cwstep(cw); + cwspin(cw, 3); + cwstep(cw); + cwspin(cw, 3); + cwstep(cw); + if(cw.spin < 0 || cw.spin >= 7 || cw.c->type != 7) exit(1); + encode(cw.c, s, 8+i, cw.spin); + } + + // c->heat = s.color + + + for(int i=0; itype; i++) { + cellwalker cw(c, s.wc2); + cwspin(cw, sgn1 * i); + cwstep(cw); + if(style == 0) cw.c->wall = waCamelot; + // cw.c->item = itSilver; + cwspin(cw, sgn*4); //6 + cwstep(cw); if(style == 0) cw.c->wall = waFloorA; + + // cw.c->item = itSilver; + cwspin(cw, sgn*4); //7 + cwstep(cw); if(style == 0) cw.c->wall = waFloorA; + // cw.c->item = itSilver; + cwspin(cw, 3); //6 + cwstep(cw); if(style == 0) cw.c->wall = waFloorA; + // cw.c->item = itSilver; + cwspin(cw, 3); //6 + cwstep(cw); if(style == 0) cw.c->wall = waFloorA; + // cw.c->item = itSilver; + cwspin(cw, sgn*3); //7 + cwstep(cw); if(style == 0) cw.c->wall = waCamelot; + // cw.c->item = itSilver; + cwspin(cw, sgn*2); //6 + cwstep(cw); // cw.c->item = itGold; + // setdist(cw.c, 8, NULL); + state50 s2 = s; s2.polarity1 = !s.polarity1; + s2.wc2 = (cw.spin + sgn1 * i + sgn + 42) % 7; + progress(cw.c, s2); + // printf("heat set %f\n", cw.c->heat); + } + + int newcol = s.color2; + + // if(s.polarity2) return; + + for(int i=0; itype; i++) { + cellwalker cw(c, s.wc2); + cwspin(cw, sgn1 * i); + cwstep(cw); // cw.c->item = itSilver; +// cw.c->item = itDiamond; + cwspin(cw, 3); // 6 + cwstep(cw); // cw.c->item = itSilver; +// cw.c->item = itDiamond; + cwspin(cw, sgn*4); // 6 + cwstep(cw); // cw.c->item = itSilver; +// cw.c->item = itDiamond; + cwspin(cw, sgn*2); // 6 + cwstep(cw); // cw.c->item = itSilver; +// cw.c->item = itDiamond; + cwspin(cw, 3); // 6 + cwstep(cw); // cw.c->item = itSilver; +// cw.c->item = itDiamond; + cwspin(cw, sgn*3); // 7 + cwstep(cw); // cw.c->item = itSilver; +// cw.c->item = itDiamond; + cwspin(cw, sgn*4); // 6 + cwstep(cw); // cw.c->item = itSilver; + // setdist(cw.c, 8, NULL); + state50 s2 = s; + s2.polarity2 = !s.polarity2; + if(s.polarity2) s2.polarity1 = !s.polarity1; + s2.color2 = s2.color; + s2.color = newcol; + s2.wc2 = cw.spin; + progress(cw.c, s2); + while(true) { newcol++; newcol &= 7; if(newcol != s2.color && newcol != s.color) break; } + // printf("heat set %f\n", cw.c->heat); + } + + } + +void progress(cell *c, state50 s) { + + while(s.wc2) { + s.wc2 += (s.polarity1?1:-1); s.wc2 %= 7; + while(true) { s.color2++; s.color2 &= 7; if(s.color2 != s.color) break; } + } + + if(map50.count(c)) { + state50 s2 = map50[c]; + if(s2.polarity1 != s.polarity1 || s2.polarity2 != s.polarity2) { + printf("Polarity mismatch!\n"); + exit(1); + } + else { + if(s2.color != s.color || s2.color2 != s.color2 || s2.wc2 != s.wc2) + printf("%d:%d color= %dv%d color2= %dv%d wc2= %dv%d\n", + s.polarity1, s.polarity2, + s.color, s2.color, + s.color2, s2.color2, + s.wc2, s2.wc2); + } + return; + } + map50[c] = s; + if(c->mpdist <= 7) + patternFiftyAt(c); + } + +long long Q; int qconflict; + +string allconflict; + +void setzebra(cellwalker cwb, int it, int type, string pathcode, int xmods) { + // printf("spin=%d type=%d\n", cwb.spin, type); + + if(cwb.spin != 1 && cwb.spin != 3 && cwb.spin != 5) { + printf("S WRONG SPIN %d\n", cwb.spin); + exit(1); + } + if(type < 0 || type > 3) { + printf("S WRONG TYPE %d\n", type); + exit(1); + } + + cwb.c->tmp = cwb.spin + 16 * type; + } + +void zebra(cellwalker cwb, int it, int type, string pathcode, int xmods) { + if(!it) return; + if(cwb.spin != 1 && cwb.spin != 3 && cwb.spin != 5) { + printf("WRONG SPIN %d\n", cwb.spin); + exit(1); + } + if(type < 0 || type > 3) { + printf("WRONG TYPE %d\n", type); + exit(1); + } + // printf("%p+%d = 0%s\n", cwb.c, cwb.spin, pathcode.c_str()); + bool redraw = false; + // int qval = Q + 99; + // redraw = cwb.c->heat == qval; + // cwb.c->heat = qval; + eWall w = colorwalls[type]; + cwb.c->wall = w; + for(int i=0; i<6; i+=2) { + cellwalker cw = cwb; + cwspin(cw, i); + cw.c->heat = 4 + type + 4 * 9; + cwstep(cw); cwspin(cw, 3); cw.c->wall = w; + int i0 = i; if(type&2 && i0) i0 = 6-i0; i0 /= 2; + cw.c->heat = 4 + type + 4 * (3+i0); + cwstep(cw); cwspin(cw, 3); cw.c->wall = w; + cw.c->heat = 4 + type + 4 * i0; + cwstep(cw); cwspin(cw, 3); cw.c->wall = w; + cw.c->heat = 4 + type + 4 * (6+i0); + cwstep(cw); cwspin(cw, -3); + cwstep(cw); cwspin(cw, -3); + cwstep(cw); cwspin(cw, -3); + cwstep(cw); cwspin(cw, -i); + cwspin(cw, 0); + setzebra(cw, it-1, type ^ 1, pathcode +'+'+char('A'+i)+char('0'+type), xmods*2); + } + + for(int i=0; i<6; i+=2) { + cellwalker cw = cwb; + cwspin(cw, (type&2)?-i:i); + cwstep(cw); cwspin(cw, 3); + cwstep(cw); cwspin(cw, 5); + if(xmods < 2) { + if(cw.c->item && cw.c->item != (1+i) && redraw && i==0) { + qconflict++; + // allconflict += pathcode; allconflict += "-"; + // cwb.c->item = itPalace; + // printf("Conflict at %p\n", cwb.c); + } + // cw.c->item = eItem(1 + i); + // cw.c->heat = 4 + type + 4 * (i/2); + } + cwstep(cw); cwspin(cw, 1); + if(type < 2) { + // cwspin(cw, i); + cwspin(cw, i); + } + else { + cwspin(cw, -i); + } + // cwspin(cw, ((Q >> (4*type)) & 12)); + setzebra(cw, it-1, 2^type, pathcode + '+'+char('a'+i)+char('0'+type), xmods+1); + } + } + +void zebraPattern() { + // int bqc = 99; + + /* for(Q=0; Q<65536; Q++) { + if((Q & (Q>>1)) & 0x5555) continue; + qconflict = false; + cellwalker cw(cwt); + cwstep(cw); cwspin(cw, 1); + qconflict = 0; + allconflict = ""; + zebra(cw, 3, 0, ""); + if(qconflict < bqc) bqc = qconflict; + // if(qconflict == bqc) + printf("%X - X-%sX\n", Q, allconflict.c_str()); + } + + Q = 0xFFFB; */ + + cellwalker cw(cwt); + cwstep(cw); cwspin(cw, 1); + setzebra(cw, 7, 0, "", -999); + // cw.c-> + // printf("Conflicts: %d\n", qconflict); + } + +int bspin(heptagon *h) { + vector xv; + xv.push_back(999); + int besti = -1; + for(int i=0; i<7; i++) { + vector yv; + for(int j=0; j<7; j++) yv.push_back(int(h->move[(i+j)%7]->c7->heat+.1)); + if(yv < xv) xv = yv, besti = i; + } + return besti; + } + +void buildAutomatonRule(heptagon *h) { + if(!h->c7->heat) return; + for(int i=0; i<7; i++) if(!h->move[i]) return; + for(int i=0; i<7; i++) for(int j=0; j<7; j++) + if(!h->move[i]->move[j] || !h->move[i]->move[j]->c7->heat) + return; + int bi = bspin(h); + printf("RULEZEBRA(%2d", int(h->c7->heat+.1)); + for(int j=0; j<7; j++) { + heptagon *h2 = h->move[(bi+j)%7]; + int bi2 = bspin(h2); + printf(", %2d%d", int(h2->c7->heat+.1), fix7(bi2 - h->spin[(bi+j)%7])); + } + printf(")\n"); + } + +void buildAutomatonRule(cell *c) { + if(c->type == 7) + buildAutomatonRule(c->master); + else { + int ii[3]; + for(int i=0; i<6; i+=2) if(!c->mov[i] || !c->mov[i]->heat || c->mov[i]->type != 7) return; + for(int i=0; i<6; i+=2) ii[i/2] = int(c->mov[i]->heat); + int z; + for(int r=0; r<2; r++) + if(ii[1] < ii[0] || ii[2] < ii[0]) + z = ii[0], ii[0] = ii[1], ii[1] = ii[2], ii[2] = z; + printf("RULEZEBRA6(%d,%d,%d,%d)\n", int(c->heat), int(ii[0]), int(ii[1]), int(ii[2])); + } + } + +// #define BUILDZEBRA diff --git a/patterns.cpp b/patterns.cpp new file mode 100644 index 00000000..1117d19e --- /dev/null +++ b/patterns.cpp @@ -0,0 +1,1053 @@ +// === EMERALD PATTERN === + +// rules for the emeraldvalues of heptagons. +int emerald_heptagon(int parent, int dir) { + + // no emeraldgen here + if(parent == 0) return 0; + + #define RULE(t1,s1,d,t2,s2) \ + if(parent == t1*8+s1 && dir == d) return t2*8+s2; + + RULE(8,0,3,12,4) + RULE(8,0,4,12,0) + RULE(8,0,5,42,0) + RULE(8,1,3,40,0) + RULE(8,1,4,12,4) + RULE(8,1,5,12,0) + RULE(8,2,3,34,0) + RULE(8,2,4,40,0) + RULE(8,2,5,12,4) + RULE(8,3,3,10,0) + RULE(8,3,4,34,0) + RULE(8,3,5,40,0) + RULE(8,4,3,32,0) + RULE(8,4,4,10,0) + RULE(8,4,5,34,0) + RULE(8,5,3,42,0) + RULE(8,5,4,32,0) + RULE(8,5,5,10,0) + RULE(8,6,3,12,0) + RULE(8,6,4,42,0) + RULE(8,6,5,32,0) + RULE(9,0,3,13,4) + RULE(9,0,4,13,0) + RULE(9,0,5,43,0) + RULE(9,1,3,41,0) + RULE(9,1,4,13,4) + RULE(9,1,5,13,0) + RULE(9,2,3,35,0) + RULE(9,2,4,41,0) + RULE(9,2,5,13,4) + RULE(9,3,3,11,0) + RULE(9,3,4,35,0) + RULE(9,3,5,41,0) + RULE(9,4,3,33,0) + RULE(9,4,4,11,0) + RULE(9,4,5,35,0) + RULE(9,5,3,43,0) + RULE(9,5,4,33,0) + RULE(9,5,5,11,0) + RULE(9,6,3,13,0) + RULE(9,6,4,43,0) + RULE(9,6,5,33,0) + RULE(10,0,3,14,4) + RULE(10,0,4,14,0) + RULE(10,0,5,40,3) + RULE(10,1,3,42,4) + RULE(10,1,4,14,4) + RULE(10,1,5,14,0) + RULE(10,2,3,32,1) + RULE(10,2,4,42,4) + RULE(10,2,5,14,4) + RULE(10,3,3,8,0) + RULE(10,3,4,32,1) + RULE(10,3,5,42,4) + RULE(10,4,3,34,6) + RULE(10,4,4,8,0) + RULE(10,4,5,32,1) + RULE(10,5,3,40,3) + RULE(10,5,4,34,6) + RULE(10,5,5,8,0) + RULE(10,6,3,14,0) + RULE(10,6,4,40,3) + RULE(10,6,5,34,6) + RULE(11,0,3,15,4) + RULE(11,0,4,15,0) + RULE(11,0,5,41,3) + RULE(11,1,3,43,4) + RULE(11,1,4,15,4) + RULE(11,1,5,15,0) + RULE(11,2,3,33,1) + RULE(11,2,4,43,4) + RULE(11,2,5,15,4) + RULE(11,3,3,9,0) + RULE(11,3,4,33,1) + RULE(11,3,5,43,4) + RULE(11,4,3,35,6) + RULE(11,4,4,9,0) + RULE(11,4,5,33,1) + RULE(11,5,3,41,3) + RULE(11,5,4,35,6) + RULE(11,5,5,9,0) + RULE(11,6,3,15,0) + RULE(11,6,4,41,3) + RULE(11,6,5,35,6) + RULE(12,0,3,8,4) + RULE(12,0,4,40,1) + RULE(12,0,5,14,2) + RULE(12,1,3,12,6) + RULE(12,1,4,8,4) + RULE(12,1,5,40,1) + RULE(12,2,0,14,2) + RULE(12,2,1,42,6) + RULE(12,2,2,8,3) + RULE(12,2,3,12,5) + RULE(12,2,4,12,6) + RULE(12,2,5,8,4) + RULE(12,2,6,40,1) + RULE(12,3,3,8,3) + RULE(12,3,4,12,5) + RULE(12,3,5,12,6) + RULE(12,4,3,42,6) + RULE(12,4,4,8,3) + RULE(12,4,5,12,5) + RULE(12,5,3,14,2) + RULE(12,5,4,42,6) + RULE(12,5,5,8,3) + RULE(12,6,3,40,1) + RULE(12,6,4,14,2) + RULE(12,6,5,42,6) + RULE(13,0,3,9,4) + RULE(13,0,4,41,1) + RULE(13,0,5,15,2) + RULE(13,1,3,13,6) + RULE(13,1,4,9,4) + RULE(13,1,5,41,1) + RULE(13,2,3,13,5) + RULE(13,2,4,13,6) + RULE(13,2,5,9,4) + RULE(13,3,3,9,3) + RULE(13,3,4,13,5) + RULE(13,3,5,13,6) + RULE(13,4,3,43,6) + RULE(13,4,4,9,3) + RULE(13,4,5,13,5) + RULE(13,5,3,15,2) + RULE(13,5,4,43,6) + RULE(13,5,5,9,3) + RULE(13,6,3,41,1) + RULE(13,6,4,15,2) + RULE(13,6,5,43,6) + RULE(14,0,3,10,4) + RULE(14,0,4,42,5) + RULE(14,0,5,12,2) + RULE(14,1,3,14,6) + RULE(14,1,4,10,4) + RULE(14,1,5,42,5) + RULE(14,2,0,12,2) + RULE(14,2,3,14,5) + RULE(14,2,4,14,6) + RULE(14,2,5,10,4) + RULE(14,3,3,10,3) + RULE(14,3,4,14,5) + RULE(14,3,5,14,6) + RULE(14,4,3,40,2) + RULE(14,4,4,10,3) + RULE(14,4,5,14,5) + RULE(14,5,3,12,2) + RULE(14,5,4,40,2) + RULE(14,5,5,10,3) + RULE(14,6,3,42,5) + RULE(14,6,4,12,2) + RULE(14,6,5,40,2) + RULE(15,0,3,11,4) + RULE(15,0,4,43,5) + RULE(15,0,5,13,2) + RULE(15,1,3,15,6) + RULE(15,1,4,11,4) + RULE(15,1,5,43,5) + RULE(15,2,3,15,5) + RULE(15,2,4,15,6) + RULE(15,2,5,11,4) + RULE(15,3,3,11,3) + RULE(15,3,4,15,5) + RULE(15,3,5,15,6) + RULE(15,4,3,41,2) + RULE(15,4,4,11,3) + RULE(15,4,5,15,5) + RULE(15,5,3,13,2) + RULE(15,5,4,41,2) + RULE(15,5,5,11,3) + RULE(15,6,3,43,5) + RULE(15,6,4,13,2) + RULE(15,6,5,41,2) + RULE(32,0,3,43,2) + RULE(32,0,4,33,3) + RULE(32,0,5,42,3) + RULE(32,1,3,33,5) + RULE(32,1,4,43,2) + RULE(32,1,5,33,3) + RULE(32,2,3,42,1) + RULE(32,2,4,33,5) + RULE(32,2,5,43,2) + RULE(32,3,3,8,1) + RULE(32,3,4,42,1) + RULE(32,3,5,33,5) + RULE(32,4,3,10,6) + RULE(32,4,4,8,1) + RULE(32,4,5,42,1) + RULE(32,5,3,42,3) + RULE(32,5,4,10,6) + RULE(32,5,5,8,1) + RULE(32,6,3,33,3) + RULE(32,6,4,42,3) + RULE(32,6,5,10,6) + RULE(33,0,3,42,2) + RULE(33,0,4,32,3) + RULE(33,0,5,43,3) + RULE(33,1,3,32,5) + RULE(33,1,4,42,2) + RULE(33,1,5,32,3) + RULE(33,2,3,43,1) + RULE(33,2,4,32,5) + RULE(33,2,5,42,2) + RULE(33,3,3,9,1) + RULE(33,3,4,43,1) + RULE(33,3,5,32,5) + RULE(33,4,3,11,6) + RULE(33,4,4,9,1) + RULE(33,4,5,43,1) + RULE(33,5,3,43,3) + RULE(33,5,4,11,6) + RULE(33,5,5,9,1) + RULE(33,6,3,32,3) + RULE(33,6,4,43,3) + RULE(33,6,5,11,6) + RULE(34,0,3,35,4) + RULE(34,0,4,41,5) + RULE(34,0,5,35,2) + RULE(34,1,3,40,4) + RULE(34,1,4,35,4) + RULE(34,1,5,41,5) + RULE(34,2,3,10,1) + RULE(34,2,4,40,4) + RULE(34,2,5,35,4) + RULE(34,3,3,8,6) + RULE(34,3,4,10,1) + RULE(34,3,5,40,4) + RULE(34,4,3,40,6) + RULE(34,4,4,8,6) + RULE(34,4,5,10,1) + RULE(34,5,3,35,2) + RULE(34,5,4,40,6) + RULE(34,5,5,8,6) + RULE(34,6,3,41,5) + RULE(34,6,4,35,2) + RULE(34,6,5,40,6) + RULE(35,0,3,34,4) + RULE(35,0,4,40,5) + RULE(35,0,5,34,2) + RULE(35,1,3,41,4) + RULE(35,1,4,34,4) + RULE(35,1,5,40,5) + RULE(35,2,3,11,1) + RULE(35,2,4,41,4) + RULE(35,2,5,34,4) + RULE(35,3,3,9,6) + RULE(35,3,4,11,1) + RULE(35,3,5,41,4) + RULE(35,4,3,41,6) + RULE(35,4,4,9,6) + RULE(35,4,5,11,1) + RULE(35,5,3,34,2) + RULE(35,5,4,41,6) + RULE(35,5,5,9,6) + RULE(35,6,3,40,5) + RULE(35,6,4,34,2) + RULE(35,6,5,41,6) + RULE(40,0,3,34,5) + RULE(40,0,4,10,2) + RULE(40,0,5,14,1) + RULE(40,1,3,35,3) + RULE(40,1,4,34,5) + RULE(40,1,5,10,2) + RULE(40,2,3,34,1) + RULE(40,2,4,35,3) + RULE(40,2,5,34,5) + RULE(40,3,3,8,5) + RULE(40,3,4,34,1) + RULE(40,3,5,35,3) + RULE(40,4,3,12,3) + RULE(40,4,4,8,5) + RULE(40,4,5,34,1) + RULE(40,5,3,14,1) + RULE(40,5,4,12,3) + RULE(40,5,5,8,5) + RULE(40,6,3,10,2) + RULE(40,6,4,14,1) + RULE(40,6,5,12,3) + RULE(41,0,3,35,5) + RULE(41,0,4,11,2) + RULE(41,0,5,15,1) + RULE(41,1,3,34,3) + RULE(41,1,4,35,5) + RULE(41,1,5,11,2) + RULE(41,2,3,35,1) + RULE(41,2,4,34,3) + RULE(41,2,5,35,5) + RULE(41,3,3,9,5) + RULE(41,3,4,35,1) + RULE(41,3,5,34,3) + RULE(41,4,3,13,3) + RULE(41,4,4,9,5) + RULE(41,4,5,35,1) + RULE(41,5,3,15,1) + RULE(41,5,4,13,3) + RULE(41,5,5,9,5) + RULE(41,6,3,11,2) + RULE(41,6,4,15,1) + RULE(41,6,5,13,3) + RULE(42,0,3,10,5) + RULE(42,0,4,32,2) + RULE(42,0,5,33,4) + RULE(42,1,3,14,3) + RULE(42,1,4,10,5) + RULE(42,1,5,32,2) + RULE(42,2,3,12,1) + RULE(42,2,4,14,3) + RULE(42,2,5,10,5) + RULE(42,3,3,8,2) + RULE(42,3,4,12,1) + RULE(42,3,5,14,3) + RULE(42,4,3,32,6) + RULE(42,4,4,8,2) + RULE(42,4,5,12,1) + RULE(42,5,3,33,4) + RULE(42,5,4,32,6) + RULE(42,5,5,8,2) + RULE(42,6,3,32,2) + RULE(42,6,4,33,4) + RULE(42,6,5,32,6) + RULE(43,0,3,11,5) + RULE(43,0,4,33,2) + RULE(43,0,5,32,4) + RULE(43,1,3,15,3) + RULE(43,1,4,11,5) + RULE(43,1,5,33,2) + RULE(43,2,3,13,1) + RULE(43,2,4,15,3) + RULE(43,2,5,11,5) + RULE(43,3,3,9,2) + RULE(43,3,4,13,1) + RULE(43,3,5,15,3) + RULE(43,4,3,33,6) + RULE(43,4,4,9,2) + RULE(43,4,5,13,1) + RULE(43,5,3,32,4) + RULE(43,5,4,33,6) + RULE(43,5,5,9,2) + RULE(43,6,3,33,2) + RULE(43,6,4,32,4) + RULE(43,6,5,33,6) + + #undef RULE + + printf("HEPTAGONAL RULE MISSING for (%d,%d)\n", parent,dir); + exit(1); + } + +// calculate the emeraldvalue of a hexagonal cell, +// based on the emeraldvalues of the neighbor heptacells. +int emerald_hexagon(int a, int b, int c) { + // pick the lexicographically smallest representation of the cycle + if(b <= a || c +#endif +#endif + +#ifndef MOBILE +#ifdef GL +#ifdef MAC +#include +#include +#else +#include +#include +#endif + +#ifdef MAC +#include +#else +#include +#endif +#endif +#endif + +#ifdef ANDROID +#ifndef FAKE +#ifdef GL +#include +#include +#include +#endif +#endif +#endif + +#define QHPC 16000 int qhpc, prehpc; @@ -85,6 +119,15 @@ void initPolyForGL() { #ifdef GL #endif +#define POLYMAX 60000 +int polyi; + +#ifdef MOBILE +short polyx[POLYMAX], polyy[POLYMAX]; +#else +Sint16 polyx[POLYMAX], polyxr[POLYMAX], polyy[POLYMAX]; +#endif + void drawqueue() { #ifdef USEPOLY @@ -264,27 +307,64 @@ void drawqueue() { } hpcshape - shFloor[2], shBFloor[2], shMFloor2[2], shWall[2], - shStarFloor[2], shCloudFloor[2], shTriFloor[2], + shFloor[2], shBFloor[2], shMFloor2[2], shMFloor3[2], shMFloor4[2], + shWall[2], shMineMark[2], + shStarFloor[2], shCloudFloor[2], shTriFloor[2], shZebra[4], shTower[7], + shEmeraldFloor[6], shFeatherFloor[2], shDemonFloor[2], shCrossFloor[2], shMFloor[2], shCaveFloor[2], shSemiFeatherFloor[2], shPowerFloor[2], shSemiFloor[2], shSemiBFloor[2], - shDesertFloor[2], + shDesertFloor[2], shRedRockFloor[3][2], shCross, shGiantStar[2], shLake, shMirror, shGem[2], shStar, shDisk, shRing, shDaisy, shTriangle, shNecro, shStatue, shKey, + shFigurine, + shElementalShard, shBranch, shIBranch, shTentacle, shTentacleX, shILeaf[2], shMovestar, - shWolf, shYeti, shDemon, shGDemon, shEagle, - shPBody, shPSword, shPHead, shPFace, shGolemhead, shHood, shArmor, + shWolf, shYeti, shDemon, shGDemon, shEagle, shGargoyleWings, shGargoyleBody, + shWolf1, shWolf2, shWolf3, + shDogStripes, + shPBody, shPSword, shPKnife, + shPHead, shPFace, shGolemhead, shHood, shArmor, + shSabre, shTurban1, shTurban2, shVikingHelmet, shKnightArmor, shKnightCloak, shGhost, shEyes, shSlime, shJoint, shWormHead, shTentHead, shShark, - shUser[8][3], shHedgehogBlade, shHedgehogBladePlayer, + shHedgehogBlade, shHedgehogBladePlayer, shWolfBody, shWolfHead, shWolfLegs, shWolfEyes, - shBigHepta, shBigTriangle, + shBigHepta, shBigTriangle, shBigHex, shBigHexTriangle, shBigHexTriangleRev, shFemaleBody, shFemaleHair, shFemaleDress, shWitchDress, shBugBody, shBugArmor, shPickAxe, shPike, shFlailBall, shFlailTrunk, shFlailChain, - shBook, shBookCover, shGrail; + shBook, shBookCover, shGrail, + shBoatOuter, shBoatInner, shCompass1, shCompass2, shCompass3, + shKnife, shTongue, shFlailMissile, + shPirateHook, shPirateHood, shEyepatch, shPirateX, + shScratch, shHeptaMarker, + shSkeletonBody, shSkull, shSkullEyes, shFatBody, shWaterElemental, + shPalaceFloor[2], shNewFloor[2], shPalaceGate, shFishTail, + shMouse, shMouseLegs, shMouseEyes, + shPrincessDress, shPrinceDress, + shBigCarpet1, shBigCarpet2, shBigCarpet3, + shGoatHead; + +#define USERLAYERS 8 +#define USERSHAPEGROUPS 8 +#define USERSHAPEIDS 256 + +struct usershapelayer { + vector list; + bool sym; + int rots; + int color; + hyperpoint shift, spin; + hpcshape sh; + }; + +struct usershape { + usershapelayer d[USERLAYERS]; + }; + +usershape *usershapes[USERSHAPEGROUPS][USERSHAPEIDS]; void drawTentacle(hpcshape &h, ld rad, ld var, ld divby) { for(int i=0; i<=20; i++) @@ -378,6 +458,17 @@ void bshape(hpcshape& sh, int p) { first = true; } +void zoomShape(hpcshape& old, hpcshape& newsh, double factor, int lev) { + + bshape(newsh, lev); + for(int i=old.s; ie = qhpc; last = NULL; @@ -834,6 +925,76 @@ void buildpolys() { hpcpush(hpxyz(-0.118344,0.338747,1.062429)); hpcpush(hpxyz(-0.097861,0.337622,1.059984)); + bshape(shNewFloor[0], 10); + hpcpush(hpxyz(-0.243151,-0.202057,1.048785)); + hpcpush(hpxyz(-0.249456,-0.026167,1.030977)); + hpcpush(hpxyz(-0.208097,0.124704,1.029007)); + hpcpush(hpxyz(-0.053410,0.311604,1.048785)); + hpcpush(hpxyz(0.102066,0.229119,1.030977)); + hpcpush(hpxyz(0.212045,0.117865,1.029007)); + hpcpush(hpxyz(0.296562,-0.109547,1.048785)); + hpcpush(hpxyz(0.147390,-0.202952,1.030977)); + hpcpush(hpxyz(-0.003949,-0.242569,1.029007)); + hpcpush(hpxyz(-0.243151,-0.202057,1.048785)); + + bshape(shNewFloor[1], 10); + hpcpush(hpxyz(-0.343473,0.068811,1.059580)); + hpcpush(hpxyz(-0.371524,0.213003,1.087842)); + hpcpush(hpxyz(-0.243649,0.253621,1.060042)); + hpcpush(hpxyz(-0.160353,0.311441,1.059580)); + hpcpush(hpxyz(-0.065108,0.423274,1.087842)); + hpcpush(hpxyz(0.046377,0.348623,1.060042)); + hpcpush(hpxyz(0.143516,0.319550,1.059580)); + hpcpush(hpxyz(0.290335,0.314811,1.087842)); + hpcpush(hpxyz(0.301479,0.181104,1.060042)); + hpcpush(hpxyz(0.339315,0.087031,1.059580)); + hpcpush(hpxyz(0.427150,-0.030712,1.087842)); + hpcpush(hpxyz(0.329562,-0.122790,1.060042)); + hpcpush(hpxyz(0.279603,-0.211024,1.059580)); + hpcpush(hpxyz(0.242312,-0.353108,1.087842)); + hpcpush(hpxyz(0.109478,-0.334220,1.060042)); + hpcpush(hpxyz(0.009344,-0.350173,1.059580)); + hpcpush(hpxyz(-0.124991,-0.409606,1.087842)); + hpcpush(hpxyz(-0.193046,-0.293976,1.060042)); + hpcpush(hpxyz(-0.267951,-0.225635,1.059580)); + hpcpush(hpxyz(-0.398174,-0.157663,1.087842)); + hpcpush(hpxyz(-0.350202,-0.032362,1.060042)); + hpcpush(hpxyz(-0.343473,0.068811,1.059580)); + + // group 0 layer 0 + + bshape(shPalaceFloor[0], 10); + hpcpush(hpxyz(0.118361,0.205152,1.027666)); + hpcpush(hpxyz(0.273318,0.190450,1.054028)); + hpcpush(hpxyz(0.273318,-0.190450,1.054028)); + hpcpush(hpxyz(0.118361,-0.205152,1.027666)); + hpcpush(hpxyz(0.118486,-0.205080,1.027666)); + hpcpush(hpxyz(0.028276,-0.331925,1.054028)); + hpcpush(hpxyz(-0.301594,-0.141475,1.054028)); + hpcpush(hpxyz(-0.236847,0.000072,1.027666)); + hpcpush(hpxyz(-0.236847,-0.000072,1.027666)); + hpcpush(hpxyz(-0.301594,0.141475,1.054028)); + hpcpush(hpxyz(0.028276,0.331925,1.054028)); + hpcpush(hpxyz(0.118486,0.205080,1.027666)); + hpcpush(hpxyz(0.118361,0.205152,1.027666)); + + bshape(shPalaceFloor[1], 10); + hpcpush(hpxyz(-0.225907,0.287688,1.064800)); + hpcpush(hpxyz(0.084073,0.355992,1.064800)); + hpcpush(hpxyz(0.330745,0.156227,1.064800)); + hpcpush(hpxyz(0.328359,-0.161181,1.064800)); + hpcpush(hpxyz(0.078712,-0.357216,1.064800)); + hpcpush(hpxyz(-0.230206,-0.284260,1.064800)); + hpcpush(hpxyz(-0.365775,0.002749,1.064800)); + hpcpush(hpxyz(-0.225907,0.287688,1.064800)); + + bshape(shPalaceGate, 13); + hpcpush(hpxyz(-0.219482,-0.025012,1.024108)); + hpcpush(hpxyz(0.135153,-0.049012,1.010281)); + hpcpush(hpxyz(0.135153,0.049012,1.010281)); + hpcpush(hpxyz(-0.219482,0.025012,1.024108)); + hpcpush(hpxyz(-0.219482,-0.025012,1.024108)); + bshape(shSemiFeatherFloor[0], 10); hpcpush(hpxyz(-0.213723,0.142000,1.032396)); hpcpush(hpxyz(-0.217805,0.186740,1.040342)); @@ -1330,7 +1491,7 @@ void buildpolys() { hpcpush(hpxyz(-0.167602,0.109998,1.019897)); hpcpush(hpxyz(-0.121700,0.283485,1.046506)); hpcpush(hpxyz(-0.122282,0.287492,1.047666)); - + bshape(shDesertFloor[1], 10); hpcpush(hpxyz(-0.336141,-0.153280,1.066061)); hpcpush(hpxyz(-0.336530,-0.140779,1.064458)); @@ -1403,7 +1564,7 @@ void buildpolys() { hpcpush(hpxyz(-0.319889,-0.175335,1.064458)); hpcpush(hpxyz(-0.329419,-0.167237,1.066061)); hpcpush(hpxyz(-0.336141,-0.153280,1.066061)); - + bshape(shFloor[0], 11); for(int t=0; t<=6; t++) hpcpush(ddi(7 + t*14, hexf*.8) * C0); @@ -1427,10 +1588,40 @@ void buildpolys() { bshape(shMFloor2[1], 13); for(int t=0; t<=7; t++) hpcpush(ddi(t*12, hexf*.7) * C0); - bshape(shBFloor[0], 14); + bshape(shMFloor3[0], 14); + for(int t=0; t<=6; t++) hpcpush(ddi(7 + t*14, hexf*.5) * C0); + + bshape(shMFloor3[1], 14); + for(int t=0; t<=7; t++) hpcpush(ddi(t*12, hexf*.6) * C0); + + bshape(shMFloor4[0], 15); + for(int t=0; t<=6; t++) hpcpush(ddi(7 + t*14, hexf*.4) * C0); + + bshape(shMFloor4[1], 15); + for(int t=0; t<=7; t++) hpcpush(ddi(t*12, hexf*.5) * C0); + + bshape(shBigCarpet1, 14); +//for(int t=0; t<=7; t++) hpcpush(ddi(t*12, -hexf*3.5) * C0); + for(int t=0; t<=7; t++) hpcpush(ddi(t*12, -hexf*2.1) * C0); + + bshape(shBigCarpet2, 15); +//for(int t=0; t<=7; t++) hpcpush(ddi(t*12, -hexf*3.4) * C0); + for(int t=0; t<=7; t++) hpcpush(ddi(t*12, -hexf*1.9) * C0); + + bshape(shBigCarpet3, 16); +//for(int t=0; t<=7; t++) hpcpush(ddi(t*12, -hexf*3.4) * C0); + for(int t=0; t<=7; t++) hpcpush(ddi(t*12*3, -hexf*1.7) * C0); + + bshape(shBFloor[0], 16); for(int t=0; t<=6; t++) hpcpush(ddi(7 + t*14, hexf*.1) * C0); - bshape(shBFloor[1], 14); + bshape(shBFloor[1], 16); + for(int t=0; t<=7; t++) hpcpush(ddi(t*12, hexf*.1) * C0); + + bshape(shMineMark[0], 50); + for(int t=0; t<=6; t++) hpcpush(ddi(7 + t*14, hexf*.1) * C0); + + bshape(shMineMark[1], 50); for(int t=0; t<=7; t++) hpcpush(ddi(t*12, hexf*.1) * C0); for(int d=0; d<2; d++) { @@ -1515,6 +1706,114 @@ void buildpolys() { bshape(shGem[1], 21); for(int t=0; t<=7; t++) hpcpush(ddi(t*36, hexf*.5) * C0); + bshape(shElementalShard, 21); + hpcpush(hpxyz(-0.345978,0.004270,1.058168)); + hpcpush(hpxyz(-0.054981,0.027419,1.001886)); + hpcpush(hpxyz(-0.063949,0.034031,1.002620)); + hpcpush(hpxyz(-0.078659,0.057318,1.004725)); + hpcpush(hpxyz(-0.103108,0.086449,1.009012)); + hpcpush(hpxyz(-0.130880,0.100059,1.013480)); + hpcpush(hpxyz(-0.157829,0.107491,1.018069)); + hpcpush(hpxyz(-0.173912,0.106860,1.020620)); + hpcpush(hpxyz(-0.191566,0.100397,1.023121)); + hpcpush(hpxyz(-0.200633,0.095930,1.024430)); + hpcpush(hpxyz(-0.216136,0.090593,1.027094)); + hpcpush(hpxyz(-0.200642,0.111259,1.025980)); + hpcpush(hpxyz(-0.173354,0.128719,1.023045)); + hpcpush(hpxyz(-0.141916,0.144399,1.020290)); + hpcpush(hpxyz(-0.106497,0.138938,1.015207)); + hpcpush(hpxyz(-0.079427,0.124373,1.010830)); + hpcpush(hpxyz(-0.053552,0.106563,1.007087)); + hpcpush(hpxyz(-0.030995,0.078798,1.003579)); + hpcpush(hpxyz(-0.024668,0.068596,1.002653)); + hpcpush(hpxyz(-0.027285,0.085742,1.004040)); + hpcpush(hpxyz(-0.033561,0.111171,1.006720)); + hpcpush(hpxyz(-0.036750,0.137167,1.010032)); + hpcpush(hpxyz(-0.035531,0.165577,1.014238)); + hpcpush(hpxyz(-0.023882,0.199023,1.019892)); + hpcpush(hpxyz(-0.002982,0.230118,1.026140)); + hpcpush(hpxyz(0.021321,0.244715,1.029728)); + hpcpush(hpxyz(0.012442,0.234213,1.027137)); + hpcpush(hpxyz(-0.002073,0.208126,1.021431)); + hpcpush(hpxyz(-0.005433,0.188040,1.017540)); + hpcpush(hpxyz(-0.004352,0.170363,1.014417)); + hpcpush(hpxyz(0.001158,0.155057,1.011951)); + hpcpush(hpxyz(0.002408,0.141554,1.009972)); + hpcpush(hpxyz(0.008798,0.125672,1.007904)); + hpcpush(hpxyz(0.018292,0.110314,1.006232)); + hpcpush(hpxyz(0.026174,0.100337,1.005362)); + hpcpush(hpxyz(0.176687,0.297491,1.058168)); + hpcpush(hpxyz(0.051236,0.033906,1.001886)); + hpcpush(hpxyz(0.061446,0.038366,1.002620)); + hpcpush(hpxyz(0.088968,0.039461,1.004725)); + hpcpush(hpxyz(0.126421,0.046070,1.009012)); + hpcpush(hpxyz(0.152094,0.063316,1.013480)); + hpcpush(hpxyz(0.172004,0.082938,1.018069)); + hpcpush(hpxyz(0.179499,0.097182,1.020620)); + hpcpush(hpxyz(0.182729,0.115702,1.023121)); + hpcpush(hpxyz(0.183395,0.125788,1.024430)); + hpcpush(hpxyz(0.186524,0.141882,1.027094)); + hpcpush(hpxyz(0.196674,0.118132,1.025980)); + hpcpush(hpxyz(0.198151,0.085770,1.023045)); + hpcpush(hpxyz(0.196011,0.050703,1.020290)); + hpcpush(hpxyz(0.173572,0.022760,1.015207)); + hpcpush(hpxyz(0.147423,0.006599,1.010830)); + hpcpush(hpxyz(0.119062,-0.006904,1.007087)); + hpcpush(hpxyz(0.083739,-0.012556,1.003579)); + hpcpush(hpxyz(0.071740,-0.012935,1.002653)); + hpcpush(hpxyz(0.087898,-0.019242,1.004040)); + hpcpush(hpxyz(0.113057,-0.026521,1.006720)); + hpcpush(hpxyz(0.137165,-0.036757,1.010032)); + hpcpush(hpxyz(0.161159,-0.052018,1.014238)); + hpcpush(hpxyz(0.184300,-0.078830,1.019892)); + hpcpush(hpxyz(0.200779,-0.112477,1.026140)); + hpcpush(hpxyz(0.201269,-0.140822,1.029728)); + hpcpush(hpxyz(0.196613,-0.127882,1.027137)); + hpcpush(hpxyz(0.181278,-0.102268,1.021431)); + hpcpush(hpxyz(0.165564,-0.089315,1.017540)); + hpcpush(hpxyz(0.149715,-0.081413,1.014417)); + hpcpush(hpxyz(0.133704,-0.078531,1.011951)); + hpcpush(hpxyz(0.121386,-0.072862,1.009972)); + hpcpush(hpxyz(0.104436,-0.070455,1.007904)); + hpcpush(hpxyz(0.086388,-0.070998,1.006232)); + hpcpush(hpxyz(0.073808,-0.072835,1.005362)); + hpcpush(hpxyz(0.169291,-0.301761,1.058168)); + hpcpush(hpxyz(0.003745,-0.061325,1.001886)); + hpcpush(hpxyz(0.002503,-0.072397,1.002620)); + hpcpush(hpxyz(-0.010310,-0.096779,1.004725)); + hpcpush(hpxyz(-0.023313,-0.132518,1.009012)); + hpcpush(hpxyz(-0.021214,-0.163375,1.013480)); + hpcpush(hpxyz(-0.014176,-0.190429,1.018069)); + hpcpush(hpxyz(-0.005587,-0.204042,1.020620)); + hpcpush(hpxyz(0.008837,-0.216099,1.023121)); + hpcpush(hpxyz(0.017239,-0.221719,1.024430)); + hpcpush(hpxyz(0.029612,-0.232476,1.027094)); + hpcpush(hpxyz(0.003968,-0.229391,1.025980)); + hpcpush(hpxyz(-0.024797,-0.214489,1.023045)); + hpcpush(hpxyz(-0.054095,-0.195102,1.020290)); + hpcpush(hpxyz(-0.067075,-0.161698,1.015207)); + hpcpush(hpxyz(-0.067996,-0.130972,1.010830)); + hpcpush(hpxyz(-0.065511,-0.099659,1.007087)); + hpcpush(hpxyz(-0.052744,-0.066242,1.003579)); + hpcpush(hpxyz(-0.047072,-0.055661,1.002653)); + hpcpush(hpxyz(-0.060613,-0.066501,1.004040)); + hpcpush(hpxyz(-0.079496,-0.084650,1.006720)); + hpcpush(hpxyz(-0.100415,-0.100410,1.010032)); + hpcpush(hpxyz(-0.125628,-0.113559,1.014238)); + hpcpush(hpxyz(-0.160419,-0.120194,1.019892)); + hpcpush(hpxyz(-0.197797,-0.117641,1.026140)); + hpcpush(hpxyz(-0.222590,-0.103893,1.029728)); + hpcpush(hpxyz(-0.209056,-0.106331,1.027137)); + hpcpush(hpxyz(-0.179206,-0.105858,1.021431)); + hpcpush(hpxyz(-0.160131,-0.098725,1.017540)); + hpcpush(hpxyz(-0.145363,-0.088950,1.014417)); + hpcpush(hpxyz(-0.134862,-0.076526,1.011951)); + hpcpush(hpxyz(-0.123793,-0.068692,1.009972)); + hpcpush(hpxyz(-0.113234,-0.055216,1.007904)); + hpcpush(hpxyz(-0.104681,-0.039315,1.006232)); + hpcpush(hpxyz(-0.099981,-0.027501,1.005362)); + hpcpush(hpxyz(-0.345978,0.004270,1.058168)); + bshape(shStar, 21); for(int t=0; t<84; t+=6) { hpcpush(ddi(t, hexf*.2) * C0); @@ -1532,6 +1831,19 @@ void buildpolys() { hpcpush(ddi(i, crossf * .30) * C0); hpcpush(ddi(0, crossf * .25) * C0); + bshape(shCompass1, 21); + for(int i=0; i<=84; i+=3) + hpcpush(ddi(i, crossf * .35) * C0); + + bshape(shCompass2, 22); + for(int i=0; i<=84; i+=3) + hpcpush(ddi(i, crossf * .3) * C0); + + bshape(shCompass3, 23); + hpcpush(ddi(0, crossf * .29) * C0); + hpcpush(ddi(21, crossf * .04) * C0); + hpcpush(ddi(-21, crossf * .04) * C0); + bshape(shNecro, 21); hpcpush(hpxyz(-0.280120,0.002558,1.038496)); hpcpush(hpxyz(-0.252806,0.037921,1.032157)); @@ -1579,6 +1891,29 @@ void buildpolys() { hpcpush(hpxyz(-0.280120,-0.002558,1.038496)); hpcpush(hpxyz(-0.280120,0.002558,1.038496)); + bshape(shFigurine, 21); + hpcpush(hpxyz(-0.105008,0.082180,1.008851)); + hpcpush(hpxyz(-0.018191,0.040930,1.001003)); + hpcpush(hpxyz(-0.011407,0.123195,1.007625)); + hpcpush(hpxyz(0.041081,0.123243,1.008403)); + hpcpush(hpxyz(0.040941,0.038667,1.001584)); + hpcpush(hpxyz(0.070555,0.027312,1.002858)); + hpcpush(hpxyz(0.086601,0.059253,1.005490)); + hpcpush(hpxyz(0.134876,0.073153,1.011703)); + hpcpush(hpxyz(0.190524,0.064273,1.020015)); + hpcpush(hpxyz(0.211472,0.036778,1.022777)); + hpcpush(hpxyz(0.211472,-0.036778,1.022777)); + hpcpush(hpxyz(0.190524,-0.064273,1.020015)); + hpcpush(hpxyz(0.134876,-0.073153,1.011703)); + hpcpush(hpxyz(0.086601,-0.059253,1.005490)); + hpcpush(hpxyz(0.070555,-0.027312,1.002858)); + hpcpush(hpxyz(0.040941,-0.038667,1.001584)); + hpcpush(hpxyz(0.041081,-0.123243,1.008403)); + hpcpush(hpxyz(-0.011407,-0.123195,1.007625)); + hpcpush(hpxyz(-0.018191,-0.040930,1.001003)); + hpcpush(hpxyz(-0.105008,-0.082180,1.008851)); + hpcpush(hpxyz(-0.105008,0.082180,1.008851)); + bshape(shStatue, 21); hpcpush(hpxyz(-0.047663,0.032172,1.001652)); hpcpush(hpxyz(-0.047670,0.034561,1.001732)); @@ -1867,6 +2202,10 @@ void buildpolys() { hpcpush(hpxyz(-0.280212,-0.017913,1.038672)); hpcpush(hpxyz(-0.280212,-0.017913,1.038672)); + for(int i=1; i<=3; i++) for(int j=0; j<2; j++) { + zoomShape(shDesertFloor[j], shRedRockFloor[i-1][j], 1 - .1 * i, 11+i); + } + // monsters bshape(shTentacleX, 31); @@ -1968,7 +2307,223 @@ void buildpolys() { bshape(shILeaf[1], 33); for(int t=0; t<=7; t++) hpcpush(ddi(t*36, hexf*.8) * C0); + bshape(shGargoyleWings, 34); + hpcpush(hpxyz(0.042241,0.002223,1.000894)); + hpcpush(hpxyz(0.041129,-0.007781,1.000876)); + hpcpush(hpxyz(0.045593,-0.034473,1.001632)); + hpcpush(hpxyz(0.066799,-0.059006,1.003964)); + hpcpush(hpxyz(0.116090,-0.071440,1.009247)); + hpcpush(hpxyz(0.169203,-0.075077,1.016989)); + hpcpush(hpxyz(0.154517,-0.085096,1.015439)); + hpcpush(hpxyz(0.124220,-0.116387,1.014385)); + hpcpush(hpxyz(0.104146,-0.144461,1.015734)); + hpcpush(hpxyz(0.082994,-0.176082,1.018770)); + hpcpush(hpxyz(0.049446,-0.209023,1.022808)); + hpcpush(hpxyz(0.004505,-0.235397,1.027342)); + hpcpush(hpxyz(-0.039494,-0.248247,1.031109)); + hpcpush(hpxyz(-0.071220,-0.256618,1.034855)); + hpcpush(hpxyz(-0.116784,-0.264180,1.040879)); + hpcpush(hpxyz(-0.160337,-0.264954,1.046857)); + hpcpush(hpxyz(-0.177592,-0.262973,1.049140)); + hpcpush(hpxyz(-0.159002,-0.255539,1.044309)); + hpcpush(hpxyz(-0.137018,-0.243463,1.038291)); + hpcpush(hpxyz(-0.124173,-0.222383,1.031927)); + hpcpush(hpxyz(-0.128481,-0.203992,1.028650)); + hpcpush(hpxyz(-0.160238,-0.194091,1.031188)); + hpcpush(hpxyz(-0.184305,-0.194482,1.035274)); + hpcpush(hpxyz(-0.160187,-0.190645,1.030536)); + hpcpush(hpxyz(-0.117943,-0.174106,1.021872)); + hpcpush(hpxyz(-0.108751,-0.156961,1.018069)); + hpcpush(hpxyz(-0.107466,-0.136571,1.014988)); + hpcpush(hpxyz(-0.120870,-0.120870,1.014504)); + hpcpush(hpxyz(-0.143330,-0.104138,1.015573)); + hpcpush(hpxyz(-0.156871,-0.097484,1.016913)); + hpcpush(hpxyz(-0.143266,-0.095138,1.014680)); + hpcpush(hpxyz(-0.119536,-0.087138,1.010882)); + hpcpush(hpxyz(-0.103741,-0.071392,1.007898)); + hpcpush(hpxyz(-0.091360,-0.051251,1.005472)); + hpcpush(hpxyz(-0.083500,-0.032287,1.003999)); + hpcpush(hpxyz(-0.077900,-0.015580,1.003151)); + hpcpush(hpxyz(-0.077900,0.015580,1.003151)); + hpcpush(hpxyz(-0.083500,0.032287,1.003999)); + hpcpush(hpxyz(-0.091360,0.051251,1.005472)); + hpcpush(hpxyz(-0.103741,0.071392,1.007898)); + hpcpush(hpxyz(-0.119536,0.087138,1.010882)); + hpcpush(hpxyz(-0.143266,0.095138,1.014680)); + hpcpush(hpxyz(-0.156871,0.097484,1.016913)); + hpcpush(hpxyz(-0.143330,0.104138,1.015573)); + hpcpush(hpxyz(-0.120870,0.120870,1.014504)); + hpcpush(hpxyz(-0.107466,0.136571,1.014988)); + hpcpush(hpxyz(-0.108751,0.156961,1.018069)); + hpcpush(hpxyz(-0.117943,0.174106,1.021872)); + hpcpush(hpxyz(-0.160187,0.190645,1.030536)); + hpcpush(hpxyz(-0.184305,0.194482,1.035274)); + hpcpush(hpxyz(-0.160238,0.194091,1.031188)); + hpcpush(hpxyz(-0.128481,0.203992,1.028650)); + hpcpush(hpxyz(-0.124173,0.222383,1.031927)); + hpcpush(hpxyz(-0.137018,0.243463,1.038291)); + hpcpush(hpxyz(-0.159002,0.255539,1.044309)); + hpcpush(hpxyz(-0.177592,0.262973,1.049140)); + hpcpush(hpxyz(-0.160337,0.264954,1.046857)); + hpcpush(hpxyz(-0.116784,0.264180,1.040879)); + hpcpush(hpxyz(-0.071220,0.256618,1.034855)); + hpcpush(hpxyz(-0.039494,0.248247,1.031109)); + hpcpush(hpxyz(0.004505,0.235397,1.027342)); + hpcpush(hpxyz(0.049446,0.209023,1.022808)); + hpcpush(hpxyz(0.082994,0.176082,1.018770)); + hpcpush(hpxyz(0.104146,0.144461,1.015734)); + hpcpush(hpxyz(0.124220,0.116387,1.014385)); + hpcpush(hpxyz(0.154517,0.085096,1.015439)); + hpcpush(hpxyz(0.169203,0.075077,1.016989)); + hpcpush(hpxyz(0.116090,0.071440,1.009247)); + hpcpush(hpxyz(0.066799,0.059006,1.003964)); + hpcpush(hpxyz(0.045593,0.034473,1.001632)); + hpcpush(hpxyz(0.041129,0.007781,1.000876)); + hpcpush(hpxyz(0.042241,-0.002223,1.000894)); + hpcpush(hpxyz(0.042241,0.002223,1.000894)); + + bshape(shGargoyleBody, 33); + hpcpush(hpxyz(0.128302,-0.002231,1.008200)); + hpcpush(hpxyz(0.128305,-0.010041,1.008247)); + hpcpush(hpxyz(0.136196,-0.021211,1.009455)); + hpcpush(hpxyz(0.146366,-0.031284,1.011139)); + hpcpush(hpxyz(0.164504,-0.042525,1.014332)); + hpcpush(hpxyz(0.161107,-0.043633,1.013834)); + hpcpush(hpxyz(0.143009,-0.042456,1.011066)); + hpcpush(hpxyz(0.127212,-0.033477,1.008615)); + hpcpush(hpxyz(0.114839,-0.025644,1.006899)); + hpcpush(hpxyz(0.108151,-0.046828,1.006921)); + hpcpush(hpxyz(0.094666,-0.021161,1.004694)); + hpcpush(hpxyz(0.081255,-0.022262,1.003543)); + hpcpush(hpxyz(0.068979,-0.022251,1.002623)); + hpcpush(hpxyz(0.057838,-0.028919,1.002089)); + hpcpush(hpxyz(0.082541,-0.093696,1.007766)); + hpcpush(hpxyz(0.108462,-0.117407,1.012694)); + hpcpush(hpxyz(0.080377,-0.111634,1.009417)); + hpcpush(hpxyz(0.074909,-0.139757,1.012494)); + hpcpush(hpxyz(0.066894,-0.095881,1.006811)); + hpcpush(hpxyz(0.056798,-0.077958,1.004641)); + hpcpush(hpxyz(0.043402,-0.066772,1.003166)); + hpcpush(hpxyz(0.031144,-0.056726,1.002092)); + hpcpush(hpxyz(0.011119,-0.053373,1.001485)); + hpcpush(hpxyz(-0.024478,-0.070096,1.002753)); + hpcpush(hpxyz(-0.007782,-0.046693,1.001120)); + hpcpush(hpxyz(-0.062361,-0.071270,1.004474)); + hpcpush(hpxyz(-0.041154,-0.050052,1.002097)); + hpcpush(hpxyz(-0.097005,-0.068015,1.006994)); + hpcpush(hpxyz(-0.066772,-0.043402,1.003166)); + hpcpush(hpxyz(-0.120555,-0.063626,1.009248)); + hpcpush(hpxyz(-0.092454,-0.038987,1.005021)); + hpcpush(hpxyz(-0.144240,-0.068206,1.012649)); + hpcpush(hpxyz(-0.151438,-0.125638,1.019175)); + hpcpush(hpxyz(-0.186951,-0.141902,1.027174)); + hpcpush(hpxyz(-0.209987,-0.145636,1.032136)); + hpcpush(hpxyz(-0.230971,-0.155113,1.037983)); + hpcpush(hpxyz(-0.216796,-0.137756,1.032462)); + hpcpush(hpxyz(-0.243372,-0.131308,1.037531)); + hpcpush(hpxyz(-0.209646,-0.120603,1.028833)); + hpcpush(hpxyz(-0.188968,-0.119230,1.024658)); + hpcpush(hpxyz(-0.167228,-0.113356,1.020203)); + hpcpush(hpxyz(-0.164543,-0.052609,1.014811)); + hpcpush(hpxyz(-0.121573,-0.023422,1.007635)); + hpcpush(hpxyz(-0.142949,-0.011168,1.010227)); + hpcpush(hpxyz(-0.187169,-0.007845,1.017396)); + hpcpush(hpxyz(-0.243507,-0.003382,1.029226)); + hpcpush(hpxyz(-0.243507,0.003382,1.029226)); + hpcpush(hpxyz(-0.187169,0.007845,1.017396)); + hpcpush(hpxyz(-0.142949,0.011168,1.010227)); + hpcpush(hpxyz(-0.121573,0.023422,1.007635)); + hpcpush(hpxyz(-0.164543,0.052609,1.014811)); + hpcpush(hpxyz(-0.167228,0.113356,1.020203)); + hpcpush(hpxyz(-0.188968,0.119230,1.024658)); + hpcpush(hpxyz(-0.209646,0.120603,1.028833)); + hpcpush(hpxyz(-0.243372,0.131308,1.037531)); + hpcpush(hpxyz(-0.216796,0.137756,1.032462)); + hpcpush(hpxyz(-0.230971,0.155113,1.037983)); + hpcpush(hpxyz(-0.209987,0.145636,1.032136)); + hpcpush(hpxyz(-0.186951,0.141902,1.027174)); + hpcpush(hpxyz(-0.151438,0.125638,1.019175)); + hpcpush(hpxyz(-0.144240,0.068206,1.012649)); + hpcpush(hpxyz(-0.092454,0.038987,1.005021)); + hpcpush(hpxyz(-0.120555,0.063626,1.009248)); + hpcpush(hpxyz(-0.066772,0.043402,1.003166)); + hpcpush(hpxyz(-0.097005,0.068015,1.006994)); + hpcpush(hpxyz(-0.041154,0.050052,1.002097)); + hpcpush(hpxyz(-0.062361,0.071270,1.004474)); + hpcpush(hpxyz(-0.007782,0.046693,1.001120)); + hpcpush(hpxyz(-0.024478,0.070096,1.002753)); + hpcpush(hpxyz(0.011119,0.053373,1.001485)); + hpcpush(hpxyz(0.031144,0.056726,1.002092)); + hpcpush(hpxyz(0.043402,0.066772,1.003166)); + hpcpush(hpxyz(0.056798,0.077958,1.004641)); + hpcpush(hpxyz(0.066894,0.095881,1.006811)); + hpcpush(hpxyz(0.074909,0.139757,1.012494)); + hpcpush(hpxyz(0.080377,0.111634,1.009417)); + hpcpush(hpxyz(0.108462,0.117407,1.012694)); + hpcpush(hpxyz(0.082541,0.093696,1.007766)); + hpcpush(hpxyz(0.057838,0.028919,1.002089)); + hpcpush(hpxyz(0.068979,0.022251,1.002623)); + hpcpush(hpxyz(0.081255,0.022262,1.003543)); + hpcpush(hpxyz(0.094666,0.021161,1.004694)); + hpcpush(hpxyz(0.108151,0.046828,1.006921)); + hpcpush(hpxyz(0.114839,0.025644,1.006899)); + hpcpush(hpxyz(0.127212,0.033477,1.008615)); + hpcpush(hpxyz(0.143009,0.042456,1.011066)); + hpcpush(hpxyz(0.161107,0.043633,1.013834)); + hpcpush(hpxyz(0.164504,0.042525,1.014332)); + hpcpush(hpxyz(0.146366,0.031284,1.011139)); + hpcpush(hpxyz(0.136196,0.021211,1.009455)); + hpcpush(hpxyz(0.128305,0.010041,1.008247)); + hpcpush(hpxyz(0.128302,0.002231,1.008200)); + hpcpush(hpxyz(0.128302,-0.002231,1.008200)); + + bshape(shDogStripes, 34); + hpcpush(hpxyz(-0.147497,-0.001105,1.010820)); + hpcpush(hpxyz(-0.159242,0.009400,1.012643)); + hpcpush(hpxyz(-0.153105,0.023214,1.011919)); + hpcpush(hpxyz(-0.135232,0.011039,1.009163)); + hpcpush(hpxyz(-0.110779,0.007165,1.006143)); + hpcpush(hpxyz(-0.119793,0.067901,1.009436)); + hpcpush(hpxyz(-0.099799,0.063959,1.007001)); + hpcpush(hpxyz(-0.090296,0.011012,1.004129)); + hpcpush(hpxyz(-0.047281,0.012095,1.001190)); + hpcpush(hpxyz(-0.058915,0.070478,1.004210)); + hpcpush(hpxyz(-0.041289,0.078174,1.003900)); + hpcpush(hpxyz(-0.021982,0.013189,1.000329)); + hpcpush(hpxyz(0.011539,0.012638,1.000146)); + hpcpush(hpxyz(-0.001651,0.079245,1.003136)); + hpcpush(hpxyz(0.011562,0.089191,1.004036)); + hpcpush(hpxyz(0.034627,0.013741,1.000694)); + hpcpush(hpxyz(0.043979,0.012094,1.001040)); + hpcpush(hpxyz(0.052798,0.032449,1.001918)); + hpcpush(hpxyz(0.058855,0.029703,1.002171)); + hpcpush(hpxyz(0.077053,0.029170,1.003388)); + hpcpush(hpxyz(0.066006,0.005501,1.002191)); + hpcpush(hpxyz(0.066006,-0.005501,1.002191)); + hpcpush(hpxyz(0.077053,-0.029170,1.003388)); + hpcpush(hpxyz(0.058855,-0.029703,1.002171)); + hpcpush(hpxyz(0.052798,-0.032449,1.001918)); + hpcpush(hpxyz(0.043979,-0.012094,1.001040)); + hpcpush(hpxyz(0.034627,-0.013741,1.000694)); + hpcpush(hpxyz(0.011562,-0.089191,1.004036)); + hpcpush(hpxyz(-0.001651,-0.079245,1.003136)); + hpcpush(hpxyz(0.011539,-0.012638,1.000146)); + hpcpush(hpxyz(-0.021982,-0.013189,1.000329)); + hpcpush(hpxyz(-0.041289,-0.078174,1.003900)); + hpcpush(hpxyz(-0.058915,-0.070478,1.004210)); + hpcpush(hpxyz(-0.047281,-0.012095,1.001190)); + hpcpush(hpxyz(-0.090296,-0.011012,1.004129)); + hpcpush(hpxyz(-0.099799,-0.063959,1.007001)); + hpcpush(hpxyz(-0.119793,-0.067901,1.009436)); + hpcpush(hpxyz(-0.110779,-0.007165,1.006143)); + hpcpush(hpxyz(-0.135232,-0.011039,1.009163)); + hpcpush(hpxyz(-0.153105,-0.023214,1.011919)); + hpcpush(hpxyz(-0.159242,-0.009400,1.012643)); + hpcpush(hpxyz(-0.147497,0.001105,1.010820)); + hpcpush(hpxyz(-0.147497,-0.001105,1.010820)); + bshape(shWolf, 33); + /* hpcpush(hpxyz(-0.310601,0.000000,1.047126)); hpcpush(hpxyz(-0.158251,0.009739,1.012491)); hpcpush(hpxyz(-0.149626,0.045009,1.012133)); @@ -2110,7 +2665,185 @@ void buildpolys() { hpcpush(hpxyz(-0.158251,-0.009739,1.012491)); hpcpush(hpxyz(-0.310601,-0.000000,1.047126)); hpcpush(hpxyz(-0.310601,0.000000,1.047126)); + */ + hpcpush(hpxyz(-0.310601,0.000000,1.047126)); + hpcpush(hpxyz(-0.158251,0.009739,1.012491)); + hpcpush(hpxyz(-0.149626,0.045009,1.012133)); + hpcpush(hpxyz(-0.173168,0.066320,1.017047)); + hpcpush(hpxyz(-0.250414,0.056912,1.032447)); + hpcpush(hpxyz(-0.242122,0.064314,1.030902)); + hpcpush(hpxyz(-0.253563,0.065926,1.033751)); + hpcpush(hpxyz(-0.241104,0.075740,1.031440)); + hpcpush(hpxyz(-0.249897,0.082453,1.034044)); + hpcpush(hpxyz(-0.237118,0.081982,1.030993)); + hpcpush(hpxyz(-0.246310,0.097762,1.034517)); + hpcpush(hpxyz(-0.230366,0.088118,1.029968)); + hpcpush(hpxyz(-0.210870,0.082352,1.025304)); + hpcpush(hpxyz(-0.194727,0.083100,1.022166)); + hpcpush(hpxyz(-0.180298,0.087679,1.019899)); + hpcpush(hpxyz(-0.162032,0.087154,1.016784)); + hpcpush(hpxyz(-0.135091,0.081542,1.012373)); + hpcpush(hpxyz(-0.116083,0.068924,1.009072)); + hpcpush(hpxyz(-0.106144,0.066340,1.007803)); + hpcpush(hpxyz(-0.084057,0.063643,1.005543)); + hpcpush(hpxyz(-0.061108,0.071892,1.004441)); + hpcpush(hpxyz(-0.044295,0.077815,1.004001)); + hpcpush(hpxyz(-0.021516,0.077698,1.003245)); + hpcpush(hpxyz(0.000000,0.078872,1.003106)); + hpcpush(hpxyz(0.025203,0.099613,1.005265)); + hpcpush(hpxyz(0.040964,0.113252,1.007226)); + hpcpush(hpxyz(0.067885,0.127285,1.010351)); + hpcpush(hpxyz(0.086481,0.135203,1.012798)); + hpcpush(hpxyz(0.104129,0.144556,1.015746)); + hpcpush(hpxyz(0.097579,0.132951,1.013508)); + hpcpush(hpxyz(0.112604,0.134635,1.015286)); + hpcpush(hpxyz(0.098603,0.124167,1.012492)); + hpcpush(hpxyz(0.118341,0.115901,1.013626)); + hpcpush(hpxyz(0.094688,0.115325,1.011072)); + hpcpush(hpxyz(0.079806,0.108826,1.009065)); + hpcpush(hpxyz(0.065011,0.097516,1.006845)); + hpcpush(hpxyz(0.053964,0.082746,1.004868)); + hpcpush(hpxyz(0.049028,0.066966,1.003438)); + hpcpush(hpxyz(0.045353,0.053708,1.002468)); + hpcpush(hpxyz(0.046494,0.040534,1.001901)); + hpcpush(hpxyz(0.051260,0.033378,1.001869)); + hpcpush(hpxyz(0.059646,0.029823,1.002221)); + hpcpush(hpxyz(0.069275,0.029860,1.002841)); + hpcpush(hpxyz(0.077732,0.029897,1.003462)); + hpcpush(hpxyz(0.081360,0.028715,1.003715)); + hpcpush(hpxyz(0.066249,0.039649,1.002976)); + hpcpush(hpxyz(0.106662,0.046229,1.006734)); + hpcpush(hpxyz(0.146020,0.025919,1.010937)); + hpcpush(hpxyz(0.159666,0.028110,1.013056)); + hpcpush(hpxyz(0.172131,0.020186,1.014907)); + hpcpush(hpxyz(0.172077,0.013438,1.014786)); + hpcpush(hpxyz(0.168613,0.007837,1.014146)); + hpcpush(hpxyz(0.168613,-0.007837,1.014146)); + hpcpush(hpxyz(0.172077,-0.013438,1.014786)); + hpcpush(hpxyz(0.172131,-0.020186,1.014907)); + hpcpush(hpxyz(0.159666,-0.028110,1.013056)); + hpcpush(hpxyz(0.146020,-0.025919,1.010937)); + hpcpush(hpxyz(0.106662,-0.046229,1.006734)); + hpcpush(hpxyz(0.066249,-0.039649,1.002976)); + hpcpush(hpxyz(0.081360,-0.028715,1.003715)); + hpcpush(hpxyz(0.077732,-0.029897,1.003462)); + hpcpush(hpxyz(0.069275,-0.029860,1.002841)); + hpcpush(hpxyz(0.059646,-0.029823,1.002221)); + hpcpush(hpxyz(0.051260,-0.033378,1.001869)); + hpcpush(hpxyz(0.046494,-0.040534,1.001901)); + hpcpush(hpxyz(0.045353,-0.053708,1.002468)); + hpcpush(hpxyz(0.049028,-0.066966,1.003438)); + hpcpush(hpxyz(0.053964,-0.082746,1.004868)); + hpcpush(hpxyz(0.065011,-0.097516,1.006845)); + hpcpush(hpxyz(0.079806,-0.108826,1.009065)); + hpcpush(hpxyz(0.094688,-0.115325,1.011072)); + hpcpush(hpxyz(0.118341,-0.115901,1.013626)); + hpcpush(hpxyz(0.098603,-0.124167,1.012492)); + hpcpush(hpxyz(0.112604,-0.134635,1.015286)); + hpcpush(hpxyz(0.097579,-0.132951,1.013508)); + hpcpush(hpxyz(0.104129,-0.144556,1.015746)); + hpcpush(hpxyz(0.086481,-0.135203,1.012798)); + hpcpush(hpxyz(0.067885,-0.127285,1.010351)); + hpcpush(hpxyz(0.040964,-0.113252,1.007226)); + hpcpush(hpxyz(0.025203,-0.099613,1.005265)); + hpcpush(hpxyz(0.000000,-0.078872,1.003106)); + hpcpush(hpxyz(-0.021516,-0.077698,1.003245)); + hpcpush(hpxyz(-0.044295,-0.077815,1.004001)); + hpcpush(hpxyz(-0.061108,-0.071892,1.004441)); + hpcpush(hpxyz(-0.084057,-0.063643,1.005543)); + hpcpush(hpxyz(-0.106144,-0.066340,1.007803)); + hpcpush(hpxyz(-0.116083,-0.068924,1.009072)); + hpcpush(hpxyz(-0.135091,-0.081542,1.012373)); + hpcpush(hpxyz(-0.162032,-0.087154,1.016784)); + hpcpush(hpxyz(-0.180298,-0.087679,1.019899)); + hpcpush(hpxyz(-0.194727,-0.083100,1.022166)); + hpcpush(hpxyz(-0.210870,-0.082352,1.025304)); + hpcpush(hpxyz(-0.230366,-0.088118,1.029968)); + hpcpush(hpxyz(-0.246310,-0.097762,1.034517)); + hpcpush(hpxyz(-0.237118,-0.081982,1.030993)); + hpcpush(hpxyz(-0.249897,-0.082453,1.034044)); + hpcpush(hpxyz(-0.241104,-0.075740,1.031440)); + hpcpush(hpxyz(-0.253563,-0.065926,1.033751)); + hpcpush(hpxyz(-0.242122,-0.064314,1.030902)); + hpcpush(hpxyz(-0.250414,-0.056912,1.032447)); + hpcpush(hpxyz(-0.173168,-0.066320,1.017047)); + hpcpush(hpxyz(-0.149626,-0.045009,1.012133)); + hpcpush(hpxyz(-0.158251,-0.009739,1.012491)); + hpcpush(hpxyz(-0.310601,0.000000,1.047126)); + hpcpush(hpxyz(-0.310601,0.000000,1.047126)); + bshape(shWolf1, 34); + hpcpush(hpxyz(0.121226,-0.019639,1.007513)); + hpcpush(hpxyz(0.119731,-0.021190,1.007365)); + hpcpush(hpxyz(0.117841,-0.022233,1.007165)); + hpcpush(hpxyz(0.115725,-0.022676,1.006929)); + hpcpush(hpxyz(0.113570,-0.022480,1.006679)); + hpcpush(hpxyz(0.111568,-0.021661,1.006438)); + hpcpush(hpxyz(0.109897,-0.020293,1.006225)); + hpcpush(hpxyz(0.108705,-0.018496,1.006061)); + hpcpush(hpxyz(0.108099,-0.016432,1.005960)); + hpcpush(hpxyz(0.108131,-0.014283,1.005931)); + hpcpush(hpxyz(0.108800,-0.012240,1.005976)); + hpcpush(hpxyz(0.110046,-0.010484,1.006091)); + hpcpush(hpxyz(0.111757,-0.009172,1.006267)); + hpcpush(hpxyz(0.113783,-0.008421,1.006488)); + hpcpush(hpxyz(0.115942,-0.008296,1.006733)); + hpcpush(hpxyz(0.118044,-0.008810,1.006982)); + hpcpush(hpxyz(0.119902,-0.009915,1.007211)); + hpcpush(hpxyz(0.121349,-0.011516,1.007402)); + hpcpush(hpxyz(0.122258,-0.013468,1.007536)); + hpcpush(hpxyz(0.122549,-0.015598,1.007602)); + hpcpush(hpxyz(0.122194,-0.017718,1.007594)); + hpcpush(hpxyz(0.121226,-0.019639,1.007513)); + + bshape(shWolf2, 34); + hpcpush(hpxyz(0.110896,0.008835,1.006169)); + hpcpush(hpxyz(0.109780,0.010595,1.006064)); + hpcpush(hpxyz(0.109236,0.012605,1.006028)); + hpcpush(hpxyz(0.109313,0.014686,1.006064)); + hpcpush(hpxyz(0.110004,0.016653,1.006170)); + hpcpush(hpxyz(0.111247,0.018331,1.006336)); + hpcpush(hpxyz(0.112933,0.019572,1.006547)); + hpcpush(hpxyz(0.114911,0.020264,1.006785)); + hpcpush(hpxyz(0.117005,0.020346,1.007027)); + hpcpush(hpxyz(0.119030,0.019812,1.007254)); + hpcpush(hpxyz(0.120806,0.018708,1.007444)); + hpcpush(hpxyz(0.122174,0.017133,1.007581)); + hpcpush(hpxyz(0.123014,0.015226,1.007653)); + hpcpush(hpxyz(0.123250,0.013158,1.007653)); + hpcpush(hpxyz(0.122862,0.011111,1.007581)); + hpcpush(hpxyz(0.121884,0.009268,1.007443)); + hpcpush(hpxyz(0.120403,0.007792,1.007252)); + hpcpush(hpxyz(0.118550,0.006815,1.007026)); + hpcpush(hpxyz(0.116491,0.006423,1.006783)); + hpcpush(hpxyz(0.114408,0.006652,1.006545)); + hpcpush(hpxyz(0.112486,0.007480,1.006334)); + hpcpush(hpxyz(0.110896,0.008835,1.006169)); + + bshape(shWolf3, 34); + hpcpush(hpxyz(0.157399,-0.008998,1.012351)); + hpcpush(hpxyz(0.154869,-0.009703,1.011968)); + hpcpush(hpxyz(0.152240,-0.009639,1.011568)); + hpcpush(hpxyz(0.149747,-0.008812,1.011188)); + hpcpush(hpxyz(0.147612,-0.007296,1.010862)); + hpcpush(hpxyz(0.146023,-0.005225,1.010619)); + hpcpush(hpxyz(0.145123,-0.002783,1.010479)); + hpcpush(hpxyz(0.144991,-0.000188,1.010456)); + hpcpush(hpxyz(0.145638,0.002331,1.010552)); + hpcpush(hpxyz(0.147008,0.004549,1.010758)); + hpcpush(hpxyz(0.148979,0.006269,1.011056)); + hpcpush(hpxyz(0.151375,0.007339,1.011419)); + hpcpush(hpxyz(0.153983,0.007663,1.011815)); + hpcpush(hpxyz(0.156573,0.007212,1.012209)); + hpcpush(hpxyz(0.158913,0.006027,1.012566)); + hpcpush(hpxyz(0.160796,0.004213,1.012854)); + hpcpush(hpxyz(0.162055,0.001931,1.013048)); + hpcpush(hpxyz(0.162577,-0.000616,1.013130)); + hpcpush(hpxyz(0.162316,-0.003201,1.013093)); + hpcpush(hpxyz(0.161296,-0.005596,1.012940)); + hpcpush(hpxyz(0.159607,-0.007588,1.012686)); + hpcpush(hpxyz(0.157399,-0.008998,1.012351)); + bshape(shEagle, 33); hpcpush(hpxyz(-0.153132,0.000000,1.011657)); hpcpush(hpxyz(-0.151960,0.025529,1.011802)); @@ -2398,6 +3131,186 @@ void buildpolys() { // bodyparts + bshape(shWaterElemental, 41); + hpcpush(hpxyz(0.033277,-0.002494,1.000557)); + hpcpush(hpxyz(0.030600,0.009657,1.000515)); + hpcpush(hpxyz(0.028387,0.043359,1.001342)); + hpcpush(hpxyz(0.023906,0.062967,1.002266)); + hpcpush(hpxyz(0.019706,0.086354,1.003915)); + hpcpush(hpxyz(0.012812,0.106509,1.005738)); + hpcpush(hpxyz(0.005882,0.110737,1.006130)); + hpcpush(hpxyz(-0.011019,0.128245,1.008250)); + hpcpush(hpxyz(-0.022186,0.143031,1.010421)); + hpcpush(hpxyz(-0.030554,0.165535,1.014069)); + hpcpush(hpxyz(-0.031448,0.191850,1.018722)); + hpcpush(hpxyz(-0.019105,0.210887,1.022173)); + hpcpush(hpxyz(-0.011140,0.218374,1.023627)); + hpcpush(hpxyz(0.003294,0.228201,1.025713)); + hpcpush(hpxyz(0.022226,0.229526,1.026244)); + hpcpush(hpxyz(0.030754,0.226143,1.025713)); + hpcpush(hpxyz(0.045164,0.218293,1.024545)); + hpcpush(hpxyz(0.048550,0.213967,1.023787)); + hpcpush(hpxyz(0.049437,0.209816,1.022970)); + hpcpush(hpxyz(0.066512,0.191298,1.020303)); + hpcpush(hpxyz(0.088299,0.195587,1.022766)); + hpcpush(hpxyz(0.104559,0.227968,1.030971)); + hpcpush(hpxyz(0.106012,0.240682,1.034005)); + hpcpush(hpxyz(0.089373,0.265934,1.038609)); + hpcpush(hpxyz(0.046213,0.273931,1.037870)); + hpcpush(hpxyz(0.013854,0.270257,1.035968)); + hpcpush(hpxyz(-0.022699,0.280947,1.038964)); + hpcpush(hpxyz(-0.082207,0.292512,1.045142)); + hpcpush(hpxyz(-0.094232,0.286583,1.044514)); + hpcpush(hpxyz(-0.060514,0.273212,1.038416)); + hpcpush(hpxyz(-0.030455,0.255305,1.032525)); + hpcpush(hpxyz(-0.028453,0.245093,1.029990)); + hpcpush(hpxyz(-0.035130,0.238686,1.028691)); + hpcpush(hpxyz(-0.050479,0.236064,1.028725)); + hpcpush(hpxyz(-0.095235,0.239928,1.032780)); + hpcpush(hpxyz(-0.156131,0.242848,1.040842)); + hpcpush(hpxyz(-0.180731,0.231002,1.042126)); + hpcpush(hpxyz(-0.161568,0.228039,1.038319)); + hpcpush(hpxyz(-0.140105,0.226302,1.034815)); + hpcpush(hpxyz(-0.114110,0.211717,1.028516)); + hpcpush(hpxyz(-0.104006,0.203643,1.025811)); + hpcpush(hpxyz(-0.096764,0.190676,1.022605)); + hpcpush(hpxyz(-0.097207,0.178784,1.020496)); + hpcpush(hpxyz(-0.104028,0.166435,1.019079)); + hpcpush(hpxyz(-0.109337,0.160521,1.018686)); + hpcpush(hpxyz(-0.119778,0.153916,1.018841)); + hpcpush(hpxyz(-0.145551,0.154306,1.022250)); + hpcpush(hpxyz(-0.196422,0.144903,1.029358)); + hpcpush(hpxyz(-0.238648,0.130576,1.036341)); + hpcpush(hpxyz(-0.251825,0.121707,1.038378)); + hpcpush(hpxyz(-0.243461,0.108932,1.034959)); + hpcpush(hpxyz(-0.227615,0.116160,1.032135)); + hpcpush(hpxyz(-0.199823,0.119359,1.026731)); + hpcpush(hpxyz(-0.155889,0.119514,1.019110)); + hpcpush(hpxyz(-0.126863,0.107638,1.013746)); + hpcpush(hpxyz(-0.121879,0.082303,1.010756)); + hpcpush(hpxyz(-0.130612,0.062191,1.010409)); + hpcpush(hpxyz(-0.149053,0.051540,1.012360)); + hpcpush(hpxyz(-0.176729,0.044071,1.016452)); + hpcpush(hpxyz(-0.213072,0.040955,1.023268)); + hpcpush(hpxyz(-0.257325,0.030738,1.033035)); + hpcpush(hpxyz(-0.282810,0.025058,1.039524)); + hpcpush(hpxyz(-0.296088,0.010521,1.042966)); + hpcpush(hpxyz(-0.296088,-0.010521,1.042966)); + hpcpush(hpxyz(-0.282810,-0.025058,1.039524)); + hpcpush(hpxyz(-0.257325,-0.030738,1.033035)); + hpcpush(hpxyz(-0.213072,-0.040955,1.023268)); + hpcpush(hpxyz(-0.176729,-0.044071,1.016452)); + hpcpush(hpxyz(-0.149053,-0.051540,1.012360)); + hpcpush(hpxyz(-0.130612,-0.062191,1.010409)); + hpcpush(hpxyz(-0.121879,-0.082303,1.010756)); + hpcpush(hpxyz(-0.126863,-0.107638,1.013746)); + hpcpush(hpxyz(-0.155889,-0.119514,1.019110)); + hpcpush(hpxyz(-0.199823,-0.119359,1.026731)); + hpcpush(hpxyz(-0.227615,-0.116160,1.032135)); + hpcpush(hpxyz(-0.243461,-0.108932,1.034959)); + hpcpush(hpxyz(-0.251825,-0.121707,1.038378)); + hpcpush(hpxyz(-0.238648,-0.130576,1.036341)); + hpcpush(hpxyz(-0.196422,-0.144903,1.029358)); + hpcpush(hpxyz(-0.145551,-0.154306,1.022250)); + hpcpush(hpxyz(-0.119778,-0.153916,1.018841)); + hpcpush(hpxyz(-0.109337,-0.160521,1.018686)); + hpcpush(hpxyz(-0.104028,-0.166435,1.019079)); + hpcpush(hpxyz(-0.097207,-0.178784,1.020496)); + hpcpush(hpxyz(-0.096764,-0.190676,1.022605)); + hpcpush(hpxyz(-0.104006,-0.203643,1.025811)); + hpcpush(hpxyz(-0.114110,-0.211717,1.028516)); + hpcpush(hpxyz(-0.140105,-0.226302,1.034815)); + hpcpush(hpxyz(-0.161568,-0.228039,1.038319)); + hpcpush(hpxyz(-0.180731,-0.231002,1.042126)); + hpcpush(hpxyz(-0.156131,-0.242848,1.040842)); + hpcpush(hpxyz(-0.095235,-0.239928,1.032780)); + hpcpush(hpxyz(-0.050479,-0.236064,1.028725)); + hpcpush(hpxyz(-0.035130,-0.238686,1.028691)); + hpcpush(hpxyz(-0.028453,-0.245093,1.029990)); + hpcpush(hpxyz(-0.030455,-0.255305,1.032525)); + hpcpush(hpxyz(-0.060514,-0.273212,1.038416)); + hpcpush(hpxyz(-0.094232,-0.286583,1.044514)); + hpcpush(hpxyz(-0.082207,-0.292512,1.045142)); + hpcpush(hpxyz(-0.022699,-0.280947,1.038964)); + hpcpush(hpxyz(0.013854,-0.270257,1.035968)); + hpcpush(hpxyz(0.046213,-0.273931,1.037870)); + hpcpush(hpxyz(0.089373,-0.265934,1.038609)); + hpcpush(hpxyz(0.106012,-0.240682,1.034005)); + hpcpush(hpxyz(0.104559,-0.227968,1.030971)); + hpcpush(hpxyz(0.088299,-0.195587,1.022766)); + hpcpush(hpxyz(0.066512,-0.191298,1.020303)); + hpcpush(hpxyz(0.049437,-0.209816,1.022970)); + hpcpush(hpxyz(0.048550,-0.213967,1.023787)); + hpcpush(hpxyz(0.045164,-0.218293,1.024545)); + hpcpush(hpxyz(0.030754,-0.226143,1.025713)); + hpcpush(hpxyz(0.022226,-0.229526,1.026244)); + hpcpush(hpxyz(0.003294,-0.228201,1.025713)); + hpcpush(hpxyz(-0.011140,-0.218374,1.023627)); + hpcpush(hpxyz(-0.019105,-0.210887,1.022173)); + hpcpush(hpxyz(-0.031448,-0.191850,1.018722)); + hpcpush(hpxyz(-0.030554,-0.165535,1.014069)); + hpcpush(hpxyz(-0.022186,-0.143031,1.010421)); + hpcpush(hpxyz(-0.011019,-0.128245,1.008250)); + hpcpush(hpxyz(0.005882,-0.110737,1.006130)); + hpcpush(hpxyz(0.012812,-0.106509,1.005738)); + hpcpush(hpxyz(0.019706,-0.086354,1.003915)); + hpcpush(hpxyz(0.023906,-0.062967,1.002266)); + hpcpush(hpxyz(0.028387,-0.043359,1.001342)); + hpcpush(hpxyz(0.030600,-0.009657,1.000515)); + hpcpush(hpxyz(0.033277,0.002494,1.000557)); + hpcpush(hpxyz(0.033277,-0.002494,1.000557)); + + bshape(shMouse, 42); + hpcpush(hpxyz(-0.180666,0.000000,1.016189)); + hpcpush(hpxyz(-0.063349,-0.003586,1.002011)); + hpcpush(hpxyz(-0.052534,-0.013134,1.001465)); + hpcpush(hpxyz(-0.040561,-0.021474,1.001053)); + hpcpush(hpxyz(-0.020260,-0.026219,1.000549)); + hpcpush(hpxyz(-0.001191,-0.028595,1.000409)); + hpcpush(hpxyz(0.025033,-0.026225,1.000657)); + hpcpush(hpxyz(0.045342,-0.015512,1.001148)); + hpcpush(hpxyz(0.056152,-0.020310,1.001781)); + hpcpush(hpxyz(0.077865,-0.014375,1.003130)); + hpcpush(hpxyz(0.094893,-0.002402,1.004495)); + hpcpush(hpxyz(0.101018,-0.000000,1.005089)); + hpcpush(hpxyz(0.101018,0.000000,1.005089)); + hpcpush(hpxyz(0.094893,0.002402,1.004495)); + hpcpush(hpxyz(0.077865,0.014375,1.003130)); + hpcpush(hpxyz(0.056152,0.020310,1.001781)); + hpcpush(hpxyz(0.045342,0.015512,1.001148)); + hpcpush(hpxyz(0.025033,0.026225,1.000657)); + hpcpush(hpxyz(-0.001191,0.028595,1.000409)); + hpcpush(hpxyz(-0.020260,0.026219,1.000549)); + hpcpush(hpxyz(-0.040561,0.021474,1.001053)); + hpcpush(hpxyz(-0.052534,0.013134,1.001465)); + hpcpush(hpxyz(-0.063349,0.003586,1.002011)); + hpcpush(hpxyz(-0.180666,-0.000000,1.016189)); + hpcpush(hpxyz(-0.180666,0.000000,1.016189)); + + bshape(shMouseLegs, 41); + hpcpush(hpxyz(-0.033372,-0.005959,1.000574)); + hpcpush(hpxyz(-0.047793,-0.037040,1.001826)); + hpcpush(hpxyz(-0.003572,-0.011907,1.000077)); + hpcpush(hpxyz(0.033422,-0.039390,1.001333)); + hpcpush(hpxyz(0.026209,-0.004765,1.000355)); + hpcpush(hpxyz(0.026209,0.004765,1.000355)); + hpcpush(hpxyz(0.033422,0.039390,1.001333)); + hpcpush(hpxyz(-0.003572,0.011907,1.000077)); + hpcpush(hpxyz(-0.047793,0.037040,1.001826)); + hpcpush(hpxyz(-0.033372,0.005959,1.000574)); + hpcpush(hpxyz(-0.033372,-0.005959,1.000574)); + + bshape(shMouseEyes, 43); + hpcpush(hpxyz(0.073016,-0.011970,1.002734)); + hpcpush(hpxyz(0.065770,-0.013154,1.002247)); + hpcpush(hpxyz(0.065764,-0.008370,1.002195)); + hpcpush(hpxyz(0.071797,-0.003590,1.002581)); + hpcpush(hpxyz(0.071797,0.003590,1.002581)); + hpcpush(hpxyz(0.065764,0.008370,1.002195)); + hpcpush(hpxyz(0.065770,0.013154,1.002247)); + hpcpush(hpxyz(0.073016,0.011970,1.002734)); + hpcpush(hpxyz(0.073016,-0.011970,1.002734)); + bshape(shPBody, 41); hpcpush(hpxyz(-0.127943,0.000000,1.008151)); hpcpush(hpxyz(-0.121732,0.008437,1.007417)); @@ -2668,6 +3581,95 @@ void buildpolys() { hpcpush(hpxyz(-0.146785,-0.001213,1.010716)); hpcpush(hpxyz(-0.146785,0.001213,1.010716)); + bshape(shKnife, 42); + hpcpush(hpxyz(-0.086373,0.015595,1.003844)); + hpcpush(hpxyz(-0.063364,0.015542,1.002126)); + hpcpush(hpxyz(-0.061008,0.033495,1.002419)); + hpcpush(hpxyz(-0.041796,0.037020,1.001557)); + hpcpush(hpxyz(-0.038168,0.021470,1.000958)); + hpcpush(hpxyz(0.085206,0.028802,1.004037)); + hpcpush(hpxyz(0.158634,0.003661,1.012511)); + hpcpush(hpxyz(0.158634,-0.003661,1.012511)); + hpcpush(hpxyz(0.085206,-0.028802,1.004037)); + hpcpush(hpxyz(-0.038168,-0.021470,1.000958)); + hpcpush(hpxyz(-0.041796,-0.037020,1.001557)); + hpcpush(hpxyz(-0.061008,-0.033495,1.002419)); + hpcpush(hpxyz(-0.063364,-0.015542,1.002126)); + hpcpush(hpxyz(-0.086373,-0.015595,1.003844)); + hpcpush(hpxyz(-0.086373,0.015595,1.003844)); + + bshape(shTongue, 42); + hpcpush(hpxyz(-0.036955,0.001192,1.000683)); + hpcpush(hpxyz(-0.036957,-0.007153,1.000708)); + hpcpush(hpxyz(-0.048967,-0.028663,1.001608)); + hpcpush(hpxyz(-0.061094,-0.050313,1.003127)); + hpcpush(hpxyz(-0.064717,-0.050336,1.003355)); + hpcpush(hpxyz(-0.049075,-0.055059,1.002716)); + hpcpush(hpxyz(-0.022708,-0.058563,1.001971)); + hpcpush(hpxyz(0.011941,-0.053734,1.001514)); + hpcpush(hpxyz(0.029846,-0.044173,1.001420)); + hpcpush(hpxyz(0.046581,-0.033443,1.001643)); + hpcpush(hpxyz(0.062159,-0.015540,1.002050)); + hpcpush(hpxyz(0.066968,-0.005979,1.002258)); + hpcpush(hpxyz(0.066968,0.005979,1.002258)); + hpcpush(hpxyz(0.062159,0.015540,1.002050)); + hpcpush(hpxyz(0.046581,0.033443,1.001643)); + hpcpush(hpxyz(0.029846,0.044173,1.001420)); + hpcpush(hpxyz(0.011941,0.053734,1.001514)); + hpcpush(hpxyz(-0.022708,0.058563,1.001971)); + hpcpush(hpxyz(-0.049075,0.055059,1.002716)); + hpcpush(hpxyz(-0.064717,0.050336,1.003355)); + hpcpush(hpxyz(-0.061094,0.050313,1.003127)); + hpcpush(hpxyz(-0.048967,0.028663,1.001608)); + hpcpush(hpxyz(-0.036957,0.007153,1.000708)); + hpcpush(hpxyz(-0.036955,-0.001192,1.000683)); + hpcpush(hpxyz(-0.036955,0.001192,1.000683)); + + bshape(shFlailMissile, 42); + hpcpush(hpxyz(-0.064558,0.008369,1.002117)); + hpcpush(hpxyz(-0.038156,0.011924,1.000799)); + hpcpush(hpxyz(-0.059223,0.027026,1.002117)); + hpcpush(hpxyz(-0.032946,0.022641,1.000799)); + hpcpush(hpxyz(-0.048626,0.043281,1.002117)); + hpcpush(hpxyz(-0.024809,0.031346,1.000799)); + hpcpush(hpxyz(-0.033708,0.055691,1.002117)); + hpcpush(hpxyz(-0.014468,0.037266,1.000799)); + hpcpush(hpxyz(-0.015796,0.063153,1.002117)); + hpcpush(hpxyz(-0.002840,0.039875,1.000799)); + hpcpush(hpxyz(0.003521,0.065003,1.002117)); + hpcpush(hpxyz(0.009039,0.038940,1.000799)); + hpcpush(hpxyz(0.022524,0.061077,1.002117)); + hpcpush(hpxyz(0.020115,0.034546,1.000799)); + hpcpush(hpxyz(0.039526,0.051724,1.002117)); + hpcpush(hpxyz(0.029404,0.027082,1.000799)); + hpcpush(hpxyz(0.053016,0.037776,1.002117)); + hpcpush(hpxyz(0.036081,0.017212,1.000799)); + hpcpush(hpxyz(0.061796,0.020471,1.002117)); + hpcpush(hpxyz(0.039551,0.005812,1.000799)); + hpcpush(hpxyz(0.065084,0.001347,1.002117)); + hpcpush(hpxyz(0.039507,-0.006104,1.000799)); + hpcpush(hpxyz(0.062590,-0.017897,1.002117)); + hpcpush(hpxyz(0.035953,-0.017477,1.000799)); + hpcpush(hpxyz(0.054534,-0.035550,1.002117)); + hpcpush(hpxyz(0.029204,-0.027298,1.000799)); + hpcpush(hpxyz(0.041632,-0.050045,1.002117)); + hpcpush(hpxyz(0.019860,-0.034693,1.000799)); + hpcpush(hpxyz(0.025031,-0.060093,1.002117)); + hpcpush(hpxyz(0.008752,-0.039006,1.000799)); + hpcpush(hpxyz(0.006207,-0.064801,1.002117)); + hpcpush(hpxyz(-0.003134,-0.039853,1.000799)); + hpcpush(hpxyz(-0.013170,-0.063752,1.002117)); + hpcpush(hpxyz(-0.014742,-0.037158,1.000799)); + hpcpush(hpxyz(-0.031376,-0.057038,1.002117)); + hpcpush(hpxyz(-0.025040,-0.031162,1.000799)); + hpcpush(hpxyz(-0.046794,-0.045256,1.002117)); + hpcpush(hpxyz(-0.033112,-0.022397,1.000799)); + hpcpush(hpxyz(-0.058054,-0.029452,1.002117)); + hpcpush(hpxyz(-0.038243,-0.011642,1.000799)); + hpcpush(hpxyz(-0.064156,-0.011032,1.002117)); + hpcpush(hpxyz(-0.039976,0.000147,1.000799)); + hpcpush(hpxyz(-0.064558,0.008369,1.002117)); + bshape(shPSword, 42); hpcpush(hpxyz(0.093822,0.244697,1.033769)); hpcpush(hpxyz(0.105758,0.251015,1.036433)); @@ -2693,6 +3695,106 @@ void buildpolys() { hpcpush(hpxyz(0.086431,0.252937,1.035107)); hpcpush(hpxyz(0.093822,0.244697,1.033769)); + bshape(shPKnife, 40); + hpcpush(hpxyz(0.070235,0.261061,1.035898)); + hpcpush(hpxyz(0.085110,0.243297,1.032685)); + hpcpush(hpxyz(0.100384,0.253764,1.036568)); + hpcpush(hpxyz(0.115592,0.241462,1.035212)); + hpcpush(hpxyz(0.106046,0.228043,1.031139)); + hpcpush(hpxyz(0.193021,0.140235,1.028068)); + hpcpush(hpxyz(0.223042,0.069158,1.026903)); + hpcpush(hpxyz(0.217457,0.064184,1.025382)); + hpcpush(hpxyz(0.149083,0.101106,1.016095)); + hpcpush(hpxyz(0.073293,0.198875,1.022214)); + hpcpush(hpxyz(0.059119,0.191168,1.019823)); + hpcpush(hpxyz(0.049288,0.208259,1.022644)); + hpcpush(hpxyz(0.061401,0.222183,1.026224)); + hpcpush(hpxyz(0.046445,0.239874,1.029415)); + hpcpush(hpxyz(0.070235,0.261061,1.035898)); + + bshape(shPirateHook, 42); + hpcpush(hpxyz(0.025637,0.290334,1.041610)); + hpcpush(hpxyz(0.015893,0.212083,1.022366)); + hpcpush(hpxyz(0.070681,0.208634,1.023975)); + hpcpush(hpxyz(0.078764,0.213716,1.025611)); + hpcpush(hpxyz(0.092820,0.214478,1.026945)); + hpcpush(hpxyz(0.128742,0.099394,1.013141)); + hpcpush(hpxyz(0.114620,0.096368,1.011150)); + hpcpush(hpxyz(0.104002,0.089501,1.009370)); + hpcpush(hpxyz(0.096284,0.072719,1.007253)); + hpcpush(hpxyz(0.093155,0.050966,1.005622)); + hpcpush(hpxyz(0.099066,0.033609,1.005457)); + hpcpush(hpxyz(0.110446,0.021946,1.006320)); + hpcpush(hpxyz(0.127291,0.014728,1.008176)); + hpcpush(hpxyz(0.145718,0.008586,1.010598)); + hpcpush(hpxyz(0.167517,0.008308,1.013968)); + hpcpush(hpxyz(0.156477,0.015183,1.012282)); + hpcpush(hpxyz(0.140613,0.023565,1.010113)); + hpcpush(hpxyz(0.132241,0.028989,1.009122)); + hpcpush(hpxyz(0.118961,0.034720,1.007649)); + hpcpush(hpxyz(0.108990,0.048739,1.007102)); + hpcpush(hpxyz(0.107378,0.058592,1.007454)); + hpcpush(hpxyz(0.115339,0.077749,1.009628)); + hpcpush(hpxyz(0.131027,0.084323,1.012066)); + hpcpush(hpxyz(0.151797,0.088283,1.015301)); + hpcpush(hpxyz(0.113111,0.234773,1.033398)); + hpcpush(hpxyz(0.104917,0.253698,1.037001)); + hpcpush(hpxyz(0.105424,0.258064,1.038129)); + hpcpush(hpxyz(0.096993,0.264198,1.038850)); + hpcpush(hpxyz(0.089213,0.264464,1.038220)); + hpcpush(hpxyz(0.087585,0.273426,1.040400)); + hpcpush(hpxyz(0.080433,0.279698,1.041489)); + hpcpush(hpxyz(0.072806,0.281526,1.041421)); + hpcpush(hpxyz(0.025637,0.290334,1.041610)); + + bshape(shSabre, 42); + hpcpush(hpxyz(0.052478,0.211644,1.023497)); + hpcpush(hpxyz(0.042242,0.185536,1.017943)); + hpcpush(hpxyz(0.057979,0.181601,1.018008)); + hpcpush(hpxyz(0.068086,0.204991,1.023062)); + hpcpush(hpxyz(0.085295,0.201073,1.023575)); + hpcpush(hpxyz(0.100829,0.193318,1.023493)); + hpcpush(hpxyz(0.113718,0.184489,1.023215)); + hpcpush(hpxyz(0.125735,0.178476,1.023554)); + hpcpush(hpxyz(0.134891,0.170005,1.023278)); + hpcpush(hpxyz(0.144264,0.162907,1.023402)); + hpcpush(hpxyz(0.152391,0.155912,1.023490)); + hpcpush(hpxyz(0.160192,0.146346,1.023269)); + hpcpush(hpxyz(0.166733,0.136894,1.023005)); + hpcpush(hpxyz(0.180659,0.123243,1.023634)); + hpcpush(hpxyz(0.189268,0.108634,1.023535)); + hpcpush(hpxyz(0.197644,0.091550,1.023447)); + hpcpush(hpxyz(0.204992,0.075866,1.023610)); + hpcpush(hpxyz(0.207394,0.063057,1.023224)); + hpcpush(hpxyz(0.213308,0.045015,1.023487)); + hpcpush(hpxyz(0.215741,0.031014,1.023477)); + hpcpush(hpxyz(0.216495,0.013402,1.023254)); + hpcpush(hpxyz(0.217512,-0.002957,1.023387)); + hpcpush(hpxyz(0.216708,-0.025412,1.023527)); + hpcpush(hpxyz(0.215602,-0.037833,1.023677)); + hpcpush(hpxyz(0.209033,-0.050943,1.022883)); + hpcpush(hpxyz(0.249210,-0.008237,1.030618)); + hpcpush(hpxyz(0.247115,0.012233,1.030153)); + hpcpush(hpxyz(0.246190,0.028812,1.030262)); + hpcpush(hpxyz(0.239192,0.052194,1.029533)); + hpcpush(hpxyz(0.237023,0.067663,1.029931)); + hpcpush(hpxyz(0.231339,0.087245,1.030111)); + hpcpush(hpxyz(0.221702,0.107109,1.029866)); + hpcpush(hpxyz(0.215996,0.124316,1.030587)); + hpcpush(hpxyz(0.206323,0.141806,1.030863)); + hpcpush(hpxyz(0.194941,0.164879,1.032079)); + hpcpush(hpxyz(0.173125,0.180454,1.030794)); + hpcpush(hpxyz(0.158905,0.191858,1.030563)); + hpcpush(hpxyz(0.143293,0.202073,1.030226)); + hpcpush(hpxyz(0.128179,0.215193,1.030892)); + hpcpush(hpxyz(0.111272,0.224403,1.030892)); + hpcpush(hpxyz(0.090433,0.232613,1.030673)); + hpcpush(hpxyz(0.079164,0.234740,1.030228)); + hpcpush(hpxyz(0.083027,0.256039,1.035591)); + hpcpush(hpxyz(0.071081,0.264147,1.036738)); + hpcpush(hpxyz(0.060044,0.234679,1.028921)); + hpcpush(hpxyz(0.052478,0.211644,1.023497)); + bshape(shHedgehogBlade, 42); hpcpush(hpxyz(0.117178,0.032617,1.007370)); hpcpush(hpxyz(0.102699,0.066452,1.007454)); @@ -2831,7 +3933,78 @@ void buildpolys() { bshape(shDemon, 43); drawDemon(1); - + + bshape(shGoatHead, 43); + hpcpush(hpxyz(0.098234,-0.008161,1.004847)); + hpcpush(hpxyz(0.097458,-0.016878,1.004880)); + hpcpush(hpxyz(0.085163,-0.036297,1.004276)); + hpcpush(hpxyz(0.074171,-0.049357,1.003961)); + hpcpush(hpxyz(0.064423,-0.056062,1.003640)); + hpcpush(hpxyz(0.071545,-0.060919,1.004405)); + hpcpush(hpxyz(0.090299,-0.086141,1.007757)); + hpcpush(hpxyz(0.099873,-0.119956,1.012109)); + hpcpush(hpxyz(0.098555,-0.155296,1.016774)); + hpcpush(hpxyz(0.084548,-0.179003,1.019407)); + hpcpush(hpxyz(0.066861,-0.191576,1.020378)); + hpcpush(hpxyz(0.016947,-0.207877,1.021519)); + hpcpush(hpxyz(-0.036121,-0.216389,1.023782)); + hpcpush(hpxyz(-0.071628,-0.210733,1.024470)); + hpcpush(hpxyz(-0.053640,-0.210686,1.023360)); + hpcpush(hpxyz(-0.029915,-0.199910,1.020225)); + hpcpush(hpxyz(-0.013982,-0.189736,1.017937)); + hpcpush(hpxyz(0.018469,-0.168500,1.014265)); + hpcpush(hpxyz(0.033113,-0.153873,1.012311)); + hpcpush(hpxyz(0.045027,-0.132252,1.009712)); + hpcpush(hpxyz(0.044982,-0.113169,1.007388)); + hpcpush(hpxyz(0.039048,-0.095429,1.005302)); + hpcpush(hpxyz(0.028215,-0.083777,1.003900)); + hpcpush(hpxyz(0.018818,-0.079369,1.003321)); + hpcpush(hpxyz(0.005692,-0.074475,1.002786)); + hpcpush(hpxyz(-0.012112,-0.070532,1.002557)); + hpcpush(hpxyz(-0.028520,-0.067591,1.002687)); + hpcpush(hpxyz(-0.047548,-0.063966,1.003171)); + hpcpush(hpxyz(-0.060278,-0.061572,1.003705)); + hpcpush(hpxyz(-0.079475,-0.058008,1.004829)); + hpcpush(hpxyz(-0.093451,-0.049712,1.005587)); + hpcpush(hpxyz(-0.106876,-0.031455,1.006187)); + hpcpush(hpxyz(-0.109804,-0.016063,1.006139)); + hpcpush(hpxyz(-0.108918,-0.001180,1.005915)); + hpcpush(hpxyz(-0.108918,0.001180,1.005915)); + hpcpush(hpxyz(-0.109804,0.016063,1.006139)); + hpcpush(hpxyz(-0.106876,0.031455,1.006187)); + hpcpush(hpxyz(-0.093451,0.049712,1.005587)); + hpcpush(hpxyz(-0.079475,0.058008,1.004829)); + hpcpush(hpxyz(-0.060278,0.061572,1.003705)); + hpcpush(hpxyz(-0.047548,0.063966,1.003171)); + hpcpush(hpxyz(-0.028520,0.067591,1.002687)); + hpcpush(hpxyz(-0.012112,0.070532,1.002557)); + hpcpush(hpxyz(0.005692,0.074475,1.002786)); + hpcpush(hpxyz(0.018818,0.079369,1.003321)); + hpcpush(hpxyz(0.028215,0.083777,1.003900)); + hpcpush(hpxyz(0.039048,0.095429,1.005302)); + hpcpush(hpxyz(0.044982,0.113169,1.007388)); + hpcpush(hpxyz(0.045027,0.132252,1.009712)); + hpcpush(hpxyz(0.033113,0.153873,1.012311)); + hpcpush(hpxyz(0.018469,0.168500,1.014265)); + hpcpush(hpxyz(-0.013982,0.189736,1.017937)); + hpcpush(hpxyz(-0.029915,0.199910,1.020225)); + hpcpush(hpxyz(-0.053640,0.210686,1.023360)); + hpcpush(hpxyz(-0.071628,0.210733,1.024470)); + hpcpush(hpxyz(-0.036121,0.216389,1.023782)); + hpcpush(hpxyz(0.016947,0.207877,1.021519)); + hpcpush(hpxyz(0.066861,0.191576,1.020378)); + hpcpush(hpxyz(0.084548,0.179003,1.019407)); + hpcpush(hpxyz(0.098555,0.155296,1.016774)); + hpcpush(hpxyz(0.099873,0.119956,1.012109)); + hpcpush(hpxyz(0.090299,0.086141,1.007757)); + hpcpush(hpxyz(0.071545,0.060919,1.004405)); + hpcpush(hpxyz(0.064423,0.056062,1.003640)); + hpcpush(hpxyz(0.074171,0.049357,1.003961)); + hpcpush(hpxyz(0.085163,0.036297,1.004276)); + hpcpush(hpxyz(0.097458,0.016878,1.004880)); + hpcpush(hpxyz(0.098234,0.008161,1.004847)); + hpcpush(hpxyz(0.098234,-0.008161,1.004847)); + bshape(shKnightArmor, 42); hpcpush(hpxyz(-0.129512,-0.004842,1.008363)); hpcpush(hpxyz(-0.129934,0.057074,1.010020)); @@ -2909,6 +4082,72 @@ void buildpolys() { hpcpush(hpxyz(0.007931,0.006370,1.000052)); hpcpush(hpxyz(-0.000015,-0.003765,1.000007)); hpcpush(hpxyz(-0.000015,0.003765,1.000007)); + + bshape(shPrincessDress, 43); + hpcpush(hpxyz(0.041877,-0.057431,1.002523)); + hpcpush(hpxyz(0.046812,-0.078020,1.004131)); + hpcpush(hpxyz(0.028859,-0.096196,1.005031)); + hpcpush(hpxyz(-0.001205,-0.110866,1.006128)); + hpcpush(hpxyz(-0.053233,-0.116144,1.008128)); + hpcpush(hpxyz(-0.110022,-0.122246,1.013434)); + hpcpush(hpxyz(-0.181271,-0.133766,1.025062)); + hpcpush(hpxyz(-0.221411,-0.145062,1.034440)); + hpcpush(hpxyz(-0.252155,-0.156465,1.043103)); + hpcpush(hpxyz(-0.285822,-0.165961,1.053203)); + hpcpush(hpxyz(-0.259590,-0.116944,1.039742)); + hpcpush(hpxyz(-0.258096,-0.089439,1.036635)); + hpcpush(hpxyz(-0.246236,-0.031569,1.030354)); + hpcpush(hpxyz(-0.247436,0.011362,1.030220)); + hpcpush(hpxyz(-0.253890,0.054586,1.033170)); + hpcpush(hpxyz(-0.268619,0.095109,1.039809)); + hpcpush(hpxyz(-0.277680,0.121972,1.044980)); + hpcpush(hpxyz(-0.286489,0.138666,1.049430)); + hpcpush(hpxyz(-0.295278,0.151594,1.053646)); + hpcpush(hpxyz(-0.248719,0.149489,1.041253)); + hpcpush(hpxyz(-0.200432,0.139924,1.029442)); + hpcpush(hpxyz(-0.139171,0.124392,1.017272)); + hpcpush(hpxyz(-0.102260,0.110782,1.011301)); + hpcpush(hpxyz(-0.077429,0.101626,1.008128)); + hpcpush(hpxyz(0.041877,-0.057431,1.002523)); + + bshape(shPrinceDress, 42); + hpcpush(hpxyz(-0.123399,0.032664,1.008114)); + hpcpush(hpxyz(-0.122325,0.049657,1.008677)); + hpcpush(hpxyz(-0.121280,0.064278,1.009376)); + hpcpush(hpxyz(-0.114003,0.076406,1.009373)); + hpcpush(hpxyz(-0.098124,0.089645,1.008794)); + hpcpush(hpxyz(-0.084789,0.101747,1.008733)); + hpcpush(hpxyz(-0.081167,0.105396,1.008809)); + hpcpush(hpxyz(-0.080113,0.115314,1.009810)); + hpcpush(hpxyz(-0.099259,0.181148,1.021111)); + hpcpush(hpxyz(-0.053980,0.166846,1.015259)); + hpcpush(hpxyz(-0.018484,0.187307,1.017559)); + hpcpush(hpxyz(-0.015849,0.154831,1.012039)); + hpcpush(hpxyz(-0.013334,0.134548,1.009099)); + hpcpush(hpxyz(0.006043,0.123271,1.007587)); + hpcpush(hpxyz(0.021636,0.096161,1.004846)); + hpcpush(hpxyz(0.031121,0.067030,1.002727)); + hpcpush(hpxyz(0.038206,0.038206,1.001459)); + hpcpush(hpxyz(0.038163,0.017889,1.000888)); + hpcpush(hpxyz(0.038163,-0.017889,1.000888)); + hpcpush(hpxyz(0.038206,-0.038206,1.001459)); + hpcpush(hpxyz(0.031121,-0.067030,1.002727)); + hpcpush(hpxyz(0.021636,-0.096161,1.004846)); + hpcpush(hpxyz(0.006043,-0.123271,1.007587)); + hpcpush(hpxyz(-0.013334,-0.134548,1.009099)); + hpcpush(hpxyz(-0.015849,-0.154831,1.012039)); + hpcpush(hpxyz(-0.018484,-0.187307,1.017559)); + hpcpush(hpxyz(-0.053980,-0.166846,1.015259)); + hpcpush(hpxyz(-0.099259,-0.181148,1.021111)); + hpcpush(hpxyz(-0.080113,-0.115314,1.009810)); + hpcpush(hpxyz(-0.081167,-0.105396,1.008809)); + hpcpush(hpxyz(-0.084789,-0.101747,1.008733)); + hpcpush(hpxyz(-0.098124,-0.089645,1.008794)); + hpcpush(hpxyz(-0.114003,-0.076406,1.009373)); + hpcpush(hpxyz(-0.121280,-0.064278,1.009376)); + hpcpush(hpxyz(-0.122325,-0.049657,1.008677)); + hpcpush(hpxyz(-0.123399,-0.032664,1.008114)); + hpcpush(hpxyz(-0.123399,0.032664,1.008114)); bshape(shArmor, 42); hpcpush(hpxyz(-0.131705,0.010875,1.008694)); @@ -2947,6 +4186,83 @@ void buildpolys() { hpcpush(hpxyz(-0.131705,-0.010875,1.008694)); hpcpush(hpxyz(-0.131705,0.010875,1.008694)); + bshape(shTurban1, 44); + hpcpush(hpxyz(-0.072384,-0.002801,1.002620)); + hpcpush(hpxyz(-0.075078,0.020302,1.003020)); + hpcpush(hpxyz(-0.067673,0.048512,1.003461)); + hpcpush(hpxyz(-0.046761,0.065782,1.003252)); + hpcpush(hpxyz(-0.011565,0.081749,1.003403)); + hpcpush(hpxyz(0.024684,0.095470,1.004850)); + hpcpush(hpxyz(0.076082,0.087352,1.006687)); + hpcpush(hpxyz(0.102859,0.061877,1.007179)); + hpcpush(hpxyz(0.113555,0.034171,1.007007)); + hpcpush(hpxyz(0.113555,-0.034171,1.007007)); + hpcpush(hpxyz(0.102859,-0.061877,1.007179)); + hpcpush(hpxyz(0.076082,-0.087352,1.006687)); + hpcpush(hpxyz(0.024684,-0.095470,1.004850)); + hpcpush(hpxyz(-0.011565,-0.081749,1.003403)); + hpcpush(hpxyz(-0.046761,-0.065782,1.003252)); + hpcpush(hpxyz(-0.067673,-0.048512,1.003461)); + hpcpush(hpxyz(-0.075078,-0.020302,1.003020)); + hpcpush(hpxyz(-0.072384,0.002801,1.002620)); + hpcpush(hpxyz(-0.072384,-0.002801,1.002620)); + + bshape(shTurban2, 45); + hpcpush(hpxyz(-0.041779,0.001538,1.000874)); + hpcpush(hpxyz(-0.029927,0.025572,1.000774)); + hpcpush(hpxyz(-0.001577,0.046885,1.001100)); + hpcpush(hpxyz(0.030017,0.051171,1.001758)); + hpcpush(hpxyz(0.051757,0.039557,1.002120)); + hpcpush(hpxyz(0.066202,0.014187,1.002289)); + hpcpush(hpxyz(0.066202,-0.014187,1.002289)); + hpcpush(hpxyz(0.051757,-0.039557,1.002120)); + hpcpush(hpxyz(0.030017,-0.051171,1.001758)); + hpcpush(hpxyz(-0.001577,-0.046885,1.001100)); + hpcpush(hpxyz(-0.029927,-0.025572,1.000774)); + hpcpush(hpxyz(-0.041779,-0.001538,1.000874)); + hpcpush(hpxyz(-0.041779,0.001538,1.000874)); + + bshape(shVikingHelmet, 44); + hpcpush(hpxyz(-0.068191,-0.016749,1.002462)); + hpcpush(hpxyz(-0.064642,-0.037110,1.002774)); + hpcpush(hpxyz(-0.055059,-0.049075,1.002716)); + hpcpush(hpxyz(-0.040676,-0.057425,1.002473)); + hpcpush(hpxyz(-0.027503,-0.060986,1.002235)); + hpcpush(hpxyz(-0.030377,-0.140951,1.010342)); + hpcpush(hpxyz(-0.026834,-0.154904,1.012282)); + hpcpush(hpxyz(-0.003670,-0.166357,1.013750)); + hpcpush(hpxyz(0.018370,-0.168999,1.014346)); + hpcpush(hpxyz(0.055380,-0.175984,1.016876)); + hpcpush(hpxyz(0.082350,-0.161012,1.016222)); + hpcpush(hpxyz(0.068527,-0.152961,1.013949)); + hpcpush(hpxyz(0.031640,-0.146029,1.011101)); + hpcpush(hpxyz(0.008493,-0.138308,1.009555)); + hpcpush(hpxyz(-0.002413,-0.117054,1.006830)); + hpcpush(hpxyz(-0.004785,-0.069381,1.002415)); + hpcpush(hpxyz(0.017935,-0.063369,1.002166)); + hpcpush(hpxyz(0.049033,-0.046641,1.002287)); + hpcpush(hpxyz(0.032200,-0.027430,1.000894)); + hpcpush(hpxyz(0.032200,0.027430,1.000894)); + hpcpush(hpxyz(0.049033,0.046641,1.002287)); + hpcpush(hpxyz(0.017935,0.063369,1.002166)); + hpcpush(hpxyz(-0.004785,0.069381,1.002415)); + hpcpush(hpxyz(-0.002413,0.117054,1.006830)); + hpcpush(hpxyz(0.008493,0.138308,1.009555)); + hpcpush(hpxyz(0.031640,0.146029,1.011101)); + hpcpush(hpxyz(0.068527,0.152961,1.013949)); + hpcpush(hpxyz(0.082350,0.161012,1.016222)); + hpcpush(hpxyz(0.055380,0.175984,1.016876)); + hpcpush(hpxyz(0.018370,0.168999,1.014346)); + hpcpush(hpxyz(-0.003670,0.166357,1.013750)); + hpcpush(hpxyz(-0.026834,0.154904,1.012282)); + hpcpush(hpxyz(-0.030377,0.140951,1.010342)); + hpcpush(hpxyz(-0.027503,0.060986,1.002235)); + hpcpush(hpxyz(-0.040676,0.057425,1.002473)); + hpcpush(hpxyz(-0.055059,0.049075,1.002716)); + hpcpush(hpxyz(-0.064642,0.037110,1.002774)); + hpcpush(hpxyz(-0.068191,0.016749,1.002462)); + hpcpush(hpxyz(-0.068191,-0.016749,1.002462)); + bshape(shHood, 43); hpcpush(hpxyz(-0.289108,0.001285,1.040954)); hpcpush(hpxyz(-0.253872,0.006315,1.031742)); @@ -3022,6 +4338,71 @@ void buildpolys() { hpcpush(hpxyz(-0.289108,-0.001285,1.040954)); hpcpush(hpxyz(-0.289108,0.001285,1.040954)); + bshape(shPirateX, 21); + hpcpush(hpxyz(-0.217493,-0.115996,1.029931)); + hpcpush(hpxyz(-0.119624,-0.071774,1.009684)); + hpcpush(hpxyz(-0.076312,-0.023848,1.003191)); + hpcpush(hpxyz(-0.076312,0.023848,1.003191)); + hpcpush(hpxyz(-0.119624,0.071774,1.009684)); + hpcpush(hpxyz(-0.217493,0.115996,1.029931)); + hpcpush(hpxyz(-0.115996,0.217493,1.029931)); + hpcpush(hpxyz(-0.071774,0.119624,1.009684)); + hpcpush(hpxyz(-0.023848,0.076312,1.003191)); + hpcpush(hpxyz(0.023848,0.076312,1.003191)); + hpcpush(hpxyz(0.071774,0.119624,1.009684)); + hpcpush(hpxyz(0.115996,0.217493,1.029931)); + hpcpush(hpxyz(0.217493,0.115996,1.029931)); + hpcpush(hpxyz(0.119624,0.071774,1.009684)); + hpcpush(hpxyz(0.076312,0.023848,1.003191)); + hpcpush(hpxyz(0.076312,-0.023848,1.003191)); + hpcpush(hpxyz(0.119624,-0.071774,1.009684)); + hpcpush(hpxyz(0.217493,-0.115996,1.029931)); + hpcpush(hpxyz(0.115996,-0.217493,1.029931)); + hpcpush(hpxyz(0.071774,-0.119624,1.009684)); + hpcpush(hpxyz(0.023848,-0.076312,1.003191)); + hpcpush(hpxyz(-0.023848,-0.076312,1.003191)); + hpcpush(hpxyz(-0.071774,-0.119624,1.009684)); + hpcpush(hpxyz(-0.115996,-0.217493,1.029931)); + hpcpush(hpxyz(-0.217493,-0.115996,1.029931)); + + bshape(shPirateHood, 47); + hpcpush(hpxyz(0.028515,-0.002137,1.000409)); + hpcpush(hpxyz(0.030041,0.018069,1.000614)); + hpcpush(hpxyz(0.041515,0.042413,1.001760)); + hpcpush(hpxyz(0.018125,0.065806,1.002327)); + hpcpush(hpxyz(-0.016208,0.072033,1.002722)); + hpcpush(hpxyz(-0.045904,0.078062,1.004092)); + hpcpush(hpxyz(-0.082076,0.083600,1.006839)); + hpcpush(hpxyz(-0.135647,0.084840,1.012718)); + hpcpush(hpxyz(-0.187346,0.092498,1.021594)); + hpcpush(hpxyz(-0.230428,0.116494,1.032796)); + hpcpush(hpxyz(-0.151031,0.111393,1.017457)); + hpcpush(hpxyz(-0.111628,0.086283,1.009904)); + hpcpush(hpxyz(-0.087869,0.069439,1.006252)); + hpcpush(hpxyz(-0.097756,0.014558,1.004872)); + hpcpush(hpxyz(-0.097756,-0.014558,1.004872)); + hpcpush(hpxyz(-0.087869,-0.069439,1.006252)); + hpcpush(hpxyz(-0.111628,-0.086283,1.009904)); + hpcpush(hpxyz(-0.151031,-0.111393,1.017457)); + hpcpush(hpxyz(-0.230428,-0.116494,1.032796)); + hpcpush(hpxyz(-0.187346,-0.092498,1.021594)); + hpcpush(hpxyz(-0.135647,-0.084840,1.012718)); + hpcpush(hpxyz(-0.082076,-0.083600,1.006839)); + hpcpush(hpxyz(-0.045904,-0.078062,1.004092)); + hpcpush(hpxyz(-0.016208,-0.072033,1.002722)); + hpcpush(hpxyz(0.018125,-0.065806,1.002327)); + hpcpush(hpxyz(0.041515,-0.042413,1.001760)); + hpcpush(hpxyz(0.030041,-0.018069,1.000614)); + hpcpush(hpxyz(0.028515,0.002137,1.000409)); + hpcpush(hpxyz(0.028515,-0.002137,1.000409)); + + bshape(shEyepatch, 46); + hpcpush(hpxyz(0.029860,-0.048970,1.001643)); + hpcpush(hpxyz(0.063361,0.014346,1.002108)); + hpcpush(hpxyz(0.059794,0.031093,1.002268)); + hpcpush(hpxyz(0.017892,-0.040556,1.000982)); + hpcpush(hpxyz(0.029860,-0.048970,1.001643)); + bshape(shPHead, 44); hpcpush(hpxyz(0.060794,0.001192,1.001847)); hpcpush(hpxyz(0.058426,0.023847,1.001989)); @@ -3666,7 +5047,7 @@ void buildpolys() { hpcpush(hpxyz(0.069133,0.279061,1.040507)); hpcpush(hpxyz(0.096293,0.278465,1.042504)); - bshape(shFlailBall, 40); + bshape(shFlailBall, 46); hpcpush(hpxyz(-0.152664,-0.216202,1.034432)); hpcpush(hpxyz(-0.169658,-0.186257,1.031250)); hpcpush(hpxyz(-0.175291,-0.180580,1.031182)); @@ -3776,37 +5157,784 @@ void buildpolys() { hpcpush(hpxyz(0.117580,-0.140943,1.016705)); hpcpush(hpxyz(0.124720,-0.151933,1.019136)); hpcpush(hpxyz(0.124731,-0.149526,1.018781)); + + bshape(shBoatOuter, 12); + + hpcpush(hpxyz(-0.254359,0.147192,1.042288)); + hpcpush(hpxyz(-0.147845,0.149087,1.021805)); + hpcpush(hpxyz(0.030409,0.144749,1.010879)); + hpcpush(hpxyz(0.120225,0.127586,1.015250)); + hpcpush(hpxyz(0.172686,0.119265,1.021785)); + hpcpush(hpxyz(0.208240,0.105375,1.026873)); + hpcpush(hpxyz(0.245303,0.092783,1.033819)); + hpcpush(hpxyz(0.286782,0.068466,1.042560)); + hpcpush(hpxyz(0.309035,0.045638,1.047657)); + hpcpush(hpxyz(0.335671,0.021145,1.055046)); + hpcpush(hpxyz(0.352147,0.009337,1.060233)); + hpcpush(hpxyz(0.357212,0.006689,1.061906)); + hpcpush(hpxyz(0.357212,-0.006689,1.061906)); + hpcpush(hpxyz(0.352147,-0.009337,1.060233)); + hpcpush(hpxyz(0.335671,-0.021145,1.055046)); + hpcpush(hpxyz(0.309035,-0.045638,1.047657)); + hpcpush(hpxyz(0.286782,-0.068466,1.042560)); + hpcpush(hpxyz(0.245303,-0.092783,1.033819)); + hpcpush(hpxyz(0.208240,-0.105375,1.026873)); + hpcpush(hpxyz(0.172686,-0.119265,1.021785)); + hpcpush(hpxyz(0.120225,-0.127586,1.015250)); + hpcpush(hpxyz(0.030409,-0.144749,1.010879)); + hpcpush(hpxyz(-0.147845,-0.149087,1.021805)); + hpcpush(hpxyz(-0.254359,-0.147192,1.042288)); + hpcpush(hpxyz(-0.254359,0.147192,1.042288)); + + bshape(shBoatInner, 13); + + hpcpush(hpxyz(-0.229820,0.121893,1.033284)); + hpcpush(hpxyz(0.022940,0.117115,1.007096)); + hpcpush(hpxyz(0.169024,0.090064,1.018175)); + hpcpush(hpxyz(0.256702,0.052103,1.033736)); + hpcpush(hpxyz(0.299070,-0.000000,1.043764)); + hpcpush(hpxyz(0.299070,0.000000,1.043764)); + hpcpush(hpxyz(0.256702,-0.052103,1.033736)); + hpcpush(hpxyz(0.169024,-0.090064,1.018175)); + hpcpush(hpxyz(0.022940,-0.117115,1.007096)); + hpcpush(hpxyz(-0.229820,-0.121893,1.033284)); + hpcpush(hpxyz(-0.229820,0.121893,1.033284)); + bshape(shScratch, 17); + hpcpush(hpxyz(-0.028983,0.241948,1.029261)); + hpcpush(hpxyz(-0.028983,-0.241948,1.029261)); + hpcpush(hpxyz(-0.028983,0.241948,1.029261)); + + bshape(shHeptaMarker, 17); + for(int t=0; t<=7; t++) hpcpush(ddi(t*12, hexf*.2) * C0); bshape(shBigHepta, 11); for(int t=0; t<=7; t++) hpcpush(ddi(t*12, -hexf*1.5) * C0); + bshape(shBigHex, 11); + for(int t=0; t<=6; t++) hpcpush(ddi(t*14, -hexf*1.3) * C0); + bshape(shBigTriangle, 11); for(int t=0; t<=3; t++) hpcpush(ddi(t*28, -hexf*1.5) * C0); + bshape(shBigHexTriangleRev, 11); + for(int t=0; t<=3; t++) hpcpush(ddi(t*28, -hexf*1.3) * C0); + + bshape(shBigHexTriangle, 11); + for(int t=0; t<=3; t++) hpcpush(ddi(14+t*28, -hexf*1.3) * C0); + + bshape(shSkeletonBody, 41); + hpcpush(hpxyz(0.001190,0.001190,1.000001)); + hpcpush(hpxyz(0.001193,-0.042936,1.000922)); + hpcpush(hpxyz(-0.004786,-0.070589,1.002500)); + hpcpush(hpxyz(-0.016803,-0.088814,1.004077)); + hpcpush(hpxyz(-0.036099,-0.097467,1.005387)); + hpcpush(hpxyz(-0.038444,-0.087700,1.004574)); + hpcpush(hpxyz(-0.028752,-0.074277,1.003167)); + hpcpush(hpxyz(-0.022672,-0.042958,1.001179)); + hpcpush(hpxyz(-0.022648,-0.027416,1.000632)); + hpcpush(hpxyz(-0.044152,-0.020286,1.001180)); + hpcpush(hpxyz(-0.046994,-0.100012,1.006087)); + hpcpush(hpxyz(-0.031489,-0.240575,1.029013)); + hpcpush(hpxyz(0.044046,-0.236589,1.028550)); + hpcpush(hpxyz(0.052529,-0.220120,1.025286)); + hpcpush(hpxyz(0.068888,-0.219190,1.026055)); + hpcpush(hpxyz(0.079398,-0.230631,1.029318)); + hpcpush(hpxyz(0.083186,-0.263635,1.037508)); + hpcpush(hpxyz(0.062603,-0.265745,1.036600)); + hpcpush(hpxyz(0.048239,-0.255158,1.033166)); + hpcpush(hpxyz(-0.048471,-0.265315,1.035732)); + hpcpush(hpxyz(-0.068926,-0.105203,1.007878)); + hpcpush(hpxyz(-0.070637,-0.026339,1.002838)); + hpcpush(hpxyz(-0.085171,-0.020393,1.003828)); + hpcpush(hpxyz(-0.085171,0.020393,1.003828)); + hpcpush(hpxyz(-0.070637,0.026339,1.002838)); + hpcpush(hpxyz(-0.068926,0.105203,1.007878)); + hpcpush(hpxyz(-0.048471,0.265315,1.035732)); + hpcpush(hpxyz(0.048239,0.255158,1.033166)); + hpcpush(hpxyz(0.062603,0.265745,1.036600)); + hpcpush(hpxyz(0.083186,0.263635,1.037508)); + hpcpush(hpxyz(0.079398,0.230631,1.029318)); + hpcpush(hpxyz(0.068888,0.219190,1.026055)); + hpcpush(hpxyz(0.052529,0.220120,1.025286)); + hpcpush(hpxyz(0.044046,0.236589,1.028550)); + hpcpush(hpxyz(-0.031489,0.240575,1.029013)); + hpcpush(hpxyz(-0.046994,0.100012,1.006087)); + hpcpush(hpxyz(-0.044152,0.020286,1.001180)); + hpcpush(hpxyz(-0.022648,0.027416,1.000632)); + hpcpush(hpxyz(-0.022672,0.042958,1.001179)); + hpcpush(hpxyz(-0.028752,0.074277,1.003167)); + hpcpush(hpxyz(-0.038444,0.087700,1.004574)); + hpcpush(hpxyz(-0.036099,0.097467,1.005387)); + hpcpush(hpxyz(-0.016803,0.088814,1.004077)); + hpcpush(hpxyz(-0.004786,0.070589,1.002500)); + hpcpush(hpxyz(0.001193,0.042936,1.000922)); + hpcpush(hpxyz(0.001190,-0.001190,1.000001)); + hpcpush(hpxyz(0.001190,0.001190,1.000001)); + + bshape(shSkull, 42); + hpcpush(hpxyz(-0.120823,0.019332,1.007458)); + hpcpush(hpxyz(-0.089124,0.061424,1.005841)); + hpcpush(hpxyz(-0.035904,0.063430,1.002653)); + hpcpush(hpxyz(0.019074,0.032188,1.000700)); + hpcpush(hpxyz(0.022631,0.004764,1.000267)); + hpcpush(hpxyz(0.022631,-0.004764,1.000267)); + hpcpush(hpxyz(0.019074,-0.032188,1.000700)); + hpcpush(hpxyz(-0.035904,-0.063430,1.002653)); + hpcpush(hpxyz(-0.089124,-0.061424,1.005841)); + hpcpush(hpxyz(-0.120823,-0.019332,1.007458)); + hpcpush(hpxyz(-0.120823,0.019332,1.007458)); + + bshape(shSkullEyes, 43); + hpcpush(hpxyz(-0.001191,0.010716,1.000058)); + hpcpush(hpxyz(-0.016673,0.009527,1.000184)); + hpcpush(hpxyz(-0.016682,0.025023,1.000452)); + hpcpush(hpxyz(-0.002382,0.022631,1.000259)); + hpcpush(hpxyz(0.001191,0.023823,1.000284)); + hpcpush(hpxyz(0.001191,-0.023823,1.000284)); + hpcpush(hpxyz(-0.002382,-0.022631,1.000259)); + hpcpush(hpxyz(-0.016682,-0.025023,1.000452)); + hpcpush(hpxyz(-0.016673,-0.009527,1.000184)); + hpcpush(hpxyz(-0.001191,-0.010716,1.000058)); + hpcpush(hpxyz(-0.001191,0.010716,1.000058)); + + bshape(shFishTail, 30); + hpcpush(hpxyz(-0.003571,0.001190,1.000007)); + hpcpush(hpxyz(-0.007145,0.015481,1.000145)); + hpcpush(hpxyz(-0.015500,0.035769,1.000760)); + hpcpush(hpxyz(-0.031072,0.053778,1.001927)); + hpcpush(hpxyz(-0.047927,0.064702,1.003236)); + hpcpush(hpxyz(-0.062478,0.073291,1.004627)); + hpcpush(hpxyz(-0.083262,0.082055,1.006810)); + hpcpush(hpxyz(-0.098001,0.082272,1.008153)); + hpcpush(hpxyz(-0.111474,0.073912,1.008905)); + hpcpush(hpxyz(-0.123761,0.063094,1.009603)); + hpcpush(hpxyz(-0.129971,0.059519,1.010166)); + hpcpush(hpxyz(-0.138754,0.057206,1.011200)); + hpcpush(hpxyz(-0.148852,0.053684,1.012442)); + hpcpush(hpxyz(-0.164257,0.053935,1.014835)); + hpcpush(hpxyz(-0.177269,0.054165,1.017034)); + hpcpush(hpxyz(-0.191786,0.054443,1.019679)); + hpcpush(hpxyz(-0.214728,0.056179,1.024336)); + hpcpush(hpxyz(-0.227189,0.058994,1.027178)); + hpcpush(hpxyz(-0.237162,0.065598,1.029829)); + hpcpush(hpxyz(-0.240110,0.069505,1.030768)); + hpcpush(hpxyz(-0.248932,0.077474,1.033426)); + hpcpush(hpxyz(-0.262350,0.087023,1.037497)); + hpcpush(hpxyz(-0.271446,0.092626,1.040318)); + hpcpush(hpxyz(-0.278978,0.094284,1.042458)); + hpcpush(hpxyz(-0.283499,0.094500,1.043696)); + hpcpush(hpxyz(-0.277139,0.087653,1.041388)); + hpcpush(hpxyz(-0.269286,0.078221,1.038573)); + hpcpush(hpxyz(-0.253927,0.055864,1.033247)); + hpcpush(hpxyz(-0.247700,0.034122,1.030786)); + hpcpush(hpxyz(-0.243240,0.018905,1.029331)); + hpcpush(hpxyz(-0.241745,0.005036,1.028818)); + hpcpush(hpxyz(-0.241745,-0.005036,1.028818)); + hpcpush(hpxyz(-0.243240,-0.018905,1.029331)); + hpcpush(hpxyz(-0.247700,-0.034122,1.030786)); + hpcpush(hpxyz(-0.253927,-0.055864,1.033247)); + hpcpush(hpxyz(-0.269286,-0.078221,1.038573)); + hpcpush(hpxyz(-0.277139,-0.087653,1.041388)); + hpcpush(hpxyz(-0.283499,-0.094500,1.043696)); + hpcpush(hpxyz(-0.278978,-0.094284,1.042458)); + hpcpush(hpxyz(-0.271446,-0.092626,1.040318)); + hpcpush(hpxyz(-0.262350,-0.087023,1.037497)); + hpcpush(hpxyz(-0.248932,-0.077474,1.033426)); + hpcpush(hpxyz(-0.240110,-0.069505,1.030768)); + hpcpush(hpxyz(-0.237162,-0.065598,1.029829)); + hpcpush(hpxyz(-0.227189,-0.058994,1.027178)); + hpcpush(hpxyz(-0.214728,-0.056179,1.024336)); + hpcpush(hpxyz(-0.191786,-0.054443,1.019679)); + hpcpush(hpxyz(-0.177269,-0.054165,1.017034)); + hpcpush(hpxyz(-0.164257,-0.053935,1.014835)); + hpcpush(hpxyz(-0.148852,-0.053684,1.012442)); + hpcpush(hpxyz(-0.138754,-0.057206,1.011200)); + hpcpush(hpxyz(-0.129971,-0.059519,1.010166)); + hpcpush(hpxyz(-0.123761,-0.063094,1.009603)); + hpcpush(hpxyz(-0.111474,-0.073912,1.008905)); + hpcpush(hpxyz(-0.098001,-0.082272,1.008153)); + hpcpush(hpxyz(-0.083262,-0.082055,1.006810)); + hpcpush(hpxyz(-0.062478,-0.073291,1.004627)); + hpcpush(hpxyz(-0.047927,-0.064702,1.003236)); + hpcpush(hpxyz(-0.031072,-0.053778,1.001927)); + hpcpush(hpxyz(-0.015500,-0.035769,1.000760)); + hpcpush(hpxyz(-0.007145,-0.015481,1.000145)); + hpcpush(hpxyz(-0.003571,-0.001190,1.000007)); + hpcpush(hpxyz(-0.003571,0.001190,1.000007)); + + bshape(shFatBody, 41); + hpcpush(hpxyz(-0.158280,0.010638,1.012505)); + hpcpush(hpxyz(-0.153491,0.063014,1.013672)); + hpcpush(hpxyz(-0.143004,0.090522,1.014221)); + hpcpush(hpxyz(-0.130133,0.119287,1.015463)); + hpcpush(hpxyz(-0.120336,0.139833,1.016875)); + hpcpush(hpxyz(-0.108707,0.144976,1.016285)); + hpcpush(hpxyz(-0.103459,0.149545,1.016399)); + hpcpush(hpxyz(-0.088463,0.147968,1.014751)); + hpcpush(hpxyz(-0.090694,0.183338,1.020705)); + hpcpush(hpxyz(-0.069574,0.274320,1.039275)); + hpcpush(hpxyz(-0.026928,0.273931,1.037190)); + hpcpush(hpxyz(0.000335,0.278791,1.038135)); + hpcpush(hpxyz(0.049634,0.254674,1.033113)); + hpcpush(hpxyz(0.064323,0.261140,1.035535)); + hpcpush(hpxyz(0.085998,0.258714,1.036498)); + hpcpush(hpxyz(0.084852,0.235757,1.030913)); + hpcpush(hpxyz(0.075972,0.211105,1.024860)); + hpcpush(hpxyz(0.051782,0.222035,1.025661)); + hpcpush(hpxyz(-0.009808,0.219631,1.023882)); + hpcpush(hpxyz(-0.037620,0.215354,1.023617)); + hpcpush(hpxyz(-0.020675,0.185577,1.017284)); + hpcpush(hpxyz(-0.021056,0.141669,1.010205)); + hpcpush(hpxyz(0.007264,0.129328,1.008354)); + hpcpush(hpxyz(0.036658,0.102338,1.005891)); + hpcpush(hpxyz(0.051136,0.057412,1.002951)); + hpcpush(hpxyz(0.056061,-0.003004,1.001575)); + hpcpush(hpxyz(0.056061,0.003004,1.001575)); + hpcpush(hpxyz(0.051136,-0.057412,1.002951)); + hpcpush(hpxyz(0.036658,-0.102338,1.005891)); + hpcpush(hpxyz(0.007264,-0.129328,1.008354)); + hpcpush(hpxyz(-0.021056,-0.141669,1.010205)); + hpcpush(hpxyz(-0.020675,-0.185577,1.017284)); + hpcpush(hpxyz(-0.037620,-0.215354,1.023617)); + hpcpush(hpxyz(-0.009808,-0.219631,1.023882)); + hpcpush(hpxyz(0.051782,-0.222035,1.025661)); + hpcpush(hpxyz(0.075972,-0.211105,1.024860)); + hpcpush(hpxyz(0.084852,-0.235757,1.030913)); + hpcpush(hpxyz(0.085998,-0.258714,1.036498)); + hpcpush(hpxyz(0.064323,-0.261140,1.035535)); + hpcpush(hpxyz(0.049634,-0.254674,1.033113)); + hpcpush(hpxyz(0.000335,-0.278791,1.038135)); + hpcpush(hpxyz(-0.026928,-0.273931,1.037190)); + hpcpush(hpxyz(-0.069574,-0.274320,1.039275)); + hpcpush(hpxyz(-0.090694,-0.183338,1.020705)); + hpcpush(hpxyz(-0.088463,-0.147968,1.014751)); + hpcpush(hpxyz(-0.103459,-0.149545,1.016399)); + hpcpush(hpxyz(-0.108707,-0.144976,1.016285)); + hpcpush(hpxyz(-0.120336,-0.139833,1.016875)); + hpcpush(hpxyz(-0.130133,-0.119287,1.015463)); + hpcpush(hpxyz(-0.143004,-0.090522,1.014221)); + hpcpush(hpxyz(-0.153491,-0.063014,1.013672)); + hpcpush(hpxyz(-0.158280,-0.010638,1.012505)); + + bshape(shZebra[0], 10); + hpcpush(hpxyz(-0.307697,-0.214329,1.067995)); + hpcpush(hpxyz(-0.339462,0.159309,1.067995)); + hpcpush(hpxyz(-0.031766,0.373637,1.067995)); + hpcpush(hpxyz(0.307697,0.214329,1.067995)); + hpcpush(hpxyz(0.339462,-0.159309,1.067995)); + hpcpush(hpxyz(0.031766,-0.373637,1.067995)); + hpcpush(hpxyz(-0.307697,-0.214329,1.067995)); + + bshape(shZebra[1], 10); + hpcpush(hpxyz(-0.192992,-0.168975,1.032375)); + hpcpush(hpxyz(-0.238865,0.204661,1.048305)); + hpcpush(hpxyz(-0.080551,0.254199,1.034942)); + hpcpush(hpxyz(0.347359,0.222111,1.081662)); + hpcpush(hpxyz(0.392920,-0.180638,1.089503)); + hpcpush(hpxyz(0.019691,-0.156962,1.012435)); + hpcpush(hpxyz(-0.192992,-0.168975,1.032375)); + + bshape(shZebra[2], 10); + hpcpush(hpxyz(-0.255158,0.223637,1.055992)); + hpcpush(hpxyz(-0.114892,0.277358,1.044092)); + hpcpush(hpxyz(0.260873,0.219611,1.056543)); + hpcpush(hpxyz(0.444210,0.107854,1.099525)); + hpcpush(hpxyz(0.255129,-0.352141,1.090456)); + hpcpush(hpxyz(-0.058563,-0.195290,1.020572)); + hpcpush(hpxyz(-0.205857,-0.164479,1.034133)); + hpcpush(hpxyz(-0.255158,0.223637,1.055992)); + + bshape(shZebra[3], 10); + hpcpush(hpxyz(0.248469,0.308508,1.075599)); + hpcpush(hpxyz(0.257329,0.012990,1.032660)); + hpcpush(hpxyz(0.288207,-0.281417,1.078081)); + hpcpush(hpxyz(0.038093,-0.236115,1.028203)); + hpcpush(hpxyz(-0.209655,-0.205481,1.042198)); + hpcpush(hpxyz(-0.224279,0.047025,1.025920)); + hpcpush(hpxyz(-0.253191,0.302526,1.075001)); + hpcpush(hpxyz(-0.002290,0.296336,1.042986)); + hpcpush(hpxyz(0.248469,0.308508,1.075599)); + + bshape(shEmeraldFloor[0], 10); // 4 + hpcpush(hpxyz(-0.056700,0.289325,1.042556)); + hpcpush(hpxyz(0.003114,0.299067,1.043768)); + hpcpush(hpxyz(0.041221,0.283536,1.040237)); + hpcpush(hpxyz(0.125459,0.234982,1.034870)); + hpcpush(hpxyz(0.181143,0.183624,1.032730)); + hpcpush(hpxyz(0.228595,0.105917,1.031249)); + hpcpush(hpxyz(0.268750,0.012281,1.035557)); + hpcpush(hpxyz(0.313793,-0.081056,1.051207)); + hpcpush(hpxyz(0.306997,-0.188603,1.062929)); + hpcpush(hpxyz(0.262425,-0.286297,1.072769)); + hpcpush(hpxyz(0.218519,-0.355547,1.083588)); + hpcpush(hpxyz(0.153244,-0.376219,1.079363)); + hpcpush(hpxyz(0.046875,-0.364611,1.065429)); + hpcpush(hpxyz(-0.019398,-0.349785,1.059588)); + hpcpush(hpxyz(-0.083546,-0.322881,1.054150)); + hpcpush(hpxyz(-0.141981,-0.272036,1.046022)); + hpcpush(hpxyz(-0.195959,-0.227784,1.044167)); + hpcpush(hpxyz(-0.221863,-0.171718,1.038610)); + hpcpush(hpxyz(-0.239605,-0.111801,1.034365)); + hpcpush(hpxyz(-0.260405,-0.063040,1.035270)); + hpcpush(hpxyz(-0.276108,0.051160,1.038679)); + hpcpush(hpxyz(-0.250004,0.138005,1.039975)); + hpcpush(hpxyz(-0.184725,0.213503,1.039089)); + hpcpush(hpxyz(-0.125567,0.259839,1.040809)); + hpcpush(hpxyz(-0.056700,0.289325,1.042556)); + + bshape(shEmeraldFloor[1], 10); // 12 + hpcpush(hpxyz(-0.012456,-0.282668,1.039258)); + hpcpush(hpxyz(0.093943,-0.261125,1.037792)); + hpcpush(hpxyz(0.176033,-0.224423,1.039881)); + hpcpush(hpxyz(0.251304,-0.129592,1.039205)); + hpcpush(hpxyz(0.253408,0.003018,1.031613)); + hpcpush(hpxyz(0.205115,0.151740,1.032035)); + hpcpush(hpxyz(0.136504,0.257503,1.041605)); + hpcpush(hpxyz(0.050478,0.321171,1.051522)); + hpcpush(hpxyz(-0.024338,0.351747,1.060339)); + hpcpush(hpxyz(-0.113671,0.338793,1.061933)); + hpcpush(hpxyz(-0.199507,0.312663,1.066565)); + hpcpush(hpxyz(-0.289397,0.244537,1.069368)); + hpcpush(hpxyz(-0.318919,0.189505,1.066593)); + hpcpush(hpxyz(-0.296780,0.103663,1.048248)); + hpcpush(hpxyz(-0.266492,-0.004074,1.034908)); + hpcpush(hpxyz(-0.225121,-0.113729,1.031316)); + hpcpush(hpxyz(-0.162566,-0.195216,1.031764)); + hpcpush(hpxyz(-0.093623,-0.256862,1.036698)); + hpcpush(hpxyz(-0.073239,-0.271190,1.038705)); + hpcpush(hpxyz(-0.012456,-0.282668,1.039258)); + + bshape(shEmeraldFloor[2], 10); // 16 + hpcpush(hpxyz(0.142342,0.315002,1.058058)); + hpcpush(hpxyz(0.192633,0.259152,1.050841)); + hpcpush(hpxyz(0.232117,0.228558,1.051721)); + hpcpush(hpxyz(0.263994,0.150040,1.045086)); + hpcpush(hpxyz(0.283920,0.084560,1.042958)); + hpcpush(hpxyz(0.289892,-0.010808,1.041227)); + hpcpush(hpxyz(0.297148,-0.086089,1.046761)); + hpcpush(hpxyz(0.297551,-0.165417,1.056361)); + hpcpush(hpxyz(0.290991,-0.200376,1.060578)); + hpcpush(hpxyz(0.258510,-0.274435,1.068710)); + hpcpush(hpxyz(0.200576,-0.292802,1.061114)); + hpcpush(hpxyz(0.137570,-0.326255,1.060833)); + hpcpush(hpxyz(0.057449,-0.363515,1.065572)); + hpcpush(hpxyz(0.007219,-0.381780,1.070424)); + hpcpush(hpxyz(-0.042563,-0.362309,1.064462)); + hpcpush(hpxyz(-0.099799,-0.296581,1.047817)); + hpcpush(hpxyz(-0.126618,-0.259997,1.040976)); + hpcpush(hpxyz(-0.164471,-0.210125,1.034989)); + hpcpush(hpxyz(-0.206762,-0.179726,1.036847)); + hpcpush(hpxyz(-0.255672,-0.132984,1.040698)); + hpcpush(hpxyz(-0.278657,-0.105484,1.043445)); + hpcpush(hpxyz(-0.292210,-0.086272,1.045385)); + hpcpush(hpxyz(-0.317777,-0.034598,1.049847)); + hpcpush(hpxyz(-0.332027,0.039956,1.054438)); + hpcpush(hpxyz(-0.311197,0.107127,1.052768)); + hpcpush(hpxyz(-0.293985,0.148441,1.052835)); + hpcpush(hpxyz(-0.261872,0.181378,1.049512)); + hpcpush(hpxyz(-0.161843,0.220098,1.036647)); + hpcpush(hpxyz(-0.080956,0.253464,1.034794)); + hpcpush(hpxyz(-0.028510,0.284753,1.040143)); + hpcpush(hpxyz(0.013578,0.313129,1.047967)); + hpcpush(hpxyz(0.055797,0.341483,1.058170)); + hpcpush(hpxyz(0.142342,0.315002,1.058058)); + + bshape(shEmeraldFloor[3], 10); // 20 + hpcpush(hpxyz(-0.163082,-0.220437,1.036913)); + hpcpush(hpxyz(-0.210355,-0.178152,1.037298)); + hpcpush(hpxyz(-0.270116,-0.134375,1.044519)); + hpcpush(hpxyz(-0.286296,-0.068967,1.042460)); + hpcpush(hpxyz(-0.322640,0.023933,1.051033)); + hpcpush(hpxyz(-0.303410,0.080931,1.048145)); + hpcpush(hpxyz(-0.256143,0.157047,1.044161)); + hpcpush(hpxyz(-0.191383,0.193946,1.036457)); + hpcpush(hpxyz(-0.112200,0.248267,1.036448)); + hpcpush(hpxyz(-0.006180,0.297906,1.043449)); + hpcpush(hpxyz(0.045011,0.314576,1.049278)); + hpcpush(hpxyz(0.123367,0.290642,1.048662)); + hpcpush(hpxyz(0.173268,0.251704,1.045647)); + hpcpush(hpxyz(0.226704,0.200367,1.044769)); + hpcpush(hpxyz(0.274509,0.112459,1.043073)); + hpcpush(hpxyz(0.272693,0.041554,1.037347)); + hpcpush(hpxyz(0.266634,-0.039227,1.035680)); + hpcpush(hpxyz(0.245934,-0.087769,1.033531)); + hpcpush(hpxyz(0.206654,-0.145971,1.031510)); + hpcpush(hpxyz(0.168911,-0.181347,1.030251)); + hpcpush(hpxyz(0.113778,-0.241571,1.035037)); + hpcpush(hpxyz(0.060166,-0.287358,1.042207)); + hpcpush(hpxyz(-0.030419,-0.300995,1.044760)); + hpcpush(hpxyz(-0.106762,-0.252814,1.036973)); + hpcpush(hpxyz(-0.163082,-0.220437,1.036913)); + + bshape(shEmeraldFloor[4], 10); // 28 + hpcpush(hpxyz(-0.121227,-0.290032,1.048244)); + hpcpush(hpxyz(-0.211853,-0.226567,1.047003)); + hpcpush(hpxyz(-0.271304,-0.142026,1.045838)); + hpcpush(hpxyz(-0.291031,-0.001756,1.041490)); + hpcpush(hpxyz(-0.289025,0.081565,1.044121)); + hpcpush(hpxyz(-0.274404,0.151774,1.048014)); + hpcpush(hpxyz(-0.270636,0.184903,1.052346)); + hpcpush(hpxyz(-0.177964,0.228844,1.041173)); + hpcpush(hpxyz(-0.109553,0.258706,1.038716)); + hpcpush(hpxyz(-0.046057,0.288157,1.041708)); + hpcpush(hpxyz(0.012352,0.334753,1.054615)); + hpcpush(hpxyz(0.093790,0.294439,1.046657)); + hpcpush(hpxyz(0.113901,0.258432,1.039115)); + hpcpush(hpxyz(0.169445,0.181108,1.030297)); + hpcpush(hpxyz(0.201022,0.133994,1.028768)); + hpcpush(hpxyz(0.217873,0.089759,1.027388)); + hpcpush(hpxyz(0.229954,0.028756,1.026502)); + hpcpush(hpxyz(0.219894,-0.023561,1.024162)); + hpcpush(hpxyz(0.191854,-0.102714,1.023405)); + hpcpush(hpxyz(0.155541,-0.176809,1.027353)); + hpcpush(hpxyz(0.124174,-0.224046,1.032287)); + hpcpush(hpxyz(0.061461,-0.284240,1.041427)); + hpcpush(hpxyz(0.004090,-0.327127,1.052154)); + hpcpush(hpxyz(-0.121227,-0.290032,1.048244)); + + bshape(shEmeraldFloor[5], 10); // 36 + hpcpush(hpxyz(-0.123950,0.204444,1.028183)); + hpcpush(hpxyz(-0.062627,0.216559,1.025095)); + hpcpush(hpxyz(0.004307,0.251676,1.031193)); + hpcpush(hpxyz(0.053230,0.277691,1.039204)); + hpcpush(hpxyz(0.104981,0.268275,1.040669)); + hpcpush(hpxyz(0.179487,0.211716,1.037805)); + hpcpush(hpxyz(0.219611,0.155886,1.035630)); + hpcpush(hpxyz(0.242732,0.098595,1.033750)); + hpcpush(hpxyz(0.253441,0.041064,1.032433)); + hpcpush(hpxyz(0.251167,-0.002564,1.031063)); + hpcpush(hpxyz(0.258569,-0.050639,1.034129)); + hpcpush(hpxyz(0.241512,-0.095904,1.033211)); + hpcpush(hpxyz(0.224178,-0.142437,1.034671)); + hpcpush(hpxyz(0.200723,-0.160460,1.032491)); + hpcpush(hpxyz(0.160438,-0.177252,1.028182)); + hpcpush(hpxyz(0.098857,-0.201735,1.024924)); + hpcpush(hpxyz(0.042704,-0.222826,1.025415)); + hpcpush(hpxyz(-0.046440,-0.220643,1.025105)); + hpcpush(hpxyz(-0.121819,-0.210954,1.029243)); + hpcpush(hpxyz(-0.193674,-0.181500,1.034626)); + hpcpush(hpxyz(-0.240226,-0.152286,1.039663)); + hpcpush(hpxyz(-0.288784,-0.106825,1.046331)); + hpcpush(hpxyz(-0.312611,-0.056858,1.049266)); + hpcpush(hpxyz(-0.322108,0.009276,1.050638)); + hpcpush(hpxyz(-0.323420,0.074633,1.053646)); + hpcpush(hpxyz(-0.320770,0.110549,1.055990)); + hpcpush(hpxyz(-0.238954,0.181091,1.043980)); + hpcpush(hpxyz(-0.123950,0.204444,1.028183)); + + /* + bshape(shTower[0], 10); // 1 + hpcpush(hpxyz(-0.286251,0.206460,1.060455)); + hpcpush(hpxyz(-0.228388,0.237443,1.052872)); + hpcpush(hpxyz(-0.159130,0.310692,1.059175)); + hpcpush(hpxyz(-0.101028,0.374054,1.072438)); + hpcpush(hpxyz(0.075166,0.301721,1.047227)); + hpcpush(hpxyz(0.296628,0.282561,1.080661)); + hpcpush(hpxyz(0.392862,0.273630,1.108699)); + hpcpush(hpxyz(0.406414,0.155729,1.090607)); + hpcpush(hpxyz(0.351704,0.039501,1.060781)); + hpcpush(hpxyz(0.238677,-0.090994,1.032108)); + hpcpush(hpxyz(0.117245,-0.194511,1.025466)); + hpcpush(hpxyz(0.021470,-0.256598,1.032620)); + hpcpush(hpxyz(-0.009932,-0.269112,1.035625)); + hpcpush(hpxyz(-0.142800,-0.030207,1.010596)); + hpcpush(hpxyz(-0.286251,0.206460,1.060455)); + + bshape(shTower[1], 10); // 2 + hpcpush(hpxyz(0.250672,0.215566,1.053236)); + hpcpush(hpxyz(-0.010561,0.166674,1.013850)); + hpcpush(hpxyz(-0.188122,0.172750,1.032101)); + hpcpush(hpxyz(-0.277968,0.195647,1.056193)); + hpcpush(hpxyz(-0.273175,-0.294725,1.077723)); + hpcpush(hpxyz(-0.058073,-0.278517,1.039685)); + hpcpush(hpxyz(0.114633,-0.264898,1.040823)); + hpcpush(hpxyz(0.214865,-0.223092,1.046870)); + hpcpush(hpxyz(0.318979,-0.166948,1.062835)); + hpcpush(hpxyz(0.348056,-0.154771,1.070092)); + hpcpush(hpxyz(0.250672,0.215566,1.053236)); + + bshape(shTower[2], 10); // 4 + hpcpush(hpxyz(-0.305085,0.182715,1.061349)); + hpcpush(hpxyz(-0.141572,-0.249919,1.040434)); + hpcpush(hpxyz(-0.082532,-0.256373,1.035634)); + hpcpush(hpxyz(0.011916,-0.200378,1.019948)); + hpcpush(hpxyz(0.107643,-0.130975,1.014269)); + hpcpush(hpxyz(0.197879,-0.052950,1.020764)); + hpcpush(hpxyz(0.275493,0.054106,1.038665)); + hpcpush(hpxyz(0.346502,0.177608,1.073130)); + hpcpush(hpxyz(0.365290,0.224553,1.088054)); + hpcpush(hpxyz(-0.042684,0.405864,1.080068)); + hpcpush(hpxyz(-0.305085,0.182715,1.061349)); + + bshape(shTower[3], 10); // 5 + hpcpush(hpxyz(-0.244566,0.213804,1.051439)); + hpcpush(hpxyz(-0.121406,0.179228,1.023163)); + hpcpush(hpxyz(0.102781,0.233054,1.031929)); + hpcpush(hpxyz(0.137859,0.248290,1.039545)); + hpcpush(hpxyz(0.219219,0.271805,1.059214)); + hpcpush(hpxyz(0.439787,-0.128376,1.099951)); + hpcpush(hpxyz(0.327884,-0.165668,1.065342)); + hpcpush(hpxyz(0.191605,-0.198467,1.037353)); + hpcpush(hpxyz(-0.015788,-0.263051,1.034140)); + hpcpush(hpxyz(-0.162942,-0.274063,1.049600)); + hpcpush(hpxyz(-0.284113,-0.264520,1.072703)); + hpcpush(hpxyz(-0.360780,-0.248815,1.091820)); + hpcpush(hpxyz(-0.244566,0.213804,1.051439)); + + bshape(shTower[4], 10); // 8 + hpcpush(hpxyz(0.571958,-0.279170,1.185357)); + hpcpush(hpxyz(0.393753,-0.334598,1.125610)); + hpcpush(hpxyz(0.230386,-0.380872,1.094596)); + hpcpush(hpxyz(0.040909,-0.353244,1.061346)); + hpcpush(hpxyz(-0.132206,-0.325608,1.059953)); + hpcpush(hpxyz(-0.193426,-0.301627,1.062258)); + hpcpush(hpxyz(-0.209589,-0.285475,1.060860)); + hpcpush(hpxyz(-0.184256,0.133876,1.025609)); + hpcpush(hpxyz(-0.122720,0.103535,1.012808)); + hpcpush(hpxyz(0.028404,0.096630,1.005059)); + hpcpush(hpxyz(0.131561,0.118840,1.015594)); + hpcpush(hpxyz(0.206961,0.143553,1.031233)); + hpcpush(hpxyz(0.285398,0.171884,1.054038)); + hpcpush(hpxyz(0.311736,0.188934,1.064366)); + hpcpush(hpxyz(0.427540,-0.043657,1.088437)); + hpcpush(hpxyz(0.571958,-0.279170,1.185357)); + + bshape(shTower[5], 10); // 10 + hpcpush(hpxyz(-0.311898,0.273433,1.082611)); + hpcpush(hpxyz(-0.241832,0.284721,1.067496)); + hpcpush(hpxyz(-0.093134,0.385666,1.075831)); + hpcpush(hpxyz(-0.048259,0.410019,1.081871)); + hpcpush(hpxyz(-0.034956,0.418726,1.084690)); + hpcpush(hpxyz(0.323554,0.088209,1.054736)); + hpcpush(hpxyz(0.281449,-0.050570,1.040082)); + hpcpush(hpxyz(0.166974,-0.175799,1.028973)); + hpcpush(hpxyz(0.053476,-0.232832,1.028139)); + hpcpush(hpxyz(-0.046497,-0.270575,1.037002)); + hpcpush(hpxyz(-0.167112,-0.296403,1.056306)); + hpcpush(hpxyz(-0.182433,-0.298027,1.059293)); + hpcpush(hpxyz(-0.237210,-0.011802,1.027817)); + hpcpush(hpxyz(-0.311898,0.273433,1.082611)); + + bshape(shTower[6], 10); // 12 + hpcpush(hpxyz(0.591895,-0.274213,1.193957)); + hpcpush(hpxyz(0.451640,-0.046334,1.098237)); + hpcpush(hpxyz(0.339584,0.178653,1.071090)); + hpcpush(hpxyz(0.075724,0.130436,1.011310)); + hpcpush(hpxyz(-0.048271,0.097633,1.005914)); + hpcpush(hpxyz(-0.223763,-0.157117,1.036704)); + hpcpush(hpxyz(-0.073558,-0.240165,1.031062)); + hpcpush(hpxyz(0.043434,-0.280964,1.039628)); + hpcpush(hpxyz(0.298734,-0.305291,1.087403)); + hpcpush(hpxyz(0.591895,-0.274213,1.193957)); + + bshape(shTower[7], 10); // 16 + hpcpush(hpxyz(0.078002,0.370221,1.069181)); + hpcpush(hpxyz(0.413248,0.133206,1.090192)); + hpcpush(hpxyz(0.355187,0.048021,1.062292)); + hpcpush(hpxyz(0.239656,-0.028483,1.028711)); + hpcpush(hpxyz(0.091569,-0.106563,1.009822)); + hpcpush(hpxyz(-0.053014,-0.170046,1.015739)); + hpcpush(hpxyz(-0.148171,-0.179787,1.026780)); + hpcpush(hpxyz(-0.226021,0.273779,1.061151)); + hpcpush(hpxyz(0.078002,0.370221,1.069181)); + + bshape(shTower[8], 10); // 17 + hpcpush(hpxyz(0.533180,-0.117639,1.139351)); + hpcpush(hpxyz(0.378296,-0.199392,1.087596)); + hpcpush(hpxyz(0.209814,-0.236744,1.048842)); + hpcpush(hpxyz(0.054537,-0.276614,1.038985)); + hpcpush(hpxyz(-0.034481,-0.273513,1.037303)); + hpcpush(hpxyz(-0.160263,-0.038320,1.013485)); + hpcpush(hpxyz(-0.297354,0.194169,1.061189)); + hpcpush(hpxyz(-0.193697,0.211849,1.040384)); + hpcpush(hpxyz(-0.063165,0.262989,1.035931)); + hpcpush(hpxyz(0.036923,0.306670,1.046618)); + hpcpush(hpxyz(0.097986,0.358635,1.066874)); + hpcpush(hpxyz(0.135238,0.379300,1.078034)); + hpcpush(hpxyz(0.318600,0.124720,1.056911)); + hpcpush(hpxyz(0.533180,-0.117639,1.139351)); + + bshape(shTower[9], 10); // 18 + hpcpush(hpxyz(-0.217261,0.132486,1.031870)); + hpcpush(hpxyz(0.024523,0.407718,1.080202)); + hpcpush(hpxyz(0.145333,0.449681,1.106045)); + hpcpush(hpxyz(0.484226,0.101907,1.115733)); + hpcpush(hpxyz(0.321456,-0.134096,1.058922)); + hpcpush(hpxyz(-0.036797,-0.295091,1.043280)); + hpcpush(hpxyz(-0.180549,-0.344274,1.072904)); + hpcpush(hpxyz(-0.259938,-0.172378,1.047512)); + hpcpush(hpxyz(-0.217261,0.132486,1.031870)); + + bshape(shTower[10], 10); // 20 + hpcpush(hpxyz(-0.174062,-0.167910,1.028830)); + hpcpush(hpxyz(-0.295951,0.239183,1.069951)); + hpcpush(hpxyz(-0.212854,0.268510,1.057074)); + hpcpush(hpxyz(-0.079667,0.325104,1.054533)); + hpcpush(hpxyz(-0.024447,0.357384,1.062224)); + hpcpush(hpxyz(0.004880,0.379437,1.069577)); + hpcpush(hpxyz(0.047240,0.411450,1.082369)); + hpcpush(hpxyz(0.404628,0.134398,1.087100)); + hpcpush(hpxyz(0.279121,0.016611,1.038357)); + hpcpush(hpxyz(0.142934,-0.078661,1.013221)); + hpcpush(hpxyz(0.031621,-0.149237,1.011569)); + hpcpush(hpxyz(-0.095567,-0.210063,1.026284)); + hpcpush(hpxyz(-0.174062,-0.167910,1.028830)); + + bshape(shTower[11], 10); // 21 + hpcpush(hpxyz(-0.261640,0.232003,1.059378)); + hpcpush(hpxyz(-0.114066,0.222344,1.030751)); + hpcpush(hpxyz(0.070087,0.311006,1.049589)); + hpcpush(hpxyz(0.146439,0.385502,1.081691)); + hpcpush(hpxyz(0.156417,0.393458,1.085944)); + hpcpush(hpxyz(0.321239,0.151530,1.061205)); + hpcpush(hpxyz(0.513393,-0.077506,1.126756)); + hpcpush(hpxyz(0.367820,-0.144703,1.075282)); + hpcpush(hpxyz(0.183543,-0.172959,1.031311)); + hpcpush(hpxyz(0.022726,-0.215721,1.023256)); + hpcpush(hpxyz(-0.158572,-0.235502,1.039522)); + hpcpush(hpxyz(-0.259609,-0.221068,1.056536)); + hpcpush(hpxyz(-0.283069,-0.211523,1.060599)); + hpcpush(hpxyz(-0.261640,0.232003,1.059378)); + */ + + bshape(shTower[0], 10); // 4 + hpcpush(hpxyz(-0.343678,0.205736,1.077238)); + hpcpush(hpxyz(-0.313502,-0.269598,1.082112)); + hpcpush(hpxyz(0.053446,-0.276534,1.038907)); + hpcpush(hpxyz(0.316036,-0.088255,1.052458)); + hpcpush(hpxyz(0.415175,0.117882,1.089159)); + hpcpush(hpxyz(-0.013091,0.329953,1.053110)); + hpcpush(hpxyz(-0.343678,0.205736,1.077238)); + + bshape(shTower[1], 10); // 5 + hpcpush(hpxyz(-0.311517,0.177757,1.062375)); + hpcpush(hpxyz(-0.277989,0.198280,1.056689)); + hpcpush(hpxyz(-0.192835,0.277382,1.055522)); + hpcpush(hpxyz(-0.118766,0.352616,1.066979)); + hpcpush(hpxyz(0.340632,0.220226,1.079134)); + hpcpush(hpxyz(0.346703,0.158836,1.070248)); + hpcpush(hpxyz(0.324069,0.046483,1.052227)); + hpcpush(hpxyz(0.255673,-0.074052,1.034820)); + hpcpush(hpxyz(0.185700,-0.149283,1.027993)); + hpcpush(hpxyz(0.033206,-0.246367,1.030436)); + hpcpush(hpxyz(-0.096570,-0.283752,1.043954)); + hpcpush(hpxyz(-0.194307,-0.258126,1.050897)); + hpcpush(hpxyz(-0.265575,-0.226804,1.059231)); + hpcpush(hpxyz(-0.285480,-0.219017,1.062764)); + hpcpush(hpxyz(-0.311517,0.177757,1.062375)); + + bshape(shTower[2], 10); // 6 + hpcpush(hpxyz(-0.287245,0.124770,1.047892)); + hpcpush(hpxyz(-0.224066,0.141558,1.034526)); + hpcpush(hpxyz(-0.131929,0.201218,1.028540)); + hpcpush(hpxyz(-0.078630,0.261221,1.036542)); + hpcpush(hpxyz(-0.020026,0.337507,1.055610)); + hpcpush(hpxyz(0.318283,0.112649,1.055459)); + hpcpush(hpxyz(0.303068,-0.062313,1.046773)); + hpcpush(hpxyz(0.276375,-0.100467,1.042342)); + hpcpush(hpxyz(0.222744,-0.146642,1.034949)); + hpcpush(hpxyz(0.008616,-0.304232,1.045290)); + hpcpush(hpxyz(-0.058987,-0.274278,1.038609)); + hpcpush(hpxyz(-0.112858,-0.303563,1.051136)); + hpcpush(hpxyz(-0.233080,-0.305264,1.071220)); + hpcpush(hpxyz(-0.372515,-0.347162,1.122180)); + hpcpush(hpxyz(-0.287245,0.124770,1.047892)); + + bshape(shTower[3], 10); // 8 + hpcpush(hpxyz(-0.276471,0.193549,1.055413)); + hpcpush(hpxyz(-0.248272,0.167366,1.043863)); + hpcpush(hpxyz(-0.131672,0.161485,1.021477)); + hpcpush(hpxyz(-0.029928,0.144574,1.010840)); + hpcpush(hpxyz(0.145677,0.141539,1.020419)); + hpcpush(hpxyz(0.244238,0.160944,1.041900)); + hpcpush(hpxyz(0.278308,0.181096,1.053685)); + hpcpush(hpxyz(0.290850,-0.178199,1.056574)); + hpcpush(hpxyz(0.244356,-0.239966,1.057021)); + hpcpush(hpxyz(0.158564,-0.296188,1.054927)); + hpcpush(hpxyz(0.052883,-0.325301,1.052909)); + hpcpush(hpxyz(-0.059036,-0.324976,1.053136)); + hpcpush(hpxyz(-0.156078,-0.299394,1.055461)); + hpcpush(hpxyz(-0.222738,-0.269837,1.059445)); + hpcpush(hpxyz(-0.251922,-0.245775,1.060127)); + hpcpush(hpxyz(-0.276471,0.193549,1.055413)); + + bshape(shTower[4], 10); // 9 + hpcpush(hpxyz(-0.311686,0.135147,1.056131)); + hpcpush(hpxyz(-0.107931,0.170082,1.020087)); + hpcpush(hpxyz(-0.054960,0.232687,1.028185)); + hpcpush(hpxyz(0.094837,0.235522,1.031729)); + hpcpush(hpxyz(0.206298,0.281848,1.059244)); + hpcpush(hpxyz(0.350261,-0.169080,1.072973)); + hpcpush(hpxyz(0.258249,-0.214408,1.054828)); + hpcpush(hpxyz(0.149756,-0.245358,1.040494)); + hpcpush(hpxyz(0.010018,-0.258374,1.032888)); + hpcpush(hpxyz(-0.164035,-0.248262,1.043332)); + hpcpush(hpxyz(-0.260903,-0.226907,1.058091)); + hpcpush(hpxyz(-0.329503,-0.207534,1.073146)); + hpcpush(hpxyz(-0.311686,0.135147,1.056131)); + + bshape(shTower[5], 10); // 10 + hpcpush(hpxyz(-0.278494,0.161752,1.050582)); + hpcpush(hpxyz(-0.132974,0.168104,1.022713)); + hpcpush(hpxyz(-0.045035,0.201619,1.021116)); + hpcpush(hpxyz(0.004416,0.226141,1.025261)); + hpcpush(hpxyz(0.097798,0.196263,1.023760)); + hpcpush(hpxyz(0.208310,0.187256,1.038488)); + hpcpush(hpxyz(0.213133,0.158213,1.034629)); + hpcpush(hpxyz(0.255407,-0.229136,1.057230)); + hpcpush(hpxyz(0.150044,-0.303075,1.055636)); + hpcpush(hpxyz(0.021265,-0.309104,1.046899)); + hpcpush(hpxyz(-0.124340,-0.302692,1.052180)); + hpcpush(hpxyz(-0.340803,-0.287456,1.094887)); + hpcpush(hpxyz(-0.338423,-0.172501,1.069713)); + hpcpush(hpxyz(-0.278494,0.161752,1.050582)); + + bshape(shTower[6], 10); // 10 + hpcpush(hpxyz(-0.033122,-0.384901,1.072029)); + hpcpush(hpxyz(0.122565,-0.232523,1.033968)); + hpcpush(hpxyz(0.222346,-0.147072,1.034924)); + hpcpush(hpxyz(0.293004,-0.141494,1.051604)); + hpcpush(hpxyz(0.228575,0.266628,1.059876)); + hpcpush(hpxyz(0.142937,0.283066,1.049074)); + hpcpush(hpxyz(0.030023,0.299757,1.044392)); + hpcpush(hpxyz(-0.078299,0.271316,1.039107)); + hpcpush(hpxyz(-0.144933,0.245692,1.039889)); + hpcpush(hpxyz(-0.207818,0.168012,1.035093)); + hpcpush(hpxyz(-0.262782,0.117599,1.040617)); + hpcpush(hpxyz(-0.313780,0.032325,1.048572)); + hpcpush(hpxyz(-0.338217,-0.056491,1.057157)); + hpcpush(hpxyz(-0.334152,-0.102325,1.059305)); + hpcpush(hpxyz(-0.033122,-0.384901,1.072029)); + + bshapeend(); - for(int i=0; i<8; i++) - shUser[i][0].prio = 1 + i, - shUser[i][1].prio = 1 + i, - shUser[i][2].prio = 50 + i; - prehpc = qhpc; + printf("hpc = %d\n", qhpc); } -struct drawshape { - vector list; - bool sym; - int rots; - hyperpoint shift, spin; - }; +void initShape(int sg, int id) { -drawshape dsUser[8][3], *dsCur; + if(!usershapes[sg][id]) { + usershape *us = new usershape; + usershapes[sg][id] = us; -int dslayer; -bool floordraw; + for(int i=0; id[i].sh.prio = (sg >= 3 ? 1:50) + i; -void pushShape(const drawshape& ds) { + us->d[i].rots = 1; + us->d[i].sym = 0; + us->d[i].shift = C0; + us->d[i].spin = Cx1; + us->d[i].color = 0; + } + } + } + +void pushShape(const usershapelayer& ds) { + + if(ds.list.empty()) return; transmatrix T = rgpushxto0(ds.shift) * rspintox(ds.spin); @@ -3827,22 +5955,29 @@ void pushShape(const drawshape& ds) { void saveImages() { qhpc = prehpc; - for(int i=0; i<8; i++) for(int j=0; j<3; j++) { - if(size(dsUser[i][j].list)) { - shUser[i][j].s = qhpc; + for(int i=0; id[l].sh.s = qhpc; first = true; - pushShape(dsUser[i][j]); - shUser[i][j].e = qhpc; + pushShape(us->d[l]); + us->d[l].sh.e = qhpc; } - else shUser[i][j].s = 0; } + + static int qhpc0; + if(qhpc != qhpc0) + printf("qhpc = %d (%d+%d)\n", qhpc0 = qhpc, prehpc, qhpc-prehpc); + + #ifdef GL + GL_initialized = false; + #endif } int poly_outline; -void queuepoly(const transmatrix& V, int ct, const hpcshape& h, int col) { - /* printf("draw poly #%d-%d at:\n", h.s, h.e); - display(V); */ +void queuepoly(const transmatrix& V, const hpcshape& h, int col) { polytodraw ptd; ptd.V = V; ptd.start = h.s, ptd.end = h.e; diff --git a/shmup.cpp b/shmup.cpp new file mode 100644 index 00000000..5ab1f5e4 --- /dev/null +++ b/shmup.cpp @@ -0,0 +1,1912 @@ +#include + +const char *lastprofile = ""; +int lt = 0; + +#ifndef MOBILE +void profile(const char *buf) { + int gt = SDL_GetTicks(); + printf("%4d %s\n", gt - lt, lastprofile); + lt = gt; + lastprofile = buf; + } +#endif + +bool drawMonsterType(eMonster m, cell *where, const transmatrix& V, int col); +void drawPlayerEffects(const transmatrix& V, cell *c); + +namespace shmup { + +long double fabsl(long double x) { return x>0?x:-x; } + +enum pcmds { + pcForward, pcBackward, pcTurnLeft, pcTurnRight, + pcMoveUp, pcMoveRight, pcMoveDown, pcMoveLeft, + pcFire, pcFace, pcFaceFire, + pcDrop, pcCenter, pcOrbPower + }; + +const char* playercmds[14] = { + "forward", "backward", "turn left", "turn right", + "move up", "move right", "move down", "move left", + "throw a knife", "face the pointer", "throw at the pointer", + "drop Dead Orb", "center the map on me", "activate Orb power" + }; + +const char* pancmds[7] = { + "pan up", "pan right", "pan down", "pan left", + "rotate left", "rotate right", "home" + }; + +#define SHMUPAXES 12 + +const char* axemodes[SHMUPAXES] = { + "do nothing", + "rotate view", + "panning X", + "panning Y", + "player 1 X", + "player 1 Y", + "player 1 go", + "player 1 spin", + "player 2 X", + "player 2 Y", + "player 2 go", + "player 2 spin" + }; + +int players; +int cpid; // player id -- an extra parameter for player-related functions +int centerplayer = -1; + +bool on = false, safety = false; + +bool lastdead = false; + +struct monster; + +multimap monstersAt; + +typedef multimap::iterator mit; + +vector active; + +map gmatrix; + +cell *findbaseAround(hyperpoint p, cell *around) { + cell *best = around; + double d0 = intval(p, gmatrix[around] * C0); + for(int i=0; itype; i++) { + cell *c2 = around->mov[i]; + if(c2 && gmatrix.count(c2)) { + double d1 = intval(p, gmatrix[c2] * C0); + if(d1 < d0) { best = c2; d0 = d1; } + } + } + return best; + } + +/* double distance(hyperpoint h) { + h = spintox(h) * h; + return inverse_sinh(h[2]); + } */ + +struct monster { + eMonster type; + cell *base; + transmatrix at; + transmatrix pat; + eMonster stk; + bool dead; + bool inBoat; + monster *parent; // who shot this missile + eMonster parenttype; // type of the parent + int nextshot; // when will it be able to shot (players/flailers) + char pid; // player ID + char hitpoints; + int stunoff; + int blowoff; + double vel; // velocity, for flail balls + + monster() { + dead = false; inBoat = false; parent = NULL; nextshot = 0; + stunoff = 0; blowoff = 0; + } + + void store() { + monstersAt.insert(make_pair(base, this)); + } + + void findpat() { + pat = gmatrix[base] * at; + } + + cell *findbase(hyperpoint p) { + return findbaseAround(p, base); + } + + void rebasePat(transmatrix new_pat) { + pat = new_pat; + cell *c2 = findbase(pat*C0); + // if(c2 != base) printf("rebase %p -> %p\n", base, c2); + base = c2; + at = inverse(gmatrix[c2]) * pat; + fixmatrix(at); + } + + void rebaseAt(transmatrix new_at) { + rebasePat(gmatrix[base] * new_at); + } + + bool trackroute(transmatrix goal, double spd) { + cell *c = base; + + // queuepoly(goal, shGrail, 0xFFFFFFC0); + + transmatrix mat = inverse(pat) * goal; + + transmatrix mat2 = spintox(mat*C0) * mat; + + double d = 0, dist = inverse_sinh(mat2[0][2]); + + while(d < dist) { + d += spd; + transmatrix nat = pat * rspintox(mat * C0) * xpush(d); + + // queuepoly(nat, shKnife, 0xFFFFFFC0); + + cell *c2 = findbaseAround(nat*C0, c); + if(c2 != c && !passable_for(type, c2, c, false)) { + return false; + } + c = c2; + } + return true; + } + + bool trackrouteView(transmatrix goal, double spd) { + cell *c = base; + + queuepoly(goal, shGrail, 0xFFFFFFC0); + + transmatrix mat = inverse(pat) * goal; + + transmatrix mat2 = spintox(mat*C0) * mat; + + double d = 0, dist = inverse_sinh(mat2[0][2]); + + while(d < dist) { + d += spd; + transmatrix nat = pat * rspintox(mat * C0) * xpush(d); + + // queuepoly(nat, shKnife, 0xFFFFFFC0); + + cell *c2 = findbaseAround(nat*C0, c); + if(c2 != c) { + if(0) printf("old dist: %lf\n", (double) intval(nat*C0, gmatrix[c]*C0)); + if(0) printf("new dist: %lf\n", (double) intval(nat*C0, gmatrix[c2]*C0)); + } + queuepoly(gmatrix[c2], shKnife, 0xFF0000FF); + if(c2 != c && !passable_for(type, c2, c, false)) + return false; + c = c2; + } + if(0) printf("dist = %lf, d = %lf, spd = %lf, lint = %lf, lcd = %lf\n", dist, d, spd, + (double) intval(pat * rspintox(mat * C0) * xpush(d)*C0, goal*C0), + (double) intval(pat * rspintox(mat * C0) * xpush(d)*C0, gmatrix[c]*C0) + ); + return true; + } + + }; + +monster *pc[2], *mousetarget; + +int curtime, nextmove, invisible_at; + +bool isBullet(monster *m) { + return + m->type == moBullet || m->type == moFlailBullet || + m->type == moFireball || m->type == moTongue || m->type == moAirball; + } +bool isPlayer(monster *m) { return m->type == moPlayer; } +bool isMonster(monster *m) { return m->type != moPlayer && m->type != moBullet; } + +void killMonster(monster* m) { + if(m->dead) return; + m->dead = true; + if(isBullet(m) || isPlayer(m)) return; + m->stk = m->base->monst; + if(m->inBoat && isWatery(m->base) && !m->base->item) { + m->base->wall = waBoat; + m->base->mondir = 0; + m->inBoat = false; + } + else if(m->inBoat && m->base->wall == waNone && ( + (m->base->land == laOcean || m->base->land == laLivefjord))) { + m->base->wall = waStrandedBoat; + m->base->mondir = 0; + m->inBoat = false; + } + m->base->monst = m->type; + killMonster(m->base); + m->base->monst = m->stk; + } + +void pushmonsters() { + for(int i=0; idead) { + m->stk = m->base->monst; + m->base->monst = m->type; + } + } + } + +void popmonsters() { + for(int i=size(active)-1; i>=0; i--) { + monster *m = active[i]; + if(!isPlayer(m) && !m->dead) { + if(m->type == m->base->monst) + m->base->monst = m->stk; + else { + m->dead = true; // already killed + // also kill all the other monsters there + for(int j=0; jbase == m->base && !isPlayer(m2) && !m2->dead) + killMonster(m2); + } + } + } + } + } + +void degradeDemons() { + for(int i=0; itype == moGreater) m->type = moLesser; + if(m->stk == moGreater) m->type = moLesser; + } + } + +// we need these for the Mimics! +double playerturn[4], playergo[4]; +bool playerfire[4]; + +void awakenMimics(monster *m, cell *c2) { + for(int i=0; imonst)) { + // straight + int i = 0; + if(m->type == moMirror) i++; + if(c->monst == moMirror) i++; + + transmatrix mirrortrans = Id; + if(i == 1) mirrortrans[0][0] = -1; + + if(!gmatrix.count(c)) continue; + monster *m2 = new monster; + m2->type = c->monst; + c->monst = moNone; + m2->base = c; + + hyperpoint H = inverse(gmatrix[c2]) * gmatrix[c] * C0; + + transmatrix xfer = rgpushxto0(H); + + if(i == 1) { + hyperpoint H2 = spintox(H) * H; + xfer = rspintox(H) * rpushxto0(H2) * mirrortrans * spintox(H); + } + + m2->pat = gmatrix[c2] * xfer * inverse(gmatrix[c2]) * m->pat; + + m2->at = inverse(gmatrix[c]) * m2->pat * mirrortrans; + m2->pid = cpid; + active.push_back(m2); + + // if you don't understand it, don't worry, + // I don't understand it either + } + } + } + +int visibleAt; + +void visibleFor(int t) { + visibleAt = max(visibleAt, curtime + t); + } + +void shootBullet(monster *m) { + monster* bullet = new monster; + bullet->base = m->base; + bullet->at = m->at; + bullet->type = moBullet; + bullet->parent = m; + bullet->pid = m->pid; + bullet->parenttype = m->type; + active.push_back(bullet); + + if(markOrb(itOrbThorns)) { + monster* bullet = new monster; + bullet->base = m->base; + bullet->at = m->at * spin(M_PI/2); + bullet->type = moBullet; + bullet->parent = m; + bullet->pid = m->pid; + bullet->parenttype = m->type; + active.push_back(bullet); + } + + if(markOrb(itOrbThorns)) { + monster* bullet = new monster; + bullet->base = m->base; + bullet->at = m->at * spin(-M_PI/2); + bullet->type = moBullet; + bullet->parent = m; + bullet->pid = m->pid; + bullet->parenttype = m->type; + active.push_back(bullet); + } + +/* if(markOrb(itOrbTrickery)) { + monster* bullet = new monster; + bullet->base = m->base; + bullet->at = m->at * spin(M_PI); + bullet->type = moBullet; + bullet->parent = m; + bullet->parenttype = m->type; + active.push_back(bullet); + } */ + } + +void killThePlayer(eMonster m) { + pc[cpid]->dead = true; + } + +#ifndef MOBILE + +void oceanCurrents(transmatrix& nat, monster *m, int delta) { + cell *c = m->base; + if(c->land == laWhirlpool) { + for(int i=0; itype; i++) { + cell *c2 = c->mov[i]; + if(!c2 || !gmatrix.count(c2)) continue; + + double spd = 0; + + if(celldistAlt(c2) < celldistAlt(c)) + spd = delta / 3000.; + else if(c2 == getWhirlpool(c, 1)) + spd = delta / 900.; + + if(spd) { + transmatrix goal = gmatrix[c2]; + + // transmatrix t = spintox(H) * xpush(delta/300.) * rspintox(H); + + hyperpoint H = inverse(m->pat) * goal * C0; + nat = nat * rspintox(H); + nat = nat * xpush(spd); + nat = nat * spintox(H); + } + } + } + } + +int actionspressed[64], axespressed[SHMUPAXES], lactionpressed[64]; + +void pressaction(int id) { + if(id >= 0 && id < 64) + actionspressed[id]++; + } + +void handleInput(int delta) { + double d = delta / 500.; + + Uint8 *keystate = SDL_GetKeyState(NULL); + + for(int i=0; i<64; i++) + lactionpressed[i] = actionspressed[i], + actionspressed[i] = 0; + + for(int i=0; ipid; + if(players > 1) vid.female = (cpid == 1); + + double mturn = 0, mgo = 0, mdx = 0, mdy = 0; + + bool shotkey = false, facemouse = false, dropgreen = false; + + int b = 16*(cpid+1); + for(int i=0; i<8; i++) if(actionspressed[b+i]) playermoved = true; + + int jb = 4*(cpid+1); + for(int i=0; i<4; i++) if(axespressed[jb+i]) playermoved = true; + + mgo = actionspressed[b+pcForward] - actionspressed[b+pcBackward] + axespressed[jb+2]/30000.; + mturn = actionspressed[b+pcTurnLeft] - actionspressed[b+pcTurnRight] + axespressed[jb+3]/30000.; + mdx = actionspressed[b+pcMoveRight] - actionspressed[b+pcMoveLeft] + axespressed[jb]/30000.; + mdy = actionspressed[b+pcMoveDown] - actionspressed[b+pcMoveUp] + axespressed[jb+1]/30000.; + + shotkey = actionspressed[b+pcFire] || actionspressed[b+pcFaceFire]; + facemouse = actionspressed[b+pcFace] || actionspressed[b+pcFaceFire]; + dropgreen = actionspressed[b+pcDrop]; + + if(actionspressed[b+pcOrbPower] && !lactionpressed[b+pcOrbPower]) { + cwt.c = m->base; + targetRangedOrb(mouseover, roKeyboard); + } + + if(actionspressed[b+pcCenter]) { + centerplayer = cpid; centerpc(100); playermoved = true; + } + + transmatrix nat = m->pat; + + if(m->base->land == laWhirlpool && !markOrb(itOrbWater)) + oceanCurrents(nat, m, delta); + + // if(ka == b+pcOrbPower) dropgreen = true; + + // if(mturn > 1) mturn = 1; + // if(mturn < -1) mturn = -1; + + playerturn[cpid] = mturn * delta / 150.0; + + double mdd = hypot(mdx, mdy); + if(mdd > 1e-6) { + hyperpoint jh = hpxy(mdx/100.0, mdy/100.0); + + hyperpoint h = inverse(m->pat) * rgpushxto0(m->pat * C0) * jh; + + playerturn[cpid] = -atan2(h[1], h[0]); + mgo += mdd; + } + + Uint8 *keystate = SDL_GetKeyState(NULL); + bool forcetarget = (keystate[SDLK_RSHIFT] | keystate[SDLK_LSHIFT]); + if(((mousepressed && !forcetarget) || facemouse) && delta > 0 && !outofmap(mouseh)) { + // playermoved = true; + hyperpoint h = inverse(m->pat) * mouseh; + playerturn[cpid] = -atan2(h[1], h[0]); + // nat = nat * spin(alpha); + // mturn += alpha * 150. / delta; + } + + bool blown = m->blowoff > curtime; + + if(playerturn[cpid] && canmove && !blown) nat = nat * spin(playerturn[cpid]); + transmatrix nat0 = nat; + + if(mgo > 1) mgo = 1; + if(mgo < -1) mgo = -1; + if(!canmove) mgo = 0; + + playergo[cpid] = mgo * delta / 600; + + bool go = false; + + cell *c2 = m->base; + + if(blown) { + playergo[cpid] = -delta / 1000.; + playerturn[cpid] = 0; + } + + for(int igo=0; igo<9 && !go; igo++) { + + go = true; + + double span[9] = { 0, + M_PI/6, -M_PI/6, + M_PI/4, -M_PI/4, + M_PI/3, -M_PI/3, + M_PI/2.1, -M_PI/2.1 + }; + + if(playergo[cpid]) nat = nat0 * spin(span[igo]) * xpush(playergo[cpid]) * spin(-span[igo]); + + // spin(span[igo]) * xpush(playergo[cpid]) * spin(-span[igo]); + + c2 = m->findbase(nat*C0); + + // don't have several players in one spot + // also don't let them run too far from each other! + monster* crashintomon = NULL; + for(int j=0; jpat*C0, nat*C0); + if(d < 0.1 || d > 100) crashintomon = pc[j]; + } + if(crashintomon) go = false; + + if(go && c2 != m->base) { + + if(c2->wall == waLake && markOrb(itOrbWinter)) { + c2->wall = waFrozenLake; + if(HEAT(c2) > .5) HEAT(c2) = .5; + } + + else if(c2->wall == waBigStatue && canPushStatueOn(m->base)) { + visibleFor(300); + c2->wall = m->base->wall; + if(cellUnstable(cwt.c)) + m->base->wall = waChasm; + else + m->base->wall = waBigStatue; + } + else if(m->inBoat && !isWateryOrBoat(c2) && player_passable(c2, m->base, false)) { + if(boatGoesThrough(c2) && markOrb(itOrbWater)) { + c2->wall = isIcyLand(m->base) ? waLake : waSea; + } + else { + if(isWatery(m->base)) + m->base->wall = waBoat, m->base->mondir = dirfromto(m->base, c2); + else if(boatStrandable(m->base)) + m->base->wall = waStrandedBoat; + else if(boatStrandable(c2)) + m->base->wall = waStrandedBoat; + m->inBoat = false; + } + } + else if(c2->wall == waThumperOn) { + int sd = dirfromto(c2, m->base); + int subdir = 1; + double bestd = 9999; + for(int di=-1; di<2; di+=2) { + cell *c = getMovR(c2, sd+di); + if(!c) continue; + if(!gmatrix.count(c)) continue; + double d = intval(gmatrix[c] * C0, m->pat * C0); + // printf("di=%d d=%lf\n", di, d); + if(dbase)); + cwspin(push, 3 * -subdir); cwstep(push); + if(!canPushThumperOn(push.c, c2, m->base) && c2->type == 7) { + cwstep(push); + cwspin(push, 1 * -subdir); + cwstep(push); + } + if(!canPushThumperOn(push.c, c2, m->base)) { + go = false; + } + else pushThumper(c2, push.c); + } + else if((blown ? !blowable(c2, m->base) : !player_passable(c2, m->base, false)) && !(isWatery(c2) && m->inBoat)) + go = false; + + } + } + + if(go) { + if(c2 != m->base) { + if(cellUnstable(m->base)) m->base->wall = waChasm; + + if(items[itOrbFire]) { + visibleFor(800); + if(makeflame(m->base, 10, false)) markOrb(itOrbFire); + } + + if(isIcyLand(m->base) && m->base->wall == waNone && markOrb(itOrbWinter)) { + invismove = false; + m->base->wall = waIcewall; + } + + if(items[itOrbDigging]) { + visibleFor(400); + int d = dirfromto(m->base, c2); + if(d >= 0 && earthMove(m->base, d)) markOrb(itOrbDigging); + } + + setdist(c2, 0, NULL); + if(c2->item && c2->land == laAlchemist) c2->wall = m->base->wall; + if(m->base->wall == waRoundTable) + roundTableMessage(c2); + if(c2->wall == waCloud) { + visibleFor(500); + createMirages(c2, 0, moMirage); + awakenMimics(m, c2); + c2->wall = waNone; + items[itShard]++; + } + if(c2->wall == waMirror) { + visibleFor(500); + cwt.c = c2; + createMirrors(c2, 0, moMirage); + awakenMimics(m, c2); + c2->wall = waNone; + items[itShard]++; + } + if(c2->wall == waGlass && items[itOrbGhost]) { + items[itOrbGhost] = 0; + addMessage(XLAT("Your Aether powers are drained by %the1!", c2->wall)); + } + movecost(m->base, c2); + + bool nomine = (c2->wall == waMineMine || c2->wall == waMineUnknown) && markOrb(itOrbGhost); + + if(!nomine) { + uncoverMines(c2, + items[itBombEgg] < 10 ? 0 : + items[itBombEgg] < 20 ? 1 : + items[itBombEgg] < 30 ? 2 : + 3 + ); + if(c2->wall == waMineMine && !markOrb(itOrbWinter)) { + items[itOrbLife] = 0; + m->dead = true; + } + explodeMine(c2); + } + + if(c2->wall == waClosePlate || c2->wall == waOpenPlate) + toggleGates(c2, c2->wall, 3); + + if(c2->item == itOrbYendor && !checkYendor(c2, false)) + ; + else collectItem(c2); + } + } + + if(go) m->rebasePat(nat); + else m->rebasePat(nat0); + + if(m->base->wall == waBoat && !m->inBoat) { + m->inBoat = true; m->base->wall = waSea; + } + + if(m->inBoat && boatStrandable(c2)) { + c2->wall = waStrandedBoat; + m->inBoat = false; + } + + if(!markOrb(itOrbGhost)) { + if(m->base->wall == waChasm || m->base->wall == waClosedGate) + m->dead = true; + + if(isWatery(m->base) && !m->inBoat && !markOrb(itOrbFish)) + m->dead = true; + + if(isFire(m->base) && !markOrb(itOrbWinter)) + m->dead = true; + } + + landvisited[m->base->land] = true; + + playerfire[cpid] = false; + + if(shotkey && canmove && curtime >= m->nextshot) { + + visibleFor(500); + if(items[itOrbFlash]) { + pushmonsters(); + killMonster(m->base); + cwt.c = m->base; + activateFlash(); + popmonsters(); + return; + } + + if(items[itOrbLightning]) { + pushmonsters(); + killMonster(m->base); + cwt.c = m->base; + activateLightning(); + popmonsters(); + return; + } + + playerfire[cpid] = true; + m->nextshot = curtime + (250 + 250 * players); + + turncount++; + shootBullet(m); + } + + if(dropgreen && m->base->item == itNone) + dropGreenStone(m->base); + } +#endif + +void moveMimic(monster *m) { + transmatrix nat = m->pat; + cpid = m->pid; + + // no need to care about Mirror images, as they already have their 'at' matrix reversed :| + nat = nat * spin(playerturn[cpid]) * xpush(playergo[cpid]); + + cell *c2 = m->findbase(nat*C0); + if(c2 != m->base && !player_passable(c2, m->base, false)) + m->dead = true; + else { + m->rebasePat(nat); + if(playerfire[cpid]) shootBullet(m); + } + + if(c2->wall == waCloud) { + createMirages(c2, 0, m->type); + awakenMimics(m, c2); + c2->wall = waNone; + } + + if(c2->wall == waMirror) { + createMirrors(c2, 0, m->type); + awakenMimics(m, c2); + c2->wall = waNone; + } + + if(c2->cpdist >= 6) + m->dead = true; + } + +bool isPlayerOrImage(eMonster m) { + return isMimic(m) || m == moPlayer; + } + +monster *parentOrSelf(monster *m) { + return m->parent ? m->parent : m; + } + +bool bulletpassable(cell *c, cell *from) { + if(c != from && thruVine(c, from)) return false; + return eaglepassable(c, from) || c->wall == waRoundTable || + isFire(c) || c->wall == waBonfireOff || + cellHalfvine(c) || c->wall == waAncientGrave || c->wall == waFreshGrave; + } + +void teleported() { + monster *m = pc[cpid]; + m->base = cwt.c; + m->at = rgpushxto0(inverse(gmatrix[cwt.c]) * mouseh) * spin(rand() % 1000 * M_PI / 2000); + m->findpat(); + for(int i=0; itype)) + active[i]->dead = true; + } + +void shoot(eItem it, monster *m) { + monster* bullet = new monster; + bullet->base = m->base; + bullet->at = m->at * rspintox(inverse(m->pat) * mouseh); + bullet->type = it == itOrbDragon ? moFireball : it == itOrbAir ? moAirball : moBullet; + bullet->parent = m; + bullet->pid = m->pid; + bullet->parenttype = m->type; + items[it]--; + active.push_back(bullet); + } + +eItem targetRangedOrb(orbAction a) { + if(!on) return itNone; + monster *wpc = pc[cpid]; + if(a != roCheck && !wpc) return itNone; + + if(items[itOrbPsi] && shmup::mousetarget && intval(mouseh, shmup::mousetarget->pat*C0) < .1) { + if(a == roCheck) return itOrbPsi; + addMessage(XLAT("You kill %the1 with a mental blast!", mousetarget->type)); + killMonster(mousetarget); + items[itOrbPsi] -= 30; + if(items[itOrbPsi]<0) items[itOrbPsi] = 0; + return itOrbPsi; + } + + if(on && items[itOrbDragon]) { + if(a == roCheck) return itOrbDragon; + shoot(itOrbDragon, wpc); + return itOrbDragon; + } + + if(on && items[itOrbAir]) { + if(a == roCheck) return itOrbAir; + shoot(itOrbAir, wpc); + return itOrbAir; + } + + if(on && items[itOrbIllusion]) { + if(a == roCheck) return itOrbIllusion; + shoot(itOrbIllusion, wpc); + return itOrbIllusion; + } + + return itNone; + } + +void moveBullet(monster *m, int delta) { + vid.female = (m->pid == 1); + m->findpat(); + transmatrix nat0 = m->pat; + transmatrix nat = m->pat; + if(m->type == moFlailBullet) { + m->vel -= delta / 600000.0; + if(m->vel < 0 && m->parent) { + // return to the flailer! + nat = nat * rspintox(inverse(m->pat) * m->parent->pat * C0) * spin(M_PI); + } + } + else if(m->type == moBullet) + m->vel = 1/300.; + else if(m->type == moFireball) + m->vel = 1/500.; + else if(m->type == moAirball) + m->vel = 1/200.; + else if(m->type == moTongue) { + m->vel = 1/1500.; + if(!m->parent || intval(nat*C0, m->parent->pat*C0) > 0.4) + m->dead = true; + } + nat = nat * xpush(delta * m->vel); + cell *c2 = m->findbase(nat*C0); + + if(isActivable(c2)) activateActiv(c2, true); + + // knives break mirrors and clouds + if(c2->wall == waCloud || c2->wall == waMirror) + c2->wall = waNone; + + if(m->type != moTongue && !bulletpassable(c2, m->base)) { + m->dead = true; + if(m->type != moAirball) killMonster(c2); + // cell *c = m->base; + if(m->parent && isPlayer(m->parent)) { + if(c2->wall == waDryTree) { + addMessage(XLAT("You start cutting down the tree.")); + c2->wall = waWetTree; + } + else if(c2->wall == waWetTree) { + addMessage(XLAT("You cut down the tree.")); + c2->wall = waNone; + } + else if(isActivable(c2)) + activateActiv(c2, true); + } + if(m->type == moFireball) { + makeflame(c2, 20, false) || makeflame(m->base, 20, false); + } + } + m->rebasePat(nat); + + // destroy stray bullets + for(int i=0; ibase->type; i++) + if(!m->base->mov[i] || !gmatrix.count(m->base->mov[i])) + m->dead = true; + + // items[itOrbWinter] = 100; items[itOrbLife] = 100; + + for(int j=0; jparent && m->vel >= 0) || m2->parent == m->parent) continue; + + // Flailers only killable by themselves + if(m2->type == moFlailer && m2 != m->parent) continue; + // be nice to your images! would be too hard otherwise... + if(isPlayerOrImage(parentOrSelf(m)->type) && isPlayerOrImage(parentOrSelf(m2)->type) && + m2->pid == m->pid) + continue; + // fireballs/airballs don't collide + if(m->type == moFireball && m2->type == moFireball) continue; + if(m->type == moAirball && m2->type == moAirball) continue; + double d = intval(m2->pat*C0, m->pat*C0); + + if(d < 0.1) { + if(m->type == moAirball && isBlowableMonster(m2->type)) { + + if(m2->blowoff < curtime) + m2->rebasePat(m2->pat * rspintox(inverse(m2->pat) * nat0 * C0)); + m2->blowoff = curtime + 1000; + continue; + } + // Hedgehog Warriors only killable outside of the 45 degree angle + if(m2->type == moHedge) { + hyperpoint h = inverse(m2->pat) * m->pat * C0; + if(h[0] > fabsl(h[1])) { m->dead = true; continue; } + } + // + if((m2->type == moPalace || m2->type == moFatGuard || m2->type == moSkeleton || + m2->type == moVizier) && m2->hitpoints > 1) { + m2->rebasePat(m2->pat * rspintox(inverse(m2->pat) * nat0 * C0)); + if(m2->type != moSkeleton) m2->hitpoints--; + m->dead = true; + if(m2->type == moVizier) ; + else if(m2->type == moFatGuard) + m2->stunoff = curtime + 600; + else if(m2->type == moSkeleton && m2->base->land != laPalace) + m2->stunoff = curtime + 2100; + else + m2->stunoff = curtime + 900; + continue; + } + // Greater Demons not killable + if(m2->type == moGreater) { + m->dead = true; + continue; + } + // Knights reflect bullets + if(m2->type == moKnight) { + if(m->parent) { + nat = nat * rspintox(inverse(m->pat) * m->parent->pat * C0); + m->rebasePat(nat); + } + m->parent = m2; + continue; + } + m->dead = true; + if(m->type == moFireball) makeflame(m->base, 20, false); + // Orb of Winter protects from fireballs + if(m->type == moFireball && ((isPlayer(m2) && markOrb(itOrbWinter)) || m2->type == moWitchWinter)) + continue; + killMonster(m2); + } + } + } + +hyperpoint closerTo; + +bool closer(monster *m1, monster *m2) { + return intval(m1->pat*C0, closerTo) < intval(m2->pat*C0, closerTo); + } + +void moveMonster(monster *m, int delta) { + + bool stunned = (isStunnable(m->type) && m->stunoff > curtime) || m->blowoff > curtime; + + if(stunned && cellUnstable(m->base)) + m->base->wall = waChasm; + + if(m->base->wall == waChasm && !survivesChasm(m->type)) + killMonster(m); + + if(isWatery(m->base) && !survivesWater(m->type) && !m->inBoat) + killMonster(m); + + if(isFire(m->base) && !survivesFire(m->type)) + killMonster(m); + + if(m->base->wall == waClosedGate && !survivesWall(m->type)) + killMonster(m); + + if(m->dead) return; + + + cell *c = m->base; + transmatrix goal = gmatrix[c]; + + bool direct = false; + + double step = delta/1000.0; + if(m->type == moWitchSpeed) + step *= 2; + else if(m->type == moEagle) + step *= 1.6; + else if(m->type == moLancer) + step *= 1.25; + else if(isDemon(m->type)) { + if(m->type == moLesserM) m->type = moLesser; + if(m->type == moGreaterM) m->type = moGreater; + step /= 2; + } + + transmatrix nat = m->pat; + + if(stunned) { + if(m->blowoff > curtime) { + step = -delta / 1000.; + } + else if(m->type == moFatGuard) + step = 0; + else step = -delta/2000.; + } + + else { + + if(m->type == moWitchFlash) for(int pid=0; pidpat*C0, m->pat*C0) < 2; + for(int i=0; itype) && intval(m2->pat*C0, m->pat*C0) < 2) + okay = false; + } + if(okay) { + addMessage(XLAT("%The1 activates her Flash spell!", m->type)); + pushmonsters(); + activateFlashFrom(m->base); + popmonsters(); + m->type = moWitch; + pc[pid]->dead = true; + } + } + if(isBug(m->type)) { + vector bugtargets; + for(int i=0; itype != m->type) + if(!isPlayer(active[i]) || !invismove) + if(!active[i]->dead) + bugtargets.push_back(active[i]); + + closerTo = m->pat * C0; + sort(bugtargets.begin(), bugtargets.end(), closer); + + for(int i=0; itrackroute(bugtargets[i]->pat, step)) { + goal = bugtargets[i]->pat; + direct = true; + break; + } + } + else if(m->type == moWolf) { + cell *cnext = c; + for(int i=0; itype; i++) { + cell *c2 = c->mov[i]; + if(c2 && gmatrix.count(c2) && HEAT(c2) > HEAT(c) && isIcyLand(c2) && + passable(c2, c, false, false, false)) + cnext = c2; + } + goal = gmatrix[cnext]; + direct = true; + } + else if(!direct && !invismove) { + for(int i=0; itrackroute(pc[i]->pat, step) && (!direct || intval(pc[i]->pat*C0, m->pat*C0) < intval(goal*C0,m->pat*C0))) { + goal = pc[i]->pat; + direct = true; + // m->trackrouteView(pc->pat, step); + } + } + + if(!direct) while(true) { + if(m->trackroute(gmatrix[c], step)) + goal = gmatrix[c]; + cell *cnext = c; + for(int i=0; itype; i++) { + cell *c2 = c->mov[i]; + if(c2 && gmatrix.count(c2) && c2->pathdist < c->pathdist && + passable_for(m->type, c2, c, false)) + cnext = c2; + } + if(cnext == c) break; + c = cnext; + } + + if(m->type == moHedge) { + hyperpoint h = inverse(m->pat) * goal * C0; + if(h[1] < 0) + nat = nat * spin(M_PI * delta / 3000); + else + nat = nat * spin(M_PI * -delta / 3000); + m->rebasePat(nat); + // at most 45 degrees + if(h[0] < fabsl(h[1])) return; + } + else { + nat = nat * rspintox(inverse(m->pat) * goal * C0); + } + } + +//if(c->land == laWhirlpool && (m->type == moShark || m->type == moCShark || m->type == moPirate)) +// oceanCurrents(nat, m, delta); + + + if(items[itOrbSpeed]) + step /= 2; + + nat = nat * xpush(step); // * spintox(wherePC); + if(intval(nat*C0, goal*C0) >= intval(m->pat*C0, goal*C0) && !stunned) + return; + + monster* crashintomon = NULL; + + for(int j=0; jtype != moBullet) { + monster* m2 = active[j]; + double d = intval(m2->pat*C0, nat*C0); + if(d < 0.1) crashintomon = active[j]; + } + + for(int i=0; idead = true; + + else if(crashintomon && isMimic(crashintomon->type)) { + crashintomon->dead = true; + crashintomon = NULL; + } + + else if(crashintomon && (isBug(m->type) || isBug(crashintomon->type)) && m->type != crashintomon->type && + !isBullet(crashintomon)) { + crashintomon->dead = true; + crashintomon = NULL; + } + + if(crashintomon) return; + + cell *c2 = m->findbase(nat*C0); + + if(isPlayerOn(c2)) { + bool usetongue = false; + if(isSlimeMover(m->type) || m->type == moWaterElemental) usetongue = true; + if(isWatery(c2) && !survivesWater(m->type) && !m->inBoat) usetongue = true; + if(c2->wall == waChasm && !survivesChasm(m->type)) usetongue = true; + if(isFire(c2) && !survivesFire(m->type) && !m->inBoat) usetongue = true; + if(usetongue) { + if(curtime < m->nextshot) return; + // m->nextshot = curtime + 25; + monster* bullet = new monster; + bullet->base = m->base; + bullet->at = m->at; + bullet->type = moTongue; + bullet->parent = m; + bullet->parenttype = m->type; + active.push_back(bullet); + return; + } + } + + if(c2 != m->base && (c2->wall == waClosePlate || c2->wall == waOpenPlate)) + toggleGates(c2, c2->wall, 3); + + if(c2 != m->base && c2->wall == waMineMine && !survivesMine(m->type)) { + explodeMine(c2); + m->dead = true; + } + + if(c2 != m->base && cellUnstable(m->base) && m->type != moEagle && m->type != moGhost) + m->base->wall = waChasm; + if(c2 != m->base && m->type == moWitchFire) makeflame(m->base, 10, false); + if(c2 != m->base && m->type == moFireElemental) makeflame(m->base, 20, false); + if(c2 != m->base && m->type == moWaterElemental) placeWater(c2, m->base); + if(c2 != m->base && m->type == moEarthElemental) { + int d = dirfromto(m->base, c2); + if(d >= 0) earthMove(m->base, d); + } + + // to do necro + + if(c2 != m->base && m->type == moNecromancer && !c2->monst) { + for(int i=0; ibase->type; i++) { + cell *c3 = m->base->mov[i]; + if(dirfromto(c3, c2) != -1 && c3->wall == waFreshGrave && gmatrix.count(c3)) { + bool monstersNear = false; + for(int i=0; ipat*C0, gmatrix[c3]*C0) < .3) + monstersNear = true; + if(active[i] != m && intval(active[i]->pat*C0, gmatrix[c2]*C0) < .3) + monstersNear = true; + } + if(!monstersNear) { + + monster* undead = new monster; + undead->base = c2; + undead->at = Id; + undead->type = moZombie; + undead->parent = m; + undead->parenttype = m->type; + undead->findpat(); + active.push_back(undead); + + undead = new monster; + undead->base = c3; + undead->at = Id; + undead->type = moGhost; + undead->parent = m; + undead->parenttype = m->type; + undead->findpat(); + active.push_back(undead); + + c3->wall = waAncientGrave; + addMessage(XLAT("%The1 raises some undead!", m->type)); + } + } + } + } + if(m->type == moGreaterShark) { + if(c2->wall == waBoat) + c2->wall = waNone; + if(c2->wall == waFrozenLake) + c2->wall = waLake; + } + if(m->type == moDarkTroll && c2->wall == waCavefloor) { + m->type = moTroll; + } + if(isLeader(m->type)) { + if(c2 != m->base) { + if(c2->wall == waBigStatue && canPushStatueOn(m->base)) { + c2->wall = m->base->wall; + if(cellUnstable(m->base)) + m->base->wall = waChasm; + else + m->base->wall = waBigStatue; + } + if(passable_for(m->type, c2, m->base, false) && !isWatery(c2) && m->inBoat) { + if(isWatery(m->base)) + m->base->wall = waBoat, m->base->mondir = dirfromto(m->base, c2); + else if(boatStrandable(c2)) c2->wall = waStrandedBoat; + else if(boatStrandable(m->base)) m->base->wall = waStrandedBoat; + m->inBoat = false; + } + } + if(c2->wall == waBoat && !m->inBoat) { + m->inBoat = true; c2->wall = waSea; + m->base = c2; + } + } + + if(stunned ? blowable(c2, m->base) : passable_for(m->type, c2, m->base, false)) + m->rebasePat(nat); + + if(direct) { + if((m->type == moPyroCultist || m->type == moCrystalSage) && curtime >= m->nextshot) { + monster* bullet = new monster; + bullet->base = m->base; + bullet->at = m->at; + bullet->type = moFireball; + bullet->parent = m; + active.push_back(bullet); + if(m->type == moPyroCultist) + m->type = moCultist; + else + m->nextshot = curtime + 100; + } + for(int i=0; itype == moAirElemental) && curtime >= m->nextshot && intval(m->pat*C0, pc[i]->pat*C0) < 2) { + monster* bullet = new monster; + bullet->base = m->base; + bullet->at = m->at; + bullet->type = moAirball; + bullet->parent = m; + active.push_back(bullet); + m->nextshot = curtime + 1500; + } + for(int i=0; itype == moFlailer && curtime >= m->nextshot && + intval(m->pat*C0, pc[i]->pat*C0) < 2) { + m->nextshot = curtime + 3500; + monster* bullet = new monster; + bullet->base = m->base; + bullet->at = m->at; + bullet->type = moFlailBullet; + bullet->parent = m; + bullet->vel = 1/400.0; + active.push_back(bullet); + break; + } + } + } + +#ifndef MOBILE +void turn(int delta) { + + bool b = vid.female; + + if(delta > 1000) delta = 1000; + + if(delta > 200) { turn(200); delta -= 200; if(!delta) return; } + + curtime += delta; + + handleInput(delta); + + invismove = (curtime >= visibleAt) && markOrb(itOrbInvis); + + // detect active monsters + for(map::iterator it = gmatrix.begin(); it != gmatrix.end(); it++) { + cell *c = it->first; + pair p = + monstersAt.equal_range(c); + for(mit it = p.first; it != p.second;) { + mit itplus = it; + itplus++; + active.push_back(it->second); + monstersAt.erase(it); + it = itplus; + } + if(c->monst && !isIvy(c) && !isWorm(c)) { + monster *enemy = new monster; + enemy->at = Id; + enemy->base = c; + enemy->type = c->monst; + enemy->hitpoints = c->hitpoints; + if(c->wall == waBoat && isLeader(c->monst)) + enemy->inBoat = true, c->wall = waNone; + c->monst = moNone; + active.push_back(enemy); + } + } + + /* printf("size: gmatrix = %ld, active = %ld, monstersAt = %ld, delta = %d\n", + gmatrix.size(), active.size(), monstersAt.size(), + delta); */ + + bool exists[motypes]; + + for(int i=0; ifindpat(); + exists[movegroup(m->type)] = true; + } + + for(int i=0; itype) { + case moPlayer: + movePlayer(m, delta); + break; + + case moBullet: case moFlailBullet: case moFireball: case moTongue: case moAirball: + moveBullet(m, delta); + break; + + default: ; + } + } + + for(int i=0; itype)) + moveMimic(m); + } + + for(int t=1; tpathdist = INFD; + } + pathq.clear(); + + for(int i=0; ipathdist = isPlayerOn(targets[i]) ? 0 : 1; + pathq.push_back(targets[i]); + } + + int qb = 0; + for(qb=0; qb < size(pathq); qb++) { + cell *c = pathq[qb]; + int d = c->pathdist; + for(int i=0; itype; i++) { + cell *c2 = c->mov[i]; + // printf("i=%d cd=%d\n", i, c->mov[i]->cpdist); + if(c2 && c2->pathdist == INFD && gmatrix.count(c2) && + (passable_for(eMonster(t), c, c2, false) || c->wall == waThumperOn)) { + c2->pathdist = d+1; + pathq.push_back(c2); + } + } + } + + // printf("time %d, t=%d, q=%d\n", curtime, t, qb); + + // move monsters of this type + + for(int i=0; itype) == t) + moveMonster(active[i], delta); + } + + bool tick = curtime >= nextmove; + keepLightning = ticks <= lightat + 1000; + cwt.c = pc[0]->base; + bfs(tick); moverefresh(); + countLocalTreasure(); + pushmonsters(); + processheat(delta / 350.0, tick); + markOrb(itOrbSpeed); + if(tick) { + nextmove += 1000; + reduceOrbPowers(); + if(!(items[itOrbSpeed] & 1)) { + moveworms(); + moveivy(); + if(havehex) movehex(); + wandering(); + livecaves(); + dryforest(); + if(havewhirlpool) movewhirlpool(); + } + } + popmonsters(); + + gmatrix.clear(); + + canmove = true; + + for(int i=0; idead && items[itOrbLife] && !items[itOrbShield]) { + items[itOrbLife]--; + items[itOrbShield] += 3; + items[itOrbGhost] += 3; + orbused[itOrbShield] = true; + } + + if(pc[i]->dead && items[itOrbShield]) { + pc[i]->dead = false; + orbused[itOrbShield] = true; + } + + if(pc[i]->dead && items[itOrbFlash]) { + pc[i]->dead = false; + pushmonsters(); + killMonster(pc[i]->base); + activateFlash(); + popmonsters(); + } + + if(pc[i]->dead && items[itOrbLightning]) { + pc[i]->dead = false; + pushmonsters(); + killMonster(pc[i]->base); + activateLightning(); + popmonsters(); + } + + if(pc[i]->dead && !lastdead) + achievement_final(true); + lastdead = pc[i]->dead; + + canmove = canmove && !pc[i]->dead; + } + + // deactivate all monsters + for(int i=0; idead && active[i] != pc[0] && active[i] != pc[1]) { + for(int j=0; jparent == active[i]) + active[j]->parent = active[i]->parent; + delete active[i]; + } + else active[i]->store(); + + active.clear(); + + if(safety) { + safety = false; + activateSafety(pc[0]->base->land); + } + + vid.female = b; + } +#endif + +void init() { + + players = vid.scfg.players; + + pc[0] = new monster; + pc[0]->type = moPlayer; + pc[0]->pid = 0; + pc[0]->at = xpush(players == 2 ? -.3:0) * spin(players == 2 ? M_PI : 0) * Id; + pc[0]->base = cwt.c; + pc[0]->inBoat = (firstland == laCaribbean || firstland == laOcean || firstland == laLivefjord); + pc[0]->store(); + + if(players == 2) { + pc[1] = new monster; + pc[1]->type = moPlayer; + pc[1]->pid = 1; + pc[1]->at = xpush(.3) * Id; + pc[1]->base = cwt.c; + pc[1]->inBoat = (firstland == laCaribbean || firstland == laOcean || firstland == laLivefjord); + pc[1]->store(); + } + else pc[1] = NULL; + + if(!safety) { + items[itOrbLife] = 3; + addMessage(XLAT("Welcome to the Shoot'em Up mode!")); + // addMessage(XLAT("F/;/Space/Enter/KP5 = fire, WASD/IJKL/Numpad = move")); + } + } + +monster *getPlayer() { + return pc[cpid]; + } + +bool drawMonster(const transmatrix& V, cell *c) { + gmatrix[c] = V; + + pair p = + monstersAt.equal_range(c); + + bool b = vid.female; + + for(mit it = p.first; it != p.second; it++) { + monster* m = it->second; + m->pat = V * m->at; + + if(!outofmap(mouseh)) + if(!mousetarget || intval(mouseh, mousetarget->pat*C0) > intval(mouseh, m->pat*C0)) + mousetarget = m; + + if(m->inBoat) { + if(m->type == moPlayer && items[itOrbWater]) { + queuepoly(m->pat, shBoatOuter, watercolor(0)); + queuepoly(m->pat, shBoatInner, 0x0060C0FF); + } + else { + queuepoly(m->pat, shBoatOuter, 0xC06000FF); + queuepoly(m->pat, shBoatInner, 0x804000FF); + } + } + + if(doHighlight()) + poly_outline = + isBullet(m) ? 0x00FFFFFF : + (isFriendly(m->type) || m->type == moPlayer) ? 0x00FF00FF : 0xFF0000FF; + + switch(m->type) { + case moPlayer: + drawPlayerEffects(m->pat, c); + cpid = m->pid; if(players == 2) vid.female = cpid; + if(mapeditor::drawplayer) drawMonsterType(moPlayer, c, m->pat, 0xFFFFFFC0); + vid.female = b; + break; + case moBullet: { + int col; + if(m->parenttype == moPlayer) + col = vid.swordcolor; + else + col = (minf[m->parenttype].color << 8) | 0xFF; + queuepoly(m->pat * spin(curtime / 50.0), shKnife, col); + break; + } + case moTongue: + queuepoly(m->pat, shTongue, (minf[m->parenttype].color << 8) | 0xFF); + break; + case moFireball: case moAirball: + queuepoly(m->pat, shPHead, (minf[m->type].color << 8) | 0xFF); + break; + case moFlailBullet: + queuepoly(m->pat * spin(curtime / 50.0), shFlailMissile, (minf[m->type].color << 8) | 0xFF); + break; + + default: + int col = minf[m->type].color; + if(m->type == moSlime) { + col = winf[c->wall].color; + col |= (col >> 1); + } + bool b = vid.female; cpid = m->pid; + if(players == 2 && isMimic(m->type)) vid.female = cpid; + if(isStunnable(m->type) && m->stunoff > curtime) + c->stuntime = 1 + (m->stunoff - curtime-1)/300; + if(hasHitpoints(m->type)) + c->hitpoints = m->hitpoints; + drawMonsterType(m->type, c, m->pat, col); + vid.female = b; + break; + } + } + + return false; + } + +void clearMemory() { + for(mit it = monstersAt.begin(); it != monstersAt.end(); it++) + delete(it->second); + for(int i=0; ibase; + } + +bool playerInBoat(int i) { + return pc[i]->inBoat; + } + +void saveConfig(FILE *f) { + fprintf(f, "%d %d", VERNUM, vid.scfg.players); + for(int i=0; i<512; i++) fprintf(f, " %d", vid.scfg.keyaction[i]); + for(int i=0; i<8; i++) for(int j=0; j 10000) buf += "+", y -= 10000; + while(y < -10000) buf += "-", y += 10000; + if(y>0) buf += "+"; + if(y<0) buf += "-"; + axeconfigs[numaxeconfigs] = &(vid.scfg.axeaction[j][ax]); + char aa = *axeconfigs[numaxeconfigs]; + string what = XLAT(shmup::axemodes[aa%SHMUPAXES]); + displayStat(numaxeconfigs, XLAT("Joystick %1, axis %2", cts('A'+j), its(ax)) + buf, + what, 'a'+numaxeconfigs); + numaxeconfigs++; + } + } + } + else if(sc == 0) { + int vy = vid.yres/2 - vid.fsize * 6; + + displayButton(vid.xres/2, vy, + ifMousing("n", vid.scfg.players == 2 ? "two players" : "one player"), 'n', 8, 2); + displayButton(vid.xres/2, vy+vid.fsize*2, + ifMousing("1", "configure player 1"), '1', 8, 2); + if(vid.scfg.players > 1) + displayButton(vid.xres/2, vy+vid.fsize*3, + ifMousing("2", "configure player 2"), '2', 8, 2); + displayButton(vid.xres/2, vy+vid.fsize*5, + ifMousing("p", "configure panning"), 'p', 8, 2); + if(numsticks > 0) + displayButton(vid.xres/2, vy+vid.fsize*7, + ifMousing("j", "configure joystick axes"), 'j', 8, 2); + displayButton(vid.xres/2, vy+vid.fsize*9, + ifMousing("s", + shmup::on && shmup::players == vid.scfg.players ? + "continue playing" + : "start playing in the shmup mode"), 's', 8, 2); + displayButton(vid.xres/2, vy+vid.fsize*10, + ifMousing("t", "return to the turn-based mode"), 't', 8, 2); + displayButton(vid.xres/2, vy+vid.fsize*11, + ifMousing("c", "save the configuration"), 'c', 8, 2); + } + + if(sc >= 1 && sc <= 3) { + getcstat = ' '; + + for(int i=0; i1 && i == (vid.scfg.setwhat&15) ? '?' : ' ') : 'a'+i); + + displayStat(-2, + XLAT(sc == 1 ? "configure player 1" : + sc == 2 ? "configure player 2" : + "configure panning"), "", ' '); + + if(vid.scfg.setwhat == 1) + displayStat(16, XLAT("press a key to unassign"), "", ' '); + else if(vid.scfg.setwhat) + displayStat(16, XLAT("press a key for '%1'", XLAT(shmupcmdtable[vid.scfg.setwhat&15])), "", ' '); + else + displayStat(16, XLAT("unassign a key"), "", 'z'); + } +#endif + } + +void handleConfig(int uni, int sym) { +#ifndef MOBILE + int sc = vid.scfg.subconfig; + if(sc == 0) { + if(uni == '1') vid.scfg.subconfig = 1; + else if(uni == '2') vid.scfg.subconfig = 2; + else if(uni == 'p') vid.scfg.subconfig = 3; + else if(uni == 'j') vid.scfg.subconfig = 4; + else if(uni == 's') { + cmode = emNormal; + if(!shmup::on) restartGame('s'); + else if(vid.scfg.players != shmup::players) restartGame(); + } + else if(uni == 't') { + cmode = emNormal; + if(shmup::on) restartGame('s'); + } + else if(uni == 'c') + ::saveConfig(); + else if(uni == 'n') + vid.scfg.players = 1 + (vid.scfg.players&1); + } + else if(sc == 4) { + if(sym) { + if(uni >= 'a' && uni < 'a' + numaxeconfigs) { + (*axeconfigs[uni - 'a'])++; + (*axeconfigs[uni - 'a']) %= SHMUPAXES; + } + else + vid.scfg.subconfig = 0; + } + } + else { + if(sym) { + if(vid.scfg.setwhat) { + vid.scfg.keyaction[sym] = vid.scfg.setwhat; + vid.scfg.setwhat = 0; + } + else if(uni >= 'a' && uni < 'a' + shmupnumkeys) + vid.scfg.setwhat = 16*sc+uni - 'a'; + else if(uni == 'z') + vid.scfg.setwhat = 1; + else + vid.scfg.subconfig = 0; + } + } +#endif + } +}