PTR zmalloc(size_t size) { unsigned blocks = BytesToBlocks(size); size_t bytes = (size_t) BlocksToBytes(blocks); register ZBLOCK *p; static unsigned amt_avail; static ZBLOCK *avail; if (!IsPoolable(blocks)) { p = (ZBLOCK *) Malloc(bytes); if (!p) out_of_mem(); RecordPtr(p, size); } else { if ((p = pool[blocks - 1]) != 0) { pool[blocks - 1] = p->link; } else { if (blocks > amt_avail) { if (amt_avail != 0) /* free avail */ { avail->link = pool[--amt_avail]; pool[amt_avail] = avail; } if (!(avail = (ZBLOCK *) Malloc((size_t) (CHUNK * ZBLOCKSZ)))) { /* if we get here, almost out of memory */ amt_avail = 0; p = (ZBLOCK *) Malloc(bytes); if (!p) out_of_mem(); RecordPtr(p, bytes); return (PTR) p; } else { RecordPtr(avail, CHUNK * ZBLOCKSZ); amt_avail = CHUNK; } } /* get p from the avail pile */ p = avail; avail += blocks; amt_avail -= blocks; } } return (PTR) p; }
void UpkeepPhase::FinishGraveyard(CommitSession& session, const Player& player) { LiveGame& game = GetGame(); const Colour c = game.GetTeam(player).GetColour(); VERIFY_MODEL(GetCurrentCmd(c) == nullptr); bool bOK = m_finished.insert(c).second; VERIFY_MODEL(bOK); const Controller& controller = session.GetController(); UpdateClient(controller, &player); if (m_finished.size() == game.GetTeams().size()) { session.DoAndPushRecord(RecordPtr(new StartRoundRecord)); if (game.HasFinished()) game.StartScorePhase(); // Deletes this. else game.StartActionPhase(); // Deletes this. game.GetPhase().UpdateClient(controller, nullptr); } session.GetController().SendMessage(Output::UpdateCurrentPlayers(session.GetGame()), session.GetGame()); }
PTR zrealloc(PTR p, size_t old_size, size_t new_size) { register PTR q; TRACE(("zrealloc %p %lu ->%lu\n", p, old_size, new_size)); if (new_size > (BlocksToBytes(POOLSZ)) && old_size > (BlocksToBytes(POOLSZ))) { if (!(q = realloc(p, new_size))) { out_of_mem(); } FinishPtr(p, old_size); RecordPtr(q, new_size); #ifdef DEBUG_ZMALLOC if (new_size > old_size) { memset((char *) q + old_size, 0, new_size - old_size); } #endif } else { q = zmalloc(new_size); memcpy(q, p, old_size < new_size ? old_size : new_size); zfree(p, old_size); } return q; }
void UpkeepPhase::FinishUpkeep(CommitSession& session, const Player& player) { const Team& team = GetGame().GetTeam(player); session.DoAndPushRecord(RecordPtr(new IncomeRecord(team.GetColour()))); if (team.GetGraveyard().IsEmpty()) FinishGraveyard(session, player); else StartCmd(CmdPtr(new GraveyardCmd(team.GetColour(), GetGame())), session); }
Cmd::ProcessResult ColoniseSquaresCmd::Process(const Input::CmdMessage& msg, CommitSession& session) { auto& m = VerifyCastInput<const Input::CmdColoniseSquares>(msg); Population pop = m.m_moved; VERIFY_INPUT_MSG("no moves specified", !pop.IsEmpty()); VERIFY_INPUT_MSG("not enough ships", pop.GetTotal() <= GetTeam(session.GetGame()).GetUnusedColonyShips()); Moves moves = GetMoves(pop, GetSquareCounts(session.GetGame())); DoRecord(RecordPtr(new ColoniseRecord(m_colour, m_pos, moves)), session); return nullptr; }
Cmd::ProcessResult AutoInfluenceCmd::Process(const Input::CmdMessage& msg, CommitSession& session) { if (dynamic_cast<const Input::CmdAbort*>(&msg)) return nullptr; std::vector<MapPos> hexes = GetHexes(session.GetGame()); auto& m = VerifyCastInput<const Input::CmdAutoInfluence>(msg); VERIFY_INPUT(m.m_selected.size() == hexes.size()); const LiveGame& game = session.GetGame(); for (size_t i = 0; i < hexes.size();++i) if (m.m_selected[i]) DoRecord(RecordPtr(new InfluenceRecord(m_colour, nullptr, &hexes[i])), session); return nullptr; }
Cmd::ProcessResult BankruptCmd::Process(const Input::CmdMessage& msg, CommitSession& session) { auto& m = VerifyCastInput<const Input::CmdInfluenceSrc>(msg); std::vector<MapPos> srcs = BankruptCmd::GetSources(session.GetGame()); VERIFY_INPUT_MSG("invalid pos index", m.m_iPos == -1 || InRange(srcs, m.m_iPos)); auto& pos = srcs[m.m_iPos]; InfluenceRecord* pRec = new InfluenceRecord(m_colour, &pos, nullptr); DoRecord(RecordPtr(pRec), session); const LiveGame& game = session.GetGame(); const Map& map = game.GetMap(); if (map.GetHex(pos).HasPopulation()) return ProcessResult(new UncoloniseCmd(m_colour, pos), nullptr); return nullptr; }
Cmd::ProcessResult TradeCmd::Process(const Input::CmdMessage& msg, CommitSession& session) { const Team& team = session.GetGame().GetTeam(m_colour); auto& storage = team.GetStorage(); auto& m = VerifyCastInput<const Input::CmdTrade>(msg); const int fromCount = m.m_count * Race(team.GetRace()).GetTradeRate(); VERIFY_INPUT_MSG("no count", m.m_count > 0); VERIFY_INPUT_MSG("to == from", m.m_from != m.m_to); VERIFY_INPUT_MSG("can't afford trade", fromCount <= storage[m.m_from]); TradeRecord::PairVec srcs{ { m.m_from, fromCount } }; TradeRecord::Pair dst(m.m_to, m.m_count); TradeRecord* pRec = new TradeRecord(m_colour, srcs, dst); DoRecord(RecordPtr(pRec), session); return nullptr; }
void UpkeepPhase::Init(CommitSession& session) { auto& game = session.GetGame(); std::set<Colour> influenceableHexes; // Team -> hex IDs. for (auto& pair : game.GetMap().GetHexes()) { auto& hex = pair.second; // "If you have at least one Ship in a hex that has no population, remove the previous controller’s Influence Disc." if (hex->IsOwned() && !hex->HasPopulation() && hex->HasForeignShip(hex->GetColour())) session.DoAndPushRecord(RecordPtr(new InfluenceRecord(hex->GetColour(), &hex->GetPos(), nullptr))); // If at the end of the Combat Phase your Ship is in a hex without an Influence Disc, you may place a disc there." Colour c = AutoInfluenceCmd::GetAutoInfluenceColour(*hex); if (c != Colour::None) influenceableHexes.insert(c); } for (auto& c : influenceableHexes) StartCmd(CmdPtr(new AutoInfluenceCmd(c, game)), session); // TODO: Stop user undoing. }
Cmd::ProcessResult DiscoverCmd::Process(const Input::CmdMessage& msg, CommitSession& session) { auto& m = VerifyCastInput<const Input::CmdDiscovery>(msg); VERIFY_INPUT(m.m_action != Input::CmdDiscovery::Action::None); auto& game = session.GetGame(); bool use = m.m_action == Input::CmdDiscovery::Action::Use; VERIFY_INPUT(!use || CanUse(game)); if (use && m_discovery == DiscoveryType::AncientTech) return ProcessResult(new ResearchDiscoveryCmd(m_colour, game, GetAncientTechs(game))); DiscoveryType discovery = m.m_action == Input::CmdDiscovery::Action::Points ? DiscoveryType::None : m_discovery; DoRecord(RecordPtr(new DiscoveryRecord(m_colour, discovery, m_idHex)), session); if (use && Discovery::GetClass(m_discovery) == DiscoveryClass::ShipPart) return ProcessResult(new UpgradeDiscoveryCmd(m_colour, session.GetGame(), Discovery::GetShipPart(m_discovery))); return ProcessResult(nullptr); }
void ChooseTeamPhase::AssignTeam(CommitSession& session, Player& player, RaceType race, Colour colour) { LiveGame& game = GetGame(); game.GetTeam(player).Assign(race, colour, game); AdvanceTurn(); session.GetController().SendMessage(Output::ChooseTeam(game, false), player); bool allAssigned = true; for (auto& team : game.GetTeams()) allAssigned &= team->GetColour() != Colour::None; if (allAssigned) { session.DoAndPushRecord(RecordPtr(new StartGameRecord)); game.StartMainGamePhase(); // Deletes this. session.GetController().SendUpdateGame(game); } else UpdateClient(session.GetController(), nullptr); }
RecordPtr ShipBattle::CreateAttackRecord(const Game& game, const Dice& dice) const { const Hits hits = AutoAssignHits(dice, game); return RecordPtr(new AttackShipsRecord(hits)); }