Синхронизация действий

Opik

Новичок
Синхронизация действий

Задача: написать скрипт, позволющий двум или более игрокам драться друг против друга в онлайн игре.
Используется БД mySQL для хранения серий ударов.
1 размен ударами между игроками (далее 1 ход) - 1 игрок ударяет второго, а второй в свою очередь бьет первого.
Механизм работы скрипта:
1) Получаем всех игроков противоложной команды.
2) Получаем тех, кого я уже бил (есть записи в БД и удар помечен как неотвеченный)
3) Из тех, кого получили в п. 1 убираем тех, кто в п.2, т.е получаем тех. кого нужно ударить.
4) Выбираем рандомно 1 игрока. Показываем форму удара.

Механизм удара:
Если пришли POST данные
1) Проверяем, действительно ли игрок ударяет своего соперника.
2) Проверяем, бил ли игрок уже этого соперника, если да, то ничего не делаем с этим. просто заного идет вышеописанный алгоритм , нет - п. 2.а
а) Проверяем, бил ли игрока соперник (его удар в режиме ожидания.) Если бил - п. 2.б), если нет - п.2.в
б) По формулам вычитаем силу удара, разные приемы и так далее. одним словом - завершаем удар и помечаем его как завершенный.
в) заносим в базу новый, неотвеченный удар.
3) и так далее пока не выиграет 1 команда.

Из-за повышенной нагрузки на сервер и замедлении времени выполнения скрипт периодически появляется проблема:
В базе оказывается 2 записи:
1) Игрок ударил соперника (незавершенный)
2) Соперника ударил игрока (незавершенный)
Если посмотреть алгоримт боев. то видно, что игрок уже не сможет ударить своего соперника. и наоборот. идет таймаут в бою (что бы не игроки специально не затягивали бои)
и в итоге плачевные результаты.
Предполагаемая ошибка:
Скрипты выполняются дольше среднего. Игрок начал бить соперника. в это же время соперник начал бить игрока.
У обоих прошли обе проверки. (т.к на тот момент ударов ещё не было в базе) и добавилось 2 неотвеченных удара.

Вариант решения:
Если пришли ПОСТ данные, блокировать таблицу на чтение, завершать все действия, разблокировать таблицу и так далее. Проблема будет решена.
НО таким образом доступ к таблице будет однопоточный. т.е всем придеться ждать разблокировки таблицы. что в целом неприемлимо.

Собсвенно сейчас в недоумении что делать. есть ли альтернативы блокировки таблицы? или может изменить логику скрипта, если да, то как?
 

Tor

Новичок
ну и какое отношение в пхп?

попробуй сделать следующее:
после удара ждется, например, 30 секунд ответного удара
если через 30 сек выясняется, что они оба ждут ответного удара, то первый удар каждого или считается промахом или сам реши как
 

Opik

Новичок
Tor
А скрипт на чем?)
если через 30 сек выясняется, что они оба ждут ответного удара, то первый удар каждого или считается промахом или сам реши как
в целом был вопрос как предотравить, а не как потом извращаться.

-~{}~ 17.01.06 17:11:

whirlwind
ну вот пока к тому и склоняюсь
 

romy4

invoke [brain]
расковыряй damocka.ru (игра ЛПК). там та же ситуация реализована
 

Opik

Новичок
whirlwind
А как правильно делать SQL транзакции?
LOCK IN SHARE MODE пробовал - не помогло.
пробовал START TRANSACTION и потом COMMIT - тоже не вышло.
Тип таблицы - InnoDB
и когда именно нужно лочить таблицу? после какого пункта?

-~{}~ 20.01.06 17:55:

мануал читал.
 
Сверху