Погода хорошая, тепло, ветра нет, можно и прогуляться. Эта остановка очень оживленная, раньше был маленький рынок, но его ликвидировали и теперь там двухэтажное здание с бутиками, но мы в них не пойдем, там шмотки в основном продают. Окультурили малость, вышло не сильно лучше, но как есть. Дальше кучка фото в количестве 14 штук.
Туда пойдем
Потихоньку лотки выезжают вперед и пока кто-то не нажалуется, ходить тесновато.
Где много людей там и пирожки.
Жареных рыбов продают, правда мало понятно каких, карасики вроде.
Выпечка, самса и вот эта штука с мазиком сверху которая "пицца".
Тут внутри, в слоеном тесте, маринованная куриная голяшка, съедобно и сытно.
и еще самсухи с разной начинкой
Еще разная самса и злая продаванка, сфотал и не купил ничего :)
Глина съедобная, еще бывает с разными вкусами о_О
Лоток для беременных которые страдают по глине. Моя супруга этого избежала, я бы офигел. Согласен когда хочется сожрать клубнику, но глину... хотя гормоны такие гормоны, кто-то шпалы нюхает. Там рядом такой же был закрыт, у них наверное пару десятков разновидностей глины.
Карусельки куриные. От Басика!
Дальше пойдем внутрь магазина, уличные пирожки останутся на улице. Внутри всё уже культурненько, супермаркет как-никак. Раньше был алкомаркетом, но разросся и теперь уже и кулинария, хлебо-булочная выпечка, тортики и всякие манты-пльмени свои производят. Ну и можно приобрести крепкую алкашку после 21:00, но чуть дороже, но можно, а остальным нельзя, а этим можно :)
Алкашный ряд с крепким, в другую сторону такой-же с винишком.
Манты есть всегда, с мясом, с тыквой, с мясом и картошкой.
И полметровые чебуреки! Там где-то внутри мясо компактно спряталось :)
Ну и тортики конечно
Как и в любой нормальной кулинарии всё свежее, пару десятков салатов и примерно столько-же вторых блюд. Первых максимум пять, их на перекусить народ у нас не особо берет, ну и конечно без десятка корейских салатов не обойтись.
Вот и весь поход, всем спасибо за внимание.
.
Надо полярик на телефон прикрутить, блики бесячие везде.
Он же провансальский (не путать с франко-провансальским!), лимузенский, язык ок (👌), язык трубадуров. Относится к романской группе и, по разным классификациям, входит в галло-романскую подгруппу или окситано-романскую подгруппу. Некоторые же исследователи выделяют пиренейскую группу, в которую включены окситанский, каталанский, гасконский и арагонский (нет, не сын Араторна) языки. Кто-то до сих пор срётся и называет эти языки диалектами, отказываясь принимать статус языка.
Распространён язык на юге Франции, территория Окситании граничит с Испанией и Италией.
Как и многие мелкие языки, насчитывает кучу диалектов (серьёзно, вас там полтора калеки, а вы всё равно по-разному говорите?!) Диалектов штук шесть, разделённых на три подгруппы: северноокситанская, южноокситанская и гасконская.
Если интересна более специфическая информация о различии диалектов, то вот табличка:
Позаимствовано из статьи Бестолковой Г.В.
Литературный (письменный) окситанский начал формироваться в X веке. Староокситанский (старопровансальский) был языком европейской литературы и использовался в науке и документах. Основной письменный источник средневекового окситанского — поэзия трубадуров.
В XVI веке письменная форма окситанского постепенно приходила в упадок и была вытеснена французским языком. Оставался он исключительно ненормированным языком бытового общения. В XX веке начались попытки возрождения языка. Как и в случае с романшским, из разрозненных диалектов была искусственно создана эталонная норма. Сейчас эта норма изучается в университетах Франции, Италии, Испании и Швейцарии как факультативный предмет. Также в Окситании существует сеть школ Каландрета, где обучение ведётся сразу на двух языках — окситанском и французском.
Во Франции окситанский язык признан региональным, а в Италии находится под защитой государства. Количество носителей языка колеблется от 500 тыс. до 2 миллионов человек.
К сожалению, количество говорящих на окситанском продолжат сокращаться. В какой-то мере из-за смерти старого поколения носителей, в какой-то из-за пуризма французов, которым нужно, чтобы всё было французским.
Чё по названию? Окситанский язык назван так благодаря итальянскому поэту Данте Алигьери. Он создал классификацию романских языков с использованием частицы "да": как пишется "да" в разных языках. Существовали lingua di sì (итальянский), lingua d'oil (французский) и lingua d'oc (окситанский) — буквально "язык да". Отсюда название langue d'oc, преобразованное в occitan. И отсюда же название области Лангедок.
До XX века наиболее используемым было название "провансальский язык" от слова провинция, так как территория распространения окситанского находится на окраине Франции. Отсюда же и слово Прованс, кстати. Окситанским язык в основном стали называть уже в современности.
При создании нормы языка больше всего был задействован лангедокский диалект как центральный и самый консервативный. Он же повлиял на произношение.
Ударение фиксированное, падает на последний или предпоследний слог. Это зависит от того, на какую букву заканчивается слово. В случае исключений ударение прописывается.
Грамматика в принципе схожа с французской.
Выделяется две нормы письма: классическая (базируется на средневековой окситанской) и мистральская — по имени Фредерика Мистраля, возрождавшего язык в XIX веке (базируется на современной французской).
Фрагмент текста для сравнения:
Слава Википедии
Ну и послушать тоже неплохо бы.
Примеры речи (разные варианты):
Анноне, Франция
Валь-д'Аран, Каталония
Сразу заметна разница в произношении и влияние государственных языков.
Ну и песенку скину, почему бы и нет. Эта группа в принципе исполняет песни на окситанском.
Вчера я остро ощутил, что очень давно не писал ничего простого, но функционального и интересного. А ещё я тут всё про игры да про игры, поэтому решил: пора!
Последнее, что я писал подобного – это змейку, которую можно было наблюдать во время обновлений сайта раньше (помните её?).
Да и ту на половину, а то и на две трети написал за меня чатГПТ. Поэтому я решил, что возьму нового подопытного и реализую всё сам. Мозг не должен забывать, как делать штуки...
В качестве основы решил взять HTML5 и ванильный JS, как технологию с самым дешёвым вариантом рендера, да и повторить, при желании, этот же алгоритм можно на любом другом движке.
Начнём с простого: нам понадобится текстовый редактор любой. Хорошо, если с подсветкой синтаксиса. Для самого простого можно взять Notepad++, для случаев чуть серьёзнее Атом или ВС код.
Создаём html страничку, она будет нашей точкой входа, рядом с ней создаём файлик стилей и основной наш скриптец. Забегая вперёд: стили нам не то, чтобы прям сильно нужны.
Дожидаемся, пока вся страница загрузится, потом инициируем игру
Пока что к самому алгоритму игры мы не приступили, это всё предварительные ласки.
В первую очередь давайте посмотрим на класс GameField.
class GameField {
constructor(width, height) {
this.width = width;
this.height = height;
this.blocks = [];
for (let i = 0; i < this.height; i++) {
let line = [];
for (let j = 0; j < this.width; j++) {
line.push(0);
}
this.blocks.push(line); //Заполняем массив ячеек поля нулями. поле по умолчанию пустое
}
}
checkLines = async () => { // тут мы проверяем, а есть ли линии, которые надо сбросить
for (let y = this.height - 1; y >= 0; y--) {
if (this.currentLineIsFill(this.blocks[y])) {
currentScore++; //плюсуем очки
for (let x = 0; x < this.width; x++) {
this.blocks[y][x] = 0;
redraw();
await sleep(LINE_CLEAR_ANIMATION_DELAY); // это просто для красивой анимации исчезновения
}
}
}
currentScore = getComboPoints(currentScore); // этот метод отдельно, там считаем прирос за комбо
}
currentLineIsEmpty = (line) => {
for (let x = 0; x < line.length; x++) {
if (line[x] === 1) { // если хоть одна ячейка заполнена, то идёт нахер
return false;
}
}
return true;
};
currentLineIsFill = (line) => {
for (let x = 0; x < line.length; x++) {
if (line[x] === 0) { // если хоть одна ячейка пустая, строка идёт нахер
return false;
}
}
return true;
};
moveLines = () => { // сдвигаем после удаления
let notEmptyLines = [];
for (let y = 0; y < this.blocks.length; y++) {
if (!this.currentLineIsEmpty(this.blocks[y])) {
notEmptyLines.push([...this.blocks[y]]); // сначала заполняем массив непустымы строками
}
}
let emptyLine = [];
for (let x = 0; x < this.width; x++) {
emptyLine.push(0); // потом досоздаём массив пустых строк
}
let newLines = []; // запиххиваем их в новый массив
for (let x = 0; x < this.height - notEmptyLines.length; x++) {
newLines.push([...emptyLine]);
}
for (let x = 0; x < notEmptyLines.length; x++) {
newLines.push([...notEmptyLines[x]]);
}
this.blocks = newLines;
}
}
Когда же мы будем всё это дёргать? И почему?
В методе, который описывает игровой цикл. Я постарался программировать так, чтоб даже при современном подходе можно было бы реализовать близкий по сути алгоритм на реальном камне, где, как известно многопоточность лишь выдуманная.
Раз в какое-то количество миллисекунд мы вызываем геймЛуп. «Почему же не сетинтервал», – спросит неокрепших неофит. А всё по тому, что это чревато как раз внезапной неконтролируемой асинхронностью, которая приведёт к гонке за ресурсы и будут беды. Поэтому метод будет вызывать сам себя только после того, как точно закончит.
const gameLoop = async () => {
if (gameMode !== GameMode.PLAYING || isLoopRunning) {
return;
}
isLoopRunning = true;
if (currentFigure === null || typeof currentFigure === 'undefined') { // у нас нет фигуры? Так давай её сделаем из того, что стоит в очереди
currentFigure = new Figure();
currentFigure.cells = nextFigure.cells.map(row => [...row]);
currentFigure.type = nextFigure.type;
currentFigure.states = nextFigure.states.map(state => state.map(row => [...row]));
currentFigure.rotationState = nextFigure.rotationState;
currentFigure.setStartPosition();
nextFigure.fillRandom(); // следующую фигуру херакнули в какую-нибудь новую рандомную
redrawNextFigure();
}
currentFigure.moveDown(); //уронили я одну клеточку
if (currentFigure.checkCollision()) {//пересеклисьс чем-нибудь?
currentFigure.moveUp(); //подняли обратно и зафиксировали с мировом пространстве
const overflow = currentFigure.placeToField();
currentFigure = null;
if (overflow) {
finishGame('top_out');
redraw();
isLoopRunning = false;
return;
}
await field.checkLines(); // все фигуры на своих местах, можно проверить, как там у нас дела
score += currentScore;
scoreEl.innerText = score;
currentScore = 0;
field.moveLines(); // сдвинем, если надо сдвинуть
}
redraw();
isLoopRunning = false;
if (gameMode === GameMode.PLAYING) {
tickTimeout = setTimeout(gameLoop, getCurrentTickDelay()); // снова запускаем всё сначала
}
};
В целом, осталось только понять, что же такое фигура.
Сама геморная часть. Там больше всего буковок.
Фигура - это сущность, в которой хранится информация о том, какой она формы и как её крутить.
class Figure {
constructor() {
this.cells = [
[0],
];
this.x = 2;
this.y = -5;
this.rotationState = 0;
}
moveDown = () => {
this.y++;
};
moveUp = () => {
this.y--;
};
moveLeft = () => {
this.x--;
if (this.checkCollision()) {
this.x++;
}
}
moveRight = () => {
this.x++;
if (this.checkCollision()) {
this.x--;
}
}
fall = () => {
while (!this.checkCollision()) {
this.y++;
}
this.moveUp();
};
checkCollision = () => {
for (let i = 0; i < this.cells.length; i++) {
for (let j = 0; j < this.cells[i].length; j++) {
let cellX = j + this.x;
let cellY = i + this.y;
if (this.cells[i][j] === 0) {
continue;
}
// Проверяем границы по X всегда (независимо от Y)
if (cellX < 0 || cellX >= field.width) {
return true;
}
// Для клеток выше видимой области не проверяем коллизии с полем
if (cellY < 0) {
continue;
}
// Проверяем нижнюю границу и коллизии с заполненными клетками
if (cellY >= field.height) {
return true;
}
if (field.blocks[cellY][cellX] === 1) {
return true;
}
}
}
return false;
};
rotate(withCollisions = true) {
const from = this.rotationState;
const to = (from + 1) % this.states.length;
const key = `${from}>${to}`;
const kickSet = (this.type === "I")
? SRS_KICKS.I[key]
: (this.type === "O" ? SRS_KICKS.O[key] : SRS_KICKS.JLSTZ[key]);
const originalX = this.x;
const originalY = this.y;
let rotated = this.states[to];
if (!withCollisions) {
this.cells = rotated;
this.x = originalX;
this.y = originalY;
this.rotationState = to;
return;
}
for (const [dx, dy] of kickSet) {
this.cells = rotated;
this.x = originalX + dx;
this.y = originalY - dy;
if (!this.checkCollision()) {
this.rotationState = to;
return;
}
}
this.cells = this.states[from];
this.x = originalX;
this.y = originalY;
}
placeToField = () => {
let overflow = false;
for (let i = 0; i < this.cells.length; i++) {
for (let j = 0; j < this.cells[i].length; j++) {
let cellX = j + this.x;
let cellY = i + this.y;
if (this.cells[i][j] === 0) {
continue;
}
if (cellY < 0) {
overflow = true;
continue;
}
if (cellY >= field.height || cellX < 0 || cellX >= field.width) {
overflow = true;
continue;
}
field.blocks[cellY][cellX] = this.cells[i][j];
}
}
return overflow;
};
setStartPosition = () => {
this.x = Math.floor(field.width / 2) - Math.floor(this.cells[0].length / 2);
if (this.type === "I" && this.rotationState === 1) {
this.y = -2;
} else if (this.type === "I") {
this.y = -4;
} else if (this.type === "O") {
this.y = -2;
} else if (this.rotationState === 3) {
this.y = -2;
} else {
this.y = -3;
}
};
fillRandom = () => {
let figure = FIGURES[Math.floor(Math.random() * FIGURES.length)];
this.cells = figure.figure.states[0].map(row => [...row]);
this.states = figure.figure.states.map(state => state.map(row => [...row]));
this.type = figure.type;
this.rotationState = 0;
let rotateSteps = Math.floor(Math.random() * 4);
for (let i = 0; i < rotateSteps; i++) {
this.rotate(false);
}
};
}
Тут, конечно, кода дофига и надо объяснить, что тут происходит. Суть в том, что поворот в тетрисе – это прям отдельная задачка. Я её для себя упростил максимально, создав «спрайты» фигур во всех положениях заранее.
А ещё есть такая штука как SRS – это прям общепринятый стандарт вращения фигур. Специальные таблицы описывают как необходимо проверять смещение фигур в пространстве игрового поля при переходе из одного состояния в другое, на случай столкновения со стенами или существующими блоками в момент вращения. Я, опять-таки, эту часть упростил максимально, вырезав очень много из стандарта, так как у меня, как минимум, нет вращение против часовой стрелки.
Логика такая: после поворота к фигуре применяются смещения по иксу и игрику по очереди из массива, сначала 0-0 (не смещается), потом, к примеру 0-1 и так далее. За идеальное состояние, которое в данный момент всех устраивает, применяется то, после которого проверка коллизии фигуры показывает, что никто ни с кем не столкнулся. Если ни один из вариантов не подошёл, значит поворот не случился.
Классические таблицы подразумевают матрицы фигур одинакового размера и квадратные по своей сути. Я тут тоже отошёл от стандарта,
Как это в итоге играется
По коду там есть у меня есть усложнение с увеличением скорости падения фигур за каждые 30 полученных очков, сохранение рекорда и прочая мишура, которая к основному алгоритму отношения уже не имеет.
Как грицца: понятно, что нифига не понятно, так что спрашивайте, господа и дамы, отвечу на недостающие вопросы)
Не помогли портянки войлочные в рабочих кирзовых сапогах. Хотя было тепло -20 в тени , а на солнце -16. Однако ноги начали замерзать. От этого потом усталость появилась.
Руки у нас замерзали. Однако я опытный... было две пары перчаток. Не собираюсь экономить на своих руках как некоторые. Лекарства стоят дороже!..
Баф помогал очень хорошо. Закрывая нос и щеки. Можно надышать там ртом тепло и радоваться . После баф намокает , но его можно повернуть сухой строй к себе. Так становится теплее.. Зайдя в помещение он высыхает за пару часов.
_____
На веле быстрее чем пешком. Менее замерзать и надёжнее чем на машине. Даже у магазина не все могут завести машину. Морозы!
Шипы на месте. Хорошо вцепляются в лёд и снег твердый. Пока некогда их подрезать . Надеюсь успею до апреля 😒🤣.
Заднее колесо без шипов. Хватает токо переднего шипованного. В основном переднее колесо на льду выбивает из рук. Заднее колесо более устойчиво.
Зимой плавное руление с плавной скоростью = кости целее... И да утепляйте сиденья на веле ( хоть М или Ж велосипедисты)
_____
Завтра будет холоднее нам и сложнее. Досадую, что не купил валенки. Буду искать себе их по доступной цене.
Есть на озоне)
@talk.about@Hippopofox@SergPrg@Linda_M@moortnelis@Aid314@Tiamin@Nataalika@Moonshine@Alenari@SergeyRY@Pepels@BespiriL@Cubinec@Palebody@DoctorDoom@rammdarkfunny@AlNiKo@kimpokom@Brainy@etoshtrudel@jewell...